Add watchpoint support for Linux on 64-bit host.

llvm-svn: 181341
This commit is contained in:
Matt Kopec
2013-05-07 19:29:28 +00:00
parent ba4e61d3f5
commit e9ea0da82e
23 changed files with 589 additions and 19 deletions

View File

@@ -15,6 +15,7 @@
// C++ Includes
// Other libraries and framework includes
// Project includes
#include "lldb/Breakpoint/Watchpoint.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Host/Host.h"
#include "lldb/Target/Process.h"
@@ -229,6 +230,10 @@ POSIXThread::Notify(const ProcessMessage &message)
BreakNotify(message);
break;
case ProcessMessage::eWatchpointMessage:
WatchNotify(message);
break;
case ProcessMessage::eCrashMessage:
CrashNotify(message);
break;
@@ -239,6 +244,58 @@ POSIXThread::Notify(const ProcessMessage &message)
}
}
bool
POSIXThread::EnableHardwareWatchpoint(Watchpoint *wp)
{
bool result = false;
if (wp)
{
addr_t wp_addr = wp->GetLoadAddress();
size_t wp_size = wp->GetByteSize();
bool wp_read = wp->WatchpointRead();
bool wp_write = wp->WatchpointWrite();
uint32_t wp_hw_index;
lldb::RegisterContextSP reg_ctx_sp = GetRegisterContext();
if (reg_ctx_sp.get())
{
wp_hw_index = reg_ctx_sp->SetHardwareWatchpoint(wp_addr, wp_size,
wp_read, wp_write);
if (wp_hw_index != LLDB_INVALID_INDEX32)
{
wp->SetHardwareIndex(wp_hw_index);
result = true;
}
}
}
return result;
}
bool
POSIXThread::DisableHardwareWatchpoint(Watchpoint *wp)
{
bool result = false;
if (wp)
{
lldb::RegisterContextSP reg_ctx_sp = GetRegisterContext();
if (reg_ctx_sp.get())
{
result = reg_ctx_sp->ClearHardwareWatchpoint(wp->GetHardwareIndex());
if (result == true)
wp->SetHardwareIndex(LLDB_INVALID_INDEX32);
}
}
return result;
}
uint32_t
POSIXThread::NumSupportedHardwareWatchpoints()
{
lldb::RegisterContextSP reg_ctx_sp = GetRegisterContext();
if (reg_ctx_sp.get())
return reg_ctx_sp->NumSupportedHardwareWatchpoints();
return 0;
}
void
POSIXThread::BreakNotify(const ProcessMessage &message)
{
@@ -260,11 +317,49 @@ POSIXThread::BreakNotify(const ProcessMessage &message)
lldb::break_id_t bp_id = bp_site->GetID();
assert(bp_site && bp_site->ValidForThisThread(this));
m_breakpoint = bp_site;
SetStopInfo (StopInfo::CreateStopReasonWithBreakpointSiteID(*this, bp_id));
}
void
POSIXThread::WatchNotify(const ProcessMessage &message)
{
Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
lldb::addr_t halt_addr = message.GetHWAddress();
if (log)
log->Printf ("POSIXThread::%s () Hardware Watchpoint Address = 0x%8.8"
PRIx64, __FUNCTION__, halt_addr);
RegisterContextPOSIX* reg_ctx = GetRegisterContextPOSIX();
if (reg_ctx)
{
uint32_t num_hw_wps = reg_ctx->NumSupportedHardwareWatchpoints();
uint32_t wp_idx;
for (wp_idx = 0; wp_idx < num_hw_wps; wp_idx++)
{
if (reg_ctx->IsWatchpointHit(wp_idx))
{
// Clear the watchpoint hit here
reg_ctx->ClearWatchpointHits();
break;
}
}
if (wp_idx == num_hw_wps)
return;
Target &target = GetProcess()->GetTarget();
lldb::addr_t wp_monitor_addr = reg_ctx->GetWatchpointAddress(wp_idx);
const WatchpointList &wp_list = target.GetWatchpointList();
lldb::WatchpointSP wp_sp = wp_list.FindByAddress(wp_monitor_addr);
if (wp_sp)
SetStopInfo (StopInfo::CreateStopReasonWithWatchpointID(*this,
wp_sp->GetID()));
}
}
void
POSIXThread::TraceNotify(const ProcessMessage &message)
{