don't crash if we disable logging when some code already has a copy of the logger. Prior to this fix, logs were handed out as pointers and if they were held onto while a log got disabled, then it could cause a crash. Now all logs are handed out as shared pointers so this problem shouldn't happen anymore. We are also using our new shared pointers that put the shared pointer count and the object into the same allocation for a tad better performance. llvm-svn: 118319
406 lines
10 KiB
C++
406 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)
|
|
{
|
|
}
|
|
|
|
StopInfoBreakpoint (Thread &thread, break_id_t break_id, bool should_stop) :
|
|
StopInfo (thread, break_id),
|
|
m_description(),
|
|
m_should_stop (should_stop),
|
|
m_should_stop_is_valid (true)
|
|
{
|
|
}
|
|
|
|
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
|
|
{
|
|
LogSP 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
|
|
{
|
|
LogSP 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::CreateStopReasonWithBreakpointSiteID (Thread &thread, break_id_t break_id, bool should_stop)
|
|
{
|
|
return StopInfoSP (new StopInfoBreakpoint (thread, break_id, should_stop));
|
|
}
|
|
|
|
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));
|
|
}
|