All UnwindPlan objects are now passed around as shared pointers.

ArchDefaultUnwindPlan plug-in interfaces are now cached per architecture 
instead of being leaked for every frame.

Split the ArchDefaultUnwindPlan_x86 into ArchDefaultUnwindPlan_x86_64 and
ArchDefaultUnwindPlan_i386 interfaces.

There were sporadic crashes that were due to something leaking or being 
destroyed when doing stack crawls. This patch should clear up these issues.

llvm-svn: 125541
This commit is contained in:
Greg Clayton 2011-02-15 00:19:15 +00:00
parent 91c08ad14a
commit e576ab2996
20 changed files with 481 additions and 320 deletions

View File

@ -43,16 +43,16 @@ public:
// On architectures where the pc points to the next instruction that will execute, this // On architectures where the pc points to the next instruction that will execute, this
// offset value will have already been decremented by 1 to stay within the bounds of the // offset value will have already been decremented by 1 to stay within the bounds of the
// correct function body. // correct function body.
UnwindPlan* lldb::UnwindPlanSP
GetUnwindPlanAtCallSite (int current_offset); GetUnwindPlanAtCallSite (int current_offset);
UnwindPlan* lldb::UnwindPlanSP
GetUnwindPlanAtNonCallSite (lldb_private::Thread& thread); GetUnwindPlanAtNonCallSite (lldb_private::Thread& thread);
UnwindPlan* lldb::UnwindPlanSP
GetUnwindPlanFastUnwind (lldb_private::Thread& Thread); GetUnwindPlanFastUnwind (lldb_private::Thread& Thread);
UnwindPlan* lldb::UnwindPlanSP
GetUnwindPlanArchitectureDefault (lldb_private::Thread& thread); GetUnwindPlanArchitectureDefault (lldb_private::Thread& thread);
Address& Address&
@ -74,10 +74,10 @@ private:
AddressRange m_range; AddressRange m_range;
Mutex m_mutex; Mutex m_mutex;
std::auto_ptr<UnwindPlan> m_unwind_at_call_site_ap; lldb::UnwindPlanSP m_unwind_plan_call_site_sp;
std::auto_ptr<UnwindPlan> m_unwind_at_non_call_site_ap; lldb::UnwindPlanSP m_unwind_plan_non_call_site_sp;
std::auto_ptr<UnwindPlan> m_unwind_fast_ap; lldb::UnwindPlanSP m_unwind_plan_fast_sp;
UnwindPlan *m_unwind_arch_default; lldb::UnwindPlanSP m_unwind_plan_arch_default_sp;
bool m_tried_unwind_at_call_site:1, bool m_tried_unwind_at_call_site:1,
m_tried_unwind_at_non_call_site:1, m_tried_unwind_at_non_call_site:1,

View File

@ -23,10 +23,10 @@ public:
virtual virtual
~ArchDefaultUnwindPlan(); ~ArchDefaultUnwindPlan();
virtual lldb_private::UnwindPlan* virtual lldb::UnwindPlanSP
GetArchDefaultUnwindPlan (Thread& thread, Address current_pc) = 0; GetArchDefaultUnwindPlan (Thread& thread, Address current_pc) = 0;
static ArchDefaultUnwindPlan* static lldb::ArchDefaultUnwindPlanSP
FindPlugin (const ArchSpec &arch); FindPlugin (const ArchSpec &arch);
protected: protected:

View File

@ -21,6 +21,7 @@ namespace lldb {
typedef SharedPtr<lldb_private::ABI>::Type ABISP; typedef SharedPtr<lldb_private::ABI>::Type ABISP;
typedef SharedPtr<lldb_private::AddressResolver>::Type AddressResolverSP; typedef SharedPtr<lldb_private::AddressResolver>::Type AddressResolverSP;
typedef SharedPtr<lldb_private::ArchDefaultUnwindPlan>::Type ArchDefaultUnwindPlanSP;
typedef SharedPtr<lldb_private::Baton>::Type BatonSP; typedef SharedPtr<lldb_private::Baton>::Type BatonSP;
typedef SharedPtr<lldb_private::Block>::Type BlockSP; typedef SharedPtr<lldb_private::Block>::Type BlockSP;
typedef SharedPtr<lldb_private::Breakpoint>::Type BreakpointSP; typedef SharedPtr<lldb_private::Breakpoint>::Type BreakpointSP;
@ -66,6 +67,7 @@ namespace lldb {
typedef SharedPtr<lldb_private::Type>::Type TypeSP; typedef SharedPtr<lldb_private::Type>::Type TypeSP;
typedef SharedPtr<lldb_private::FuncUnwinders>::Type FuncUnwindersSP; typedef SharedPtr<lldb_private::FuncUnwinders>::Type FuncUnwindersSP;
typedef SharedPtr<lldb_private::UserSettingsController>::Type UserSettingsControllerSP; typedef SharedPtr<lldb_private::UserSettingsController>::Type UserSettingsControllerSP;
typedef SharedPtr<lldb_private::UnwindPlan>::Type UnwindPlanSP;
typedef SharedPtr<lldb_private::ValueObject>::Type ValueObjectSP; typedef SharedPtr<lldb_private::ValueObject>::Type ValueObjectSP;
typedef SharedPtr<lldb_private::Variable>::Type VariableSP; typedef SharedPtr<lldb_private::Variable>::Type VariableSP;
typedef SharedPtr<lldb_private::VariableList>::Type VariableListSP; typedef SharedPtr<lldb_private::VariableList>::Type VariableListSP;

View File

@ -8,67 +8,29 @@
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#include "ArchDefaultUnwindPlan-x86.h" #include "ArchDefaultUnwindPlan-x86.h"
#include "llvm/Support/MachO.h"
#include "lldb/lldb-private.h"
#include "lldb/Utility/ArchDefaultUnwindPlan.h"
#include "lldb/Core/ArchSpec.h" #include "lldb/Core/ArchSpec.h"
#include "lldb/Core/PluginManager.h" #include "lldb/Core/PluginManager.h"
#include "lldb/lldb-enumerations.h" #include "lldb/Utility/ArchDefaultUnwindPlan.h"
using namespace lldb; using namespace lldb;
using namespace lldb_private; using namespace lldb_private;
lldb_private::UnwindPlan*
ArchDefaultUnwindPlan_x86::GetArchDefaultUnwindPlan (Thread& thread, Address current_pc)
{
if (m_cpu == llvm::MachO::CPUTypeX86_64)
{
return &m_64bit_default;
}
if (m_cpu == llvm::MachO::CPUTypeI386)
{
return &m_32bit_default;
}
return NULL;
}
lldb_private::ArchDefaultUnwindPlan * lldb_private::ArchDefaultUnwindPlan *
ArchDefaultUnwindPlan_x86::CreateInstance (const lldb_private::ArchSpec &arch) ArchDefaultUnwindPlan_x86_64::CreateInstance (const lldb_private::ArchSpec &arch)
{ {
uint32_t cpu = arch.GetCPUType (); if (arch.GetGenericCPUType () == ArchSpec::eCPU_x86_64)
if (cpu != llvm::MachO::CPUTypeX86_64 && cpu != llvm::MachO::CPUTypeI386) return new ArchDefaultUnwindPlan_x86_64 ();
return NULL; return NULL;
return new ArchDefaultUnwindPlan_x86 (cpu);
} }
ArchDefaultUnwindPlan_x86::ArchDefaultUnwindPlan_x86(int cpu) : ArchDefaultUnwindPlan_x86_64::ArchDefaultUnwindPlan_x86_64() :
lldb_private::ArchDefaultUnwindPlan(), lldb_private::ArchDefaultUnwindPlan(),
m_cpu(cpu), m_unwind_plan_sp (new UnwindPlan)
m_32bit_default(),
m_64bit_default()
{ {
UnwindPlan::Row row; UnwindPlan::Row row;
UnwindPlan::Row::RegisterLocation regloc; UnwindPlan::Row::RegisterLocation regloc;
m_32bit_default.SetRegisterKind (eRegisterKindGeneric); m_unwind_plan_sp->SetRegisterKind (eRegisterKindGeneric);
row.SetCFARegister (LLDB_REGNUM_GENERIC_FP);
row.SetCFAOffset (2 * 4);
row.SetOffset (0);
regloc.SetAtCFAPlusOffset (2 * -4);
row.SetRegisterInfo (LLDB_REGNUM_GENERIC_FP, regloc);
regloc.SetAtCFAPlusOffset (1 * -4);
row.SetRegisterInfo (LLDB_REGNUM_GENERIC_PC, regloc);
regloc.SetIsCFAPlusOffset (0);
row.SetRegisterInfo (LLDB_REGNUM_GENERIC_SP, regloc);
m_32bit_default.AppendRow (row);
m_32bit_default.SetSourceName ("architectural default");
row.Clear();
m_64bit_default.SetRegisterKind (eRegisterKindGeneric);
row.SetCFARegister (LLDB_REGNUM_GENERIC_FP); row.SetCFARegister (LLDB_REGNUM_GENERIC_FP);
row.SetCFAOffset (2 * 8); row.SetCFAOffset (2 * 8);
row.SetOffset (0); row.SetOffset (0);
@ -80,43 +42,40 @@ ArchDefaultUnwindPlan_x86::ArchDefaultUnwindPlan_x86(int cpu) :
regloc.SetIsCFAPlusOffset (0); regloc.SetIsCFAPlusOffset (0);
row.SetRegisterInfo (LLDB_REGNUM_GENERIC_SP, regloc); row.SetRegisterInfo (LLDB_REGNUM_GENERIC_SP, regloc);
m_64bit_default.AppendRow (row); m_unwind_plan_sp->AppendRow (row);
m_64bit_default.SetSourceName ("architectural default"); m_unwind_plan_sp->SetSourceName ("x86_64 architectural default");
} }
//------------------------------------------------------------------ //------------------------------------------------------------------
// PluginInterface protocol in UnwindAssemblyParser_x86 // PluginInterface protocol in UnwindAssemblyParser_x86
//------------------------------------------------------------------ //------------------------------------------------------------------
const char * const char *
ArchDefaultUnwindPlan_x86::GetPluginName() ArchDefaultUnwindPlan_x86_64::GetPluginName()
{ {
return "ArchDefaultUnwindPlan_x86"; return "ArchDefaultUnwindPlan_x86_64";
} }
const char * const char *
ArchDefaultUnwindPlan_x86::GetShortPluginName() ArchDefaultUnwindPlan_x86_64::GetShortPluginName()
{ {
return "archdefaultunwindplan.x86"; return "lldb.arch-default-unwind-plan.x86-64";
} }
uint32_t uint32_t
ArchDefaultUnwindPlan_x86::GetPluginVersion() ArchDefaultUnwindPlan_x86_64::GetPluginVersion()
{ {
return 1; return 1;
} }
void void
ArchDefaultUnwindPlan_x86::GetPluginCommandHelp (const char *command, Stream *strm) ArchDefaultUnwindPlan_x86_64::GetPluginCommandHelp (const char *command, Stream *strm)
{ {
} }
Error Error
ArchDefaultUnwindPlan_x86::ExecutePluginCommand (Args &command, Stream *strm) ArchDefaultUnwindPlan_x86_64::ExecutePluginCommand (Args &command, Stream *strm)
{ {
Error error; Error error;
error.SetErrorString("No plug-in command are currently supported."); error.SetErrorString("No plug-in command are currently supported.");
@ -124,13 +83,13 @@ ArchDefaultUnwindPlan_x86::ExecutePluginCommand (Args &command, Stream *strm)
} }
Log * Log *
ArchDefaultUnwindPlan_x86::EnablePluginLogging (Stream *strm, Args &command) ArchDefaultUnwindPlan_x86_64::EnablePluginLogging (Stream *strm, Args &command)
{ {
return NULL; return NULL;
} }
void void
ArchDefaultUnwindPlan_x86::Initialize() ArchDefaultUnwindPlan_x86_64::Initialize()
{ {
PluginManager::RegisterPlugin (GetPluginNameStatic(), PluginManager::RegisterPlugin (GetPluginNameStatic(),
GetPluginDescriptionStatic(), GetPluginDescriptionStatic(),
@ -138,20 +97,135 @@ ArchDefaultUnwindPlan_x86::Initialize()
} }
void void
ArchDefaultUnwindPlan_x86::Terminate() ArchDefaultUnwindPlan_x86_64::Terminate()
{ {
PluginManager::UnregisterPlugin (CreateInstance); PluginManager::UnregisterPlugin (CreateInstance);
} }
const char * const char *
ArchDefaultUnwindPlan_x86::GetPluginNameStatic() ArchDefaultUnwindPlan_x86_64::GetPluginNameStatic()
{ {
return "ArchDefaultUnwindPlan_x86"; return "ArchDefaultUnwindPlan_x86_64";
} }
const char * const char *
ArchDefaultUnwindPlan_x86::GetPluginDescriptionStatic() ArchDefaultUnwindPlan_x86_64::GetPluginDescriptionStatic()
{ {
return "i386 and x86_64 architecture default unwind plan assembly plugin."; return "x86_64 architecture default unwind plan assembly plugin.";
} }
UnwindPlanSP
ArchDefaultUnwindPlan_x86_64::GetArchDefaultUnwindPlan (Thread& thread, Address current_pc)
{
return m_unwind_plan_sp;
}
lldb_private::ArchDefaultUnwindPlan *
ArchDefaultUnwindPlan_i386::CreateInstance (const lldb_private::ArchSpec &arch)
{
if (arch.GetGenericCPUType () == ArchSpec::eCPU_i386)
return new ArchDefaultUnwindPlan_i386 ();
return NULL;
}
ArchDefaultUnwindPlan_i386::ArchDefaultUnwindPlan_i386() :
lldb_private::ArchDefaultUnwindPlan(),
m_unwind_plan_sp (new UnwindPlan)
{
UnwindPlan::Row row;
UnwindPlan::Row::RegisterLocation regloc;
m_unwind_plan_sp->SetRegisterKind (eRegisterKindGeneric);
row.SetCFARegister (LLDB_REGNUM_GENERIC_FP);
row.SetCFAOffset (2 * 4);
row.SetOffset (0);
regloc.SetAtCFAPlusOffset (2 * -4);
row.SetRegisterInfo (LLDB_REGNUM_GENERIC_FP, regloc);
regloc.SetAtCFAPlusOffset (1 * -4);
row.SetRegisterInfo (LLDB_REGNUM_GENERIC_PC, regloc);
regloc.SetIsCFAPlusOffset (0);
row.SetRegisterInfo (LLDB_REGNUM_GENERIC_SP, regloc);
m_unwind_plan_sp->AppendRow (row);
m_unwind_plan_sp->SetSourceName ("i386 architectural default");
}
//------------------------------------------------------------------
// PluginInterface protocol in UnwindAssemblyParser_x86
//------------------------------------------------------------------
const char *
ArchDefaultUnwindPlan_i386::GetPluginName()
{
return "ArchDefaultUnwindPlan_i386";
}
const char *
ArchDefaultUnwindPlan_i386::GetShortPluginName()
{
return "archdefaultunwindplan.x86";
}
uint32_t
ArchDefaultUnwindPlan_i386::GetPluginVersion()
{
return 1;
}
void
ArchDefaultUnwindPlan_i386::GetPluginCommandHelp (const char *command, Stream *strm)
{
}
Error
ArchDefaultUnwindPlan_i386::ExecutePluginCommand (Args &command, Stream *strm)
{
Error error;
error.SetErrorString("No plug-in command are currently supported.");
return error;
}
Log *
ArchDefaultUnwindPlan_i386::EnablePluginLogging (Stream *strm, Args &command)
{
return NULL;
}
void
ArchDefaultUnwindPlan_i386::Initialize()
{
PluginManager::RegisterPlugin (GetPluginNameStatic(),
GetPluginDescriptionStatic(),
CreateInstance);
}
void
ArchDefaultUnwindPlan_i386::Terminate()
{
PluginManager::UnregisterPlugin (CreateInstance);
}
const char *
ArchDefaultUnwindPlan_i386::GetPluginNameStatic()
{
return "ArchDefaultUnwindPlan_i386";
}
const char *
ArchDefaultUnwindPlan_i386::GetPluginDescriptionStatic()
{
return "i386 architecture default unwind plan assembly plugin.";
}
UnwindPlanSP
ArchDefaultUnwindPlan_i386::GetArchDefaultUnwindPlan (Thread& thread, Address current_pc)
{
return m_unwind_plan_sp;
}

View File

@ -17,13 +17,13 @@
namespace lldb_private { namespace lldb_private {
class ArchDefaultUnwindPlan_x86 : public lldb_private::ArchDefaultUnwindPlan class ArchDefaultUnwindPlan_x86_64 : public lldb_private::ArchDefaultUnwindPlan
{ {
public: public:
~ArchDefaultUnwindPlan_x86 () { } ~ArchDefaultUnwindPlan_x86_64 () { }
virtual lldb_private::UnwindPlan* virtual lldb::UnwindPlanSP
GetArchDefaultUnwindPlan (Thread& thread, Address current_pc); GetArchDefaultUnwindPlan (Thread& thread, Address current_pc);
static lldb_private::ArchDefaultUnwindPlan * static lldb_private::ArchDefaultUnwindPlan *
@ -63,11 +63,60 @@ public:
EnablePluginLogging (lldb_private::Stream *strm, lldb_private::Args &command); EnablePluginLogging (lldb_private::Stream *strm, lldb_private::Args &command);
private: private:
ArchDefaultUnwindPlan_x86(int cpu); // Call CreateInstance instead. ArchDefaultUnwindPlan_x86_64(); // Call CreateInstance instead.
int m_cpu; lldb::UnwindPlanSP m_unwind_plan_sp;
lldb_private::UnwindPlan m_32bit_default; };
lldb_private::UnwindPlan m_64bit_default;
class ArchDefaultUnwindPlan_i386 : public lldb_private::ArchDefaultUnwindPlan
{
public:
~ArchDefaultUnwindPlan_i386 () { }
virtual lldb::UnwindPlanSP
GetArchDefaultUnwindPlan (Thread& thread, Address current_pc);
static lldb_private::ArchDefaultUnwindPlan *
CreateInstance (const lldb_private::ArchSpec &arch);
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
static void
Initialize();
static void
Terminate();
static const char *
GetPluginNameStatic();
static const char *
GetPluginDescriptionStatic();
virtual const char *
GetPluginName();
virtual const char *
GetShortPluginName();
virtual uint32_t
GetPluginVersion();
virtual void
GetPluginCommandHelp (const char *command, lldb_private::Stream *strm);
virtual lldb_private::Error
ExecutePluginCommand (lldb_private::Args &command, lldb_private::Stream *strm);
virtual lldb_private::Log *
EnablePluginLogging (lldb_private::Stream *strm, lldb_private::Args &command);
private:
ArchDefaultUnwindPlan_i386(); // Call CreateInstance instead.
lldb::UnwindPlanSP m_unwind_plan_sp;
}; };

View File

@ -34,7 +34,7 @@ using namespace lldb_private;
RegisterContextLLDB::RegisterContextLLDB RegisterContextLLDB::RegisterContextLLDB
( (
Thread& thread, Thread& thread,
const RegisterContextSP &next_frame, const SharedPtr &next_frame,
SymbolContext& sym_ctx, SymbolContext& sym_ctx,
uint32_t frame_number uint32_t frame_number
) : ) :
@ -48,8 +48,8 @@ RegisterContextLLDB::RegisterContextLLDB
m_start_pc (), m_start_pc (),
m_current_pc (), m_current_pc (),
m_frame_number (frame_number), m_frame_number (frame_number),
m_full_unwind_plan(NULL), m_full_unwind_plan_sp (),
m_fast_unwind_plan(NULL), m_fast_unwind_plan_sp (),
m_frame_type (-1), m_frame_type (-1),
m_current_offset (0), m_current_offset (0),
m_current_offset_backed_up_one (0), m_current_offset_backed_up_one (0),
@ -68,20 +68,9 @@ RegisterContextLLDB::RegisterContextLLDB
} }
// This same code exists over in the GetFullUnwindPlanForFrame() but it may not have been executed yet // This same code exists over in the GetFullUnwindPlanForFrame() but it may not have been executed yet
bool behaves_like_zeroth_frame = false; if (IsFrameZero()
if (IsFrameZero()) || m_next_frame->m_frame_type == eSigtrampFrame
{ || m_next_frame->m_frame_type == eDebuggerFrame)
behaves_like_zeroth_frame = true;
}
if (!IsFrameZero() && ((RegisterContextLLDB*) m_next_frame.get())->m_frame_type == eSigtrampFrame)
{
behaves_like_zeroth_frame = true;
}
if (!IsFrameZero() && ((RegisterContextLLDB*) m_next_frame.get())->m_frame_type == eDebuggerFrame)
{
behaves_like_zeroth_frame = true;
}
if (behaves_like_zeroth_frame)
{ {
m_all_registers_available = true; m_all_registers_available = true;
} }
@ -124,6 +113,7 @@ RegisterContextLLDB::InitializeZerothFrame()
if (addr_range.GetBaseAddress().IsValid()) if (addr_range.GetBaseAddress().IsValid())
{ {
m_start_pc = addr_range.GetBaseAddress(); m_start_pc = addr_range.GetBaseAddress();
assert (frame_sp->GetFrameCodeAddress().GetSection() == m_start_pc.GetSection());
m_current_offset = frame_sp->GetFrameCodeAddress().GetOffset() - m_start_pc.GetOffset(); m_current_offset = frame_sp->GetFrameCodeAddress().GetOffset() - m_start_pc.GetOffset();
m_current_offset_backed_up_one = m_current_offset; m_current_offset_backed_up_one = m_current_offset;
} }
@ -136,16 +126,16 @@ RegisterContextLLDB::InitializeZerothFrame()
// We've set m_frame_type and m_sym_ctx before these calls. // We've set m_frame_type and m_sym_ctx before these calls.
m_fast_unwind_plan = GetFastUnwindPlanForFrame (); m_fast_unwind_plan_sp = GetFastUnwindPlanForFrame ();
m_full_unwind_plan = GetFullUnwindPlanForFrame (); m_full_unwind_plan_sp = GetFullUnwindPlanForFrame ();
const UnwindPlan::Row *active_row = NULL; const UnwindPlan::Row *active_row = NULL;
int cfa_offset = 0; int cfa_offset = 0;
int row_register_kind; int row_register_kind;
if (m_full_unwind_plan && m_full_unwind_plan->PlanValidAtAddress (m_current_pc)) if (m_full_unwind_plan_sp && m_full_unwind_plan_sp->PlanValidAtAddress (m_current_pc))
{ {
active_row = m_full_unwind_plan->GetRowForFunctionOffset (m_current_offset); active_row = m_full_unwind_plan_sp->GetRowForFunctionOffset (m_current_offset);
row_register_kind = m_full_unwind_plan->GetRegisterKind (); row_register_kind = m_full_unwind_plan_sp->GetRegisterKind ();
} }
if (active_row == NULL) if (active_row == NULL)
@ -189,7 +179,7 @@ RegisterContextLLDB::InitializeZerothFrame()
m_frame_number, m_frame_number,
(uint64_t) m_current_pc.GetLoadAddress (&m_thread.GetProcess().GetTarget()), (uint64_t) m_current_pc.GetLoadAddress (&m_thread.GetProcess().GetTarget()),
(uint64_t) m_cfa, (uint64_t) m_cfa,
m_full_unwind_plan->GetSourceName().GetCString()); m_full_unwind_plan_sp->GetSourceName().GetCString());
} }
} }
@ -205,7 +195,8 @@ RegisterContextLLDB::InitializeNonZerothFrame()
m_frame_type = eNotAValidFrame; m_frame_type = eNotAValidFrame;
return; return;
} }
if (!((RegisterContextLLDB*)m_next_frame.get())->IsValid())
if (!m_next_frame->IsValid())
{ {
m_frame_type = eNotAValidFrame; m_frame_type = eNotAValidFrame;
return; return;
@ -244,20 +235,20 @@ RegisterContextLLDB::InitializeNonZerothFrame()
log->Printf("%*sFrame %u using architectural default unwind method", log->Printf("%*sFrame %u using architectural default unwind method",
m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number); m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number);
} }
ArchSpec arch = m_thread.GetProcess().GetTarget().GetArchitecture (); const ArchSpec &arch = m_thread.GetProcess().GetTarget().GetArchitecture ();
ArchDefaultUnwindPlan *arch_default = ArchDefaultUnwindPlan::FindPlugin (arch); ArchDefaultUnwindPlanSP arch_default_sp (ArchDefaultUnwindPlan::FindPlugin (arch));
if (arch_default) if (arch_default_sp)
{ {
m_fast_unwind_plan = NULL; m_fast_unwind_plan_sp.reset();
m_full_unwind_plan = arch_default->GetArchDefaultUnwindPlan (m_thread, m_current_pc); m_full_unwind_plan_sp = arch_default_sp->GetArchDefaultUnwindPlan (m_thread, m_current_pc);
m_frame_type = eNormalFrame; m_frame_type = eNormalFrame;
m_all_registers_available = false; m_all_registers_available = false;
m_current_offset = -1; m_current_offset = -1;
m_current_offset_backed_up_one = -1; m_current_offset_backed_up_one = -1;
addr_t cfa_regval; addr_t cfa_regval;
int row_register_kind = m_full_unwind_plan->GetRegisterKind (); int row_register_kind = m_full_unwind_plan_sp->GetRegisterKind ();
uint32_t cfa_regnum = m_full_unwind_plan->GetRowForFunctionOffset(0)->GetCFARegister(); uint32_t cfa_regnum = m_full_unwind_plan_sp->GetRowForFunctionOffset(0)->GetCFARegister();
int cfa_offset = m_full_unwind_plan->GetRowForFunctionOffset(0)->GetCFAOffset(); int cfa_offset = m_full_unwind_plan_sp->GetRowForFunctionOffset(0)->GetCFAOffset();
if (!ReadGPRValue (row_register_kind, cfa_regnum, cfa_regval)) if (!ReadGPRValue (row_register_kind, cfa_regnum, cfa_regval))
{ {
if (log) if (log)
@ -315,8 +306,8 @@ RegisterContextLLDB::InitializeNonZerothFrame()
// Or if we're in the middle of the stack (and not "above" an asynchronous event like sigtramp), // Or if we're in the middle of the stack (and not "above" an asynchronous event like sigtramp),
// and our "current" pc is the start of a function... // and our "current" pc is the start of a function...
if (m_sym_ctx_valid if (m_sym_ctx_valid
&& ((RegisterContextLLDB*) m_next_frame.get())->m_frame_type != eSigtrampFrame && m_next_frame->m_frame_type != eSigtrampFrame
&& ((RegisterContextLLDB*) m_next_frame.get())->m_frame_type != eDebuggerFrame && m_next_frame->m_frame_type != eDebuggerFrame
&& addr_range.GetBaseAddress().IsValid() && addr_range.GetBaseAddress().IsValid()
&& addr_range.GetBaseAddress().GetSection() == m_current_pc.GetSection() && addr_range.GetBaseAddress().GetSection() == m_current_pc.GetSection()
&& addr_range.GetBaseAddress().GetOffset() == m_current_pc.GetOffset()) && addr_range.GetBaseAddress().GetOffset() == m_current_pc.GetOffset())
@ -374,7 +365,7 @@ RegisterContextLLDB::InitializeNonZerothFrame()
} }
// We've set m_frame_type and m_sym_ctx before this call. // We've set m_frame_type and m_sym_ctx before this call.
m_fast_unwind_plan = GetFastUnwindPlanForFrame (); m_fast_unwind_plan_sp = GetFastUnwindPlanForFrame ();
const UnwindPlan::Row *active_row = NULL; const UnwindPlan::Row *active_row = NULL;
int cfa_offset = 0; int cfa_offset = 0;
@ -383,18 +374,18 @@ RegisterContextLLDB::InitializeNonZerothFrame()
// Try to get by with just the fast UnwindPlan if possible - the full UnwindPlan may be expensive to get // Try to get by with just the fast UnwindPlan if possible - the full UnwindPlan may be expensive to get
// (e.g. if we have to parse the entire eh_frame section of an ObjectFile for the first time.) // (e.g. if we have to parse the entire eh_frame section of an ObjectFile for the first time.)
if (m_fast_unwind_plan && m_fast_unwind_plan->PlanValidAtAddress (m_current_pc)) if (m_fast_unwind_plan_sp && m_fast_unwind_plan_sp->PlanValidAtAddress (m_current_pc))
{ {
active_row = m_fast_unwind_plan->GetRowForFunctionOffset (m_current_offset); active_row = m_fast_unwind_plan_sp->GetRowForFunctionOffset (m_current_offset);
row_register_kind = m_fast_unwind_plan->GetRegisterKind (); row_register_kind = m_fast_unwind_plan_sp->GetRegisterKind ();
} }
else else
{ {
m_full_unwind_plan = GetFullUnwindPlanForFrame (); m_full_unwind_plan_sp = GetFullUnwindPlanForFrame ();
if (m_full_unwind_plan && m_full_unwind_plan->PlanValidAtAddress (m_current_pc)) if (m_full_unwind_plan_sp && m_full_unwind_plan_sp->PlanValidAtAddress (m_current_pc))
{ {
active_row = m_full_unwind_plan->GetRowForFunctionOffset (m_current_offset); active_row = m_full_unwind_plan_sp->GetRowForFunctionOffset (m_current_offset);
row_register_kind = m_full_unwind_plan->GetRegisterKind (); row_register_kind = m_full_unwind_plan_sp->GetRegisterKind ();
} }
} }
@ -460,49 +451,47 @@ RegisterContextLLDB::IsFrameZero () const
// 3. m_current_pc should have the current pc value for this frame // 3. m_current_pc should have the current pc value for this frame
// 4. m_current_offset_backed_up_one should have the current byte offset into the function, maybe backed up by 1, -1 if unknown // 4. m_current_offset_backed_up_one should have the current byte offset into the function, maybe backed up by 1, -1 if unknown
UnwindPlan * UnwindPlanSP
RegisterContextLLDB::GetFastUnwindPlanForFrame () RegisterContextLLDB::GetFastUnwindPlanForFrame ()
{ {
UnwindPlanSP unwind_plan_sp;
if (!m_current_pc.IsValid() || m_current_pc.GetModule() == NULL || m_current_pc.GetModule()->GetObjectFile() == NULL) if (!m_current_pc.IsValid() || m_current_pc.GetModule() == NULL || m_current_pc.GetModule()->GetObjectFile() == NULL)
{ return unwind_plan_sp;
return NULL;
}
if (IsFrameZero ()) if (IsFrameZero ())
{ return unwind_plan_sp;
return NULL;
}
FuncUnwindersSP fu; FuncUnwindersSP func_unwinders_sp (m_current_pc.GetModule()->GetObjectFile()->GetUnwindTable().GetFuncUnwindersContainingAddress (m_current_pc, m_sym_ctx));
fu = m_current_pc.GetModule()->GetObjectFile()->GetUnwindTable().GetFuncUnwindersContainingAddress (m_current_pc, m_sym_ctx); if (!func_unwinders_sp)
if (fu.get() == NULL) return unwind_plan_sp;
{
return NULL;
}
// If we're in _sigtramp(), unwinding past this frame requires special knowledge. // If we're in _sigtramp(), unwinding past this frame requires special knowledge.
if (m_frame_type == eSigtrampFrame || m_frame_type == eDebuggerFrame) if (m_frame_type == eSigtrampFrame || m_frame_type == eDebuggerFrame)
{ return unwind_plan_sp;
return NULL;
}
if (fu->GetUnwindPlanFastUnwind (m_thread) unwind_plan_sp = func_unwinders_sp->GetUnwindPlanFastUnwind (m_thread);
&& fu->GetUnwindPlanFastUnwind (m_thread)->PlanValidAtAddress (m_current_pc)) if (unwind_plan_sp)
{
if (unwind_plan_sp->PlanValidAtAddress (m_current_pc))
{ {
LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND)); LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
if (log && IsLogVerbose()) if (log && IsLogVerbose())
{ {
const char *has_fast = ""; const char *has_fast = "";
if (m_fast_unwind_plan) if (m_fast_unwind_plan_sp)
has_fast = ", and has a fast UnwindPlan"; has_fast = ", and has a fast UnwindPlan";
log->Printf("%*sFrame %u frame has a fast UnwindPlan", log->Printf("%*sFrame %u frame has a fast UnwindPlan",
m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number); m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number);
} }
m_frame_type = eNormalFrame; m_frame_type = eNormalFrame;
return fu->GetUnwindPlanFastUnwind (m_thread); return unwind_plan_sp;
} }
else
return NULL; {
unwind_plan_sp.reset();
}
}
return unwind_plan_sp;
} }
// On entry to this method, // On entry to this method,
@ -512,37 +501,25 @@ RegisterContextLLDB::GetFastUnwindPlanForFrame ()
// 3. m_current_pc should have the current pc value for this frame // 3. m_current_pc should have the current pc value for this frame
// 4. m_current_offset_backed_up_one should have the current byte offset into the function, maybe backed up by 1, -1 if unknown // 4. m_current_offset_backed_up_one should have the current byte offset into the function, maybe backed up by 1, -1 if unknown
UnwindPlan * UnwindPlanSP
RegisterContextLLDB::GetFullUnwindPlanForFrame () RegisterContextLLDB::GetFullUnwindPlanForFrame ()
{ {
UnwindPlanSP unwind_plan_sp;
LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND)); LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
UnwindPlan *up; UnwindPlanSP arch_default_unwind_plan_sp;
UnwindPlan *arch_default_up = NULL; const ArchSpec &arch = m_thread.GetProcess().GetTarget().GetArchitecture ();
ArchSpec arch = m_thread.GetProcess().GetTarget().GetArchitecture (); ArchDefaultUnwindPlanSP arch_default_sp (ArchDefaultUnwindPlan::FindPlugin (arch));
ArchDefaultUnwindPlan *arch_default = ArchDefaultUnwindPlan::FindPlugin (arch); if (arch_default_sp)
if (arch_default) arch_default_unwind_plan_sp = arch_default_sp->GetArchDefaultUnwindPlan (m_thread, m_current_pc);
{
arch_default_up = arch_default->GetArchDefaultUnwindPlan (m_thread, m_current_pc);
}
bool behaves_like_zeroth_frame = false; bool behaves_like_zeroth_frame = false;
if (IsFrameZero ()) if (IsFrameZero ()
|| m_next_frame->m_frame_type == eSigtrampFrame
|| m_next_frame->m_frame_type == eDebuggerFrame)
{ {
behaves_like_zeroth_frame = true; behaves_like_zeroth_frame = true;
} // If this frame behaves like a 0th frame (currently executing or
if (!IsFrameZero () && ((RegisterContextLLDB*) m_next_frame.get())->m_frame_type == eSigtrampFrame) // interrupted asynchronously), all registers can be retrieved.
{
behaves_like_zeroth_frame = true;
}
if (!IsFrameZero () && ((RegisterContextLLDB*) m_next_frame.get())->m_frame_type == eDebuggerFrame)
{
behaves_like_zeroth_frame = true;
}
// If this frame behaves like a 0th frame (currently executing or interrupted asynchronously), all registers
// can be retrieved.
if (behaves_like_zeroth_frame)
{
m_all_registers_available = true; m_all_registers_available = true;
} }
@ -550,20 +527,20 @@ RegisterContextLLDB::GetFullUnwindPlanForFrame ()
if (!m_current_pc.IsValid() || m_current_pc.GetModule() == NULL || m_current_pc.GetModule()->GetObjectFile() == NULL) if (!m_current_pc.IsValid() || m_current_pc.GetModule() == NULL || m_current_pc.GetModule()->GetObjectFile() == NULL)
{ {
m_frame_type = eNormalFrame; m_frame_type = eNormalFrame;
return arch_default_up; return arch_default_unwind_plan_sp;
} }
FuncUnwindersSP fu; FuncUnwindersSP func_unwinders_sp;
if (m_sym_ctx_valid) if (m_sym_ctx_valid)
{ {
fu = m_current_pc.GetModule()->GetObjectFile()->GetUnwindTable().GetFuncUnwindersContainingAddress (m_current_pc, m_sym_ctx); func_unwinders_sp = m_current_pc.GetModule()->GetObjectFile()->GetUnwindTable().GetFuncUnwindersContainingAddress (m_current_pc, m_sym_ctx);
} }
// No FuncUnwinders available for this pc, try using architectural default unwind. // No FuncUnwinders available for this pc, try using architectural default unwind.
if (fu.get() == NULL) if (!func_unwinders_sp)
{ {
m_frame_type = eNormalFrame; m_frame_type = eNormalFrame;
return arch_default_up; return arch_default_unwind_plan_sp;
} }
// If we're in _sigtramp(), unwinding past this frame requires special knowledge. On Mac OS X this knowledge // If we're in _sigtramp(), unwinding past this frame requires special knowledge. On Mac OS X this knowledge
@ -572,53 +549,54 @@ RegisterContextLLDB::GetFullUnwindPlanForFrame ()
// how to unwind out of sigtramp. // how to unwind out of sigtramp.
if (m_frame_type == eSigtrampFrame) if (m_frame_type == eSigtrampFrame)
{ {
m_fast_unwind_plan = NULL; m_fast_unwind_plan_sp.reset();
up = fu->GetUnwindPlanAtCallSite (m_current_offset_backed_up_one); unwind_plan_sp = func_unwinders_sp->GetUnwindPlanAtCallSite (m_current_offset_backed_up_one);
if (up && up->PlanValidAtAddress (m_current_pc)) if (unwind_plan_sp && unwind_plan_sp->PlanValidAtAddress (m_current_pc))
{ return unwind_plan_sp;
return up;
}
} }
// Typically the NonCallSite UnwindPlan is the unwind created by inspecting the assembly language instructions // Typically the NonCallSite UnwindPlan is the unwind created by inspecting the assembly language instructions
up = fu->GetUnwindPlanAtNonCallSite (m_thread); if (behaves_like_zeroth_frame)
if (behaves_like_zeroth_frame && up && up->PlanValidAtAddress (m_current_pc)) {
unwind_plan_sp = func_unwinders_sp->GetUnwindPlanAtNonCallSite (m_thread);
if (unwind_plan_sp && unwind_plan_sp->PlanValidAtAddress (m_current_pc))
{ {
if (log && IsLogVerbose()) if (log && IsLogVerbose())
{ {
log->Printf("%*sFrame %u frame uses %s for full UnwindPlan", log->Printf("%*sFrame %u frame uses %s for full UnwindPlan",
m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number, m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
up->GetSourceName().GetCString()); unwind_plan_sp->GetSourceName().GetCString());
}
return unwind_plan_sp;
} }
return up;
} }
// Typically this is unwind info from an eh_frame section intended for exception handling; only valid at call sites // Typically this is unwind info from an eh_frame section intended for exception handling; only valid at call sites
up = fu->GetUnwindPlanAtCallSite (m_current_offset_backed_up_one); unwind_plan_sp = func_unwinders_sp->GetUnwindPlanAtCallSite (m_current_offset_backed_up_one);
if (up && up->PlanValidAtAddress (m_current_pc)) if (unwind_plan_sp && unwind_plan_sp->PlanValidAtAddress (m_current_pc))
{ {
if (log && IsLogVerbose()) if (log && IsLogVerbose())
{ {
log->Printf("%*sFrame %u frame uses %s for full UnwindPlan", log->Printf("%*sFrame %u frame uses %s for full UnwindPlan",
m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number, m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
up->GetSourceName().GetCString()); unwind_plan_sp->GetSourceName().GetCString());
} }
return up; return unwind_plan_sp;
} }
// We'd prefer to use an UnwindPlan intended for call sites when we're at a call site but if we've // We'd prefer to use an UnwindPlan intended for call sites when we're at a call site but if we've
// struck out on that, fall back to using the non-call-site assembly inspection UnwindPlan if possible. // struck out on that, fall back to using the non-call-site assembly inspection UnwindPlan if possible.
up = fu->GetUnwindPlanAtNonCallSite (m_thread); unwind_plan_sp = func_unwinders_sp->GetUnwindPlanAtNonCallSite (m_thread);
if (up && up->PlanValidAtAddress (m_current_pc)) if (unwind_plan_sp && unwind_plan_sp->PlanValidAtAddress (m_current_pc))
{ {
if (log && IsLogVerbose()) if (log && IsLogVerbose())
{ {
log->Printf("%*sFrame %u frame uses %s for full UnwindPlan", log->Printf("%*sFrame %u frame uses %s for full UnwindPlan",
m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number, m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
up->GetSourceName().GetCString()); unwind_plan_sp->GetSourceName().GetCString());
} }
return up; return unwind_plan_sp;
} }
// If nothing else, use the architectural default UnwindPlan and hope that does the job. // If nothing else, use the architectural default UnwindPlan and hope that does the job.
@ -626,9 +604,9 @@ RegisterContextLLDB::GetFullUnwindPlanForFrame ()
{ {
log->Printf("%*sFrame %u frame uses %s for full UnwindPlan", log->Printf("%*sFrame %u frame uses %s for full UnwindPlan",
m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number, m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
arch_default_up->GetSourceName().GetCString()); arch_default_unwind_plan_sp->GetSourceName().GetCString());
} }
return arch_default_up; return arch_default_unwind_plan_sp;
} }
@ -812,9 +790,9 @@ RegisterContextLLDB::SavedLocationForRegister (uint32_t lldb_regnum, RegisterLoc
LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND)); LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
// Have we already found this register location? // Have we already found this register location?
std::map<uint32_t, RegisterLocation>::const_iterator iterator; if (!m_registers.empty())
if (m_registers.size() > 0)
{ {
std::map<uint32_t, RegisterLocation>::const_iterator iterator;
iterator = m_registers.find (lldb_regnum); iterator = m_registers.find (lldb_regnum);
if (iterator != m_registers.end()) if (iterator != m_registers.end())
{ {
@ -843,10 +821,10 @@ RegisterContextLLDB::SavedLocationForRegister (uint32_t lldb_regnum, RegisterLoc
bool have_unwindplan_regloc = false; bool have_unwindplan_regloc = false;
int unwindplan_registerkind = -1; int unwindplan_registerkind = -1;
if (m_fast_unwind_plan) if (m_fast_unwind_plan_sp)
{ {
const UnwindPlan::Row *active_row = m_fast_unwind_plan->GetRowForFunctionOffset (m_current_offset); const UnwindPlan::Row *active_row = m_fast_unwind_plan_sp->GetRowForFunctionOffset (m_current_offset);
unwindplan_registerkind = m_fast_unwind_plan->GetRegisterKind (); unwindplan_registerkind = m_fast_unwind_plan_sp->GetRegisterKind ();
uint32_t row_regnum; uint32_t row_regnum;
if (!m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds (eRegisterKindLLDB, lldb_regnum, unwindplan_registerkind, row_regnum)) if (!m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds (eRegisterKindLLDB, lldb_regnum, unwindplan_registerkind, row_regnum))
{ {
@ -872,15 +850,14 @@ RegisterContextLLDB::SavedLocationForRegister (uint32_t lldb_regnum, RegisterLoc
if (!have_unwindplan_regloc) if (!have_unwindplan_regloc)
{ {
// m_full_unwind_plan being NULL means that we haven't tried to find a full UnwindPlan yet // m_full_unwind_plan_sp being NULL means that we haven't tried to find a full UnwindPlan yet
if (m_full_unwind_plan == NULL) if (!m_full_unwind_plan_sp)
m_full_unwind_plan_sp = GetFullUnwindPlanForFrame ();
if (m_full_unwind_plan_sp)
{ {
m_full_unwind_plan = GetFullUnwindPlanForFrame (); const UnwindPlan::Row *active_row = m_full_unwind_plan_sp->GetRowForFunctionOffset (m_current_offset);
} unwindplan_registerkind = m_full_unwind_plan_sp->GetRegisterKind ();
if (m_full_unwind_plan)
{
const UnwindPlan::Row *active_row = m_full_unwind_plan->GetRowForFunctionOffset (m_current_offset);
unwindplan_registerkind = m_full_unwind_plan->GetRegisterKind ();
uint32_t row_regnum; uint32_t row_regnum;
if (!m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds (eRegisterKindLLDB, lldb_regnum, unwindplan_registerkind, row_regnum)) if (!m_thread.GetRegisterContext()->ConvertBetweenRegisterKinds (eRegisterKindLLDB, lldb_regnum, unwindplan_registerkind, row_regnum))
{ {
@ -905,7 +882,7 @@ RegisterContextLLDB::SavedLocationForRegister (uint32_t lldb_regnum, RegisterLoc
{ {
log->Printf("%*sFrame %u supplying caller's saved reg %d's location using %s UnwindPlan", log->Printf("%*sFrame %u supplying caller's saved reg %d's location using %s UnwindPlan",
m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number, m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
lldb_regnum, m_full_unwind_plan->GetSourceName().GetCString()); lldb_regnum, m_full_unwind_plan_sp->GetSourceName().GetCString());
} }
} }
} }
@ -915,7 +892,7 @@ RegisterContextLLDB::SavedLocationForRegister (uint32_t lldb_regnum, RegisterLoc
{ {
// If a volatile register is being requested, we don't want to forward m_next_frame's register contents // If a volatile register is being requested, we don't want to forward m_next_frame's register contents
// up the stack -- the register is not retrievable at this frame. // up the stack -- the register is not retrievable at this frame.
ArchSpec arch = m_thread.GetProcess().GetTarget().GetArchitecture (); const ArchSpec &arch = m_thread.GetProcess().GetTarget().GetArchitecture ();
ArchVolatileRegs *volatile_regs = ArchVolatileRegs::FindPlugin (arch); ArchVolatileRegs *volatile_regs = ArchVolatileRegs::FindPlugin (arch);
if (volatile_regs && volatile_regs->RegisterIsVolatile (m_thread, lldb_regnum)) if (volatile_regs && volatile_regs->RegisterIsVolatile (m_thread, lldb_regnum))
{ {
@ -928,11 +905,7 @@ RegisterContextLLDB::SavedLocationForRegister (uint32_t lldb_regnum, RegisterLoc
return false; return false;
} }
if (!IsFrameZero ()) if (IsFrameZero ())
{
return ((RegisterContextLLDB*)m_next_frame.get())->SavedLocationForRegister (lldb_regnum, regloc);
}
else
{ {
// This is frame 0 - we should return the actual live register context value // This is frame 0 - we should return the actual live register context value
RegisterLocation new_regloc; RegisterLocation new_regloc;
@ -942,6 +915,10 @@ RegisterContextLLDB::SavedLocationForRegister (uint32_t lldb_regnum, RegisterLoc
regloc = new_regloc; regloc = new_regloc;
return true; return true;
} }
else
{
return m_next_frame->SavedLocationForRegister (lldb_regnum, regloc);
}
if (log) if (log)
{ {
log->Printf("%*sFrame %u could not supply caller's reg %d location", log->Printf("%*sFrame %u could not supply caller's reg %d location",
@ -968,11 +945,7 @@ RegisterContextLLDB::SavedLocationForRegister (uint32_t lldb_regnum, RegisterLoc
if (unwindplan_regloc.IsSame()) if (unwindplan_regloc.IsSame())
{ {
if (!IsFrameZero ()) if (IsFrameZero ())
{
return ((RegisterContextLLDB*)m_next_frame.get())->SavedLocationForRegister (lldb_regnum, regloc);
}
else
{ {
if (log) if (log)
{ {
@ -982,6 +955,10 @@ RegisterContextLLDB::SavedLocationForRegister (uint32_t lldb_regnum, RegisterLoc
} }
return false; return false;
} }
else
{
return m_next_frame->SavedLocationForRegister (lldb_regnum, regloc);
}
} }
if (unwindplan_regloc.IsCFAPlusOffset()) if (unwindplan_regloc.IsCFAPlusOffset())
@ -1116,14 +1093,11 @@ RegisterContextLLDB::ReadGPRValue (int register_kind, uint32_t regnum, addr_t &v
value = data.GetAddress (&offset); value = data.GetAddress (&offset);
return true; return true;
} }
else
{
return false; return false;
} }
}
RegisterLocation regloc; RegisterLocation regloc;
if (!((RegisterContextLLDB*)m_next_frame.get())->SavedLocationForRegister (lldb_regnum, regloc)) if (!m_next_frame->SavedLocationForRegister (lldb_regnum, regloc))
{ {
return false; return false;
} }
@ -1166,7 +1140,7 @@ RegisterContextLLDB::ReadRegisterBytes (uint32_t lldb_reg, DataExtractor& data)
RegisterLocation regloc; RegisterLocation regloc;
// Find out where the NEXT frame saved THIS frame's register contents // Find out where the NEXT frame saved THIS frame's register contents
if (!((RegisterContextLLDB*)m_next_frame.get())->SavedLocationForRegister (lldb_reg, regloc)) if (!m_next_frame->SavedLocationForRegister (lldb_reg, regloc))
return false; return false;
return ReadRegisterBytesFromRegisterLocation (lldb_reg, regloc, data); return ReadRegisterBytesFromRegisterLocation (lldb_reg, regloc, data);
@ -1200,7 +1174,7 @@ RegisterContextLLDB::WriteRegisterBytes (uint32_t lldb_reg, DataExtractor &data,
RegisterLocation regloc; RegisterLocation regloc;
// Find out where the NEXT frame saved THIS frame's register contents // Find out where the NEXT frame saved THIS frame's register contents
if (!((RegisterContextLLDB*)m_next_frame.get())->SavedLocationForRegister (lldb_reg, regloc)) if (!m_next_frame->SavedLocationForRegister (lldb_reg, regloc))
return false; return false;
return WriteRegisterBytesToRegisterLocation (lldb_reg, regloc, data, data_offset); return WriteRegisterBytesToRegisterLocation (lldb_reg, regloc, data, data_offset);

View File

@ -20,8 +20,10 @@
class RegisterContextLLDB : public lldb_private::RegisterContext class RegisterContextLLDB : public lldb_private::RegisterContext
{ {
public: public:
typedef lldb::SharedPtr<RegisterContextLLDB>::Type SharedPtr;
RegisterContextLLDB (lldb_private::Thread &thread, RegisterContextLLDB (lldb_private::Thread &thread,
const lldb::RegisterContextSP& next_frame, const SharedPtr& next_frame,
lldb_private::SymbolContext& sym_ctx, lldb_private::SymbolContext& sym_ctx,
uint32_t frame_number); uint32_t frame_number);
@ -147,22 +149,23 @@ private:
bool bool
ReadGPRValue (int register_kind, uint32_t regnum, lldb::addr_t &value); ReadGPRValue (int register_kind, uint32_t regnum, lldb::addr_t &value);
lldb_private::UnwindPlan * lldb::UnwindPlanSP
GetFastUnwindPlanForFrame (); GetFastUnwindPlanForFrame ();
lldb_private::UnwindPlan * lldb::UnwindPlanSP
GetFullUnwindPlanForFrame (); GetFullUnwindPlanForFrame ();
lldb_private::Thread& m_thread; lldb_private::Thread& m_thread;
lldb::RegisterContextSP m_next_frame;
SharedPtr m_next_frame;
/// ///
// The following tell us how to retrieve the CALLER's register values (ie the "previous" frame, aka the frame above) // The following tell us how to retrieve the CALLER's register values (ie the "previous" frame, aka the frame above)
// i.e. where THIS frame saved them // i.e. where THIS frame saved them
/// ///
lldb_private::UnwindPlan *m_fast_unwind_plan; // may be NULL lldb::UnwindPlanSP m_fast_unwind_plan_sp; // may be NULL
lldb_private::UnwindPlan *m_full_unwind_plan; lldb::UnwindPlanSP m_full_unwind_plan_sp;
bool m_all_registers_available; // Can we retrieve all regs or just nonvolatile regs? bool m_all_registers_available; // Can we retrieve all regs or just nonvolatile regs?
int m_frame_type; // enum FrameType int m_frame_type; // enum FrameType

View File

@ -15,10 +15,12 @@
#include "lldb/Symbol/FuncUnwinders.h" #include "lldb/Symbol/FuncUnwinders.h"
#include "lldb/Symbol/Function.h" #include "lldb/Symbol/Function.h"
#include "lldb/Utility/ArchDefaultUnwindPlan.h" #include "lldb/Utility/ArchDefaultUnwindPlan.h"
#include "UnwindLLDB.h"
#include "lldb/Symbol/UnwindPlan.h" #include "lldb/Symbol/UnwindPlan.h"
#include "lldb/Core/Log.h" #include "lldb/Core/Log.h"
#include "UnwindLLDB.h"
#include "RegisterContextLLDB.h"
using namespace lldb; using namespace lldb;
using namespace lldb_private; using namespace lldb_private;
@ -65,8 +67,10 @@ UnwindLLDB::AddFirstFrame ()
{ {
// First, set up the 0th (initial) frame // First, set up the 0th (initial) frame
CursorSP first_cursor_sp(new Cursor ()); CursorSP first_cursor_sp(new Cursor ());
RegisterContextSP no_frame; std::auto_ptr<RegisterContextLLDB> first_register_ctx_ap (new RegisterContextLLDB (m_thread,
std::auto_ptr<RegisterContextLLDB> first_register_ctx_ap (new RegisterContextLLDB(m_thread, no_frame, first_cursor_sp->sctx, 0)); RegisterContextLLDB::SharedPtr(),
first_cursor_sp->sctx,
0));
if (first_register_ctx_ap.get() == NULL) if (first_register_ctx_ap.get() == NULL)
return false; return false;
@ -150,8 +154,8 @@ UnwindLLDB::AddOneMoreFrame ()
return false; return false;
} }
} }
RegisterContextSP register_ctx_sp(register_ctx_ap.release()); RegisterContextLLDB::SharedPtr reg_ctx_sp(register_ctx_ap.release());
cursor_sp->reg_ctx = register_ctx_sp; cursor_sp->reg_ctx = reg_ctx_sp;
m_frames.push_back (cursor_sp); m_frames.push_back (cursor_sp);
return true; return true;
} }

View File

@ -10,15 +10,15 @@
#ifndef lldb_UnwindLLDB_h_ #ifndef lldb_UnwindLLDB_h_
#define lldb_UnwindLLDB_h_ #define lldb_UnwindLLDB_h_
#include "lldb/lldb-private.h"
#include "lldb/lldb-types.h"
#include "lldb/Target/Unwind.h"
#include "lldb/Symbol/FuncUnwinders.h"
#include "lldb/Symbol/UnwindPlan.h"
#include "RegisterContextLLDB.h"
#include "lldb/Target/RegisterContext.h"
#include <vector> #include <vector>
#include "lldb/lldb-include.h"
#include "lldb/Symbol/FuncUnwinders.h"
#include "lldb/Symbol/UnwindPlan.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/Unwind.h"
#include "RegisterContextLLDB.h"
namespace lldb_private { namespace lldb_private {
@ -53,7 +53,7 @@ private:
lldb::addr_t start_pc; // The start address of the function/symbol for this frame - current pc if unknown lldb::addr_t start_pc; // The start address of the function/symbol for this frame - current pc if unknown
lldb::addr_t cfa; // The canonical frame address for this stack frame lldb::addr_t cfa; // The canonical frame address for this stack frame
lldb_private::SymbolContext sctx; // A symbol context we'll contribute to & provide to the StackFrame creation lldb_private::SymbolContext sctx; // A symbol context we'll contribute to & provide to the StackFrame creation
lldb::RegisterContextSP reg_ctx; // These are all RegisterContextLLDB's RegisterContextLLDB::SharedPtr reg_ctx; // These are all RegisterContextLLDB's
Cursor () : start_pc (LLDB_INVALID_ADDRESS), cfa (LLDB_INVALID_ADDRESS), sctx(), reg_ctx() { } Cursor () : start_pc (LLDB_INVALID_ADDRESS), cfa (LLDB_INVALID_ADDRESS), sctx(), reg_ctx() { }
private: private:

View File

@ -178,11 +178,12 @@ GDBRemoteRegisterContext::ReadRegisterValue (uint32_t reg, Scalar &value)
return false; return false;
} }
void bool
GDBRemoteRegisterContext::PrivateSetRegisterValue (uint32_t reg, StringExtractor &response) GDBRemoteRegisterContext::PrivateSetRegisterValue (uint32_t reg, StringExtractor &response)
{ {
const RegisterInfo *reg_info = GetRegisterInfoAtIndex (reg); const RegisterInfo *reg_info = GetRegisterInfoAtIndex (reg);
assert (reg_info); if (reg_info == NULL)
return false;
// Invalidate if needed // Invalidate if needed
InvalidateIfNeeded(false); InvalidateIfNeeded(false);
@ -200,6 +201,7 @@ GDBRemoteRegisterContext::PrivateSetRegisterValue (uint32_t reg, StringExtractor
// leave it as it was. // leave it as it was.
m_reg_valid[reg] = false; m_reg_valid[reg] = false;
} }
return success;
} }

View File

@ -228,7 +228,7 @@ public:
protected: protected:
friend class ThreadGDBRemote; friend class ThreadGDBRemote;
void bool
PrivateSetRegisterValue (uint32_t reg, StringExtractor &response); PrivateSetRegisterValue (uint32_t reg, StringExtractor &response);
void void

View File

@ -642,7 +642,6 @@ ProcessGDBRemote::DidLaunchOrAttach ()
StreamString strm; StreamString strm;
;
// See if the GDB server supports the qHostInfo information // See if the GDB server supports the qHostInfo information
const char *vendor = m_gdb_comm.GetVendorString().AsCString(); const char *vendor = m_gdb_comm.GetVendorString().AsCString();
const char *os_type = m_gdb_comm.GetOSString().AsCString(); const char *os_type = m_gdb_comm.GetOSString().AsCString();
@ -1176,6 +1175,18 @@ ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet)
case 'T': case 'T':
case 'S': case 'S':
{ {
if (GetStopID() == 0)
{
// Our first stop, make sure we have a process ID, and also make
// sure we know about our registers
if (GetID() == LLDB_INVALID_PROCESS_ID)
{
lldb::pid_t pid = m_gdb_comm.GetCurrentProcessID (1);
if (pid != LLDB_INVALID_PROCESS_ID)
SetID (pid);
}
BuildDynamicRegisterInfo (true);
}
// Stop with signal and thread info // Stop with signal and thread info
const uint8_t signo = stop_packet.GetHexU8(); const uint8_t signo = stop_packet.GetHexU8();
std::string name; std::string name;
@ -1209,7 +1220,14 @@ ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet)
{ {
// thread in big endian hex // thread in big endian hex
tid = Args::StringToUInt32 (value.c_str(), 0, 16); tid = Args::StringToUInt32 (value.c_str(), 0, 16);
Mutex::Locker locker (m_thread_list.GetMutex ());
thread_sp = m_thread_list.FindThreadByID(tid, false); thread_sp = m_thread_list.FindThreadByID(tid, false);
if (!thread_sp)
{
// Create the thread if we need to
thread_sp.reset (new ThreadGDBRemote (*this, tid));
m_thread_list.AddThread(thread_sp);
}
} }
else if (name.compare("hexname") == 0) else if (name.compare("hexname") == 0)
{ {
@ -1242,7 +1260,15 @@ ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet)
StringExtractor reg_value_extractor; StringExtractor reg_value_extractor;
// Swap "value" over into "reg_value_extractor" // Swap "value" over into "reg_value_extractor"
reg_value_extractor.GetStringRef().swap(value); reg_value_extractor.GetStringRef().swap(value);
static_cast<ThreadGDBRemote *> (thread_sp.get())->PrivateSetRegisterValue (reg, reg_value_extractor); if (!static_cast<ThreadGDBRemote *> (thread_sp.get())->PrivateSetRegisterValue (reg, reg_value_extractor))
{
Host::SetCrashDescriptionWithFormat("Setting thread register '%s' (decoded to %u (0x%x)) with value '%s' for stop packet: '%s'",
name.c_str(),
reg,
reg,
reg_value_extractor.GetStringRef().c_str(),
stop_packet.GetStringRef().c_str());
}
} }
} }
} }

View File

@ -26,7 +26,7 @@
#include "Plugins/Process/Utility/UnwindLLDB.h" #include "Plugins/Process/Utility/UnwindLLDB.h"
#include "Utility/StringExtractorGDBRemote.h" #include "Utility/StringExtractorGDBRemote.h"
#ifdef __APPLE__ #if defined(__APPLE__)
#include "UnwindMacOSXFrameBackchain.h" #include "UnwindMacOSXFrameBackchain.h"
#endif #endif
@ -98,6 +98,7 @@ ThreadGDBRemote::WillResume (StateType resume_state)
{ {
case eStateSuspended: case eStateSuspended:
case eStateStopped: case eStateStopped:
// Don't append anything for threads that should stay stopped.
break; break;
case eStateRunning: case eStateRunning:
@ -145,7 +146,7 @@ ThreadGDBRemote::GetUnwinder ()
{ {
m_unwinder_ap.reset (new UnwindLLDB (*this)); m_unwinder_ap.reset (new UnwindLLDB (*this));
} }
#ifdef __APPLE__ #if defined(__APPLE__)
else else
{ {
m_unwinder_ap.reset (new UnwindMacOSXFrameBackchain (*this)); m_unwinder_ap.reset (new UnwindMacOSXFrameBackchain (*this));
@ -207,12 +208,12 @@ ThreadGDBRemote::CreateRegisterContextForFrame (StackFrame *frame)
return reg_ctx_sp; return reg_ctx_sp;
} }
void bool
ThreadGDBRemote::PrivateSetRegisterValue (uint32_t reg, StringExtractor &response) ThreadGDBRemote::PrivateSetRegisterValue (uint32_t reg, StringExtractor &response)
{ {
GDBRemoteRegisterContext *gdb_reg_ctx = static_cast<GDBRemoteRegisterContext *>(GetRegisterContext ().get()); GDBRemoteRegisterContext *gdb_reg_ctx = static_cast<GDBRemoteRegisterContext *>(GetRegisterContext ().get());
assert (gdb_reg_ctx); assert (gdb_reg_ctx);
gdb_reg_ctx->PrivateSetRegisterValue (reg, response); return gdb_reg_ctx->PrivateSetRegisterValue (reg, response);
} }
bool bool

View File

@ -105,7 +105,7 @@ protected:
virtual bool virtual bool
RestoreSaveFrameZero (const RegisterCheckpoint &checkpoint); RestoreSaveFrameZero (const RegisterCheckpoint &checkpoint);
void bool
PrivateSetRegisterValue (uint32_t reg, PrivateSetRegisterValue (uint32_t reg,
StringExtractor &response); StringExtractor &response);

View File

@ -197,6 +197,14 @@ GetDWARFMachOSegmentName ()
return g_dwarf_section_name; return g_dwarf_section_name;
} }
UniqueDWARFASTTypeMap &
SymbolFileDWARF::GetUniqueDWARFASTTypeMap ()
{
if (m_debug_map_symfile)
return m_debug_map_symfile->GetUniqueDWARFASTTypeMap ();
return m_unique_ast_type_map;
}
ClangASTContext & ClangASTContext &
SymbolFileDWARF::GetClangASTContext () SymbolFileDWARF::GetClangASTContext ()
{ {
@ -3172,7 +3180,7 @@ SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu,
UniqueDWARFASTType unique_ast_entry; UniqueDWARFASTType unique_ast_entry;
if (decl.IsValid()) if (decl.IsValid())
{ {
if (m_unique_ast_type_map.Find (type_name_const_str, if (GetUniqueDWARFASTTypeMap().Find (type_name_const_str,
die, die,
decl, decl,
unique_ast_entry)) unique_ast_entry))
@ -3273,7 +3281,7 @@ SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu,
unique_ast_entry.m_type_sp = type_sp; unique_ast_entry.m_type_sp = type_sp;
unique_ast_entry.m_die = die; unique_ast_entry.m_die = die;
unique_ast_entry.m_declaration = decl; unique_ast_entry.m_declaration = decl;
m_unique_ast_type_map.Insert (type_name_const_str, GetUniqueDWARFASTTypeMap().Insert (type_name_const_str,
unique_ast_entry); unique_ast_entry);
if (die->HasChildren() == false && is_forward_declaration == false) if (die->HasChildren() == false && is_forward_declaration == false)
@ -3824,14 +3832,6 @@ SymbolFileDWARF::ParseType (const SymbolContext& sc, DWARFCompileUnit* dwarf_cu,
type_sp->SetSymbolContextScope(symbol_context_scope); type_sp->SetSymbolContextScope(symbol_context_scope);
} }
// if (udt_sp.get())
// {
// if (is_forward_declaration)
// udt_sp->GetFlags().Set(UserDefType::flagIsForwardDefinition);
// type_sp->SetUserDefinedType(udt_sp);
// }
//printf ("Adding type to map: 0x%8.8x for %s\n", die->GetOffset(), type_sp->GetName().GetCString());
// We are ready to put this type into the uniqued list up at the module level // We are ready to put this type into the uniqued list up at the module level
type_list->Insert (type_sp); type_list->Insert (type_sp);

View File

@ -321,6 +321,9 @@ protected:
clang::NamespaceDecl * clang::NamespaceDecl *
ResolveNamespaceDIE (DWARFCompileUnit *curr_cu, const DWARFDebugInfoEntry *die); ResolveNamespaceDIE (DWARFCompileUnit *curr_cu, const DWARFDebugInfoEntry *die);
UniqueDWARFASTTypeMap &
GetUniqueDWARFASTTypeMap ();
SymbolFileDWARFDebugMap * m_debug_map_symfile; SymbolFileDWARFDebugMap * m_debug_map_symfile;
clang::TranslationUnitDecl * m_clang_tu_decl; clang::TranslationUnitDecl * m_clang_tu_decl;
lldb_private::Flags m_flags; lldb_private::Flags m_flags;

View File

@ -15,6 +15,8 @@
#include <bitset> #include <bitset>
#include "lldb/Symbol/SymbolFile.h" #include "lldb/Symbol/SymbolFile.h"
#include "UniqueDWARFASTType.h"
class SymbolFileDWARF; class SymbolFileDWARF;
class DWARFCompileUnit; class DWARFCompileUnit;
class DWARFDebugInfoEntry; class DWARFDebugInfoEntry;
@ -211,6 +213,11 @@ protected:
const DWARFDebugInfoEntry *die, const DWARFDebugInfoEntry *die,
const lldb_private::ConstString &type_name); const lldb_private::ConstString &type_name);
UniqueDWARFASTTypeMap &
GetUniqueDWARFASTTypeMap ()
{
return m_unique_ast_type_map;
}
//------------------------------------------------------------------ //------------------------------------------------------------------
// Member Variables // Member Variables
//------------------------------------------------------------------ //------------------------------------------------------------------
@ -218,6 +225,7 @@ protected:
std::vector<CompileUnitInfo> m_compile_unit_infos; std::vector<CompileUnitInfo> m_compile_unit_infos;
std::vector<uint32_t> m_func_indexes; // Sorted by address std::vector<uint32_t> m_func_indexes; // Sorted by address
std::vector<uint32_t> m_glob_indexes; std::vector<uint32_t> m_glob_indexes;
UniqueDWARFASTTypeMap m_unique_ast_type_map;
}; };
#endif // #ifndef liblldb_SymbolFileDWARFDebugMap_h_ #endif // #ifndef liblldb_SymbolFileDWARFDebugMap_h_

View File

@ -34,10 +34,10 @@ FuncUnwinders::FuncUnwinders
m_assembly_profiler(assembly_profiler), m_assembly_profiler(assembly_profiler),
m_range(range), m_range(range),
m_mutex (Mutex::eMutexTypeNormal), m_mutex (Mutex::eMutexTypeNormal),
m_unwind_at_call_site_ap (), m_unwind_plan_call_site_sp (),
m_unwind_at_non_call_site_ap (), m_unwind_plan_non_call_site_sp (),
m_unwind_fast_ap (), m_unwind_plan_fast_sp (),
m_unwind_arch_default (NULL), m_unwind_plan_arch_default_sp (),
m_tried_unwind_at_call_site (false), m_tried_unwind_at_call_site (false),
m_tried_unwind_at_non_call_site (false), m_tried_unwind_at_non_call_site (false),
m_tried_unwind_fast (false), m_tried_unwind_fast (false),
@ -50,15 +50,15 @@ FuncUnwinders::~FuncUnwinders ()
{ {
} }
UnwindPlan* UnwindPlanSP
FuncUnwinders::GetUnwindPlanAtCallSite (int current_offset) FuncUnwinders::GetUnwindPlanAtCallSite (int current_offset)
{ {
// Lock the mutex to ensure we can always give out the most appropriate // Lock the mutex to ensure we can always give out the most appropriate
// information. We want to make sure if someone requests a call site unwind // information. We want to make sure if someone requests a call site unwind
// plan, that they get one and don't run into a race condition where one // plan, that they get one and don't run into a race condition where one
// thread has started to create the unwind plan and has put it into // thread has started to create the unwind plan and has put it into
// m_unwind_at_call_site_ap, and have another thread enter this function // m_unwind_plan_call_site_sp, and have another thread enter this function
// and return the partially filled in m_unwind_at_call_site_ap pointer. // and return the partially filled in m_unwind_plan_call_site_sp pointer.
// We also want to make sure that we lock out other unwind plans from // We also want to make sure that we lock out other unwind plans from
// being accessed until this one is done creating itself in case someone // being accessed until this one is done creating itself in case someone
// had some code like: // had some code like:
@ -66,7 +66,7 @@ FuncUnwinders::GetUnwindPlanAtCallSite (int current_offset)
// if (best_unwind_plan == NULL) // if (best_unwind_plan == NULL)
// best_unwind_plan = GetUnwindPlanAtNonCallSite (...) // best_unwind_plan = GetUnwindPlanAtNonCallSite (...)
Mutex::Locker locker (m_mutex); Mutex::Locker locker (m_mutex);
if (m_tried_unwind_at_call_site == false && m_unwind_at_call_site_ap.get() == NULL) if (m_tried_unwind_at_call_site == false && m_unwind_plan_call_site_sp.get() == NULL)
{ {
m_tried_unwind_at_call_site = true; m_tried_unwind_at_call_site = true;
// We have cases (e.g. with _sigtramp on Mac OS X) where the hand-written eh_frame unwind info for a // We have cases (e.g. with _sigtramp on Mac OS X) where the hand-written eh_frame unwind info for a
@ -84,16 +84,16 @@ FuncUnwinders::GetUnwindPlanAtCallSite (int current_offset)
DWARFCallFrameInfo *eh_frame = m_unwind_table.GetEHFrameInfo(); DWARFCallFrameInfo *eh_frame = m_unwind_table.GetEHFrameInfo();
if (eh_frame) if (eh_frame)
{ {
m_unwind_at_call_site_ap.reset (new UnwindPlan); m_unwind_plan_call_site_sp.reset (new UnwindPlan);
if (!eh_frame->GetUnwindPlan (current_pc, *m_unwind_at_call_site_ap)) if (!eh_frame->GetUnwindPlan (current_pc, *m_unwind_plan_call_site_sp))
m_unwind_at_call_site_ap.reset(); m_unwind_plan_call_site_sp.reset();
} }
} }
} }
return m_unwind_at_call_site_ap.get(); return m_unwind_plan_call_site_sp;
} }
UnwindPlan* UnwindPlanSP
FuncUnwinders::GetUnwindPlanAtNonCallSite (Thread& thread) FuncUnwinders::GetUnwindPlanAtNonCallSite (Thread& thread)
{ {
// Lock the mutex to ensure we can always give out the most appropriate // Lock the mutex to ensure we can always give out the most appropriate
@ -109,17 +109,17 @@ FuncUnwinders::GetUnwindPlanAtNonCallSite (Thread& thread)
// if (best_unwind_plan == NULL) // if (best_unwind_plan == NULL)
// best_unwind_plan = GetUnwindPlanAtNonCallSite (...) // best_unwind_plan = GetUnwindPlanAtNonCallSite (...)
Mutex::Locker locker (m_mutex); Mutex::Locker locker (m_mutex);
if (m_tried_unwind_at_non_call_site == false && m_unwind_at_non_call_site_ap.get() == NULL) if (m_tried_unwind_at_non_call_site == false && m_unwind_plan_non_call_site_sp.get() == NULL)
{ {
m_tried_unwind_at_non_call_site = true; m_tried_unwind_at_non_call_site = true;
m_unwind_at_non_call_site_ap.reset (new UnwindPlan); m_unwind_plan_non_call_site_sp.reset (new UnwindPlan);
if (!m_assembly_profiler->GetNonCallSiteUnwindPlanFromAssembly (m_range, thread, *m_unwind_at_non_call_site_ap)) if (!m_assembly_profiler->GetNonCallSiteUnwindPlanFromAssembly (m_range, thread, *m_unwind_plan_non_call_site_sp))
m_unwind_at_non_call_site_ap.reset(); m_unwind_plan_non_call_site_sp.reset();
} }
return m_unwind_at_non_call_site_ap.get(); return m_unwind_plan_non_call_site_sp;
} }
UnwindPlan* UnwindPlanSP
FuncUnwinders::GetUnwindPlanFastUnwind (Thread& thread) FuncUnwinders::GetUnwindPlanFastUnwind (Thread& thread)
{ {
// Lock the mutex to ensure we can always give out the most appropriate // Lock the mutex to ensure we can always give out the most appropriate
@ -135,17 +135,17 @@ FuncUnwinders::GetUnwindPlanFastUnwind (Thread& thread)
// if (best_unwind_plan == NULL) // if (best_unwind_plan == NULL)
// best_unwind_plan = GetUnwindPlanAtNonCallSite (...) // best_unwind_plan = GetUnwindPlanAtNonCallSite (...)
Mutex::Locker locker (m_mutex); Mutex::Locker locker (m_mutex);
if (m_tried_unwind_fast == false && m_unwind_fast_ap.get() == NULL) if (m_tried_unwind_fast == false && m_unwind_plan_fast_sp.get() == NULL)
{ {
m_tried_unwind_fast = true; m_tried_unwind_fast = true;
m_unwind_fast_ap.reset (new UnwindPlan); m_unwind_plan_fast_sp.reset (new UnwindPlan);
if (!m_assembly_profiler->GetFastUnwindPlan (m_range, thread, *m_unwind_fast_ap)) if (!m_assembly_profiler->GetFastUnwindPlan (m_range, thread, *m_unwind_plan_fast_sp))
m_unwind_fast_ap.reset(); m_unwind_plan_fast_sp.reset();
} }
return m_unwind_fast_ap.get(); return m_unwind_plan_fast_sp;
} }
UnwindPlan* UnwindPlanSP
FuncUnwinders::GetUnwindPlanArchitectureDefault (Thread& thread) FuncUnwinders::GetUnwindPlanArchitectureDefault (Thread& thread)
{ {
// Lock the mutex to ensure we can always give out the most appropriate // Lock the mutex to ensure we can always give out the most appropriate
@ -161,21 +161,20 @@ FuncUnwinders::GetUnwindPlanArchitectureDefault (Thread& thread)
// if (best_unwind_plan == NULL) // if (best_unwind_plan == NULL)
// best_unwind_plan = GetUnwindPlanAtNonCallSite (...) // best_unwind_plan = GetUnwindPlanAtNonCallSite (...)
Mutex::Locker locker (m_mutex); Mutex::Locker locker (m_mutex);
if (m_tried_unwind_arch_default == false && m_unwind_arch_default == NULL) if (m_tried_unwind_arch_default == false && m_unwind_plan_arch_default_sp.get() == NULL)
{ {
m_tried_unwind_arch_default = true; m_tried_unwind_arch_default = true;
Address current_pc; Address current_pc;
Target *target = thread.CalculateTarget(); Target *target = thread.CalculateTarget();
if (target) if (target)
{ {
ArchSpec arch = target->GetArchitecture (); ArchDefaultUnwindPlanSP arch_default_sp (ArchDefaultUnwindPlan::FindPlugin (target->GetArchitecture ()));
ArchDefaultUnwindPlan *arch_default = ArchDefaultUnwindPlan::FindPlugin (arch); if (arch_default_sp)
if (arch_default) m_unwind_plan_arch_default_sp = arch_default_sp->GetArchDefaultUnwindPlan (thread, current_pc);
m_unwind_arch_default = arch_default->GetArchDefaultUnwindPlan (thread, current_pc);
} }
} }
return m_unwind_arch_default; return m_unwind_plan_arch_default_sp;
} }
Address& Address&

View File

@ -7,28 +7,42 @@
// //
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#include "lldb/lldb-private.h"
#include "lldb/Core/PluginManager.h" #include "lldb/Core/PluginManager.h"
#include <map>
#include "lldb/Core/ArchSpec.h"
#include "lldb/Core/PluginInterface.h" #include "lldb/Core/PluginInterface.h"
#include "lldb/Host/Mutex.h"
#include "lldb/Utility/ArchDefaultUnwindPlan.h" #include "lldb/Utility/ArchDefaultUnwindPlan.h"
using namespace lldb; using namespace lldb;
using namespace lldb_private; using namespace lldb_private;
ArchDefaultUnwindPlan* ArchDefaultUnwindPlanSP
ArchDefaultUnwindPlan::FindPlugin (const ArchSpec &arch) ArchDefaultUnwindPlan::FindPlugin (const ArchSpec &arch)
{ {
ArchDefaultUnwindPlanCreateInstance create_callback; ArchDefaultUnwindPlanCreateInstance create_callback;
typedef std::map <const ArchSpec, ArchDefaultUnwindPlanSP> ArchDefaultUnwindPlanMap;
static ArchDefaultUnwindPlanMap g_plugin_map;
static Mutex g_plugin_map_mutex (Mutex::eMutexTypeRecursive);
Mutex::Locker locker (g_plugin_map_mutex);
ArchDefaultUnwindPlanMap::iterator pos = g_plugin_map.find (arch);
if (pos != g_plugin_map.end())
return pos->second;
for (uint32_t idx = 0; for (uint32_t idx = 0;
(create_callback = PluginManager::GetArchDefaultUnwindPlanCreateCallbackAtIndex(idx)) != NULL; (create_callback = PluginManager::GetArchDefaultUnwindPlanCreateCallbackAtIndex(idx)) != NULL;
++idx) ++idx)
{ {
std::auto_ptr<ArchDefaultUnwindPlan> default_unwind_plan_ap (create_callback (arch)); ArchDefaultUnwindPlanSP default_unwind_plan_sp (create_callback (arch));
if (default_unwind_plan_ap.get ()) if (default_unwind_plan_sp)
return default_unwind_plan_ap.release (); {
g_plugin_map[arch] = default_unwind_plan_sp;
return default_unwind_plan_sp;
} }
return NULL; }
return ArchDefaultUnwindPlanSP();
} }
ArchDefaultUnwindPlan::ArchDefaultUnwindPlan () ArchDefaultUnwindPlan::ArchDefaultUnwindPlan ()

View File

@ -76,7 +76,8 @@ lldb_private::Initialize ()
SymbolFileDWARF::Initialize(); SymbolFileDWARF::Initialize();
SymbolFileSymtab::Initialize(); SymbolFileSymtab::Initialize();
UnwindAssemblyProfiler_x86::Initialize(); UnwindAssemblyProfiler_x86::Initialize();
ArchDefaultUnwindPlan_x86::Initialize(); ArchDefaultUnwindPlan_x86_64::Initialize();
ArchDefaultUnwindPlan_i386::Initialize();
ArchVolatileRegs_x86::Initialize(); ArchVolatileRegs_x86::Initialize();
ScriptInterpreter::Initialize (); ScriptInterpreter::Initialize ();
@ -123,7 +124,8 @@ lldb_private::Terminate ()
SymbolFileDWARF::Terminate(); SymbolFileDWARF::Terminate();
SymbolFileSymtab::Terminate(); SymbolFileSymtab::Terminate();
UnwindAssemblyProfiler_x86::Terminate(); UnwindAssemblyProfiler_x86::Terminate();
ArchDefaultUnwindPlan_x86::Terminate(); ArchDefaultUnwindPlan_i386::Terminate();
ArchDefaultUnwindPlan_x86_64::Terminate();
ArchVolatileRegs_x86::Terminate(); ArchVolatileRegs_x86::Terminate();
ScriptInterpreter::Terminate (); ScriptInterpreter::Terminate ();