forked from OSchip/llvm-project
392 lines
10 KiB
C++
392 lines
10 KiB
C++
//===-- StopInfo.cpp ---------------------------------------------*- C++ -*-===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "lldb/Target/StopInfo.h"
|
|
|
|
// C Includes
|
|
// C++ Includes
|
|
#include <string>
|
|
|
|
// Other libraries and framework includes
|
|
// Project includes
|
|
#include "lldb/Core/Log.h"
|
|
#include "lldb/Breakpoint/BreakpointLocation.h"
|
|
#include "lldb/Breakpoint/StoppointCallbackContext.h"
|
|
#include "lldb/Core/StreamString.h"
|
|
#include "lldb/Target/Thread.h"
|
|
#include "lldb/Target/ThreadPlan.h"
|
|
#include "lldb/Target/Process.h"
|
|
#include "lldb/Target/UnixSignals.h"
|
|
|
|
using namespace lldb;
|
|
using namespace lldb_private;
|
|
|
|
StopInfo::StopInfo (Thread &thread, uint64_t value) :
|
|
m_thread (thread),
|
|
m_stop_id (thread.GetProcess().GetStopID()),
|
|
m_value (value)
|
|
{
|
|
}
|
|
|
|
bool
|
|
StopInfo::IsValid () const
|
|
{
|
|
return m_thread.GetProcess().GetStopID() == m_stop_id;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
// StopInfoBreakpoint
|
|
//----------------------------------------------------------------------
|
|
|
|
class StopInfoBreakpoint : public StopInfo
|
|
{
|
|
public:
|
|
|
|
StopInfoBreakpoint (Thread &thread, break_id_t break_id) :
|
|
StopInfo (thread, break_id),
|
|
m_description(),
|
|
m_should_stop (false),
|
|
m_should_stop_is_valid (false)
|
|
{
|
|
}
|
|
|
|
virtual ~StopInfoBreakpoint ()
|
|
{
|
|
}
|
|
|
|
virtual StopReason
|
|
GetStopReason () const
|
|
{
|
|
return eStopReasonBreakpoint;
|
|
}
|
|
|
|
virtual bool
|
|
ShouldStop (Event *event_ptr)
|
|
{
|
|
if (!m_should_stop_is_valid)
|
|
{
|
|
// Only check once if we should stop at a breakpoint
|
|
BreakpointSiteSP bp_site_sp (m_thread.GetProcess().GetBreakpointSiteList().FindByID (m_value));
|
|
if (bp_site_sp)
|
|
{
|
|
StoppointCallbackContext context (event_ptr,
|
|
&m_thread.GetProcess(),
|
|
&m_thread,
|
|
m_thread.GetStackFrameAtIndex(0).get(),
|
|
true);
|
|
|
|
m_should_stop = bp_site_sp->ShouldStop (&context);
|
|
}
|
|
else
|
|
{
|
|
Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS);
|
|
|
|
if (log)
|
|
log->Printf ("Process::%s could not find breakpoint site id: %lld...", __FUNCTION__, m_value);
|
|
|
|
m_should_stop = true;
|
|
}
|
|
m_should_stop_is_valid = true;
|
|
}
|
|
return m_should_stop;
|
|
}
|
|
|
|
virtual void
|
|
PerformAction (Event *event_ptr)
|
|
{
|
|
BreakpointSiteSP bp_site_sp (m_thread.GetProcess().GetBreakpointSiteList().FindByID (m_value));
|
|
if (bp_site_sp)
|
|
{
|
|
size_t num_owners = bp_site_sp->GetNumberOfOwners();
|
|
for (size_t j = 0; j < num_owners; j++)
|
|
{
|
|
// The breakpoint action is an asynchronous breakpoint callback. If we ever need to have both
|
|
// callbacks and actions on the same breakpoint, we'll have to split this into two.
|
|
lldb::BreakpointLocationSP bp_loc_sp = bp_site_sp->GetOwnerAtIndex(j);
|
|
StoppointCallbackContext context (event_ptr,
|
|
&m_thread.GetProcess(),
|
|
&m_thread,
|
|
m_thread.GetStackFrameAtIndex(0).get(),
|
|
false);
|
|
bp_loc_sp->InvokeCallback (&context);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS);
|
|
|
|
if (log)
|
|
log->Printf ("Process::%s could not find breakpoint site id: %lld...", __FUNCTION__, m_value);
|
|
}
|
|
}
|
|
|
|
virtual bool
|
|
ShouldNotify (Event *event_ptr)
|
|
{
|
|
BreakpointSiteSP bp_site_sp (m_thread.GetProcess().GetBreakpointSiteList().FindByID (m_value));
|
|
if (bp_site_sp)
|
|
{
|
|
bool all_internal = true;
|
|
|
|
for (uint32_t i = 0; i < bp_site_sp->GetNumberOfOwners(); i++)
|
|
{
|
|
if (!bp_site_sp->GetOwnerAtIndex(i)->GetBreakpoint().IsInternal())
|
|
{
|
|
all_internal = false;
|
|
break;
|
|
}
|
|
}
|
|
return all_internal == false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
virtual const char *
|
|
GetDescription ()
|
|
{
|
|
if (m_description.empty())
|
|
{
|
|
BreakpointSiteSP bp_site_sp (m_thread.GetProcess().GetBreakpointSiteList().FindByID (m_value));
|
|
if (bp_site_sp)
|
|
{
|
|
StreamString strm;
|
|
strm.Printf("breakpoint ");
|
|
bp_site_sp->GetDescription(&strm, eDescriptionLevelBrief);
|
|
m_description.swap (strm.GetString());
|
|
}
|
|
else
|
|
{
|
|
StreamString strm;
|
|
strm.Printf("breakpoint site %lli", m_value);
|
|
m_description.swap (strm.GetString());
|
|
}
|
|
}
|
|
return m_description.c_str();
|
|
}
|
|
|
|
private:
|
|
std::string m_description;
|
|
bool m_should_stop;
|
|
bool m_should_stop_is_valid;
|
|
};
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
// StopInfoWatchpoint
|
|
//----------------------------------------------------------------------
|
|
|
|
class StopInfoWatchpoint : public StopInfo
|
|
{
|
|
public:
|
|
|
|
StopInfoWatchpoint (Thread &thread, break_id_t watch_id) :
|
|
StopInfo (thread, watch_id),
|
|
m_description()
|
|
{
|
|
}
|
|
|
|
virtual ~StopInfoWatchpoint ()
|
|
{
|
|
}
|
|
|
|
virtual StopReason
|
|
GetStopReason () const
|
|
{
|
|
return eStopReasonWatchpoint;
|
|
}
|
|
|
|
virtual const char *
|
|
GetDescription ()
|
|
{
|
|
if (m_description.empty())
|
|
{
|
|
StreamString strm;
|
|
strm.Printf("watchpoint %lli", m_value);
|
|
m_description.swap (strm.GetString());
|
|
}
|
|
return m_description.c_str();
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
std::string m_description;
|
|
};
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
// StopInfoUnixSignal
|
|
//----------------------------------------------------------------------
|
|
|
|
class StopInfoUnixSignal : public StopInfo
|
|
{
|
|
public:
|
|
|
|
StopInfoUnixSignal (Thread &thread, int signo) :
|
|
StopInfo (thread, signo),
|
|
m_description()
|
|
{
|
|
}
|
|
|
|
virtual ~StopInfoUnixSignal ()
|
|
{
|
|
}
|
|
|
|
|
|
virtual StopReason
|
|
GetStopReason () const
|
|
{
|
|
return eStopReasonSignal;
|
|
}
|
|
|
|
virtual bool
|
|
ShouldStop (Event *event_ptr)
|
|
{
|
|
return m_thread.GetProcess().GetUnixSignals().GetShouldStop (m_value);
|
|
}
|
|
|
|
|
|
// If should stop returns false, check if we should notify of this event
|
|
virtual bool
|
|
ShouldNotify (Event *event_ptr)
|
|
{
|
|
return m_thread.GetProcess().GetUnixSignals().GetShouldNotify (m_value);
|
|
}
|
|
|
|
|
|
virtual void
|
|
WillResume (lldb::StateType resume_state)
|
|
{
|
|
if (m_thread.GetProcess().GetUnixSignals().GetShouldSuppress(m_value) == false)
|
|
m_thread.SetResumeSignal(m_value);
|
|
}
|
|
|
|
virtual const char *
|
|
GetDescription ()
|
|
{
|
|
if (m_description.empty())
|
|
{
|
|
StreamString strm;
|
|
const char *signal_name = m_thread.GetProcess().GetUnixSignals().GetSignalAsCString (m_value);
|
|
if (signal_name)
|
|
strm.Printf("signal = %s", signal_name);
|
|
else
|
|
strm.Printf("signal = %lli", m_value);
|
|
m_description.swap (strm.GetString());
|
|
}
|
|
return m_description.c_str();
|
|
}
|
|
|
|
private:
|
|
std::string m_description;
|
|
};
|
|
|
|
//----------------------------------------------------------------------
|
|
// StopInfoTrace
|
|
//----------------------------------------------------------------------
|
|
|
|
class StopInfoTrace : public StopInfo
|
|
{
|
|
public:
|
|
|
|
StopInfoTrace (Thread &thread) :
|
|
StopInfo (thread, LLDB_INVALID_UID)
|
|
{
|
|
}
|
|
|
|
virtual ~StopInfoTrace ()
|
|
{
|
|
}
|
|
|
|
virtual StopReason
|
|
GetStopReason () const
|
|
{
|
|
return eStopReasonTrace;
|
|
}
|
|
|
|
virtual const char *
|
|
GetDescription ()
|
|
{
|
|
return "trace";
|
|
}
|
|
};
|
|
|
|
|
|
//----------------------------------------------------------------------
|
|
// StopInfoThreadPlan
|
|
//----------------------------------------------------------------------
|
|
|
|
class StopInfoThreadPlan : public StopInfo
|
|
{
|
|
public:
|
|
|
|
StopInfoThreadPlan (ThreadPlanSP &plan_sp) :
|
|
StopInfo (plan_sp->GetThread(), LLDB_INVALID_UID),
|
|
m_plan_sp (plan_sp)
|
|
{
|
|
}
|
|
|
|
virtual ~StopInfoThreadPlan ()
|
|
{
|
|
}
|
|
|
|
virtual StopReason
|
|
GetStopReason () const
|
|
{
|
|
return eStopReasonPlanComplete;
|
|
}
|
|
|
|
virtual const char *
|
|
GetDescription ()
|
|
{
|
|
if (m_description.empty())
|
|
{
|
|
StreamString strm;
|
|
m_plan_sp->GetDescription (&strm, eDescriptionLevelBrief);
|
|
m_description.swap (strm.GetString());
|
|
}
|
|
return m_description.c_str();
|
|
}
|
|
|
|
private:
|
|
ThreadPlanSP m_plan_sp;
|
|
std::string m_description;
|
|
};
|
|
|
|
StopInfoSP
|
|
StopInfo::CreateStopReasonWithBreakpointSiteID (Thread &thread, break_id_t break_id)
|
|
{
|
|
return StopInfoSP (new StopInfoBreakpoint (thread, break_id));
|
|
}
|
|
|
|
StopInfoSP
|
|
StopInfo::CreateStopReasonWithWatchpointID (Thread &thread, break_id_t watch_id)
|
|
{
|
|
return StopInfoSP (new StopInfoWatchpoint (thread, watch_id));
|
|
}
|
|
|
|
StopInfoSP
|
|
StopInfo::CreateStopReasonWithSignal (Thread &thread, int signo)
|
|
{
|
|
return StopInfoSP (new StopInfoUnixSignal (thread, signo));
|
|
}
|
|
|
|
StopInfoSP
|
|
StopInfo::CreateStopReasonToTrace (Thread &thread)
|
|
{
|
|
return StopInfoSP (new StopInfoTrace (thread));
|
|
}
|
|
|
|
StopInfoSP
|
|
StopInfo::CreateStopReasonWithPlan (ThreadPlanSP &plan_sp)
|
|
{
|
|
return StopInfoSP (new StopInfoThreadPlan (plan_sp));
|
|
}
|