Watchpoint work in progress:

Add a virtual method GetHardwareWatchpointHit() to the DNBArchProtocol base class
which consults the architecture to return the watchpoint hit; otherwise return an
invalid index.

Add impl. of the method to X86_64 and I386 subclasses, plus reset the debug status
register before we resume execution of the inferior thread.

llvm-svn: 139034
This commit is contained in:
Johnny Chen 2011-09-02 21:13:07 +00:00
parent 7aa58f1eea
commit 1bd08dd878
5 changed files with 71 additions and 0 deletions

View File

@ -79,6 +79,7 @@ public:
virtual uint32_t EnableHardwareWatchpoint (nub_addr_t addr, nub_size_t size, bool read, bool write) { return INVALID_NUB_HW_INDEX; }
virtual bool DisableHardwareBreakpoint (uint32_t hw_index) { return false; }
virtual bool DisableHardwareWatchpoint (uint32_t hw_index) { return false; }
virtual uint32_t GetHardwareWatchpointHit() { return INVALID_NUB_HW_INDEX; }
virtual bool StepNotComplete () { return false; }
};

View File

@ -545,6 +545,17 @@ DNBArchImplI386::ThreadWillResume()
// This is the primary thread, let the arch do anything it needs
EnableHardwareSingleStep(true);
}
// Reset the debug status register before we resume.
kern_return_t kret = GetDBGState(false);
DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplI386::ThreadWillResume() GetDBGState() => 0x%8.8x.", kret);
if (kret == KERN_SUCCESS)
{
DBG debug_state = m_state.context.dbg;
ClearWatchpointHits(debug_state);
kret = SetDBGState();
DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplI386::ThreadWillResume() SetDBGState() => 0x%8.8x.", kret);
}
}
bool
@ -625,6 +636,29 @@ DNBArchImplI386::NotifyException(MachException::Data& exc)
return false;
}
// Iterate through the debug status register; return the index of the first hit.
uint32_t
DNBArchImplI386::GetHardwareWatchpointHit()
{
// Read the debug state
kern_return_t kret = GetDBGState(false);
DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplI386::GetHardwareWatchpointHit() GetDBGState() => 0x%8.8x.", kret);
if (kret == KERN_SUCCESS)
{
DBG debug_state = m_state.context.dbg;
uint32_t i, num = NumSupportedHardwareWatchpoints();
for (i = 0; i < num; ++i)
{
if (IsWatchpointHit(debug_state, i))
{
DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplX86_64::GetHardwareWatchpointHit() found => %u.", i);
return i;
}
}
}
return INVALID_NUB_HW_INDEX;
}
uint32_t
DNBArchImplI386::NumSupportedHardwareWatchpoints()
{

View File

@ -54,6 +54,7 @@ public:
virtual uint32_t NumSupportedHardwareWatchpoints();
virtual uint32_t EnableHardwareWatchpoint (nub_addr_t addr, nub_size_t size, bool read, bool write);
virtual bool DisableHardwareWatchpoint (uint32_t hw_break_index);
virtual uint32_t GetHardwareWatchpointHit();
protected:
kern_return_t EnableHardwareSingleStep (bool enable);

View File

@ -474,6 +474,17 @@ DNBArchImplX86_64::ThreadWillResume()
// This is the primary thread, let the arch do anything it needs
EnableHardwareSingleStep(true);
}
// Reset the debug status register before we resume.
kern_return_t kret = GetDBGState(false);
DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplX86_64::ThreadWillResume() GetDBGState() => 0x%8.8x.", kret);
if (kret == KERN_SUCCESS)
{
DBG debug_state = m_state.context.dbg;
ClearWatchpointHits(debug_state);
kret = SetDBGState();
DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplX86_64::ThreadWillResume() SetDBGState() => 0x%8.8x.", kret);
}
}
bool
@ -759,6 +770,29 @@ DNBArchImplX86_64::DisableHardwareWatchpoint (uint32_t hw_index)
return false;
}
// Iterate through the debug status register; return the index of the first hit.
uint32_t
DNBArchImplX86_64::GetHardwareWatchpointHit()
{
// Read the debug state
kern_return_t kret = GetDBGState(false);
DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplX86_64::GetHardwareWatchpointHit() GetDBGState() => 0x%8.8x.", kret);
if (kret == KERN_SUCCESS)
{
DBG debug_state = m_state.context.dbg;
uint32_t i, num = NumSupportedHardwareWatchpoints();
for (i = 0; i < num; ++i)
{
if (IsWatchpointHit(debug_state, i))
{
DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplX86_64::GetHardwareWatchpointHit() found => %u.", i);
return i;
}
}
}
return INVALID_NUB_HW_INDEX;
}
// Set the single step bit in the processor status register.
kern_return_t
DNBArchImplX86_64::EnableHardwareSingleStep (bool enable)

View File

@ -53,6 +53,7 @@ public:
virtual uint32_t NumSupportedHardwareWatchpoints();
virtual uint32_t EnableHardwareWatchpoint (nub_addr_t addr, nub_size_t size, bool read, bool write);
virtual bool DisableHardwareWatchpoint (uint32_t hw_break_index);
virtual uint32_t GetHardwareWatchpointHit();
protected:
kern_return_t EnableHardwareSingleStep (bool enable);