forked from OSchip/llvm-project
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:
parent
91c08ad14a
commit
e576ab2996
|
@ -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,
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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*
|
lldb_private::ArchDefaultUnwindPlan *
|
||||||
ArchDefaultUnwindPlan_x86::GetArchDefaultUnwindPlan (Thread& thread, Address current_pc)
|
ArchDefaultUnwindPlan_x86_64::CreateInstance (const lldb_private::ArchSpec &arch)
|
||||||
{
|
{
|
||||||
if (m_cpu == llvm::MachO::CPUTypeX86_64)
|
if (arch.GetGenericCPUType () == ArchSpec::eCPU_x86_64)
|
||||||
{
|
return new ArchDefaultUnwindPlan_x86_64 ();
|
||||||
return &m_64bit_default;
|
|
||||||
}
|
|
||||||
if (m_cpu == llvm::MachO::CPUTypeI386)
|
|
||||||
{
|
|
||||||
return &m_32bit_default;
|
|
||||||
}
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
lldb_private::ArchDefaultUnwindPlan *
|
ArchDefaultUnwindPlan_x86_64::ArchDefaultUnwindPlan_x86_64() :
|
||||||
ArchDefaultUnwindPlan_x86::CreateInstance (const lldb_private::ArchSpec &arch)
|
|
||||||
{
|
|
||||||
uint32_t cpu = arch.GetCPUType ();
|
|
||||||
if (cpu != llvm::MachO::CPUTypeX86_64 && cpu != llvm::MachO::CPUTypeI386)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
return new ArchDefaultUnwindPlan_x86 (cpu);
|
|
||||||
}
|
|
||||||
|
|
||||||
ArchDefaultUnwindPlan_x86::ArchDefaultUnwindPlan_x86(int cpu) :
|
|
||||||
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
|
if (unwind_plan_sp->PlanValidAtAddress (m_current_pc))
|
||||||
if (log && IsLogVerbose())
|
|
||||||
{
|
{
|
||||||
const char *has_fast = "";
|
LogSP log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));
|
||||||
if (m_fast_unwind_plan)
|
if (log && IsLogVerbose())
|
||||||
has_fast = ", and has a fast UnwindPlan";
|
{
|
||||||
log->Printf("%*sFrame %u frame has a fast UnwindPlan",
|
const char *has_fast = "";
|
||||||
m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number);
|
if (m_fast_unwind_plan_sp)
|
||||||
|
has_fast = ", and 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_type = eNormalFrame;
|
||||||
|
return unwind_plan_sp;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
unwind_plan_sp.reset();
|
||||||
}
|
}
|
||||||
m_frame_type = eNormalFrame;
|
|
||||||
return fu->GetUnwindPlanFastUnwind (m_thread);
|
|
||||||
}
|
}
|
||||||
|
return unwind_plan_sp;
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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))
|
|
||||||
{
|
{
|
||||||
if (log && IsLogVerbose())
|
unwind_plan_sp = func_unwinders_sp->GetUnwindPlanAtNonCallSite (m_thread);
|
||||||
|
if (unwind_plan_sp && unwind_plan_sp->PlanValidAtAddress (m_current_pc))
|
||||||
{
|
{
|
||||||
log->Printf("%*sFrame %u frame uses %s for full UnwindPlan",
|
if (log && IsLogVerbose())
|
||||||
m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
|
{
|
||||||
up->GetSourceName().GetCString());
|
log->Printf("%*sFrame %u frame uses %s for full UnwindPlan",
|
||||||
|
m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number,
|
||||||
|
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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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,10 +3180,10 @@ 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))
|
||||||
{
|
{
|
||||||
// We have already parsed this type or from another
|
// We have already parsed this type or from another
|
||||||
// compile unit. GCC loves to use the "one definition
|
// compile unit. GCC loves to use the "one definition
|
||||||
|
@ -3273,8 +3281,8 @@ 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);
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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_
|
||||||
|
|
|
@ -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&
|
||||||
|
|
|
@ -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 ()
|
||||||
|
|
|
@ -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 ();
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue