mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-12-15 12:09:51 +00:00
The first part of an lldb native stack unwinder.
The Unwind and RegisterContext subclasses still need to be finished; none of this code is used by lldb at this point (unless you call into it by hand). The ObjectFile class now has an UnwindTable object. The UnwindTable object has a series of FuncUnwinders objects (Function Unwinders) -- one for each function in that ObjectFile we've backtraced through during this debug session. The FuncUnwinders object has a few different UnwindPlans. UnwindPlans are a generic way of describing how to find the canonical address of a given function's stack frame (the CFA idea from DWARF/eh_frame) and how to restore the caller frame's register values, if they have been saved by this function. UnwindPlans are created from different sources. One source is the eh_frame exception handling information generated by the compiler for unwinding an exception throw. Another source is an assembly language inspection class (UnwindAssemblyProfiler, uses the Plugin architecture) which looks at the instructions in the funciton prologue and describes the stack movements/register saves that are done. Two additional types of UnwindPlans that are worth noting are the "fast" stack UnwindPlan which is useful for making a first pass over a thread's stack, determining how many stack frames there are and retrieving the pc and CFA values for each frame (enough to create StackFrameIDs). Only a minimal set of registers is recovered during a fast stack walk. The final UnwindPlan is an architectural default unwind plan. These are provided by the ArchDefaultUnwindPlan class (which uses the plugin architecture). When no symbol/function address range can be found for a given pc value -- when we have no eh_frame information and when we don't have a start address so we can't examine the assembly language instrucitons -- we have to make a best guess about how to unwind. That's when we use the architectural default UnwindPlan. On x86_64, this would be to assume that rbp is used as a stack pointer and we can use that to find the caller's frame pointer and pc value. It's a last-ditch best guess about how to unwind out of a frame. There are heuristics about when to use one UnwindPlan versues the other -- this will all happen in the still-begin-written UnwindLLDB subclass of Unwind which runs the UnwindPlans. llvm-svn: 113581
This commit is contained in:
parent
6a6dac2fbf
commit
fbcb7f2c4e
@ -429,7 +429,7 @@ public:
|
||||
SetSection (const Section* section) { m_section = section; }
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Reconstruct a symbol context from ad address.
|
||||
/// Reconstruct a symbol context from an address.
|
||||
///
|
||||
/// This class doesn't inherit from SymbolContextScope because many
|
||||
/// address objects have short lifespans. Address objects that are
|
||||
|
@ -178,6 +178,41 @@ public:
|
||||
|
||||
static SymbolVendorCreateInstance
|
||||
GetSymbolVendorCreateCallbackForPluginName (const char *name);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// UnwindAssemblyProfiler
|
||||
//------------------------------------------------------------------
|
||||
static bool
|
||||
RegisterPlugin (const char *name,
|
||||
const char *description,
|
||||
UnwindAssemblyProfilerCreateInstance create_callback);
|
||||
|
||||
static bool
|
||||
UnregisterPlugin (UnwindAssemblyProfilerCreateInstance create_callback);
|
||||
|
||||
static UnwindAssemblyProfilerCreateInstance
|
||||
GetUnwindAssemblyProfilerCreateCallbackAtIndex (uint32_t idx);
|
||||
|
||||
static UnwindAssemblyProfilerCreateInstance
|
||||
GetUnwindAssemblyProfilerCreateCallbackForPluginName (const char *name);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// ArchDefaultUnwindPlan
|
||||
//------------------------------------------------------------------
|
||||
static bool
|
||||
RegisterPlugin (const char *name,
|
||||
const char *description,
|
||||
ArchDefaultUnwindPlanCreateInstance create_callback);
|
||||
|
||||
static bool
|
||||
UnregisterPlugin (ArchDefaultUnwindPlanCreateInstance create_callback);
|
||||
|
||||
static ArchDefaultUnwindPlanCreateInstance
|
||||
GetArchDefaultUnwindPlanCreateCallbackAtIndex (uint32_t idx);
|
||||
|
||||
static ArchDefaultUnwindPlanCreateInstance
|
||||
GetArchDefaultUnwindPlanCreateCallbackForPluginName (const char *name);
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
@ -10,301 +10,120 @@
|
||||
#ifndef liblldb_DWARFCallFrameInfo_h_
|
||||
#define liblldb_DWARFCallFrameInfo_h_
|
||||
|
||||
// C Includes
|
||||
// C++ Includes
|
||||
#include <map>
|
||||
|
||||
// Other libraries and framework includes
|
||||
// Project includes
|
||||
#include "lldb/lldb-private.h"
|
||||
#include "lldb/Core/DataExtractor.h"
|
||||
#include "lldb/Core/Flags.h"
|
||||
#include "lldb/Core/AddressRange.h"
|
||||
#include "lldb/Core/VMRange.h"
|
||||
#include "lldb/Core/dwarf.h"
|
||||
#include "lldb/Symbol/UnwindPlan.h"
|
||||
#include "lldb/Symbol/ObjectFile.h"
|
||||
|
||||
namespace lldb_private {
|
||||
//----------------------------------------------------------------------
|
||||
// DWARFCallFrameInfo
|
||||
//
|
||||
// State that describes all register locations for a given address
|
||||
// range.
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
// DWARFCallFrameInfo is a class which can read eh_frame and DWARF
|
||||
// Call Frame Information FDEs. It stores little information internally.
|
||||
// Only two APIs are exported - one to find the high/low pc values
|
||||
// of a function given a text address via the information in the
|
||||
// eh_frame / debug_frame, and one to generate an UnwindPlan based
|
||||
// on the FDE in the eh_frame / debug_frame section.
|
||||
|
||||
class DWARFCallFrameInfo
|
||||
{
|
||||
public:
|
||||
|
||||
DWARFCallFrameInfo (ObjectFile& objfile, lldb::SectionSP& section, uint32_t reg_kind, bool is_eh_frame);
|
||||
|
||||
~DWARFCallFrameInfo();
|
||||
|
||||
// Locate an AddressRange that includes the provided Address in this
|
||||
// object's eh_frame/debug_info
|
||||
// Returns true if a range is found to cover that address.
|
||||
bool
|
||||
GetAddressRange (Address addr, AddressRange &range);
|
||||
|
||||
// Return an UnwindPlan based on the call frame information encoded
|
||||
// in the FDE of this DWARFCallFrameInfo section.
|
||||
bool
|
||||
GetUnwindPlan (Address addr, UnwindPlan& unwind_plan);
|
||||
|
||||
|
||||
private:
|
||||
enum
|
||||
{
|
||||
CFI_AUG_MAX_SIZE = 8,
|
||||
CFI_HEADER_SIZE = 8
|
||||
};
|
||||
|
||||
class Row;
|
||||
|
||||
class RegisterLocation
|
||||
{
|
||||
public:
|
||||
|
||||
enum Type
|
||||
{
|
||||
unspecified, // not specified, we may be able to assume this is the same register.
|
||||
// gcc doesn't specify all initial values so we really don't know...
|
||||
isUndefined, // reg is not available
|
||||
isSame, // reg is unchanged
|
||||
atCFAPlusOffset,// reg = deref(CFA + offset)
|
||||
isCFAPlusOffset,// reg = CFA + offset
|
||||
inOtherRegister,// reg = other reg
|
||||
atDWARFExpression, // reg = deref(eval(dwarf_expr))
|
||||
isDWARFExpression // reg = eval(dwarf_expr)
|
||||
};
|
||||
|
||||
RegisterLocation();
|
||||
|
||||
bool
|
||||
operator == (const RegisterLocation& rhs) const;
|
||||
|
||||
void
|
||||
Dump(Stream *s, const DWARFCallFrameInfo &cfi, Thread *thread, const Row *row, uint32_t reg_num) const;
|
||||
|
||||
void
|
||||
SetUnspecified();
|
||||
|
||||
void
|
||||
SetUndefined();
|
||||
|
||||
void
|
||||
SetSame() ;
|
||||
|
||||
void
|
||||
SetAtCFAPlusOffset (int64_t offset);
|
||||
|
||||
void
|
||||
SetIsCFAPlusOffset (int64_t offset);
|
||||
|
||||
void
|
||||
SetInRegister (uint32_t reg_num);
|
||||
|
||||
void
|
||||
SetAtDWARFExpression (const uint8_t *opcodes, uint32_t len);
|
||||
|
||||
void
|
||||
SetIsDWARFExpression (const uint8_t *opcodes, uint32_t len);
|
||||
|
||||
protected:
|
||||
Type m_type; // How do we locate this register?
|
||||
union
|
||||
{
|
||||
// For m_type == atCFAPlusOffset or m_type == isCFAPlusOffset
|
||||
int32_t offset;
|
||||
// For m_type == inOtherRegister
|
||||
uint32_t reg_num; // The register number
|
||||
// For m_type == atDWARFExpression or m_type == isDWARFExpression
|
||||
struct {
|
||||
const uint8_t *opcodes;
|
||||
uint32_t length;
|
||||
} expr;
|
||||
} m_location;
|
||||
};
|
||||
|
||||
class Row
|
||||
{
|
||||
public:
|
||||
|
||||
Row ();
|
||||
|
||||
~Row ();
|
||||
|
||||
void
|
||||
Clear();
|
||||
|
||||
void
|
||||
Dump(Stream* s, const DWARFCallFrameInfo &cfi, Thread *thread, lldb::addr_t base_addr) const;
|
||||
|
||||
bool
|
||||
GetRegisterInfo (uint32_t reg_num, RegisterLocation& register_location) const;
|
||||
|
||||
void
|
||||
SetRegisterInfo (uint32_t reg_num, const RegisterLocation& register_location);
|
||||
|
||||
lldb::addr_t
|
||||
GetOffset() const
|
||||
{
|
||||
return m_offset;
|
||||
}
|
||||
|
||||
void
|
||||
SetOffset(lldb::addr_t offset)
|
||||
{
|
||||
m_offset = offset;
|
||||
}
|
||||
|
||||
void
|
||||
SlideOffset (lldb::addr_t slide)
|
||||
{
|
||||
m_offset += slide;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
GetCFARegister () const
|
||||
{
|
||||
return m_cfa_reg_num;
|
||||
}
|
||||
|
||||
void
|
||||
SetCFARegister (uint32_t reg_num)
|
||||
{
|
||||
m_cfa_reg_num = reg_num;
|
||||
}
|
||||
|
||||
int32_t
|
||||
GetCFAOffset () const
|
||||
{
|
||||
return m_cfa_offset;
|
||||
}
|
||||
|
||||
void
|
||||
SetCFAOffset (int32_t offset)
|
||||
{
|
||||
m_cfa_offset = offset;
|
||||
}
|
||||
|
||||
protected:
|
||||
typedef std::map<uint32_t, RegisterLocation> collection;
|
||||
lldb::addr_t m_offset; // The an offset into the DBAddressRange that owns this row.
|
||||
uint32_t m_cfa_reg_num; // The Call Frame Address register number
|
||||
int32_t m_cfa_offset; // The offset from the CFA for this row
|
||||
collection m_register_locations;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// Common Information Entry (CIE)
|
||||
//------------------------------------------------------------------
|
||||
protected:
|
||||
|
||||
struct CIE
|
||||
{
|
||||
typedef lldb::SharedPtr<CIE>::Type shared_ptr;
|
||||
dw_offset_t cie_offset;
|
||||
uint8_t version;
|
||||
char augmentation[CFI_AUG_MAX_SIZE]; // This is typically empty or very short. If we ever run into the limit, make this a NSData pointer
|
||||
char augmentation[CFI_AUG_MAX_SIZE]; // This is typically empty or very short.
|
||||
uint32_t code_align;
|
||||
int32_t data_align;
|
||||
uint32_t return_addr_reg_num;
|
||||
dw_offset_t inst_offset; // offset of CIE instructions in mCFIData
|
||||
uint32_t inst_length; // length of CIE instructions in mCFIData
|
||||
uint8_t ptr_encoding;
|
||||
lldb_private::UnwindPlan::Row initial_row;
|
||||
|
||||
CIE(dw_offset_t offset);
|
||||
~CIE();
|
||||
|
||||
void
|
||||
Dump(Stream *s, Thread* threadState, const ArchSpec *arch, uint32_t reg_kind) const;
|
||||
CIE(dw_offset_t offset) : cie_offset(offset), initial_row() {}
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// Frame Description Entry (FDE)
|
||||
//------------------------------------------------------------------
|
||||
public:
|
||||
typedef lldb::SharedPtr<CIE>::Type CIESP;
|
||||
|
||||
class FDE
|
||||
struct FDEEntry
|
||||
{
|
||||
public:
|
||||
typedef lldb::SharedPtr<FDE>::Type shared_ptr;
|
||||
AddressRange bounds; // function bounds
|
||||
dw_offset_t offset; // offset to this FDE within the Section
|
||||
|
||||
FDE (uint32_t offset, const AddressRange &range);
|
||||
~FDE();
|
||||
|
||||
const AddressRange &
|
||||
GetAddressRange() const;
|
||||
|
||||
void
|
||||
AppendRow (const Row &row);
|
||||
|
||||
bool
|
||||
IsValidRowIndex (uint32_t idx) const;
|
||||
|
||||
void
|
||||
Dump (Stream *s, const DWARFCallFrameInfo &cfi, Thread* thread) const;
|
||||
|
||||
const Row&
|
||||
GetRowAtIndex (uint32_t idx);
|
||||
|
||||
protected:
|
||||
typedef std::vector<Row> collection;
|
||||
uint32_t m_fde_offset;
|
||||
AddressRange m_range;
|
||||
collection m_row_list;
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN (FDE);
|
||||
inline bool
|
||||
operator<(const DWARFCallFrameInfo::FDEEntry& b) const
|
||||
{
|
||||
if (bounds.GetBaseAddress().GetOffset() < b.bounds.GetBaseAddress().GetOffset())
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
DWARFCallFrameInfo(ObjectFile *objfile, lldb_private::Section *section, uint32_t reg_kind);
|
||||
|
||||
~DWARFCallFrameInfo();
|
||||
typedef std::map<off_t, CIESP> cie_map_t;
|
||||
|
||||
bool
|
||||
IsEHFrame() const;
|
||||
|
||||
const ArchSpec *
|
||||
GetArchitecture() const;
|
||||
|
||||
uint32_t
|
||||
GetRegisterKind () const;
|
||||
bool
|
||||
GetFDEEntryByAddress (Address addr, FDEEntry& fde_entry);
|
||||
|
||||
void
|
||||
SetRegisterKind (uint32_t reg_kind);
|
||||
GetFDEIndex ();
|
||||
|
||||
void
|
||||
Index ();
|
||||
bool
|
||||
FDEToUnwindPlan (uint32_t offset, Address startaddr, UnwindPlan& unwind_plan);
|
||||
|
||||
// bool UnwindRegister (const uint32_t reg_num, const Thread* currState, const Row* row, Thread* unwindState);
|
||||
// uint32_t UnwindThreadState(const Thread* curr_state, bool is_first_frame, Thread* unwound_state);
|
||||
const FDE *
|
||||
FindFDE(const Address &addr);
|
||||
const CIE*
|
||||
GetCIE(dw_offset_t cie_offset);
|
||||
|
||||
void
|
||||
Dump(Stream *s, Thread *thread) const;
|
||||
ObjectFile& m_objfile;
|
||||
lldb::SectionSP m_section;
|
||||
uint32_t m_reg_kind;
|
||||
Flags m_flags;
|
||||
cie_map_t m_cie_map;
|
||||
|
||||
void
|
||||
ParseAll();
|
||||
protected:
|
||||
DataExtractor m_cfi_data;
|
||||
bool m_cfi_data_initialized; // only copy the section into the DE once
|
||||
|
||||
enum
|
||||
{
|
||||
eFlagParsedIndex = (1 << 0)
|
||||
};
|
||||
std::vector<FDEEntry> m_fde_index;
|
||||
bool m_fde_index_initialized; // only scan the section for FDEs once
|
||||
|
||||
typedef std::map<off_t, CIE::shared_ptr> cie_map_t;
|
||||
struct FDEInfo
|
||||
{
|
||||
off_t fde_offset;
|
||||
FDE::shared_ptr fde_sp;
|
||||
FDEInfo (off_t offset);
|
||||
FDEInfo ();
|
||||
bool m_is_eh_frame;
|
||||
|
||||
};
|
||||
typedef std::map<VMRange, FDEInfo> fde_map_t;
|
||||
|
||||
ObjectFile * m_objfile;
|
||||
lldb_private::Section * m_section;
|
||||
uint32_t m_reg_kind;
|
||||
Flags m_flags;
|
||||
DataExtractor m_cfi_data;
|
||||
cie_map_t m_cie_map;
|
||||
fde_map_t m_fde_map;
|
||||
|
||||
const CIE*
|
||||
GetCIE (uint32_t offset);
|
||||
|
||||
void
|
||||
ParseInstructions(const CIE *cie, FDE *fde, uint32_t instr_offset, uint32_t instr_length);
|
||||
|
||||
CIE::shared_ptr
|
||||
CIESP
|
||||
ParseCIE (const uint32_t cie_offset);
|
||||
|
||||
FDE::shared_ptr
|
||||
ParseFDE (const uint32_t fde_offset);
|
||||
};
|
||||
|
||||
} // namespace lldb_private
|
||||
|
91
lldb/include/lldb/Symbol/FuncUnwinders.h
Normal file
91
lldb/include/lldb/Symbol/FuncUnwinders.h
Normal file
@ -0,0 +1,91 @@
|
||||
#ifndef liblldb_FuncUnwinders_h
|
||||
#define liblldb_FuncUnwinders_h
|
||||
|
||||
#include "lldb/lldb-private.h"
|
||||
#include "lldb/lldb-forward.h"
|
||||
#include "lldb/lldb-forward-rtti.h"
|
||||
#include "lldb/Core/AddressRange.h"
|
||||
#include "lldb/Core/ArchSpec.h"
|
||||
#include <memory>
|
||||
|
||||
namespace lldb_private {
|
||||
|
||||
class UnwindTable;
|
||||
|
||||
class FuncUnwinders
|
||||
{
|
||||
public:
|
||||
// FuncUnwinders objects are used to track UnwindPlans for a function
|
||||
// (named or not - really just an address range)
|
||||
|
||||
// We'll record three different UnwindPlans for each address range:
|
||||
// 1. Unwinding from a call site (a valid exception throw location)
|
||||
// This is often sourced from the eh_frame exception handling info
|
||||
// 2. Unwinding from a non-call site (any location in the function)
|
||||
// This is often done by analyzing the function prologue assembly
|
||||
// langauge instructions
|
||||
// 3. A fast unwind method for this function which only retrieves a
|
||||
// limited set of registers necessary to walk the stack
|
||||
// 4. An architectural default unwind plan when none of the above are
|
||||
// available for some reason.
|
||||
|
||||
// Additionally, FuncUnwinds object can be asked where the prologue
|
||||
// instructions are finished for migrating breakpoints past the
|
||||
// stack frame setup instructions when we don't have line table information.
|
||||
|
||||
FuncUnwinders (lldb_private::UnwindTable& unwind_table, lldb_private::UnwindAssemblyProfiler *assembly_profiler, AddressRange range);
|
||||
|
||||
~FuncUnwinders ();
|
||||
|
||||
UnwindPlan*
|
||||
GetUnwindPlanAtCallSite ();
|
||||
|
||||
UnwindPlan*
|
||||
GetUnwindPlanAtNonCallSite (lldb_private::Thread& thread);
|
||||
|
||||
UnwindPlan*
|
||||
GetUnwindPlanFastUnwind (lldb_private::Thread& Thread);
|
||||
|
||||
UnwindPlan*
|
||||
GetUnwindPlanArchitectureDefault (lldb_private::Thread& thread);
|
||||
|
||||
Address&
|
||||
GetFirstNonPrologueInsn (Target& target);
|
||||
|
||||
const Address&
|
||||
GetFunctionStartAddress () const;
|
||||
|
||||
bool
|
||||
ContainsAddress (const Address& addr) const
|
||||
{
|
||||
return m_range.ContainsFileAddress (addr);
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
UnwindTable& m_unwind_table;
|
||||
UnwindAssemblyProfiler *m_assembly_profiler;
|
||||
AddressRange m_range;
|
||||
|
||||
UnwindPlan* m_unwind_at_call_site;
|
||||
UnwindPlan* m_unwind_at_non_call_site;
|
||||
UnwindPlan* m_fast_unwind;
|
||||
UnwindPlan* m_arch_default_unwind;
|
||||
|
||||
Address m_first_non_prologue_insn;
|
||||
|
||||
}; // class FuncUnwinders
|
||||
|
||||
inline bool
|
||||
operator<(const FuncUnwinders& a, const FuncUnwinders& b)
|
||||
{
|
||||
if (a.GetFunctionStartAddress().GetOffset() < b.GetFunctionStartAddress().GetOffset())
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace lldb_private
|
||||
|
||||
|
||||
#endif //liblldb_FuncUnwinders_h
|
@ -16,6 +16,7 @@
|
||||
#include "lldb/Core/ModuleChild.h"
|
||||
#include "lldb/Core/PluginInterface.h"
|
||||
#include "lldb/Symbol/Symtab.h"
|
||||
#include "lldb/Symbol/UnwindTable.h"
|
||||
|
||||
namespace lldb_private {
|
||||
|
||||
@ -66,7 +67,8 @@ public:
|
||||
m_file (), // This file could be different from the original module's file
|
||||
m_offset (offset),
|
||||
m_length (length),
|
||||
m_data (headerDataSP, lldb::eByteOrderHost, 4)
|
||||
m_data (headerDataSP, lldb::eByteOrderHost, 4),
|
||||
m_unwind_table (*this)
|
||||
{
|
||||
if (file_spec_ptr)
|
||||
m_file = *file_spec_ptr;
|
||||
@ -294,6 +296,21 @@ public:
|
||||
virtual bool
|
||||
ParseHeader () = 0;
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Returns a reference to the UnwindTable for this ObjectFile
|
||||
///
|
||||
/// The UnwindTable contains FuncUnwinders objects for any function in
|
||||
/// this ObjectFile. If a FuncUnwinders object hasn't been created yet
|
||||
/// (i.e. the function has yet to be unwound in a stack walk), it
|
||||
/// will be created when requested. Specifically, we do not create
|
||||
/// FuncUnwinders objects for functions until they are needed.
|
||||
///
|
||||
/// @return
|
||||
/// Returns the unwind table for this object file.
|
||||
//------------------------------------------------------------------
|
||||
virtual lldb_private::UnwindTable&
|
||||
GetUnwindTable () { return m_unwind_table; }
|
||||
|
||||
protected:
|
||||
//------------------------------------------------------------------
|
||||
// Member variables.
|
||||
@ -302,6 +319,7 @@ protected:
|
||||
lldb::addr_t m_offset; ///< The offset in bytes into the file, or the address in memory
|
||||
lldb::addr_t m_length; ///< The length of this object file if it is known (can be zero if length is unknown or can't be determined).
|
||||
DataExtractor m_data; ///< The data for this object file so things can be parsed lazily.
|
||||
lldb_private::UnwindTable m_unwind_table; /// < Table of FuncUnwinders objects created for this ObjectFile's functions
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Sets the architecture for a module. At present the architecture
|
||||
|
224
lldb/include/lldb/Symbol/UnwindPlan.h
Normal file
224
lldb/include/lldb/Symbol/UnwindPlan.h
Normal file
@ -0,0 +1,224 @@
|
||||
#ifndef liblldb_UnwindPlan_h
|
||||
#define liblldb_UnwindPlan_h
|
||||
|
||||
#include "lldb/lldb-private.h"
|
||||
#include "lldb/Core/AddressRange.h"
|
||||
#include "lldb/Core/Stream.h"
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
namespace lldb_private {
|
||||
|
||||
// The UnwindPlan object specifies how to unwind out of a function - where
|
||||
// this function saves the caller's register values before modifying them
|
||||
// (for non-volatile aka saved registers) and how to find this frame's
|
||||
// Canonical Frame Address (CFA).
|
||||
|
||||
// Most commonly, registers are saved on the stack, offset some bytes from
|
||||
// the Canonical Frame Address, or CFA, which is the starting address of
|
||||
// this function's stack frame (the CFA is same as the eh_frame's CFA,
|
||||
// whatever that may be on a given architecture).
|
||||
// The CFA address for the stack frame does not change during
|
||||
// the lifetime of the function.
|
||||
|
||||
// Internally, the UnwindPlan is structured as a vector of register locations
|
||||
// organized by code address in the function, showing which registers have been
|
||||
// saved at that point and where they are saved.
|
||||
// It can be thought of as the expanded table form of the DWARF CFI
|
||||
// encoded information.
|
||||
|
||||
// Other unwind information sources will be converted into UnwindPlans before
|
||||
// being added to a FuncUnwinders object. The unwind source may be
|
||||
// an eh_frame FDE, a DWARF debug_frame FDE, or assembly language based
|
||||
// prologue analysis.
|
||||
// The UnwindPlan is the canonical form of this information that the unwinder
|
||||
// code will use when walking the stack.
|
||||
|
||||
class UnwindPlan {
|
||||
public:
|
||||
|
||||
class Row {
|
||||
public:
|
||||
class RegisterLocation
|
||||
{
|
||||
public:
|
||||
|
||||
typedef enum RestoreType
|
||||
{
|
||||
unspecified, // not specified, we may be able to assume this
|
||||
// is the same register. gcc doesn't specify all
|
||||
// initial values so we really don't know...
|
||||
isUndefined, // reg is not available, e.g. volatile reg
|
||||
isSame, // reg is unchanged
|
||||
atCFAPlusOffset, // reg = deref(CFA + offset)
|
||||
isCFAPlusOffset, // reg = CFA + offset
|
||||
inOtherRegister, // reg = other reg
|
||||
atDWARFExpression, // reg = deref(eval(dwarf_expr))
|
||||
isDWARFExpression // reg = eval(dwarf_expr)
|
||||
};
|
||||
|
||||
RegisterLocation() : m_type(unspecified) { }
|
||||
|
||||
bool
|
||||
operator == (const RegisterLocation& rhs) const;
|
||||
|
||||
void SetUnspecified();
|
||||
|
||||
void SetUndefined();
|
||||
|
||||
void SetSame();
|
||||
|
||||
void SetAtCFAPlusOffset (int32_t offset);
|
||||
|
||||
void SetIsCFAPlusOffset (int32_t offset);
|
||||
|
||||
void SetInRegister (uint32_t reg_num);
|
||||
|
||||
RestoreType GetLocationType () const { return m_type; }
|
||||
|
||||
int32_t GetOffset () const { return m_location.offset; }
|
||||
|
||||
uint32_t GetRegNum () const { return m_location.reg_num; }
|
||||
|
||||
void GetDWARFExpr (const uint8_t **opcodes, uint16_t& len) const { *opcodes = m_location.expr.opcodes; len = m_location.expr.length; }
|
||||
|
||||
void
|
||||
SetAtDWARFExpression (const uint8_t *opcodes, uint32_t len);
|
||||
|
||||
void
|
||||
SetIsDWARFExpression (const uint8_t *opcodes, uint32_t len);
|
||||
|
||||
void
|
||||
Dump (Stream &s) const;
|
||||
|
||||
private:
|
||||
RestoreType m_type; // How do we locate this register?
|
||||
union
|
||||
{
|
||||
// For m_type == atCFAPlusOffset or m_type == isCFAPlusOffset
|
||||
int32_t offset;
|
||||
// For m_type == inOtherRegister
|
||||
uint32_t reg_num; // The register number
|
||||
// For m_type == atDWARFExpression or m_type == isDWARFExpression
|
||||
struct {
|
||||
const uint8_t *opcodes;
|
||||
uint16_t length;
|
||||
} expr;
|
||||
} m_location;
|
||||
};
|
||||
|
||||
public:
|
||||
Row ();
|
||||
|
||||
bool
|
||||
GetRegisterInfo (uint32_t reg_num, RegisterLocation& register_location) const;
|
||||
|
||||
void
|
||||
SetRegisterInfo (uint32_t reg_num, const RegisterLocation register_location);
|
||||
|
||||
lldb::addr_t
|
||||
GetOffset() const
|
||||
{
|
||||
return m_offset;
|
||||
}
|
||||
|
||||
void
|
||||
SetOffset(lldb::addr_t offset)
|
||||
{
|
||||
m_offset = offset;
|
||||
}
|
||||
|
||||
void
|
||||
SlideOffset(lldb::addr_t offset)
|
||||
{
|
||||
m_offset += offset;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
GetCFARegister () const
|
||||
{
|
||||
return m_cfa_reg_num;
|
||||
}
|
||||
|
||||
void
|
||||
SetCFARegister (uint32_t reg_num)
|
||||
{
|
||||
m_cfa_reg_num = reg_num;
|
||||
}
|
||||
|
||||
int32_t
|
||||
GetCFAOffset () const
|
||||
{
|
||||
return m_cfa_offset;
|
||||
}
|
||||
|
||||
void
|
||||
SetCFAOffset (int32_t offset)
|
||||
{
|
||||
m_cfa_offset = offset;
|
||||
}
|
||||
|
||||
void
|
||||
Clear ();
|
||||
|
||||
void
|
||||
Dump (Stream& s, int register_kind, Thread* thread) const;
|
||||
|
||||
protected:
|
||||
typedef std::map<uint32_t, RegisterLocation> collection;
|
||||
lldb::addr_t m_offset; // Offset into the function for this row
|
||||
uint32_t m_cfa_reg_num; // The Call Frame Address register number
|
||||
int32_t m_cfa_offset; // The offset from the CFA for this row
|
||||
collection m_register_locations;
|
||||
|
||||
}; // class Row
|
||||
|
||||
public:
|
||||
|
||||
UnwindPlan () : m_register_kind(-1), m_row_list(), m_plan_valid_address_range() { }
|
||||
|
||||
void Dump (Stream& s, Process* process, Thread* thread) const;
|
||||
|
||||
void
|
||||
AppendRow (const Row& row);
|
||||
|
||||
const Row*
|
||||
GetRowForFunctionOffset (int offset) const;
|
||||
|
||||
void
|
||||
SetRegisterKind (uint32_t rk);
|
||||
|
||||
uint32_t
|
||||
GetRegisterKind (void) const;
|
||||
|
||||
// This UnwindPlan may not be valid at every address of the function span.
|
||||
// For instance, a FastUnwindPlan will not be valid at the prologue setup
|
||||
// instructions - only in the body of the function.
|
||||
void
|
||||
SetPlanValidAddressRange (const AddressRange& range);
|
||||
|
||||
bool
|
||||
PlanValidAtAddress (Address addr);
|
||||
|
||||
bool
|
||||
IsValidRowIndex (uint32_t idx) const;
|
||||
|
||||
const UnwindPlan::Row&
|
||||
GetRowAtIndex (uint32_t idx) const;
|
||||
|
||||
int
|
||||
GetRowCount () const;
|
||||
|
||||
private:
|
||||
|
||||
typedef std::vector<Row> collection;
|
||||
collection m_row_list;
|
||||
AddressRange m_plan_valid_address_range;
|
||||
uint32_t m_register_kind; // The RegisterKind these register numbers are in terms of - will need to be
|
||||
// translated to lldb native reg nums at unwind time
|
||||
}; // class UnwindPlan
|
||||
|
||||
} // namespace lldb_private
|
||||
|
||||
#endif //liblldb_UnwindPlan_h
|
55
lldb/include/lldb/Symbol/UnwindTable.h
Normal file
55
lldb/include/lldb/Symbol/UnwindTable.h
Normal file
@ -0,0 +1,55 @@
|
||||
//===-- Symtab.h ------------------------------------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
|
||||
#ifndef liblldb_UnwindTable_h
|
||||
#define liblldb_UnwindTable_h
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "lldb/lldb-private.h"
|
||||
|
||||
namespace lldb_private {
|
||||
|
||||
// A class which holds all the FuncUnwinders objects for a given ObjectFile.
|
||||
// The UnwindTable is populated with FuncUnwinders objects lazily during
|
||||
// the debug session.
|
||||
|
||||
class UnwindTable
|
||||
{
|
||||
public:
|
||||
UnwindTable(ObjectFile& objfile);
|
||||
~UnwindTable();
|
||||
|
||||
lldb_private::DWARFCallFrameInfo *
|
||||
GetEHFrameInfo ();
|
||||
|
||||
lldb::FuncUnwindersSP
|
||||
GetFuncUnwindersContainingAddress (const Address& addr, SymbolContext &sc);
|
||||
|
||||
private:
|
||||
void initialize ();
|
||||
|
||||
typedef std::vector<lldb::FuncUnwindersSP> collection;
|
||||
typedef collection::iterator iterator;
|
||||
typedef collection::const_iterator const_iterator;
|
||||
|
||||
ObjectFile& m_object_file;
|
||||
collection m_unwinds;
|
||||
|
||||
bool m_initialized; // delay some initialization until ObjectFile is set up
|
||||
|
||||
UnwindAssemblyProfiler* m_assembly_profiler;
|
||||
|
||||
DWARFCallFrameInfo* m_eh_frame;
|
||||
};
|
||||
|
||||
} // namespace lldb_private
|
||||
|
||||
#endif // liblldb_UnwindTable_h
|
@ -142,6 +142,9 @@ public:
|
||||
bool
|
||||
WriteRegisterFromUnsigned (uint32_t reg, uint64_t uval);
|
||||
|
||||
bool
|
||||
ConvertBetweenRegisterKinds (int source_rk, uint32_t source_regnum, int target_rk, uint32_t target_regnum);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// lldb::ExecutionContextScope pure virtual functions
|
||||
//------------------------------------------------------------------
|
||||
|
42
lldb/include/lldb/Utility/ArchDefaultUnwindPlan.h
Normal file
42
lldb/include/lldb/Utility/ArchDefaultUnwindPlan.h
Normal file
@ -0,0 +1,42 @@
|
||||
//===---------------------ArchDefaultUnwindPlan.h ---------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef utility_ArchDefaultUnwindPlan_h_
|
||||
#define utility_ArchDefaultUnwindPlan_h_
|
||||
|
||||
#include "lldb-private.h"
|
||||
#include "lldb/Core/PluginInterface.h"
|
||||
|
||||
namespace lldb_private {
|
||||
|
||||
class ArchDefaultUnwindPlan :
|
||||
public PluginInterface
|
||||
{
|
||||
public:
|
||||
|
||||
virtual
|
||||
~ArchDefaultUnwindPlan();
|
||||
|
||||
virtual lldb_private::UnwindPlan*
|
||||
GetArchDefaultUnwindPlan (Thread& thread, Address current_pc) = 0;
|
||||
|
||||
static ArchDefaultUnwindPlan*
|
||||
FindPlugin (const ArchSpec &arch);
|
||||
|
||||
protected:
|
||||
ArchDefaultUnwindPlan();
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN (ArchDefaultUnwindPlan);
|
||||
};
|
||||
|
||||
} // namespace lldb_private
|
||||
|
||||
#endif //utility_ArchDefaultUnwindPlan_h_
|
||||
|
||||
|
49
lldb/include/lldb/Utility/UnwindAssemblyProfiler.h
Normal file
49
lldb/include/lldb/Utility/UnwindAssemblyProfiler.h
Normal file
@ -0,0 +1,49 @@
|
||||
//===---------------------UnwindAssemblyProfiler.h --------------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef utility_UnwindAssemblyProfiler_h_
|
||||
#define utility_UnwindAssemblyProfiler_h_
|
||||
|
||||
#include "lldb-private.h"
|
||||
#include "lldb/Core/PluginInterface.h"
|
||||
|
||||
namespace lldb_private {
|
||||
|
||||
class UnwindAssemblyProfiler :
|
||||
public PluginInterface
|
||||
{
|
||||
public:
|
||||
|
||||
virtual
|
||||
~UnwindAssemblyProfiler();
|
||||
|
||||
virtual bool
|
||||
GetNonCallSiteUnwindPlanFromAssembly (lldb_private::AddressRange& func, Thread& thread, lldb_private::UnwindPlan& unwind_plan) = 0;
|
||||
|
||||
virtual bool
|
||||
GetFastUnwindPlan (lldb_private::AddressRange& func, Thread& thread, lldb_private::UnwindPlan &unwind_plan) = 0;
|
||||
|
||||
// thread may be NULL in which case we only use the Target (e.g. if this is called pre-process-launch).
|
||||
virtual bool
|
||||
FirstNonPrologueInsn (lldb_private::AddressRange& func, Target& target, Thread* thread, lldb_private::Address& first_non_prologue_insn) = 0;
|
||||
|
||||
static UnwindAssemblyProfiler*
|
||||
FindPlugin (const ArchSpec &arch);
|
||||
|
||||
protected:
|
||||
UnwindAssemblyProfiler();
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN (UnwindAssemblyProfiler);
|
||||
};
|
||||
|
||||
} // namespace lldb_private
|
||||
|
||||
#endif //utility_UnwindAssemblyProfiler_h_
|
||||
|
||||
|
@ -198,10 +198,11 @@ typedef enum ScriptLanguage
|
||||
//----------------------------------------------------------------------
|
||||
typedef enum RegisterKind
|
||||
{
|
||||
eRegisterKindGCC = 0,
|
||||
eRegisterKindDWARF,
|
||||
eRegisterKindGeneric,
|
||||
eRegisterKindGDB,
|
||||
eRegisterKindGCC = 0, // the register numbers seen in eh_frame
|
||||
eRegisterKindDWARF, // the register numbers seen DWARF
|
||||
eRegisterKindGeneric, // insn ptr reg, stack ptr reg, etc not specific to any particular target
|
||||
eRegisterKindGDB, // the register numbers gdb uses (matches stabs numbers?)
|
||||
eRegisterKindLLDB, // lldb's internal register numbers
|
||||
kNumRegisterKinds
|
||||
} RegisterKind;
|
||||
|
||||
|
@ -59,6 +59,7 @@ namespace lldb {
|
||||
typedef SharedPtr<lldb_private::Thread>::Type ThreadSP;
|
||||
typedef SharedPtr<lldb_private::ThreadPlan>::Type ThreadPlanSP;
|
||||
typedef SharedPtr<lldb_private::Type>::Type TypeSP;
|
||||
typedef SharedPtr<lldb_private::FuncUnwinders>::Type FuncUnwindersSP;
|
||||
typedef SharedPtr<lldb_private::UserSettingsController>::Type UserSettingsControllerSP;
|
||||
typedef SharedPtr<lldb_private::ValueObject>::Type ValueObjectSP;
|
||||
typedef SharedPtr<lldb_private::Variable>::Type VariableSP;
|
||||
|
@ -22,33 +22,33 @@ class Address;
|
||||
class AddressRange;
|
||||
class AddressResolver;
|
||||
class ArchSpec;
|
||||
class ArchDefaultUnwindPlan;
|
||||
class Args;
|
||||
class Baton;
|
||||
class Block;
|
||||
class Breakpoint;
|
||||
class BreakpointID;
|
||||
class BreakpointIDList;
|
||||
class BreakpointSite;
|
||||
class BreakpointSiteList;
|
||||
class BreakpointList;
|
||||
class BreakpointLocation;
|
||||
class BreakpointLocationCollection;
|
||||
class BreakpointLocationList;
|
||||
class BreakpointOptions;
|
||||
class BreakpointResolver;
|
||||
class BreakpointSite;
|
||||
class BreakpointSiteList;
|
||||
class Broadcaster;
|
||||
class ClangASTContext;
|
||||
class ClangExpression;
|
||||
class ClangExpressionDeclMap;
|
||||
class ClangExpressionVariableList;
|
||||
class ClangExpressionVariableStore;
|
||||
class Debugger;
|
||||
class CommandInterpreter;
|
||||
class CommandObject;
|
||||
class CommandReturnObject;
|
||||
class Communication;
|
||||
class Condition;
|
||||
class CompileUnit;
|
||||
class Condition;
|
||||
class Connection;
|
||||
class ConnectionFileDescriptor;
|
||||
class ConstString;
|
||||
@ -57,6 +57,7 @@ class DWARFExpression;
|
||||
class DataBuffer;
|
||||
class DataExtractor;
|
||||
class Debugger;
|
||||
class Debugger;
|
||||
class Declaration;
|
||||
class Disassembler;
|
||||
class DynamicLoader;
|
||||
@ -68,12 +69,12 @@ class ExecutionContextScope;
|
||||
class FileSpec;
|
||||
class FileSpecList;
|
||||
class Flags;
|
||||
class FuncUnwinders;
|
||||
class Function;
|
||||
class FunctionInfo;
|
||||
class InlineFunctionInfo;
|
||||
class InputReader;
|
||||
class InstanceSettings;
|
||||
struct LineEntry;
|
||||
class LineTable;
|
||||
class Listener;
|
||||
class Log;
|
||||
@ -123,19 +124,22 @@ class Thread;
|
||||
class ThreadList;
|
||||
class ThreadPlan;
|
||||
class ThreadPlanBase;
|
||||
class ThreadPlanRunToAddress;
|
||||
class ThreadPlanStepInstruction;
|
||||
class ThreadPlanStepOut;
|
||||
class ThreadPlanStepOverBreakpoint;
|
||||
class ThreadPlanStepThrough;
|
||||
class ThreadPlanStepRange;
|
||||
class ThreadPlanRunToAddress;
|
||||
class ThreadPlanStepThrough;
|
||||
class ThreadSpec;
|
||||
class TimeValue;
|
||||
class Type;
|
||||
class TypeList;
|
||||
class Unwind;
|
||||
class UserSettingsController;
|
||||
class UUID;
|
||||
class Unwind;
|
||||
class UnwindAssemblyProfiler;
|
||||
class UnwindPlan;
|
||||
class UnwindTable;
|
||||
class UserSettingsController;
|
||||
class VMRange;
|
||||
class Value;
|
||||
class ValueList;
|
||||
@ -144,6 +148,7 @@ class ValueObjectList;
|
||||
class Variable;
|
||||
class VariableList;
|
||||
class WatchpointLocation;
|
||||
struct LineEntry;
|
||||
|
||||
} // namespace lldb_private
|
||||
|
||||
|
@ -28,6 +28,8 @@ namespace lldb_private
|
||||
typedef bool (*BreakpointHitCallback) (void *baton, StoppointCallbackContext *context, lldb::user_id_t break_id, lldb::user_id_t break_loc_id);
|
||||
typedef bool (*WatchpointHitCallback) (void *baton, StoppointCallbackContext *context, lldb::user_id_t watch_id, uint32_t type);
|
||||
typedef ThreadPlan * (*ThreadPlanShouldStopHereCallback) (ThreadPlan *current_plan, Flags &flags, void *baton);
|
||||
typedef UnwindAssemblyProfiler* (*UnwindAssemblyProfilerCreateInstance) (const ArchSpec &arch);
|
||||
typedef ArchDefaultUnwindPlan* (*ArchDefaultUnwindPlanCreateInstance) (const ArchSpec &arch);
|
||||
} // namespace lldb_private
|
||||
|
||||
#endif // #if defined(__cplusplus)
|
||||
|
@ -107,7 +107,6 @@ namespace lldb {
|
||||
uint32_t byte_offset; // The byte offset in the register context data where this register's value is found
|
||||
lldb::Encoding encoding; // Encoding of the register bits
|
||||
lldb::Format format; // Default display format
|
||||
uint32_t reg; // The native register number for this register
|
||||
uint32_t kinds[kNumRegisterKinds]; // Holds all of the various register numbers for all register kinds
|
||||
} RegisterInfo;
|
||||
|
||||
|
@ -354,6 +354,15 @@
|
||||
69A01E241236C5D400C660B5 /* Mutex.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 69A01E1E1236C5D400C660B5 /* Mutex.cpp */; };
|
||||
69A01E251236C5D400C660B5 /* Symbols.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 69A01E1F1236C5D400C660B5 /* Symbols.cpp */; };
|
||||
69A01E261236C5D400C660B5 /* TimeValue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 69A01E201236C5D400C660B5 /* TimeValue.cpp */; };
|
||||
961FABBB1235DE1600F93A47 /* FuncUnwinders.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 961FABB81235DE1600F93A47 /* FuncUnwinders.cpp */; };
|
||||
961FABBC1235DE1600F93A47 /* UnwindPlan.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 961FABB91235DE1600F93A47 /* UnwindPlan.cpp */; };
|
||||
961FABBD1235DE1600F93A47 /* UnwindTable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 961FABBA1235DE1600F93A47 /* UnwindTable.cpp */; };
|
||||
961FABE51235F15900F93A47 /* UnwindAssemblyProfiler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 961FABE41235F15900F93A47 /* UnwindAssemblyProfiler.cpp */; };
|
||||
961FABEA1235F26800F93A47 /* UnwindAssemblyProfiler-x86.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 961FABE81235F26800F93A47 /* UnwindAssemblyProfiler-x86.cpp */; };
|
||||
961FABEB1235F26800F93A47 /* UnwindAssemblyProfiler-x86.h in Headers */ = {isa = PBXBuildFile; fileRef = 961FABE91235F26800F93A47 /* UnwindAssemblyProfiler-x86.h */; };
|
||||
961FAC19123605A200F93A47 /* ArchDefaultUnwindPlan.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 961FAC18123605A200F93A47 /* ArchDefaultUnwindPlan.cpp */; };
|
||||
961FAC1E12360C7D00F93A47 /* ArchDefaultUnwindPlan-x86.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 961FAC1C12360C7D00F93A47 /* ArchDefaultUnwindPlan-x86.cpp */; };
|
||||
961FAC1F12360C7D00F93A47 /* ArchDefaultUnwindPlan-x86.h in Headers */ = {isa = PBXBuildFile; fileRef = 961FAC1D12360C7D00F93A47 /* ArchDefaultUnwindPlan-x86.h */; };
|
||||
9A19A6AF1163BBB200E0D453 /* SBValue.h in Headers */ = {isa = PBXBuildFile; fileRef = 9A19A6A51163BB7E00E0D453 /* SBValue.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
9A19A6B01163BBB300E0D453 /* SBValue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9A19A6AD1163BB9800E0D453 /* SBValue.cpp */; };
|
||||
9A357583116CFDEE00E8ED2F /* SBValueList.h in Headers */ = {isa = PBXBuildFile; fileRef = 9A357582116CFDEE00E8ED2F /* SBValueList.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
@ -967,6 +976,15 @@
|
||||
69A01E1E1236C5D400C660B5 /* Mutex.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Mutex.cpp; sourceTree = "<group>"; };
|
||||
69A01E1F1236C5D400C660B5 /* Symbols.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Symbols.cpp; sourceTree = "<group>"; };
|
||||
69A01E201236C5D400C660B5 /* TimeValue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TimeValue.cpp; sourceTree = "<group>"; };
|
||||
961FABB81235DE1600F93A47 /* FuncUnwinders.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FuncUnwinders.cpp; path = source/Symbol/FuncUnwinders.cpp; sourceTree = "<group>"; };
|
||||
961FABB91235DE1600F93A47 /* UnwindPlan.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = UnwindPlan.cpp; path = source/Symbol/UnwindPlan.cpp; sourceTree = "<group>"; };
|
||||
961FABBA1235DE1600F93A47 /* UnwindTable.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = UnwindTable.cpp; path = source/Symbol/UnwindTable.cpp; sourceTree = "<group>"; };
|
||||
961FABE41235F15900F93A47 /* UnwindAssemblyProfiler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = UnwindAssemblyProfiler.cpp; path = source/Utility/UnwindAssemblyProfiler.cpp; sourceTree = "<group>"; };
|
||||
961FABE81235F26800F93A47 /* UnwindAssemblyProfiler-x86.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "UnwindAssemblyProfiler-x86.cpp"; path = "Utility/UnwindAssemblyProfiler-x86.cpp"; sourceTree = "<group>"; };
|
||||
961FABE91235F26800F93A47 /* UnwindAssemblyProfiler-x86.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "UnwindAssemblyProfiler-x86.h"; path = "Utility/UnwindAssemblyProfiler-x86.h"; sourceTree = "<group>"; };
|
||||
961FAC18123605A200F93A47 /* ArchDefaultUnwindPlan.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ArchDefaultUnwindPlan.cpp; path = source/Utility/ArchDefaultUnwindPlan.cpp; sourceTree = "<group>"; };
|
||||
961FAC1C12360C7D00F93A47 /* ArchDefaultUnwindPlan-x86.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = "ArchDefaultUnwindPlan-x86.cpp"; path = "Utility/ArchDefaultUnwindPlan-x86.cpp"; sourceTree = "<group>"; };
|
||||
961FAC1D12360C7D00F93A47 /* ArchDefaultUnwindPlan-x86.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "ArchDefaultUnwindPlan-x86.h"; path = "Utility/ArchDefaultUnwindPlan-x86.h"; sourceTree = "<group>"; };
|
||||
9654F79C1197DA1300F72B43 /* MacOSXLibunwindCallbacks.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MacOSXLibunwindCallbacks.cpp; path = Utility/MacOSXLibunwindCallbacks.cpp; sourceTree = "<group>"; };
|
||||
9654F79D1197DA1300F72B43 /* MacOSXLibunwindCallbacks.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MacOSXLibunwindCallbacks.h; path = Utility/MacOSXLibunwindCallbacks.h; sourceTree = "<group>"; };
|
||||
9654F7A11197DA3F00F72B43 /* libunwind.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = libunwind.h; sourceTree = "<group>"; };
|
||||
@ -1520,6 +1538,8 @@
|
||||
2682F168115ED9C800CCFF99 /* Utility */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
961FAC18123605A200F93A47 /* ArchDefaultUnwindPlan.cpp */,
|
||||
961FABE41235F15900F93A47 /* UnwindAssemblyProfiler.cpp */,
|
||||
264723A511FA076E00DE380C /* CleanUp.h */,
|
||||
261B5A5211C3F2AD00AABD0A /* SharingPtr.cpp */,
|
||||
261B5A5311C3F2AD00AABD0A /* SharingPtr.h */,
|
||||
@ -1547,6 +1567,10 @@
|
||||
26B4666E11A2080F00CF6220 /* Utility */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
961FAC1C12360C7D00F93A47 /* ArchDefaultUnwindPlan-x86.cpp */,
|
||||
961FAC1D12360C7D00F93A47 /* ArchDefaultUnwindPlan-x86.h */,
|
||||
961FABE81235F26800F93A47 /* UnwindAssemblyProfiler-x86.cpp */,
|
||||
961FABE91235F26800F93A47 /* UnwindAssemblyProfiler-x86.h */,
|
||||
9654F79F1197DA3F00F72B43 /* libunwind */,
|
||||
26B4667011A2091600CF6220 /* LibUnwindRegisterContext.h */,
|
||||
26B4666F11A2091600CF6220 /* LibUnwindRegisterContext.cpp */,
|
||||
@ -1690,6 +1714,9 @@
|
||||
26BC7C4B10F1B6C100F91463 /* Symbol */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
961FABB81235DE1600F93A47 /* FuncUnwinders.cpp */,
|
||||
961FABB91235DE1600F93A47 /* UnwindPlan.cpp */,
|
||||
961FABBA1235DE1600F93A47 /* UnwindTable.cpp */,
|
||||
26BC7C5510F1B6E900F91463 /* Block.h */,
|
||||
26BC7F1310F1B8EC00F91463 /* Block.cpp */,
|
||||
26BC7C5610F1B6E900F91463 /* ClangASTContext.h */,
|
||||
@ -2235,6 +2262,8 @@
|
||||
4911934C1226383D00578B7F /* ASTStructExtractor.h in Headers */,
|
||||
497C86C2122823F300B54702 /* ClangUtilityFunction.h in Headers */,
|
||||
49CF9834122C718B007A0B96 /* IRDynamicChecks.h in Headers */,
|
||||
961FABEB1235F26800F93A47 /* UnwindAssemblyProfiler-x86.h in Headers */,
|
||||
961FAC1F12360C7D00F93A47 /* ArchDefaultUnwindPlan-x86.h in Headers */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@ -2685,6 +2714,13 @@
|
||||
491193521226386000578B7F /* ASTStructExtractor.cpp in Sources */,
|
||||
497C86BE122823D800B54702 /* ClangUtilityFunction.cpp in Sources */,
|
||||
49CF982A122C70BD007A0B96 /* IRDynamicChecks.cpp in Sources */,
|
||||
961FABBB1235DE1600F93A47 /* FuncUnwinders.cpp in Sources */,
|
||||
961FABBC1235DE1600F93A47 /* UnwindPlan.cpp in Sources */,
|
||||
961FABBD1235DE1600F93A47 /* UnwindTable.cpp in Sources */,
|
||||
961FABE51235F15900F93A47 /* UnwindAssemblyProfiler.cpp in Sources */,
|
||||
961FABEA1235F26800F93A47 /* UnwindAssemblyProfiler-x86.cpp in Sources */,
|
||||
961FAC19123605A200F93A47 /* ArchDefaultUnwindPlan.cpp in Sources */,
|
||||
961FAC1E12360C7D00F93A47 /* ArchDefaultUnwindPlan-x86.cpp in Sources */,
|
||||
69A01E211236C5D400C660B5 /* Condition.cpp in Sources */,
|
||||
69A01E221236C5D400C660B5 /* Host.cpp in Sources */,
|
||||
69A01E241236C5D400C660B5 /* Mutex.cpp in Sources */,
|
||||
|
@ -106,7 +106,7 @@ public:
|
||||
if (reg_info)
|
||||
{
|
||||
output_stream.Printf("%-12s = ", reg_info->name);
|
||||
if (reg_context->ReadRegisterBytes(reg_info->reg, reg_data))
|
||||
if (reg_context->ReadRegisterBytes(reg_info->kinds[eRegisterKindLLDB], reg_data))
|
||||
{
|
||||
reg_data.Dump(&output_stream, 0, reg_info->format, reg_info->byte_size, 1, UINT32_MAX, LLDB_INVALID_ADDRESS, 0, 0);
|
||||
}
|
||||
@ -183,7 +183,7 @@ public:
|
||||
Error error(scalar.SetValueFromCString (value_str, reg_info->encoding, reg_info->byte_size));
|
||||
if (error.Success())
|
||||
{
|
||||
if (reg_context->WriteRegisterValue(reg_info->reg, scalar))
|
||||
if (reg_context->WriteRegisterValue(reg_info->kinds[eRegisterKindLLDB], scalar))
|
||||
{
|
||||
result.SetStatus (eReturnStatusSuccessFinishNoResult);
|
||||
return true;
|
||||
|
@ -1131,3 +1131,244 @@ PluginManager::GetSymbolVendorCreateCallbackForPluginName (const char *name)
|
||||
}
|
||||
|
||||
|
||||
#pragma mark UnwindAssemblyProfiler
|
||||
|
||||
struct UnwindAssemblyProfilerInstance
|
||||
{
|
||||
UnwindAssemblyProfilerInstance() :
|
||||
name(),
|
||||
description(),
|
||||
create_callback(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
std::string name;
|
||||
std::string description;
|
||||
UnwindAssemblyProfilerCreateInstance create_callback;
|
||||
};
|
||||
|
||||
typedef std::vector<UnwindAssemblyProfilerInstance> UnwindAssemblyProfilerInstances;
|
||||
|
||||
static bool
|
||||
AccessUnwindAssemblyProfilerInstances (PluginAction action, UnwindAssemblyProfilerInstance &instance, uint32_t index)
|
||||
{
|
||||
static UnwindAssemblyProfilerInstances g_plugin_instances;
|
||||
|
||||
switch (action)
|
||||
{
|
||||
case ePluginRegisterInstance:
|
||||
if (instance.create_callback)
|
||||
{
|
||||
g_plugin_instances.push_back (instance);
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
|
||||
case ePluginUnregisterInstance:
|
||||
if (instance.create_callback)
|
||||
{
|
||||
UnwindAssemblyProfilerInstances::iterator pos, end = g_plugin_instances.end();
|
||||
for (pos = g_plugin_instances.begin(); pos != end; ++ pos)
|
||||
{
|
||||
if (pos->create_callback == instance.create_callback)
|
||||
{
|
||||
g_plugin_instances.erase(pos);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case ePluginGetInstanceAtIndex:
|
||||
if (index < g_plugin_instances.size())
|
||||
{
|
||||
instance = g_plugin_instances[index];
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
PluginManager::RegisterPlugin
|
||||
(
|
||||
const char *name,
|
||||
const char *description,
|
||||
UnwindAssemblyProfilerCreateInstance create_callback
|
||||
)
|
||||
{
|
||||
if (create_callback)
|
||||
{
|
||||
UnwindAssemblyProfilerInstance instance;
|
||||
assert (name && name[0]);
|
||||
instance.name = name;
|
||||
if (description && description[0])
|
||||
instance.description = description;
|
||||
instance.create_callback = create_callback;
|
||||
return AccessUnwindAssemblyProfilerInstances (ePluginRegisterInstance, instance, 0);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
PluginManager::UnregisterPlugin (UnwindAssemblyProfilerCreateInstance create_callback)
|
||||
{
|
||||
if (create_callback)
|
||||
{
|
||||
UnwindAssemblyProfilerInstance instance;
|
||||
instance.create_callback = create_callback;
|
||||
return AccessUnwindAssemblyProfilerInstances (ePluginUnregisterInstance, instance, 0);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
UnwindAssemblyProfilerCreateInstance
|
||||
PluginManager::GetUnwindAssemblyProfilerCreateCallbackAtIndex (uint32_t idx)
|
||||
{
|
||||
UnwindAssemblyProfilerInstance instance;
|
||||
if (AccessUnwindAssemblyProfilerInstances (ePluginGetInstanceAtIndex, instance, idx))
|
||||
return instance.create_callback;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
UnwindAssemblyProfilerCreateInstance
|
||||
PluginManager::GetUnwindAssemblyProfilerCreateCallbackForPluginName (const char *name)
|
||||
{
|
||||
if (name && name[0])
|
||||
{
|
||||
UnwindAssemblyProfilerInstance instance;
|
||||
std::string ss_name(name);
|
||||
for (uint32_t idx = 0; AccessUnwindAssemblyProfilerInstances (ePluginGetInstanceAtIndex, instance, idx); ++idx)
|
||||
{
|
||||
if (instance.name == ss_name)
|
||||
return instance.create_callback;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#pragma mark ArchDefaultUnwindPlan
|
||||
|
||||
struct ArchDefaultUnwindPlanInstance
|
||||
{
|
||||
ArchDefaultUnwindPlanInstance() :
|
||||
name(),
|
||||
description(),
|
||||
create_callback(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
std::string name;
|
||||
std::string description;
|
||||
ArchDefaultUnwindPlanCreateInstance create_callback;
|
||||
};
|
||||
|
||||
typedef std::vector<ArchDefaultUnwindPlanInstance> ArchDefaultUnwindPlanInstances;
|
||||
|
||||
static bool
|
||||
AccessArchDefaultUnwindPlanInstances (PluginAction action, ArchDefaultUnwindPlanInstance &instance, uint32_t index)
|
||||
{
|
||||
static ArchDefaultUnwindPlanInstances g_plugin_instances;
|
||||
|
||||
switch (action)
|
||||
{
|
||||
case ePluginRegisterInstance:
|
||||
if (instance.create_callback)
|
||||
{
|
||||
g_plugin_instances.push_back (instance);
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
|
||||
case ePluginUnregisterInstance:
|
||||
if (instance.create_callback)
|
||||
{
|
||||
ArchDefaultUnwindPlanInstances::iterator pos, end = g_plugin_instances.end();
|
||||
for (pos = g_plugin_instances.begin(); pos != end; ++ pos)
|
||||
{
|
||||
if (pos->create_callback == instance.create_callback)
|
||||
{
|
||||
g_plugin_instances.erase(pos);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case ePluginGetInstanceAtIndex:
|
||||
if (index < g_plugin_instances.size())
|
||||
{
|
||||
instance = g_plugin_instances[index];
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
PluginManager::RegisterPlugin
|
||||
(
|
||||
const char *name,
|
||||
const char *description,
|
||||
ArchDefaultUnwindPlanCreateInstance create_callback
|
||||
)
|
||||
{
|
||||
if (create_callback)
|
||||
{
|
||||
ArchDefaultUnwindPlanInstance instance;
|
||||
assert (name && name[0]);
|
||||
instance.name = name;
|
||||
if (description && description[0])
|
||||
instance.description = description;
|
||||
instance.create_callback = create_callback;
|
||||
return AccessArchDefaultUnwindPlanInstances (ePluginRegisterInstance, instance, 0);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
PluginManager::UnregisterPlugin (ArchDefaultUnwindPlanCreateInstance create_callback)
|
||||
{
|
||||
if (create_callback)
|
||||
{
|
||||
ArchDefaultUnwindPlanInstance instance;
|
||||
instance.create_callback = create_callback;
|
||||
return AccessArchDefaultUnwindPlanInstances (ePluginUnregisterInstance, instance, 0);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
ArchDefaultUnwindPlanCreateInstance
|
||||
PluginManager::GetArchDefaultUnwindPlanCreateCallbackAtIndex (uint32_t idx)
|
||||
{
|
||||
ArchDefaultUnwindPlanInstance instance;
|
||||
if (AccessArchDefaultUnwindPlanInstances (ePluginGetInstanceAtIndex, instance, idx))
|
||||
return instance.create_callback;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ArchDefaultUnwindPlanCreateInstance
|
||||
PluginManager::GetArchDefaultUnwindPlanCreateCallbackForPluginName (const char *name)
|
||||
{
|
||||
if (name && name[0])
|
||||
{
|
||||
ArchDefaultUnwindPlanInstance instance;
|
||||
std::string ss_name(name);
|
||||
for (uint32_t idx = 0; AccessArchDefaultUnwindPlanInstances (ePluginGetInstanceAtIndex, instance, idx); ++idx)
|
||||
{
|
||||
if (instance.name == ss_name)
|
||||
return instance.create_callback;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
@ -11,6 +11,7 @@
|
||||
|
||||
// C Includes
|
||||
#include <dirent.h>
|
||||
#include <mach/machine.h>
|
||||
#include "llvm/Support/MachO.h"
|
||||
|
||||
// C++ Includes
|
||||
|
@ -472,8 +472,8 @@ ABIMacOSX_i386::GetReturnValue (Thread &thread,
|
||||
{
|
||||
size_t bit_width = ClangASTType::GetClangTypeBitWidth(ast_context, value_type);
|
||||
|
||||
unsigned eax_id = reg_ctx->GetRegisterInfoByName("eax", 0)->reg;
|
||||
unsigned edx_id = reg_ctx->GetRegisterInfoByName("edx", 0)->reg;
|
||||
unsigned eax_id = reg_ctx->GetRegisterInfoByName("eax", 0)->kinds[eRegisterKindLLDB];
|
||||
unsigned edx_id = reg_ctx->GetRegisterInfoByName("edx", 0)->kinds[eRegisterKindLLDB];
|
||||
|
||||
switch (bit_width)
|
||||
{
|
||||
@ -512,7 +512,7 @@ ABIMacOSX_i386::GetReturnValue (Thread &thread,
|
||||
}
|
||||
else if (ClangASTContext::IsPointerType (value_type))
|
||||
{
|
||||
unsigned eax_id = reg_ctx->GetRegisterInfoByName("eax", 0)->reg;
|
||||
unsigned eax_id = reg_ctx->GetRegisterInfoByName("eax", 0)->kinds[eRegisterKindLLDB];
|
||||
uint32_t ptr = thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xffffffff;
|
||||
value.GetScalar() = ptr;
|
||||
}
|
||||
|
@ -63,7 +63,7 @@ ABISysV_x86_64::PrepareTrivialCall (Thread &thread,
|
||||
if (!reg_ctx)
|
||||
return false;
|
||||
|
||||
uint32_t rdiID = reg_ctx->GetRegisterInfoByName("rdi", 0)->reg;
|
||||
uint32_t rdiID = reg_ctx->GetRegisterInfoByName("rdi", 0)->kinds[eRegisterKindLLDB];
|
||||
#define CHAIN_RBP
|
||||
|
||||
#ifndef CHAIN_RBP
|
||||
@ -226,12 +226,12 @@ ABISysV_x86_64::GetArgumentValues (Thread &thread,
|
||||
|
||||
uint32_t argument_register_ids[6];
|
||||
|
||||
argument_register_ids[0] = reg_ctx->GetRegisterInfoByName("rdi", 0)->reg;
|
||||
argument_register_ids[1] = reg_ctx->GetRegisterInfoByName("rsi", 0)->reg;
|
||||
argument_register_ids[2] = reg_ctx->GetRegisterInfoByName("rdx", 0)->reg;
|
||||
argument_register_ids[3] = reg_ctx->GetRegisterInfoByName("rcx", 0)->reg;
|
||||
argument_register_ids[4] = reg_ctx->GetRegisterInfoByName("r8", 0)->reg;
|
||||
argument_register_ids[5] = reg_ctx->GetRegisterInfoByName("r9", 0)->reg;
|
||||
argument_register_ids[0] = reg_ctx->GetRegisterInfoByName("rdi", 0)->kinds[eRegisterKindLLDB];
|
||||
argument_register_ids[1] = reg_ctx->GetRegisterInfoByName("rsi", 0)->kinds[eRegisterKindLLDB];
|
||||
argument_register_ids[2] = reg_ctx->GetRegisterInfoByName("rdx", 0)->kinds[eRegisterKindLLDB];
|
||||
argument_register_ids[3] = reg_ctx->GetRegisterInfoByName("rcx", 0)->kinds[eRegisterKindLLDB];
|
||||
argument_register_ids[4] = reg_ctx->GetRegisterInfoByName("r8", 0)->kinds[eRegisterKindLLDB];
|
||||
argument_register_ids[5] = reg_ctx->GetRegisterInfoByName("r9", 0)->kinds[eRegisterKindLLDB];
|
||||
|
||||
unsigned int current_argument_register = 0;
|
||||
|
||||
@ -313,7 +313,7 @@ ABISysV_x86_64::GetReturnValue (Thread &thread,
|
||||
// Extract the register context so we can read arguments from registers
|
||||
|
||||
size_t bit_width = ClangASTType::GetClangTypeBitWidth(ast_context, value_type);
|
||||
unsigned rax_id = reg_ctx->GetRegisterInfoByName("rax", 0)->reg;
|
||||
unsigned rax_id = reg_ctx->GetRegisterInfoByName("rax", 0)->kinds[eRegisterKindLLDB];
|
||||
|
||||
switch (bit_width)
|
||||
{
|
||||
@ -349,7 +349,7 @@ ABISysV_x86_64::GetReturnValue (Thread &thread,
|
||||
}
|
||||
else if (ClangASTContext::IsPointerType (value_type))
|
||||
{
|
||||
unsigned rax_id = reg_ctx->GetRegisterInfoByName("rax", 0)->reg;
|
||||
unsigned rax_id = reg_ctx->GetRegisterInfoByName("rax", 0)->kinds[eRegisterKindLLDB];
|
||||
value.GetScalar() = (uint64_t)thread.GetRegisterContext()->ReadRegisterAsUnsigned(rax_id, 0);
|
||||
}
|
||||
else
|
||||
|
@ -305,23 +305,23 @@ g_reg_sets[k_num_register_sets] =
|
||||
|
||||
#define DEFINE_GPR(reg, alt, kind1, kind2, kind3, kind4) \
|
||||
{ #reg, alt, GPR_SIZE(reg), GPR_OFFSET(reg), eEncodingUint, \
|
||||
eFormatHex, gpr_##reg, { kind1, kind2, kind3, kind4 } }
|
||||
eFormatHex, { kind1, kind2, kind3, kind4, gpr_##reg } }
|
||||
|
||||
#define DEFINE_FPR(reg, kind1, kind2, kind3, kind4) \
|
||||
{ #reg, NULL, FPR_SIZE(reg), FPR_OFFSET(reg), eEncodingUint, \
|
||||
eFormatHex, fpu_##reg, { kind1, kind2, kind3, kind4 } }
|
||||
eFormatHex, { kind1, kind2, kind3, kind4, fpu_##reg } }
|
||||
|
||||
#define DEFINE_FP(reg, i) \
|
||||
{ #reg#i, NULL, FP_SIZE, FPR_OFFSET(reg[i]), eEncodingVector, \
|
||||
eFormatVectorOfUInt8, fpu_##reg##i, \
|
||||
eFormatVectorOfUInt8, \
|
||||
{ gcc_dwarf_fpu_##reg##i, gcc_dwarf_fpu_##reg##i, \
|
||||
LLDB_INVALID_REGNUM, gdb_fpu_##reg##i } }
|
||||
LLDB_INVALID_REGNUM, gdb_fpu_##reg##i, fpu_##reg##i } }
|
||||
|
||||
#define DEFINE_XMM(reg, i) \
|
||||
{ #reg#i, NULL, XMM_SIZE, FPR_OFFSET(reg[i]), eEncodingVector, \
|
||||
eFormatVectorOfUInt8, fpu_##reg##i, \
|
||||
eFormatVectorOfUInt8, \
|
||||
{ gcc_dwarf_fpu_##reg##i, gcc_dwarf_fpu_##reg##i, \
|
||||
LLDB_INVALID_REGNUM, gdb_fpu_##reg##i } }
|
||||
LLDB_INVALID_REGNUM, gdb_fpu_##reg##i, fpu_##reg##i } }
|
||||
|
||||
static RegisterInfo
|
||||
g_register_infos[k_num_registers] =
|
||||
@ -642,6 +642,10 @@ RegisterContextLinux_x86_64::ConvertRegisterKindToRegisterNumber(uint32_t kind,
|
||||
return LLDB_INVALID_REGNUM;
|
||||
}
|
||||
}
|
||||
else if (kind == eRegisterKindLLDB)
|
||||
{
|
||||
return reg;
|
||||
}
|
||||
|
||||
return LLDB_INVALID_REGNUM;
|
||||
}
|
||||
|
@ -86,11 +86,11 @@ MachThreadContext_arm::InitializeInstance()
|
||||
const RegisterInfo * reg_info;
|
||||
reg_info = reg_ctx->GetRegisterInfoByName ("bvr0");
|
||||
if (reg_info)
|
||||
m_bvr0_reg = reg_info->reg;
|
||||
m_bvr0_reg = reg_info->kinds[eRegisterKindLLDB];
|
||||
|
||||
reg_info = reg_ctx->GetRegisterInfoByName ("bcr0");
|
||||
if (reg_info)
|
||||
m_bcr0_reg = reg_info->reg;
|
||||
m_bcr0_reg = reg_info->kinds[eRegisterKindLLDB];
|
||||
}
|
||||
|
||||
|
||||
|
@ -182,69 +182,69 @@ RegisterContextMach_arm::~RegisterContextMach_arm()
|
||||
#define EXC_OFFSET(idx) ((idx) * 4 + sizeof (RegisterContextMach_arm::GPR) + sizeof (RegisterContextMach_arm::FPU))
|
||||
#define DBG_OFFSET(reg) (offsetof (RegisterContextMach_arm::DBG, reg) + sizeof (RegisterContextMach_arm::GPR) + sizeof (RegisterContextMach_arm::FPU) + sizeof (RegisterContextMach_arm::EXC))
|
||||
|
||||
#define DEFINE_DBG(reg, i) #reg, NULL, sizeof(((RegisterContextMach_arm::DBG *)NULL)->reg[i]), DBG_OFFSET(reg[i]), eEncodingUint, eFormatHex, dbg_##reg##i, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }
|
||||
#define DEFINE_DBG(reg, i) #reg, NULL, sizeof(((RegisterContextMach_arm::DBG *)NULL)->reg[i]), DBG_OFFSET(reg[i]), eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, dbg_##reg##i }
|
||||
#define REG_CONTEXT_SIZE (sizeof (RegisterContextMach_arm::GPR) + sizeof (RegisterContextMach_arm::FPU) + sizeof (RegisterContextMach_arm::EXC))
|
||||
// General purpose registers
|
||||
static lldb::RegisterInfo
|
||||
g_register_infos[] =
|
||||
{
|
||||
// NAME ALT SZ OFFSET ENCODING FORMAT NATIVE COMPILER DWARF GENERIC
|
||||
// ====== ======= == ============= ============= ============ ========== =============== =============== =========
|
||||
{ "r0", NULL, 4, GPR_OFFSET(0), eEncodingUint, eFormatHex, gpr_r0, { gcc_r0, dwarf_r0, LLDB_INVALID_REGNUM }},
|
||||
{ "r1", NULL, 4, GPR_OFFSET(1), eEncodingUint, eFormatHex, gpr_r1, { gcc_r1, dwarf_r1, LLDB_INVALID_REGNUM }},
|
||||
{ "r2", NULL, 4, GPR_OFFSET(2), eEncodingUint, eFormatHex, gpr_r2, { gcc_r2, dwarf_r2, LLDB_INVALID_REGNUM }},
|
||||
{ "r3", NULL, 4, GPR_OFFSET(3), eEncodingUint, eFormatHex, gpr_r3, { gcc_r3, dwarf_r3, LLDB_INVALID_REGNUM }},
|
||||
{ "r4", NULL, 4, GPR_OFFSET(4), eEncodingUint, eFormatHex, gpr_r4, { gcc_r4, dwarf_r4, LLDB_INVALID_REGNUM }},
|
||||
{ "r5", NULL, 4, GPR_OFFSET(5), eEncodingUint, eFormatHex, gpr_r5, { gcc_r5, dwarf_r5, LLDB_INVALID_REGNUM }},
|
||||
{ "r6", NULL, 4, GPR_OFFSET(6), eEncodingUint, eFormatHex, gpr_r6, { gcc_r6, dwarf_r6, LLDB_INVALID_REGNUM }},
|
||||
{ "r7", NULL, 4, GPR_OFFSET(7), eEncodingUint, eFormatHex, gpr_r7, { gcc_r7, dwarf_r7, LLDB_REGNUM_GENERIC_FP }},
|
||||
{ "r8", NULL, 4, GPR_OFFSET(8), eEncodingUint, eFormatHex, gpr_r8, { gcc_r8, dwarf_r8, LLDB_INVALID_REGNUM }},
|
||||
{ "r9", NULL, 4, GPR_OFFSET(9), eEncodingUint, eFormatHex, gpr_r9, { gcc_r9, dwarf_r9, LLDB_INVALID_REGNUM }},
|
||||
{ "r10", NULL, 4, GPR_OFFSET(10), eEncodingUint, eFormatHex, gpr_r10, { gcc_r10, dwarf_r10, LLDB_INVALID_REGNUM }},
|
||||
{ "r11", NULL, 4, GPR_OFFSET(11), eEncodingUint, eFormatHex, gpr_r11, { gcc_r11, dwarf_r11, LLDB_INVALID_REGNUM }},
|
||||
{ "r12", NULL, 4, GPR_OFFSET(12), eEncodingUint, eFormatHex, gpr_r12, { gcc_r12, dwarf_r12, LLDB_INVALID_REGNUM }},
|
||||
{ "sp", "r13", 4, GPR_OFFSET(13), eEncodingUint, eFormatHex, gpr_sp, { gcc_sp, dwarf_sp, LLDB_REGNUM_GENERIC_SP }},
|
||||
{ "lr", "r14", 4, GPR_OFFSET(14), eEncodingUint, eFormatHex, gpr_lr, { gcc_lr, dwarf_lr, LLDB_REGNUM_GENERIC_RA }},
|
||||
{ "pc", "r15", 4, GPR_OFFSET(15), eEncodingUint, eFormatHex, gpr_pc, { gcc_pc, dwarf_pc, LLDB_REGNUM_GENERIC_PC }},
|
||||
{ "cpsr", "psr", 4, GPR_OFFSET(16), eEncodingUint, eFormatHex, gpr_cpsr, { gcc_cpsr, dwarf_cpsr, LLDB_REGNUM_GENERIC_FLAGS }},
|
||||
// NAME ALT SZ OFFSET ENCODING FORMAT COMPILER DWARF GENERIC LLDB NATIVE
|
||||
// ====== ======= == ============= ============= ============ =============== =============== ========= ==========
|
||||
{ "r0", NULL, 4, GPR_OFFSET(0), eEncodingUint, eFormatHex, { gcc_r0, dwarf_r0, LLDB_INVALID_REGNUM, gpr_r0 }},
|
||||
{ "r1", NULL, 4, GPR_OFFSET(1), eEncodingUint, eFormatHex, { gcc_r1, dwarf_r1, LLDB_INVALID_REGNUM, gpr_r1 }},
|
||||
{ "r2", NULL, 4, GPR_OFFSET(2), eEncodingUint, eFormatHex, { gcc_r2, dwarf_r2, LLDB_INVALID_REGNUM, gpr_r2 }},
|
||||
{ "r3", NULL, 4, GPR_OFFSET(3), eEncodingUint, eFormatHex, { gcc_r3, dwarf_r3, LLDB_INVALID_REGNUM, gpr_r3 }},
|
||||
{ "r4", NULL, 4, GPR_OFFSET(4), eEncodingUint, eFormatHex, { gcc_r4, dwarf_r4, LLDB_INVALID_REGNUM, gpr_r4 }},
|
||||
{ "r5", NULL, 4, GPR_OFFSET(5), eEncodingUint, eFormatHex, { gcc_r5, dwarf_r5, LLDB_INVALID_REGNUM, gpr_r5 }},
|
||||
{ "r6", NULL, 4, GPR_OFFSET(6), eEncodingUint, eFormatHex, { gcc_r6, dwarf_r6, LLDB_INVALID_REGNUM, gpr_r6 }},
|
||||
{ "r7", NULL, 4, GPR_OFFSET(7), eEncodingUint, eFormatHex, { gcc_r7, dwarf_r7, LLDB_REGNUM_GENERIC_FP, gpr_r7 }},
|
||||
{ "r8", NULL, 4, GPR_OFFSET(8), eEncodingUint, eFormatHex, { gcc_r8, dwarf_r8, LLDB_INVALID_REGNUM, gpr_r8 }},
|
||||
{ "r9", NULL, 4, GPR_OFFSET(9), eEncodingUint, eFormatHex, { gcc_r9, dwarf_r9, LLDB_INVALID_REGNUM, gpr_r9 }},
|
||||
{ "r10", NULL, 4, GPR_OFFSET(10), eEncodingUint, eFormatHex, { gcc_r10, dwarf_r10, LLDB_INVALID_REGNUM, gpr_r10 }},
|
||||
{ "r11", NULL, 4, GPR_OFFSET(11), eEncodingUint, eFormatHex, { gcc_r11, dwarf_r11, LLDB_INVALID_REGNUM, gpr_r11 }},
|
||||
{ "r12", NULL, 4, GPR_OFFSET(12), eEncodingUint, eFormatHex, { gcc_r12, dwarf_r12, LLDB_INVALID_REGNUM, gpr_r12 }},
|
||||
{ "sp", "r13", 4, GPR_OFFSET(13), eEncodingUint, eFormatHex, { gcc_sp, dwarf_sp, LLDB_REGNUM_GENERIC_SP, gpr_sp }},
|
||||
{ "lr", "r14", 4, GPR_OFFSET(14), eEncodingUint, eFormatHex, { gcc_lr, dwarf_lr, LLDB_REGNUM_GENERIC_RA, gpr_lr }},
|
||||
{ "pc", "r15", 4, GPR_OFFSET(15), eEncodingUint, eFormatHex, { gcc_pc, dwarf_pc, LLDB_REGNUM_GENERIC_PC, gpr_pc }},
|
||||
{ "cpsr", "psr", 4, GPR_OFFSET(16), eEncodingUint, eFormatHex, { gcc_cpsr, dwarf_cpsr, LLDB_REGNUM_GENERIC_FLAGS, gpr_cpsr }},
|
||||
|
||||
{ "s0", NULL, 4, FPU_OFFSET(0), eEncodingIEEE754,eFormatFloat, fpu_s0, { LLDB_INVALID_REGNUM, dwarf_s0, LLDB_INVALID_REGNUM }},
|
||||
{ "s1", NULL, 4, FPU_OFFSET(1), eEncodingIEEE754,eFormatFloat, fpu_s1, { LLDB_INVALID_REGNUM, dwarf_s1, LLDB_INVALID_REGNUM }},
|
||||
{ "s2", NULL, 4, FPU_OFFSET(2), eEncodingIEEE754,eFormatFloat, fpu_s2, { LLDB_INVALID_REGNUM, dwarf_s2, LLDB_INVALID_REGNUM }},
|
||||
{ "s3", NULL, 4, FPU_OFFSET(3), eEncodingIEEE754,eFormatFloat, fpu_s3, { LLDB_INVALID_REGNUM, dwarf_s3, LLDB_INVALID_REGNUM }},
|
||||
{ "s4", NULL, 4, FPU_OFFSET(4), eEncodingIEEE754,eFormatFloat, fpu_s4, { LLDB_INVALID_REGNUM, dwarf_s4, LLDB_INVALID_REGNUM }},
|
||||
{ "s5", NULL, 4, FPU_OFFSET(5), eEncodingIEEE754,eFormatFloat, fpu_s5, { LLDB_INVALID_REGNUM, dwarf_s5, LLDB_INVALID_REGNUM }},
|
||||
{ "s6", NULL, 4, FPU_OFFSET(6), eEncodingIEEE754,eFormatFloat, fpu_s6, { LLDB_INVALID_REGNUM, dwarf_s6, LLDB_INVALID_REGNUM }},
|
||||
{ "s7", NULL, 4, FPU_OFFSET(7), eEncodingIEEE754,eFormatFloat, fpu_s7, { LLDB_INVALID_REGNUM, dwarf_s7, LLDB_INVALID_REGNUM }},
|
||||
{ "s8", NULL, 4, FPU_OFFSET(8), eEncodingIEEE754,eFormatFloat, fpu_s8, { LLDB_INVALID_REGNUM, dwarf_s8, LLDB_INVALID_REGNUM }},
|
||||
{ "s9", NULL, 4, FPU_OFFSET(9), eEncodingIEEE754,eFormatFloat, fpu_s9, { LLDB_INVALID_REGNUM, dwarf_s9, LLDB_INVALID_REGNUM }},
|
||||
{ "s10", NULL, 4, FPU_OFFSET(10), eEncodingIEEE754,eFormatFloat, fpu_s10, { LLDB_INVALID_REGNUM, dwarf_s10, LLDB_INVALID_REGNUM }},
|
||||
{ "s11", NULL, 4, FPU_OFFSET(11), eEncodingIEEE754,eFormatFloat, fpu_s11, { LLDB_INVALID_REGNUM, dwarf_s11, LLDB_INVALID_REGNUM }},
|
||||
{ "s12", NULL, 4, FPU_OFFSET(12), eEncodingIEEE754,eFormatFloat, fpu_s12, { LLDB_INVALID_REGNUM, dwarf_s12, LLDB_INVALID_REGNUM }},
|
||||
{ "s13", NULL, 4, FPU_OFFSET(13), eEncodingIEEE754,eFormatFloat, fpu_s13, { LLDB_INVALID_REGNUM, dwarf_s13, LLDB_INVALID_REGNUM }},
|
||||
{ "s14", NULL, 4, FPU_OFFSET(14), eEncodingIEEE754,eFormatFloat, fpu_s14, { LLDB_INVALID_REGNUM, dwarf_s14, LLDB_INVALID_REGNUM }},
|
||||
{ "s15", NULL, 4, FPU_OFFSET(15), eEncodingIEEE754,eFormatFloat, fpu_s15, { LLDB_INVALID_REGNUM, dwarf_s15, LLDB_INVALID_REGNUM }},
|
||||
{ "s16", NULL, 4, FPU_OFFSET(16), eEncodingIEEE754,eFormatFloat, fpu_s16, { LLDB_INVALID_REGNUM, dwarf_s16, LLDB_INVALID_REGNUM }},
|
||||
{ "s17", NULL, 4, FPU_OFFSET(17), eEncodingIEEE754,eFormatFloat, fpu_s17, { LLDB_INVALID_REGNUM, dwarf_s17, LLDB_INVALID_REGNUM }},
|
||||
{ "s18", NULL, 4, FPU_OFFSET(18), eEncodingIEEE754,eFormatFloat, fpu_s18, { LLDB_INVALID_REGNUM, dwarf_s18, LLDB_INVALID_REGNUM }},
|
||||
{ "s19", NULL, 4, FPU_OFFSET(19), eEncodingIEEE754,eFormatFloat, fpu_s19, { LLDB_INVALID_REGNUM, dwarf_s19, LLDB_INVALID_REGNUM }},
|
||||
{ "s20", NULL, 4, FPU_OFFSET(20), eEncodingIEEE754,eFormatFloat, fpu_s20, { LLDB_INVALID_REGNUM, dwarf_s20, LLDB_INVALID_REGNUM }},
|
||||
{ "s21", NULL, 4, FPU_OFFSET(21), eEncodingIEEE754,eFormatFloat, fpu_s21, { LLDB_INVALID_REGNUM, dwarf_s21, LLDB_INVALID_REGNUM }},
|
||||
{ "s22", NULL, 4, FPU_OFFSET(22), eEncodingIEEE754,eFormatFloat, fpu_s22, { LLDB_INVALID_REGNUM, dwarf_s22, LLDB_INVALID_REGNUM }},
|
||||
{ "s23", NULL, 4, FPU_OFFSET(23), eEncodingIEEE754,eFormatFloat, fpu_s23, { LLDB_INVALID_REGNUM, dwarf_s23, LLDB_INVALID_REGNUM }},
|
||||
{ "s24", NULL, 4, FPU_OFFSET(24), eEncodingIEEE754,eFormatFloat, fpu_s24, { LLDB_INVALID_REGNUM, dwarf_s24, LLDB_INVALID_REGNUM }},
|
||||
{ "s25", NULL, 4, FPU_OFFSET(25), eEncodingIEEE754,eFormatFloat, fpu_s25, { LLDB_INVALID_REGNUM, dwarf_s25, LLDB_INVALID_REGNUM }},
|
||||
{ "s26", NULL, 4, FPU_OFFSET(26), eEncodingIEEE754,eFormatFloat, fpu_s26, { LLDB_INVALID_REGNUM, dwarf_s26, LLDB_INVALID_REGNUM }},
|
||||
{ "s27", NULL, 4, FPU_OFFSET(27), eEncodingIEEE754,eFormatFloat, fpu_s27, { LLDB_INVALID_REGNUM, dwarf_s27, LLDB_INVALID_REGNUM }},
|
||||
{ "s28", NULL, 4, FPU_OFFSET(28), eEncodingIEEE754,eFormatFloat, fpu_s28, { LLDB_INVALID_REGNUM, dwarf_s28, LLDB_INVALID_REGNUM }},
|
||||
{ "s29", NULL, 4, FPU_OFFSET(29), eEncodingIEEE754,eFormatFloat, fpu_s29, { LLDB_INVALID_REGNUM, dwarf_s29, LLDB_INVALID_REGNUM }},
|
||||
{ "s30", NULL, 4, FPU_OFFSET(30), eEncodingIEEE754,eFormatFloat, fpu_s30, { LLDB_INVALID_REGNUM, dwarf_s30, LLDB_INVALID_REGNUM }},
|
||||
{ "s31", NULL, 4, FPU_OFFSET(31), eEncodingIEEE754,eFormatFloat, fpu_s31, { LLDB_INVALID_REGNUM, dwarf_s31, LLDB_INVALID_REGNUM }},
|
||||
{ "fpscr", NULL, 4, FPU_OFFSET(32), eEncodingUint, eFormatHex, fpu_fpscr, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }},
|
||||
{ "s0", NULL, 4, FPU_OFFSET(0), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s0, LLDB_INVALID_REGNUM, fpu_s0 }},
|
||||
{ "s1", NULL, 4, FPU_OFFSET(1), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s1, LLDB_INVALID_REGNUM, fpu_s1 }},
|
||||
{ "s2", NULL, 4, FPU_OFFSET(2), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s2, LLDB_INVALID_REGNUM, fpu_s2 }},
|
||||
{ "s3", NULL, 4, FPU_OFFSET(3), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s3, LLDB_INVALID_REGNUM, fpu_s3 }},
|
||||
{ "s4", NULL, 4, FPU_OFFSET(4), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s4, LLDB_INVALID_REGNUM, fpu_s4 }},
|
||||
{ "s5", NULL, 4, FPU_OFFSET(5), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s5, LLDB_INVALID_REGNUM, fpu_s5 }},
|
||||
{ "s6", NULL, 4, FPU_OFFSET(6), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s6, LLDB_INVALID_REGNUM, fpu_s6 }},
|
||||
{ "s7", NULL, 4, FPU_OFFSET(7), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s7, LLDB_INVALID_REGNUM, fpu_s7 }},
|
||||
{ "s8", NULL, 4, FPU_OFFSET(8), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s8, LLDB_INVALID_REGNUM, fpu_s8 }},
|
||||
{ "s9", NULL, 4, FPU_OFFSET(9), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s9, LLDB_INVALID_REGNUM, fpu_s9 }},
|
||||
{ "s10", NULL, 4, FPU_OFFSET(10), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s10, LLDB_INVALID_REGNUM, fpu_s10 }},
|
||||
{ "s11", NULL, 4, FPU_OFFSET(11), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s11, LLDB_INVALID_REGNUM, fpu_s11 }},
|
||||
{ "s12", NULL, 4, FPU_OFFSET(12), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s12, LLDB_INVALID_REGNUM, fpu_s12 }},
|
||||
{ "s13", NULL, 4, FPU_OFFSET(13), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s13, LLDB_INVALID_REGNUM, fpu_s13 }},
|
||||
{ "s14", NULL, 4, FPU_OFFSET(14), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s14, LLDB_INVALID_REGNUM, fpu_s14 }},
|
||||
{ "s15", NULL, 4, FPU_OFFSET(15), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s15, LLDB_INVALID_REGNUM, fpu_s15 }},
|
||||
{ "s16", NULL, 4, FPU_OFFSET(16), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s16, LLDB_INVALID_REGNUM, fpu_s16 }},
|
||||
{ "s17", NULL, 4, FPU_OFFSET(17), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s17, LLDB_INVALID_REGNUM, fpu_s17 }},
|
||||
{ "s18", NULL, 4, FPU_OFFSET(18), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s18, LLDB_INVALID_REGNUM, fpu_s18 }},
|
||||
{ "s19", NULL, 4, FPU_OFFSET(19), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s19, LLDB_INVALID_REGNUM, fpu_s19 }},
|
||||
{ "s20", NULL, 4, FPU_OFFSET(20), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s20, LLDB_INVALID_REGNUM, fpu_s20 }},
|
||||
{ "s21", NULL, 4, FPU_OFFSET(21), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s21, LLDB_INVALID_REGNUM, fpu_s21 }},
|
||||
{ "s22", NULL, 4, FPU_OFFSET(22), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s22, LLDB_INVALID_REGNUM, fpu_s22 }},
|
||||
{ "s23", NULL, 4, FPU_OFFSET(23), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s23, LLDB_INVALID_REGNUM, fpu_s23 }},
|
||||
{ "s24", NULL, 4, FPU_OFFSET(24), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s24, LLDB_INVALID_REGNUM, fpu_s24 }},
|
||||
{ "s25", NULL, 4, FPU_OFFSET(25), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s25, LLDB_INVALID_REGNUM, fpu_s25 }},
|
||||
{ "s26", NULL, 4, FPU_OFFSET(26), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s26, LLDB_INVALID_REGNUM, fpu_s26 }},
|
||||
{ "s27", NULL, 4, FPU_OFFSET(27), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s27, LLDB_INVALID_REGNUM, fpu_s27 }},
|
||||
{ "s28", NULL, 4, FPU_OFFSET(28), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s28, LLDB_INVALID_REGNUM, fpu_s28 }},
|
||||
{ "s29", NULL, 4, FPU_OFFSET(29), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s29, LLDB_INVALID_REGNUM, fpu_s29 }},
|
||||
{ "s30", NULL, 4, FPU_OFFSET(30), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s30, LLDB_INVALID_REGNUM, fpu_s30 }},
|
||||
{ "s31", NULL, 4, FPU_OFFSET(31), eEncodingIEEE754,eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s31, LLDB_INVALID_REGNUM, fpu_s31 }},
|
||||
{ "fpscr", NULL, 4, FPU_OFFSET(32), eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpu_fpscr }},
|
||||
|
||||
{ "exception",NULL, 4, EXC_OFFSET(0), eEncodingUint, eFormatHex, exc_exception,{ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }},
|
||||
{ "fsr", NULL, 4, EXC_OFFSET(1), eEncodingUint, eFormatHex, exc_fsr, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }},
|
||||
{ "far", NULL, 4, EXC_OFFSET(2), eEncodingUint, eFormatHex, exc_far, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM }},
|
||||
{ "exception",NULL, 4, EXC_OFFSET(0), eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, exc_exception }},
|
||||
{ "fsr", NULL, 4, EXC_OFFSET(1), eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, exc_fsr }},
|
||||
{ "far", NULL, 4, EXC_OFFSET(2), eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, exc_far }},
|
||||
|
||||
{ DEFINE_DBG (bvr, 0) },
|
||||
{ DEFINE_DBG (bvr, 0) },
|
||||
@ -1138,6 +1138,10 @@ RegisterContextMach_arm::ConvertRegisterKindToRegisterNumber (uint32_t kind, uin
|
||||
case gcc_cpsr: return gpr_cpsr;
|
||||
}
|
||||
}
|
||||
else if (kind == eRegisterKindLLDB)
|
||||
{
|
||||
return reg;
|
||||
}
|
||||
return LLDB_INVALID_REGNUM;
|
||||
}
|
||||
|
||||
|
@ -212,44 +212,44 @@ RegisterContextMach_i386::~RegisterContextMach_i386()
|
||||
// register offset, encoding, format and native register. This ensures that
|
||||
// the register state structures are defined correctly and have the correct
|
||||
// sizes and offsets.
|
||||
#define DEFINE_GPR(reg, alt) #reg, alt, sizeof(((RegisterContextMach_i386::GPR *)NULL)->reg), GPR_OFFSET(reg), eEncodingUint, eFormatHex, gpr_##reg
|
||||
#define DEFINE_FPU_UINT(reg) #reg, NULL, sizeof(((RegisterContextMach_i386::FPU *)NULL)->reg), FPU_OFFSET(reg), eEncodingUint, eFormatHex, fpu_##reg
|
||||
#define DEFINE_FPU_VECT(reg, i) #reg#i, NULL, sizeof(((RegisterContextMach_i386::FPU *)NULL)->reg[i].bytes), FPU_OFFSET(reg[i]), eEncodingVector, eFormatVectorOfUInt8, fpu_##reg##i, { LLDB_INVALID_REGNUM, dwarf_##reg##i, LLDB_INVALID_REGNUM, gdb_##reg##i }
|
||||
#define DEFINE_GPR(reg, alt) #reg, alt, sizeof(((RegisterContextMach_i386::GPR *)NULL)->reg), GPR_OFFSET(reg), eEncodingUint, eFormatHex
|
||||
#define DEFINE_FPU_UINT(reg) #reg, NULL, sizeof(((RegisterContextMach_i386::FPU *)NULL)->reg), FPU_OFFSET(reg), eEncodingUint, eFormatHex
|
||||
#define DEFINE_FPU_VECT(reg, i) #reg#i, NULL, sizeof(((RegisterContextMach_i386::FPU *)NULL)->reg[i].bytes), FPU_OFFSET(reg[i]), eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_##reg##i, LLDB_INVALID_REGNUM, gdb_##reg##i, fpu_##reg##i }
|
||||
|
||||
#define DEFINE_EXC(reg) #reg, NULL, sizeof(((RegisterContextMach_i386::EXC *)NULL)->reg), EXC_OFFSET(reg), eEncodingUint, eFormatHex, exc_##reg
|
||||
#define DEFINE_EXC(reg) #reg, NULL, sizeof(((RegisterContextMach_i386::EXC *)NULL)->reg), EXC_OFFSET(reg), eEncodingUint, eFormatHex
|
||||
#define REG_CONTEXT_SIZE (sizeof (RegisterContextMach_i386::GPR) + sizeof (RegisterContextMach_i386::FPU) + sizeof (RegisterContextMach_i386::EXC))
|
||||
|
||||
static RegisterInfo g_register_infos[] =
|
||||
{
|
||||
// Macro auto defines most stuff GCC REG KIND NUM DWARF REG KIND NUM GENERIC REG KIND NUM GDB REG KIND NUM
|
||||
// =============================== ======================= =================== ========================== ==========================
|
||||
{ DEFINE_GPR(eax , NULL) , { gcc_eax , dwarf_eax , LLDB_INVALID_REGNUM , gdb_eax }},
|
||||
{ DEFINE_GPR(ebx , NULL) , { gcc_ebx , dwarf_ebx , LLDB_INVALID_REGNUM , gdb_ebx }},
|
||||
{ DEFINE_GPR(ecx , NULL) , { gcc_ecx , dwarf_ecx , LLDB_INVALID_REGNUM , gdb_ecx }},
|
||||
{ DEFINE_GPR(edx , NULL) , { gcc_edx , dwarf_edx , LLDB_INVALID_REGNUM , gdb_edx }},
|
||||
{ DEFINE_GPR(edi , NULL) , { gcc_edi , dwarf_edi , LLDB_INVALID_REGNUM , gdb_edi }},
|
||||
{ DEFINE_GPR(esi , NULL) , { gcc_esi , dwarf_esi , LLDB_INVALID_REGNUM , gdb_esi }},
|
||||
{ DEFINE_GPR(ebp , "fp") , { gcc_ebp , dwarf_ebp , LLDB_REGNUM_GENERIC_FP , gdb_ebp }},
|
||||
{ DEFINE_GPR(esp , "sp") , { gcc_esp , dwarf_esp , LLDB_REGNUM_GENERIC_SP , gdb_esp }},
|
||||
{ DEFINE_GPR(ss , NULL) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_ss }},
|
||||
{ DEFINE_GPR(eflags , "flags") , { gcc_eflags , dwarf_eflags , LLDB_REGNUM_GENERIC_FLAGS , gdb_eflags }},
|
||||
{ DEFINE_GPR(eip , "pc") , { gcc_eip , dwarf_eip , LLDB_REGNUM_GENERIC_PC , gdb_eip }},
|
||||
{ DEFINE_GPR(cs , NULL) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_cs }},
|
||||
{ DEFINE_GPR(ds , NULL) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_ds }},
|
||||
{ DEFINE_GPR(es , NULL) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_es }},
|
||||
{ DEFINE_GPR(fs , NULL) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fs }},
|
||||
{ DEFINE_GPR(gs , NULL) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_gs }},
|
||||
// Macro auto defines most stuff GCC REG KIND NUM DWARF REG KIND NUM GENERIC REG KIND NUM GDB REG KIND NUM LLDB REG KIND NUM
|
||||
// =============================== ======================= =================== ========================== ========================== =================
|
||||
{ DEFINE_GPR(eax , NULL) , { gcc_eax , dwarf_eax , LLDB_INVALID_REGNUM , gdb_eax , gpr_eax }},
|
||||
{ DEFINE_GPR(ebx , NULL) , { gcc_ebx , dwarf_ebx , LLDB_INVALID_REGNUM , gdb_ebx , gpr_ebx }},
|
||||
{ DEFINE_GPR(ecx , NULL) , { gcc_ecx , dwarf_ecx , LLDB_INVALID_REGNUM , gdb_ecx , gpr_ecx }},
|
||||
{ DEFINE_GPR(edx , NULL) , { gcc_edx , dwarf_edx , LLDB_INVALID_REGNUM , gdb_edx , gpr_edx }},
|
||||
{ DEFINE_GPR(edi , NULL) , { gcc_edi , dwarf_edi , LLDB_INVALID_REGNUM , gdb_edi , gpr_edi }},
|
||||
{ DEFINE_GPR(esi , NULL) , { gcc_esi , dwarf_esi , LLDB_INVALID_REGNUM , gdb_esi , gpr_esi }},
|
||||
{ DEFINE_GPR(ebp , "fp") , { gcc_ebp , dwarf_ebp , LLDB_REGNUM_GENERIC_FP , gdb_ebp , gpr_ebp }},
|
||||
{ DEFINE_GPR(esp , "sp") , { gcc_esp , dwarf_esp , LLDB_REGNUM_GENERIC_SP , gdb_esp , gpr_esp }},
|
||||
{ DEFINE_GPR(ss , NULL) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_ss , gpr_ss }},
|
||||
{ DEFINE_GPR(eflags , "flags") , { gcc_eflags , dwarf_eflags , LLDB_REGNUM_GENERIC_FLAGS , gdb_eflags , gpr_eflags }},
|
||||
{ DEFINE_GPR(eip , "pc") , { gcc_eip , dwarf_eip , LLDB_REGNUM_GENERIC_PC , gdb_eip , gpr_eip }},
|
||||
{ DEFINE_GPR(cs , NULL) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_cs , gpr_cs }},
|
||||
{ DEFINE_GPR(ds , NULL) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_ds , gpr_ds }},
|
||||
{ DEFINE_GPR(es , NULL) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_es , gpr_es }},
|
||||
{ DEFINE_GPR(fs , NULL) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fs , gpr_fs }},
|
||||
{ DEFINE_GPR(gs , NULL) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_gs , gpr_gs }},
|
||||
|
||||
{ DEFINE_FPU_UINT(fcw) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fcw }},
|
||||
{ DEFINE_FPU_UINT(fsw) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fsw }},
|
||||
{ DEFINE_FPU_UINT(ftw) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_ftw }},
|
||||
{ DEFINE_FPU_UINT(fop) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fop }},
|
||||
{ DEFINE_FPU_UINT(ip) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_ip }},
|
||||
{ DEFINE_FPU_UINT(cs) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_cs }},
|
||||
{ DEFINE_FPU_UINT(dp) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_dp }},
|
||||
{ DEFINE_FPU_UINT(ds) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_ds }},
|
||||
{ DEFINE_FPU_UINT(mxcsr) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_mxcsr }},
|
||||
{ DEFINE_FPU_UINT(mxcsrmask) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM }},
|
||||
{ DEFINE_FPU_UINT(fcw) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fcw , fpu_fcw }},
|
||||
{ DEFINE_FPU_UINT(fsw) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fsw , fpu_fsw }},
|
||||
{ DEFINE_FPU_UINT(ftw) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_ftw , fpu_ftw }},
|
||||
{ DEFINE_FPU_UINT(fop) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fop , fpu_fop }},
|
||||
{ DEFINE_FPU_UINT(ip) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_ip , fpu_ip }},
|
||||
{ DEFINE_FPU_UINT(cs) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_cs , fpu_cs }},
|
||||
{ DEFINE_FPU_UINT(dp) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_dp , fpu_dp }},
|
||||
{ DEFINE_FPU_UINT(ds) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_ds , fpu_ds }},
|
||||
{ DEFINE_FPU_UINT(mxcsr) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_mxcsr , fpu_mxcsr }},
|
||||
{ DEFINE_FPU_UINT(mxcsrmask) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , fpu_mxcsrmask }},
|
||||
{ DEFINE_FPU_VECT(stmm,0) },
|
||||
{ DEFINE_FPU_VECT(stmm,1) },
|
||||
{ DEFINE_FPU_VECT(stmm,2) },
|
||||
@ -267,9 +267,9 @@ static RegisterInfo g_register_infos[] =
|
||||
{ DEFINE_FPU_VECT(xmm,6) },
|
||||
{ DEFINE_FPU_VECT(xmm,7) },
|
||||
|
||||
{ DEFINE_EXC(trapno) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM }},
|
||||
{ DEFINE_EXC(err) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM }},
|
||||
{ DEFINE_EXC(faultvaddr) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM }}
|
||||
{ DEFINE_EXC(trapno) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , exc_trapno }},
|
||||
{ DEFINE_EXC(err) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , exc_err }},
|
||||
{ DEFINE_EXC(faultvaddr) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , exc_faultvaddr }}
|
||||
};
|
||||
|
||||
static size_t k_num_register_infos = (sizeof(g_register_infos)/sizeof(RegisterInfo));
|
||||
@ -1167,6 +1167,10 @@ RegisterContextMach_i386::ConvertRegisterKindToRegisterNumber (uint32_t kind, ui
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (kind == eRegisterKindLLDB)
|
||||
{
|
||||
return reg;
|
||||
}
|
||||
return LLDB_INVALID_REGNUM;
|
||||
}
|
||||
|
||||
|
@ -233,50 +233,50 @@ RegisterContextMach_x86_64::~RegisterContextMach_x86_64()
|
||||
// register offset, encoding, format and native register. This ensures that
|
||||
// the register state structures are defined correctly and have the correct
|
||||
// sizes and offsets.
|
||||
#define DEFINE_GPR(reg, alt) #reg, alt, sizeof(((RegisterContextMach_x86_64::GPR *)NULL)->reg), GPR_OFFSET(reg), eEncodingUint, eFormatHex, gpr_##reg
|
||||
#define DEFINE_FPU_UINT(reg) #reg, NULL, sizeof(((RegisterContextMach_x86_64::FPU *)NULL)->reg), FPU_OFFSET(reg), eEncodingUint, eFormatHex, fpu_##reg
|
||||
#define DEFINE_FPU_VECT(reg, i) #reg#i, NULL, sizeof(((RegisterContextMach_x86_64::FPU *)NULL)->reg[i].bytes), FPU_OFFSET(reg[i]), eEncodingVector, eFormatVectorOfUInt8, fpu_##reg##i, { gcc_dwarf_fpu_##reg##i, gcc_dwarf_fpu_##reg##i, LLDB_INVALID_REGNUM, gdb_fpu_##reg##i }
|
||||
#define DEFINE_EXC(reg) #reg, NULL, sizeof(((RegisterContextMach_x86_64::EXC *)NULL)->reg), EXC_OFFSET(reg), eEncodingUint, eFormatHex, exc_##reg
|
||||
#define DEFINE_GPR(reg, alt) #reg, alt, sizeof(((RegisterContextMach_x86_64::GPR *)NULL)->reg), GPR_OFFSET(reg), eEncodingUint, eFormatHex
|
||||
#define DEFINE_FPU_UINT(reg) #reg, NULL, sizeof(((RegisterContextMach_x86_64::FPU *)NULL)->reg), FPU_OFFSET(reg), eEncodingUint, eFormatHex
|
||||
#define DEFINE_FPU_VECT(reg, i) #reg#i, NULL, sizeof(((RegisterContextMach_x86_64::FPU *)NULL)->reg[i].bytes), FPU_OFFSET(reg[i]), eEncodingVector, eFormatVectorOfUInt8, { gcc_dwarf_fpu_##reg##i, gcc_dwarf_fpu_##reg##i, LLDB_INVALID_REGNUM, gdb_fpu_##reg##i, fpu_##reg##i }
|
||||
#define DEFINE_EXC(reg) #reg, NULL, sizeof(((RegisterContextMach_x86_64::EXC *)NULL)->reg), EXC_OFFSET(reg), eEncodingUint, eFormatHex
|
||||
|
||||
#define REG_CONTEXT_SIZE (sizeof (RegisterContextMach_x86_64::GPR) + sizeof (RegisterContextMach_x86_64::FPU) + sizeof (RegisterContextMach_x86_64::EXC))
|
||||
|
||||
// General purpose registers for 64 bit
|
||||
static RegisterInfo g_register_infos[] =
|
||||
{
|
||||
// Macro auto defines most stuff GCC REG KIND NUM DWARF REG KIND NUM GENERIC REG KIND NUM GDB REG KIND NUM
|
||||
// =============================== ======================= =================== ========================== ==========================
|
||||
{ DEFINE_GPR (rax , NULL) , { gcc_dwarf_gpr_rax , gcc_dwarf_gpr_rax , LLDB_INVALID_REGNUM , gdb_gpr_rax }},
|
||||
{ DEFINE_GPR (rbx , NULL) , { gcc_dwarf_gpr_rbx , gcc_dwarf_gpr_rbx , LLDB_INVALID_REGNUM , gdb_gpr_rbx }},
|
||||
{ DEFINE_GPR (rcx , NULL) , { gcc_dwarf_gpr_rcx , gcc_dwarf_gpr_rcx , LLDB_INVALID_REGNUM , gdb_gpr_rcx }},
|
||||
{ DEFINE_GPR (rdx , NULL) , { gcc_dwarf_gpr_rdx , gcc_dwarf_gpr_rdx , LLDB_INVALID_REGNUM , gdb_gpr_rdx }},
|
||||
{ DEFINE_GPR (rdi , NULL) , { gcc_dwarf_gpr_rdi , gcc_dwarf_gpr_rdi , LLDB_INVALID_REGNUM , gdb_gpr_rdi }},
|
||||
{ DEFINE_GPR (rsi , NULL) , { gcc_dwarf_gpr_rsi , gcc_dwarf_gpr_rsi , LLDB_INVALID_REGNUM , gdb_gpr_rsi }},
|
||||
{ DEFINE_GPR (rbp , "fp") , { gcc_dwarf_gpr_rbp , gcc_dwarf_gpr_rbp , LLDB_REGNUM_GENERIC_FP , gdb_gpr_rbp }},
|
||||
{ DEFINE_GPR (rsp , "sp") , { gcc_dwarf_gpr_rsp , gcc_dwarf_gpr_rsp , LLDB_REGNUM_GENERIC_SP , gdb_gpr_rsp }},
|
||||
{ DEFINE_GPR (r8 , NULL) , { gcc_dwarf_gpr_r8 , gcc_dwarf_gpr_r8 , LLDB_INVALID_REGNUM , gdb_gpr_r8 }},
|
||||
{ DEFINE_GPR (r9 , NULL) , { gcc_dwarf_gpr_r9 , gcc_dwarf_gpr_r9 , LLDB_INVALID_REGNUM , gdb_gpr_r9 }},
|
||||
{ DEFINE_GPR (r10 , NULL) , { gcc_dwarf_gpr_r10 , gcc_dwarf_gpr_r10 , LLDB_INVALID_REGNUM , gdb_gpr_r10 }},
|
||||
{ DEFINE_GPR (r11 , NULL) , { gcc_dwarf_gpr_r11 , gcc_dwarf_gpr_r11 , LLDB_INVALID_REGNUM , gdb_gpr_r11 }},
|
||||
{ DEFINE_GPR (r12 , NULL) , { gcc_dwarf_gpr_r12 , gcc_dwarf_gpr_r12 , LLDB_INVALID_REGNUM , gdb_gpr_r12 }},
|
||||
{ DEFINE_GPR (r13 , NULL) , { gcc_dwarf_gpr_r13 , gcc_dwarf_gpr_r13 , LLDB_INVALID_REGNUM , gdb_gpr_r13 }},
|
||||
{ DEFINE_GPR (r14 , NULL) , { gcc_dwarf_gpr_r14 , gcc_dwarf_gpr_r14 , LLDB_INVALID_REGNUM , gdb_gpr_r14 }},
|
||||
{ DEFINE_GPR (r15 , NULL) , { gcc_dwarf_gpr_r15 , gcc_dwarf_gpr_r15 , LLDB_INVALID_REGNUM , gdb_gpr_r15 }},
|
||||
{ DEFINE_GPR (rip , "pc") , { gcc_dwarf_gpr_rip , gcc_dwarf_gpr_rip , LLDB_REGNUM_GENERIC_PC , gdb_gpr_rip }},
|
||||
{ DEFINE_GPR (rflags, "flags") , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_REGNUM_GENERIC_FLAGS , gdb_gpr_rflags}},
|
||||
{ DEFINE_GPR (cs , NULL) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_gpr_cs }},
|
||||
{ DEFINE_GPR (fs , NULL) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_gpr_fs }},
|
||||
{ DEFINE_GPR (gs , NULL) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_gpr_gs }},
|
||||
// Macro auto defines most stuff GCC REG KIND NUM DWARF REG KIND NUM GENERIC REG KIND NUM GDB REG KIND NUM LLDB REG KIND NUM
|
||||
// =============================== ======================= =================== ========================== ========================== =====================
|
||||
{ DEFINE_GPR (rax , NULL) , { gcc_dwarf_gpr_rax , gcc_dwarf_gpr_rax , LLDB_INVALID_REGNUM , gdb_gpr_rax , gpr_rax }},
|
||||
{ DEFINE_GPR (rbx , NULL) , { gcc_dwarf_gpr_rbx , gcc_dwarf_gpr_rbx , LLDB_INVALID_REGNUM , gdb_gpr_rbx , gpr_rbx }},
|
||||
{ DEFINE_GPR (rcx , NULL) , { gcc_dwarf_gpr_rcx , gcc_dwarf_gpr_rcx , LLDB_INVALID_REGNUM , gdb_gpr_rcx , gpr_rcx }},
|
||||
{ DEFINE_GPR (rdx , NULL) , { gcc_dwarf_gpr_rdx , gcc_dwarf_gpr_rdx , LLDB_INVALID_REGNUM , gdb_gpr_rdx , gpr_rdx }},
|
||||
{ DEFINE_GPR (rdi , NULL) , { gcc_dwarf_gpr_rdi , gcc_dwarf_gpr_rdi , LLDB_INVALID_REGNUM , gdb_gpr_rdi , gpr_rdi }},
|
||||
{ DEFINE_GPR (rsi , NULL) , { gcc_dwarf_gpr_rsi , gcc_dwarf_gpr_rsi , LLDB_INVALID_REGNUM , gdb_gpr_rsi , gpr_rsi }},
|
||||
{ DEFINE_GPR (rbp , "fp") , { gcc_dwarf_gpr_rbp , gcc_dwarf_gpr_rbp , LLDB_REGNUM_GENERIC_FP , gdb_gpr_rbp , gpr_rbp }},
|
||||
{ DEFINE_GPR (rsp , "sp") , { gcc_dwarf_gpr_rsp , gcc_dwarf_gpr_rsp , LLDB_REGNUM_GENERIC_SP , gdb_gpr_rsp , gpr_rsp }},
|
||||
{ DEFINE_GPR (r8 , NULL) , { gcc_dwarf_gpr_r8 , gcc_dwarf_gpr_r8 , LLDB_INVALID_REGNUM , gdb_gpr_r8 , gpr_r8 }},
|
||||
{ DEFINE_GPR (r9 , NULL) , { gcc_dwarf_gpr_r9 , gcc_dwarf_gpr_r9 , LLDB_INVALID_REGNUM , gdb_gpr_r9 , gpr_r9 }},
|
||||
{ DEFINE_GPR (r10 , NULL) , { gcc_dwarf_gpr_r10 , gcc_dwarf_gpr_r10 , LLDB_INVALID_REGNUM , gdb_gpr_r10 , gpr_r10 }},
|
||||
{ DEFINE_GPR (r11 , NULL) , { gcc_dwarf_gpr_r11 , gcc_dwarf_gpr_r11 , LLDB_INVALID_REGNUM , gdb_gpr_r11 , gpr_r11 }},
|
||||
{ DEFINE_GPR (r12 , NULL) , { gcc_dwarf_gpr_r12 , gcc_dwarf_gpr_r12 , LLDB_INVALID_REGNUM , gdb_gpr_r12 , gpr_r12 }},
|
||||
{ DEFINE_GPR (r13 , NULL) , { gcc_dwarf_gpr_r13 , gcc_dwarf_gpr_r13 , LLDB_INVALID_REGNUM , gdb_gpr_r13 , gpr_r13 }},
|
||||
{ DEFINE_GPR (r14 , NULL) , { gcc_dwarf_gpr_r14 , gcc_dwarf_gpr_r14 , LLDB_INVALID_REGNUM , gdb_gpr_r14 , gpr_r14 }},
|
||||
{ DEFINE_GPR (r15 , NULL) , { gcc_dwarf_gpr_r15 , gcc_dwarf_gpr_r15 , LLDB_INVALID_REGNUM , gdb_gpr_r15 , gpr_r15 }},
|
||||
{ DEFINE_GPR (rip , "pc") , { gcc_dwarf_gpr_rip , gcc_dwarf_gpr_rip , LLDB_REGNUM_GENERIC_PC , gdb_gpr_rip , gpr_rip }},
|
||||
{ DEFINE_GPR (rflags, "flags") , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_REGNUM_GENERIC_FLAGS , gdb_gpr_rflags , gpr_rflags }},
|
||||
{ DEFINE_GPR (cs , NULL) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_gpr_cs , gpr_cs }},
|
||||
{ DEFINE_GPR (fs , NULL) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_gpr_fs , gpr_fs }},
|
||||
{ DEFINE_GPR (gs , NULL) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_gpr_gs , gpr_gs }},
|
||||
|
||||
{ DEFINE_FPU_UINT(fcw) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fpu_fcw }},
|
||||
{ DEFINE_FPU_UINT(fsw) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fpu_fsw }},
|
||||
{ DEFINE_FPU_UINT(ftw) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fpu_ftw }},
|
||||
{ DEFINE_FPU_UINT(fop) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fpu_fop }},
|
||||
{ DEFINE_FPU_UINT(ip) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fpu_ip }},
|
||||
{ DEFINE_FPU_UINT(cs) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fpu_cs }},
|
||||
{ DEFINE_FPU_UINT(dp) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fpu_dp }},
|
||||
{ DEFINE_FPU_UINT(ds) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fpu_ds }},
|
||||
{ DEFINE_FPU_UINT(mxcsr) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fpu_mxcsr }},
|
||||
{ DEFINE_FPU_UINT(mxcsrmask) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM }},
|
||||
{ DEFINE_FPU_UINT(fcw) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fpu_fcw , fpu_fcw }},
|
||||
{ DEFINE_FPU_UINT(fsw) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fpu_fsw , fpu_fsw }},
|
||||
{ DEFINE_FPU_UINT(ftw) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fpu_ftw , fpu_ftw }},
|
||||
{ DEFINE_FPU_UINT(fop) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fpu_fop , fpu_fop }},
|
||||
{ DEFINE_FPU_UINT(ip) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fpu_ip , fpu_ip }},
|
||||
{ DEFINE_FPU_UINT(cs) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fpu_cs , fpu_cs }},
|
||||
{ DEFINE_FPU_UINT(dp) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fpu_dp , fpu_dp }},
|
||||
{ DEFINE_FPU_UINT(ds) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fpu_ds , fpu_ds }},
|
||||
{ DEFINE_FPU_UINT(mxcsr) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , gdb_fpu_mxcsr , fpu_mxcsr }},
|
||||
{ DEFINE_FPU_UINT(mxcsrmask) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , fpu_mxcsrmask }},
|
||||
{ DEFINE_FPU_VECT(stmm,0) },
|
||||
{ DEFINE_FPU_VECT(stmm,1) },
|
||||
{ DEFINE_FPU_VECT(stmm,2) },
|
||||
@ -302,9 +302,9 @@ static RegisterInfo g_register_infos[] =
|
||||
{ DEFINE_FPU_VECT(xmm,14) },
|
||||
{ DEFINE_FPU_VECT(xmm,15) },
|
||||
|
||||
{ DEFINE_EXC(trapno) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM }},
|
||||
{ DEFINE_EXC(err) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM }},
|
||||
{ DEFINE_EXC(faultvaddr) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM }}
|
||||
{ DEFINE_EXC(trapno) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , exc_trapno }},
|
||||
{ DEFINE_EXC(err) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , exc_err }},
|
||||
{ DEFINE_EXC(faultvaddr) , { LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , LLDB_INVALID_REGNUM , exc_faultvaddr }}
|
||||
};
|
||||
|
||||
static size_t k_num_register_infos = (sizeof(g_register_infos)/sizeof(RegisterInfo));
|
||||
@ -1297,6 +1297,10 @@ RegisterContextMach_x86_64::ConvertRegisterKindToRegisterNumber (uint32_t kind,
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (kind == eRegisterKindLLDB)
|
||||
{
|
||||
return reg;
|
||||
}
|
||||
return LLDB_INVALID_REGNUM;
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,155 @@
|
||||
//===-- ArchDefaultUnwindPlan-x86.cpp --------------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "ArchDefaultUnwindPlan-x86.h"
|
||||
|
||||
#include "lldb/lldb-private.h"
|
||||
#include "lldb/Utility/ArchDefaultUnwindPlan.h"
|
||||
#include "lldb/Core/ArchSpec.h"
|
||||
#include "lldb/Core/PluginManager.h"
|
||||
#include "lldb/lldb-enumerations.h"
|
||||
|
||||
using namespace lldb;
|
||||
using namespace lldb_private;
|
||||
|
||||
lldb_private::UnwindPlan*
|
||||
ArchDefaultUnwindPlan_x86::GetArchDefaultUnwindPlan (Thread& thread, Address current_pc)
|
||||
{
|
||||
if (m_cpu == CPU_TYPE_X86_64)
|
||||
{
|
||||
return &m_64bit_default;
|
||||
}
|
||||
if (m_cpu == CPU_TYPE_I386)
|
||||
{
|
||||
return &m_32bit_default;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
lldb_private::ArchDefaultUnwindPlan *
|
||||
ArchDefaultUnwindPlan_x86::CreateInstance (const lldb_private::ArchSpec &arch)
|
||||
{
|
||||
uint32_t cpu = arch.GetCPUType ();
|
||||
if (cpu != CPU_TYPE_X86_64 && cpu != CPU_TYPE_I386)
|
||||
return NULL;
|
||||
|
||||
return new ArchDefaultUnwindPlan_x86 (cpu);
|
||||
}
|
||||
|
||||
ArchDefaultUnwindPlan_x86::ArchDefaultUnwindPlan_x86(int cpu) :
|
||||
lldb_private::ArchDefaultUnwindPlan(),
|
||||
m_cpu(cpu),
|
||||
m_32bit_default(),
|
||||
m_64bit_default()
|
||||
{
|
||||
UnwindPlan::Row row;
|
||||
UnwindPlan::Row::RegisterLocation regloc;
|
||||
|
||||
m_32bit_default.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);
|
||||
|
||||
row.Clear();
|
||||
|
||||
m_64bit_default.SetRegisterKind (eRegisterKindGeneric);
|
||||
row.SetCFARegister (LLDB_REGNUM_GENERIC_FP);
|
||||
row.SetCFAOffset (2 * 8);
|
||||
row.SetOffset (0);
|
||||
|
||||
regloc.SetAtCFAPlusOffset (2 * -8);
|
||||
row.SetRegisterInfo (LLDB_REGNUM_GENERIC_FP, regloc);
|
||||
regloc.SetAtCFAPlusOffset (1 * -8);
|
||||
row.SetRegisterInfo (LLDB_REGNUM_GENERIC_PC, regloc);
|
||||
regloc.SetIsCFAPlusOffset (0);
|
||||
row.SetRegisterInfo (LLDB_REGNUM_GENERIC_SP, regloc);
|
||||
|
||||
m_64bit_default.AppendRow (row);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// PluginInterface protocol in UnwindAssemblyParser_x86
|
||||
//------------------------------------------------------------------
|
||||
|
||||
const char *
|
||||
ArchDefaultUnwindPlan_x86::GetPluginName()
|
||||
{
|
||||
return "ArchDefaultUnwindPlan_x86";
|
||||
}
|
||||
|
||||
const char *
|
||||
ArchDefaultUnwindPlan_x86::GetShortPluginName()
|
||||
{
|
||||
return "archdefaultunwindplan.x86";
|
||||
}
|
||||
|
||||
|
||||
uint32_t
|
||||
ArchDefaultUnwindPlan_x86::GetPluginVersion()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
ArchDefaultUnwindPlan_x86::GetPluginCommandHelp (const char *command, Stream *strm)
|
||||
{
|
||||
}
|
||||
|
||||
Error
|
||||
ArchDefaultUnwindPlan_x86::ExecutePluginCommand (Args &command, Stream *strm)
|
||||
{
|
||||
Error error;
|
||||
error.SetErrorString("No plug-in command are currently supported.");
|
||||
return error;
|
||||
}
|
||||
|
||||
Log *
|
||||
ArchDefaultUnwindPlan_x86::EnablePluginLogging (Stream *strm, Args &command)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
ArchDefaultUnwindPlan_x86::Initialize()
|
||||
{
|
||||
PluginManager::RegisterPlugin (GetPluginNameStatic(),
|
||||
GetPluginDescriptionStatic(),
|
||||
CreateInstance);
|
||||
}
|
||||
|
||||
void
|
||||
ArchDefaultUnwindPlan_x86::Terminate()
|
||||
{
|
||||
PluginManager::UnregisterPlugin (CreateInstance);
|
||||
}
|
||||
|
||||
|
||||
const char *
|
||||
ArchDefaultUnwindPlan_x86::GetPluginNameStatic()
|
||||
{
|
||||
return "ArchDefaultUnwindPlan_x86";
|
||||
}
|
||||
|
||||
const char *
|
||||
ArchDefaultUnwindPlan_x86::GetPluginDescriptionStatic()
|
||||
{
|
||||
return "i386 and x86_64 architecture default unwind plan assembly plugin.";
|
||||
}
|
@ -0,0 +1,76 @@
|
||||
//===-- ArchDefaultUnwindPlan-x86.h ----------------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef liblldb_ArchDefaultUnwindPlan_x86_h_
|
||||
#define liblldb_ArchDefaultUnwindPlan_x86_h_
|
||||
|
||||
#include "lldb/lldb-private.h"
|
||||
#include "lldb/Utility/ArchDefaultUnwindPlan.h"
|
||||
#include "lldb/Target/Thread.h"
|
||||
#include "lldb/Symbol/UnwindPlan.h"
|
||||
|
||||
namespace lldb_private {
|
||||
|
||||
class ArchDefaultUnwindPlan_x86 : public lldb_private::ArchDefaultUnwindPlan
|
||||
{
|
||||
public:
|
||||
|
||||
~ArchDefaultUnwindPlan_x86 () { }
|
||||
|
||||
virtual lldb_private::UnwindPlan*
|
||||
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_x86(int cpu); // Call CreateInstance instead.
|
||||
|
||||
int m_cpu;
|
||||
lldb_private::UnwindPlan m_32bit_default;
|
||||
lldb_private::UnwindPlan m_64bit_default;
|
||||
};
|
||||
|
||||
|
||||
} // namespace lldb_private
|
||||
|
||||
#endif // liblldb_UnwindAssemblyProfiler_x86_h_
|
@ -0,0 +1,803 @@
|
||||
//===-- UnwindAssemblyProfiler-x86.cpp --------------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "UnwindAssemblyProfiler-x86.h"
|
||||
|
||||
#include "lldb/lldb-private.h"
|
||||
#include "lldb/Utility/UnwindAssemblyProfiler.h"
|
||||
#include "lldb/Core/Address.h"
|
||||
#include "lldb/Core/Error.h"
|
||||
#include "lldb/Core/ArchSpec.h"
|
||||
#include "lldb/Core/PluginManager.h"
|
||||
#include "lldb/Target/ExecutionContext.h"
|
||||
#include "lldb/Target/Process.h"
|
||||
#include "lldb/Target/RegisterContext.h"
|
||||
#include "lldb/Target/Thread.h"
|
||||
#include "lldb/Target/Target.h"
|
||||
#include "lldb/Symbol/UnwindPlan.h"
|
||||
|
||||
#include "lldb/lldb-enumerations.h"
|
||||
#include "llvm-c/EnhancedDisassembly.h"
|
||||
|
||||
#include "UnwindAssemblyProfiler-x86.h"
|
||||
|
||||
|
||||
using namespace lldb;
|
||||
using namespace lldb_private;
|
||||
|
||||
enum CPU {
|
||||
k_i386,
|
||||
k_x86_64
|
||||
};
|
||||
|
||||
enum i386_register_numbers {
|
||||
k_machine_eax = 0,
|
||||
k_machine_ecx = 1,
|
||||
k_machine_edx = 2,
|
||||
k_machine_ebx = 3,
|
||||
k_machine_esp = 4,
|
||||
k_machine_ebp = 5,
|
||||
k_machine_esi = 6,
|
||||
k_machine_edi = 7,
|
||||
k_machine_eip = 8
|
||||
};
|
||||
|
||||
enum x86_64_register_numbers {
|
||||
k_machine_rax = 0,
|
||||
k_machine_rcx = 1,
|
||||
k_machine_rdx = 2,
|
||||
k_machine_rbx = 3,
|
||||
k_machine_rsp = 4,
|
||||
k_machine_rbp = 5,
|
||||
k_machine_rsi = 6,
|
||||
k_machine_rdi = 7,
|
||||
k_machine_r8 = 8,
|
||||
k_machine_r9 = 9,
|
||||
k_machine_r10 = 10,
|
||||
k_machine_r11 = 11,
|
||||
k_machine_r12 = 12,
|
||||
k_machine_r13 = 13,
|
||||
k_machine_r14 = 14,
|
||||
k_machine_r15 = 15,
|
||||
k_machine_rip = 16
|
||||
};
|
||||
|
||||
struct regmap_ent {
|
||||
const char *name;
|
||||
int machine_regno;
|
||||
int lldb_regno;
|
||||
};
|
||||
|
||||
static struct regmap_ent i386_register_map[] = {
|
||||
{"eax", k_machine_eax, -1},
|
||||
{"ecx", k_machine_ecx, -1},
|
||||
{"edx", k_machine_edx, -1},
|
||||
{"ebx", k_machine_ebx, -1},
|
||||
{"esp", k_machine_esp, -1},
|
||||
{"ebp", k_machine_ebp, -1},
|
||||
{"esi", k_machine_esi, -1},
|
||||
{"edi", k_machine_edi, -1},
|
||||
{"eip", k_machine_eip, -1}
|
||||
};
|
||||
|
||||
const int size_of_i386_register_map = sizeof (i386_register_map) / sizeof (struct regmap_ent);
|
||||
|
||||
static int i386_register_map_initialized = 0;
|
||||
|
||||
static struct regmap_ent x86_64_register_map[] = {
|
||||
{"rax", k_machine_rax, -1},
|
||||
{"rcx", k_machine_rcx, -1},
|
||||
{"rdx", k_machine_rdx, -1},
|
||||
{"rbx", k_machine_rbx, -1},
|
||||
{"rsp", k_machine_rsp, -1},
|
||||
{"rbp", k_machine_rbp, -1},
|
||||
{"rsi", k_machine_rsi, -1},
|
||||
{"rdi", k_machine_rdi, -1},
|
||||
{"r8", k_machine_r8, -1},
|
||||
{"r9", k_machine_r9, -1},
|
||||
{"r10", k_machine_r10, -1},
|
||||
{"r11", k_machine_r11, -1},
|
||||
{"r12", k_machine_r12, -1},
|
||||
{"r13", k_machine_r13, -1},
|
||||
{"r14", k_machine_r14, -1},
|
||||
{"r15", k_machine_r15, -1},
|
||||
{"rip", k_machine_rip, -1}
|
||||
};
|
||||
|
||||
const int size_of_x86_64_register_map = sizeof (x86_64_register_map) / sizeof (struct regmap_ent);
|
||||
|
||||
static int x86_64_register_map_initialized = 0;
|
||||
|
||||
//-----------------------------------------------------------------------------------------------
|
||||
// AssemblyParse_x86 local-file class definition & implementation functions
|
||||
//-----------------------------------------------------------------------------------------------
|
||||
|
||||
class AssemblyParse_x86 {
|
||||
public:
|
||||
|
||||
AssemblyParse_x86 (Target &target, Thread *thread, int cpu, AddressRange func);
|
||||
|
||||
bool get_non_call_site_unwind_plan (UnwindPlan &unwind_plan);
|
||||
|
||||
bool get_fast_unwind_plan (UnwindPlan &unwind_plan);
|
||||
|
||||
bool find_first_non_prologue_insn (Address &address);
|
||||
|
||||
private:
|
||||
enum { kMaxInstructionByteSize = 32 };
|
||||
|
||||
bool nonvolatile_reg_p (int machine_regno);
|
||||
bool push_rbp_pattern_p ();
|
||||
bool push_0_pattern_p ();
|
||||
bool mov_rsp_rbp_pattern_p ();
|
||||
bool sub_rsp_pattern_p (int& amount);
|
||||
bool push_reg_p (int& regno);
|
||||
bool mov_reg_to_local_stack_frame_p (int& regno, int& fp_offset);
|
||||
bool ret_pattern_p ();
|
||||
uint32_t extract_4 (uint8_t *b);
|
||||
bool machine_regno_to_lldb_regno (int machine_regno, uint32_t& lldb_regno);
|
||||
bool instruction_length (Address addr, int &length);
|
||||
|
||||
Target &m_target;
|
||||
Thread* m_thread;
|
||||
|
||||
AddressRange m_func_bounds;
|
||||
|
||||
Address m_cur_insn;
|
||||
uint8_t m_cur_insn_bytes[kMaxInstructionByteSize];
|
||||
|
||||
int m_machine_ip_regnum;
|
||||
int m_machine_sp_regnum;
|
||||
int m_machine_fp_regnum;
|
||||
|
||||
int m_lldb_ip_regnum;
|
||||
int m_lldb_sp_regnum;
|
||||
int m_lldb_fp_regnum;
|
||||
|
||||
int m_wordsize;
|
||||
int m_cpu;
|
||||
};
|
||||
|
||||
AssemblyParse_x86::AssemblyParse_x86 (Target& target, Thread* thread, int cpu, AddressRange func) :
|
||||
m_target (target), m_thread (thread), m_cpu(cpu), m_func_bounds(func)
|
||||
{
|
||||
int *initialized_flag = NULL;
|
||||
m_lldb_ip_regnum = m_lldb_sp_regnum = m_lldb_fp_regnum = -1;
|
||||
if (cpu == k_i386)
|
||||
{
|
||||
m_machine_ip_regnum = k_machine_eip;
|
||||
m_machine_sp_regnum = k_machine_esp;
|
||||
m_machine_fp_regnum = k_machine_ebp;
|
||||
m_wordsize = 4;
|
||||
initialized_flag = &i386_register_map_initialized;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_machine_ip_regnum = k_machine_rip;
|
||||
m_machine_sp_regnum = k_machine_rsp;
|
||||
m_machine_fp_regnum = k_machine_rbp;
|
||||
m_wordsize = 8;
|
||||
initialized_flag = &x86_64_register_map_initialized;
|
||||
}
|
||||
|
||||
// we only look at prologue - it will be complete earlier than 512 bytes into func
|
||||
if (m_func_bounds.GetByteSize() == 0)
|
||||
m_func_bounds.SetByteSize(512);
|
||||
|
||||
if (m_thread && *initialized_flag == 0)
|
||||
{
|
||||
RegisterContext *rctx = m_thread->GetRegisterContext();
|
||||
if (rctx)
|
||||
{
|
||||
struct regmap_ent *ent;
|
||||
int count, i;
|
||||
if (cpu == k_i386)
|
||||
{
|
||||
ent = i386_register_map;
|
||||
count = size_of_i386_register_map;
|
||||
}
|
||||
else
|
||||
{
|
||||
ent = x86_64_register_map;
|
||||
count = size_of_x86_64_register_map;
|
||||
}
|
||||
for (i = 0; i < count; i++, ent++)
|
||||
{
|
||||
const RegisterInfo *ri = rctx->GetRegisterInfoByName (ent->name);
|
||||
if (ri)
|
||||
ent->lldb_regno = ri->kinds[eRegisterKindLLDB];
|
||||
}
|
||||
*initialized_flag = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// on initial construction we may not have a Thread so these have to remain
|
||||
// uninitialized until we can get a RegisterContext to set up the register map table
|
||||
if (*initialized_flag == 1)
|
||||
{
|
||||
uint32_t lldb_regno;
|
||||
if (machine_regno_to_lldb_regno (m_machine_sp_regnum, lldb_regno))
|
||||
m_lldb_sp_regnum = lldb_regno;
|
||||
if (machine_regno_to_lldb_regno (m_machine_fp_regnum, lldb_regno))
|
||||
m_lldb_fp_regnum = lldb_regno;
|
||||
if (machine_regno_to_lldb_regno (m_machine_ip_regnum, lldb_regno))
|
||||
m_lldb_ip_regnum = lldb_regno;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// This function expects an x86 native register number (i.e. the bits stripped out of the
|
||||
// actual instruction), not an lldb register number.
|
||||
|
||||
bool
|
||||
AssemblyParse_x86::nonvolatile_reg_p (int machine_regno)
|
||||
{
|
||||
if (m_cpu == k_i386)
|
||||
{
|
||||
switch (machine_regno) {
|
||||
case k_machine_ebx:
|
||||
case k_machine_ebp: // not actually a nonvolatile but often treated as such by convention
|
||||
case k_machine_esi:
|
||||
case k_machine_edi:
|
||||
case k_machine_esp:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (m_cpu == k_x86_64)
|
||||
{
|
||||
switch (machine_regno) {
|
||||
case k_machine_rbx:
|
||||
case k_machine_rsp:
|
||||
case k_machine_rbp: // not actually a nonvolatile but often treated as such by convention
|
||||
case k_machine_r12:
|
||||
case k_machine_r13:
|
||||
case k_machine_r14:
|
||||
case k_machine_r15:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// Macro to detect if this is a REX mode prefix byte.
|
||||
#define REX_W_PREFIX_P(opcode) (((opcode) & (~0x5)) == 0x48)
|
||||
|
||||
// The high bit which should be added to the source register number (the "R" bit)
|
||||
#define REX_W_SRCREG(opcode) (((opcode) & 0x4) >> 2)
|
||||
|
||||
// The high bit which should be added to the destination register number (the "B" bit)
|
||||
#define REX_W_DSTREG(opcode) ((opcode) & 0x1)
|
||||
|
||||
// pushq %rbp [0x55]
|
||||
bool AssemblyParse_x86::push_rbp_pattern_p () {
|
||||
uint8_t *p = m_cur_insn_bytes;
|
||||
if (*p == 0x55)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
// pushq $0 ; the first instruction in start() [0x6a 0x00]
|
||||
bool AssemblyParse_x86::push_0_pattern_p ()
|
||||
{
|
||||
uint8_t *p = m_cur_insn_bytes;
|
||||
if (*p == 0x6a && *(p + 1) == 0x0)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
// movq %rsp, %rbp [0x48 0x8b 0xec] or [0x48 0x89 0xe5]
|
||||
// movl %esp, %ebp [0x8b 0xec] or [0x89 0xe5]
|
||||
bool AssemblyParse_x86::mov_rsp_rbp_pattern_p () {
|
||||
uint8_t *p = m_cur_insn_bytes;
|
||||
if (m_wordsize == 8 && *p == 0x48)
|
||||
p++;
|
||||
if (*(p) == 0x8b && *(p + 1) == 0xec)
|
||||
return true;
|
||||
if (*(p) == 0x89 && *(p + 1) == 0xe5)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
// subq $0x20, %rsp
|
||||
bool AssemblyParse_x86::sub_rsp_pattern_p (int& amount) {
|
||||
uint8_t *p = m_cur_insn_bytes;
|
||||
if (m_wordsize == 8 && *p == 0x48)
|
||||
p++;
|
||||
// 8-bit immediate operand
|
||||
if (*p == 0x83 && *(p + 1) == 0xec) {
|
||||
amount = (int8_t) *(p + 2);
|
||||
return true;
|
||||
}
|
||||
// 32-bit immediate operand
|
||||
if (*p == 0x81 && *(p + 1) == 0xec) {
|
||||
amount = (int32_t) extract_4 (p + 2);
|
||||
return true;
|
||||
}
|
||||
// Not handled: [0x83 0xc4] for imm8 with neg values
|
||||
// [0x81 0xc4] for imm32 with neg values
|
||||
return false;
|
||||
}
|
||||
|
||||
// pushq %rbx
|
||||
// pushl $ebx
|
||||
bool AssemblyParse_x86::push_reg_p (int& regno) {
|
||||
uint8_t *p = m_cur_insn_bytes;
|
||||
int regno_prefix_bit = 0;
|
||||
// If we have a rex prefix byte, check to see if a B bit is set
|
||||
if (m_wordsize == 8 && *p == 0x41) {
|
||||
regno_prefix_bit = 1 << 3;
|
||||
p++;
|
||||
}
|
||||
if (*p >= 0x50 && *p <= 0x57) {
|
||||
regno = (*p - 0x50) | regno_prefix_bit;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Look for an instruction sequence storing a nonvolatile register
|
||||
// on to the stack frame.
|
||||
|
||||
// movq %rax, -0x10(%rbp) [0x48 0x89 0x45 0xf0]
|
||||
// movl %eax, -0xc(%ebp) [0x89 0x45 0xf4]
|
||||
bool AssemblyParse_x86::mov_reg_to_local_stack_frame_p (int& regno, int& rbp_offset) {
|
||||
uint8_t *p = m_cur_insn_bytes;
|
||||
int src_reg_prefix_bit = 0;
|
||||
int target_reg_prefix_bit = 0;
|
||||
|
||||
if (m_wordsize == 8 && REX_W_PREFIX_P (*p)) {
|
||||
src_reg_prefix_bit = REX_W_SRCREG (*p) << 3;
|
||||
target_reg_prefix_bit = REX_W_DSTREG (*p) << 3;
|
||||
if (target_reg_prefix_bit == 1) {
|
||||
// rbp/ebp don't need a prefix bit - we know this isn't the
|
||||
// reg we care about.
|
||||
return false;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
|
||||
if (*p == 0x89) {
|
||||
/* Mask off the 3-5 bits which indicate the destination register
|
||||
if this is a ModR/M byte. */
|
||||
int opcode_destreg_masked_out = *(p + 1) & (~0x38);
|
||||
|
||||
/* Is this a ModR/M byte with Mod bits 01 and R/M bits 101
|
||||
and three bits between them, e.g. 01nnn101
|
||||
We're looking for a destination of ebp-disp8 or ebp-disp32. */
|
||||
int immsize;
|
||||
if (opcode_destreg_masked_out == 0x45)
|
||||
immsize = 2;
|
||||
else if (opcode_destreg_masked_out == 0x85)
|
||||
immsize = 4;
|
||||
else
|
||||
return false;
|
||||
|
||||
int offset = 0;
|
||||
if (immsize == 2)
|
||||
offset = (int8_t) *(p + 2);
|
||||
if (immsize == 4)
|
||||
offset = (uint32_t) extract_4 (p + 2);
|
||||
if (offset > 0)
|
||||
return false;
|
||||
|
||||
regno = ((*(p + 1) >> 3) & 0x7) | src_reg_prefix_bit;
|
||||
rbp_offset = offset > 0 ? offset : -offset;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// ret [0xc9] or [0xc2 imm8] or [0xca imm8]
|
||||
bool
|
||||
AssemblyParse_x86::ret_pattern_p ()
|
||||
{
|
||||
uint8_t *p = m_cur_insn_bytes;
|
||||
if (*p == 0xc9 || *p == 0xc2 || *p == 0xca || *p == 0xc3)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
AssemblyParse_x86::extract_4 (uint8_t *b)
|
||||
{
|
||||
uint32_t v = 0;
|
||||
for (int i = 3; i >= 0; i--)
|
||||
v = (v << 8) | b[i];
|
||||
return v;
|
||||
}
|
||||
|
||||
bool
|
||||
AssemblyParse_x86::machine_regno_to_lldb_regno (int machine_regno, uint32_t &lldb_regno)
|
||||
{
|
||||
struct regmap_ent *ent;
|
||||
int count, i;
|
||||
if (m_cpu == k_i386)
|
||||
{
|
||||
ent = i386_register_map;
|
||||
count = size_of_i386_register_map;
|
||||
}
|
||||
else
|
||||
{
|
||||
ent = x86_64_register_map;
|
||||
count = size_of_x86_64_register_map;
|
||||
}
|
||||
for (i = 0; i < count; i++, ent++)
|
||||
{
|
||||
if (ent->machine_regno == machine_regno)
|
||||
if (ent->lldb_regno != -1)
|
||||
{
|
||||
lldb_regno = ent->lldb_regno;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
struct edis_byte_read_token
|
||||
{
|
||||
Address *address;
|
||||
Target *target;
|
||||
};
|
||||
|
||||
|
||||
static int
|
||||
read_byte_for_edis (uint8_t *buf, uint64_t offset_address, void *arg)
|
||||
{
|
||||
if (arg == 0)
|
||||
return -1;
|
||||
struct edis_byte_read_token *tok = (edis_byte_read_token *) arg;
|
||||
Address *base_address = tok->address;
|
||||
Target *target = tok->target;
|
||||
|
||||
Address read_addr = *base_address;
|
||||
read_addr.SetOffset (offset_address);
|
||||
|
||||
uint8_t onebyte_buf[1];
|
||||
Error error;
|
||||
if (target->ReadMemory (read_addr, onebyte_buf, 1, error) != -1)
|
||||
{
|
||||
*buf = onebyte_buf[0];
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
AssemblyParse_x86::instruction_length (Address addr, int &length)
|
||||
{
|
||||
const char *triple;
|
||||
// FIXME should probably pass down the ArchSpec and work from that to make a portable triple
|
||||
if (m_cpu == k_i386)
|
||||
triple = "i386-apple-darwin";
|
||||
else
|
||||
triple = "x86_64-apple-darwin";
|
||||
|
||||
EDDisassemblerRef disasm;
|
||||
EDInstRef cur_insn;
|
||||
|
||||
if (EDGetDisassembler (&disasm, "i386-apple-darwin", kEDAssemblySyntaxX86ATT) != 0)
|
||||
{
|
||||
false;
|
||||
}
|
||||
|
||||
uint64_t addr_offset = addr.GetOffset();
|
||||
struct edis_byte_read_token arg;
|
||||
arg.address = &addr;
|
||||
arg.target = &m_target;
|
||||
if (EDCreateInsts (&cur_insn, 1, disasm, read_byte_for_edis, addr_offset, &arg) != 1)
|
||||
{
|
||||
false;
|
||||
}
|
||||
length = EDInstByteSize (cur_insn);
|
||||
EDReleaseInst (cur_insn);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
AssemblyParse_x86::get_non_call_site_unwind_plan (UnwindPlan &unwind_plan)
|
||||
{
|
||||
UnwindPlan up;
|
||||
UnwindPlan::Row row;
|
||||
int non_prologue_insn_count = 0;
|
||||
Address m_cur_insn = m_func_bounds.GetBaseAddress ();
|
||||
int current_func_text_offset = 0;
|
||||
int current_sp_bytes_offset_from_cfa = 0;
|
||||
UnwindPlan::Row::RegisterLocation regloc;
|
||||
|
||||
unwind_plan.SetPlanValidAddressRange (m_func_bounds);
|
||||
unwind_plan.SetRegisterKind (eRegisterKindLLDB);
|
||||
|
||||
// At the start of the function, find the CFA by adding wordsize to the SP register
|
||||
row.SetOffset (current_func_text_offset);
|
||||
row.SetCFARegister (m_lldb_sp_regnum);
|
||||
row.SetCFAOffset (m_wordsize);
|
||||
|
||||
// caller's stack pointer value before the call insn is the CFA address
|
||||
regloc.SetIsCFAPlusOffset (0);
|
||||
row.SetRegisterInfo (m_lldb_sp_regnum, regloc);
|
||||
|
||||
// saved instruction pointer can be found at CFA - wordsize.
|
||||
current_sp_bytes_offset_from_cfa = m_wordsize;
|
||||
regloc.SetAtCFAPlusOffset (-current_sp_bytes_offset_from_cfa);
|
||||
row.SetRegisterInfo (m_lldb_ip_regnum, regloc);
|
||||
|
||||
unwind_plan.AppendRow (row);
|
||||
|
||||
while (m_func_bounds.ContainsFileAddress (m_cur_insn) && non_prologue_insn_count < 10)
|
||||
{
|
||||
int stack_offset, insn_len;
|
||||
int machine_regno; // register numbers masked directly out of instructions
|
||||
uint32_t lldb_regno; // register numbers in lldb's eRegisterKindLLDB numbering scheme
|
||||
Error error;
|
||||
|
||||
if (!instruction_length (m_cur_insn, insn_len) || insn_len == 0 || insn_len > kMaxInstructionByteSize)
|
||||
{
|
||||
// An unrecognized/junk instruction
|
||||
break;
|
||||
}
|
||||
if (m_target.ReadMemory (m_cur_insn, m_cur_insn_bytes, insn_len, error) == -1)
|
||||
{
|
||||
// Error reading the instruction out of the file, stop scanning
|
||||
break;
|
||||
}
|
||||
|
||||
if (push_rbp_pattern_p ())
|
||||
{
|
||||
row.SetOffset (current_func_text_offset + insn_len);
|
||||
current_sp_bytes_offset_from_cfa += m_wordsize;
|
||||
row.SetCFAOffset (current_sp_bytes_offset_from_cfa);
|
||||
UnwindPlan::Row::RegisterLocation regloc;
|
||||
regloc.SetAtCFAPlusOffset (-row.GetCFAOffset());
|
||||
row.SetRegisterInfo (m_lldb_fp_regnum, regloc);
|
||||
unwind_plan.AppendRow (row);
|
||||
goto loopnext;
|
||||
}
|
||||
|
||||
if (push_0_pattern_p ())
|
||||
{
|
||||
row.SetOffset (current_func_text_offset + insn_len);
|
||||
current_sp_bytes_offset_from_cfa += m_wordsize;
|
||||
row.SetCFAOffset (current_sp_bytes_offset_from_cfa);
|
||||
unwind_plan.AppendRow (row);
|
||||
goto loopnext;
|
||||
}
|
||||
|
||||
if (push_reg_p (machine_regno))
|
||||
{
|
||||
current_sp_bytes_offset_from_cfa += m_wordsize;
|
||||
if (nonvolatile_reg_p (machine_regno) && machine_regno_to_lldb_regno (machine_regno, lldb_regno))
|
||||
{
|
||||
row.SetOffset (current_func_text_offset + insn_len);
|
||||
if (row.GetCFARegister() == m_lldb_sp_regnum)
|
||||
{
|
||||
row.SetCFAOffset (current_sp_bytes_offset_from_cfa);
|
||||
}
|
||||
UnwindPlan::Row::RegisterLocation regloc;
|
||||
regloc.SetAtCFAPlusOffset (-current_sp_bytes_offset_from_cfa);
|
||||
row.SetRegisterInfo (lldb_regno, regloc);
|
||||
unwind_plan.AppendRow (row);
|
||||
}
|
||||
goto loopnext;
|
||||
}
|
||||
|
||||
if (mov_reg_to_local_stack_frame_p (machine_regno, stack_offset) && nonvolatile_reg_p (machine_regno))
|
||||
{
|
||||
if (machine_regno_to_lldb_regno (machine_regno, lldb_regno))
|
||||
{
|
||||
row.SetOffset (current_func_text_offset + insn_len);
|
||||
UnwindPlan::Row::RegisterLocation regloc;
|
||||
regloc.SetAtCFAPlusOffset (-row.GetCFAOffset());
|
||||
row.SetRegisterInfo (lldb_regno, regloc);
|
||||
unwind_plan.AppendRow (row);
|
||||
goto loopnext;
|
||||
}
|
||||
}
|
||||
|
||||
if (sub_rsp_pattern_p (stack_offset))
|
||||
{
|
||||
current_sp_bytes_offset_from_cfa += stack_offset;
|
||||
if (row.GetCFARegister() == m_lldb_sp_regnum)
|
||||
{
|
||||
row.SetOffset (current_func_text_offset + insn_len);
|
||||
row.SetCFAOffset (current_sp_bytes_offset_from_cfa);
|
||||
unwind_plan.AppendRow (row);
|
||||
}
|
||||
goto loopnext;
|
||||
}
|
||||
|
||||
if (mov_rsp_rbp_pattern_p ())
|
||||
{
|
||||
row.SetOffset (current_func_text_offset + insn_len);
|
||||
row.SetCFARegister (m_lldb_fp_regnum);
|
||||
unwind_plan.AppendRow (row);
|
||||
goto loopnext;
|
||||
}
|
||||
|
||||
if (ret_pattern_p ())
|
||||
{
|
||||
// we know where the end of the function is; set the limit on the PlanValidAddressRange
|
||||
// in case our initial "high pc" value was overly large
|
||||
// int original_size = m_func_bounds.GetByteSize();
|
||||
// int calculated_size = m_cur_insn.GetOffset() - m_func_bounds.GetBaseAddress().GetOffset() + insn_len + 1;
|
||||
// m_func_bounds.SetByteSize (calculated_size);
|
||||
// unwind_plan.SetPlanValidAddressRange (m_func_bounds);
|
||||
break;
|
||||
}
|
||||
|
||||
// FIXME recognize the i386 picbase setup instruction sequence,
|
||||
// 0x1f16: call 0x1f1b ; main + 11 at /private/tmp/a.c:3
|
||||
// 0x1f1b: popl %eax
|
||||
// and record the temporary stack movements if the CFA is not expressed in terms of ebp.
|
||||
|
||||
non_prologue_insn_count++;
|
||||
loopnext:
|
||||
m_cur_insn.SetOffset (m_cur_insn.GetOffset() + insn_len);
|
||||
current_func_text_offset += insn_len;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
AssemblyParse_x86::get_fast_unwind_plan (UnwindPlan &unwind_plan)
|
||||
{
|
||||
UnwindPlan up;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
AssemblyParse_x86::find_first_non_prologue_insn (Address &address)
|
||||
{
|
||||
m_cur_insn = m_func_bounds.GetBaseAddress ();
|
||||
while (m_func_bounds.ContainsFileAddress (m_cur_insn))
|
||||
{
|
||||
Error error;
|
||||
int insn_len, offset, regno;
|
||||
if (!instruction_length (m_cur_insn, insn_len) || insn_len > kMaxInstructionByteSize || insn_len == 0)
|
||||
{
|
||||
// An error parsing the instruction, i.e. probably data/garbage - stop scanning
|
||||
break;
|
||||
}
|
||||
if (m_target.ReadMemory (m_cur_insn, m_cur_insn_bytes, insn_len, error) == -1)
|
||||
{
|
||||
// Error reading the instruction out of the file, stop scanning
|
||||
break;
|
||||
}
|
||||
|
||||
if (push_rbp_pattern_p () || mov_rsp_rbp_pattern_p () || sub_rsp_pattern_p (offset)
|
||||
|| push_reg_p (regno) || mov_reg_to_local_stack_frame_p (regno, offset))
|
||||
{
|
||||
m_cur_insn.SetOffset (m_cur_insn.GetOffset() + insn_len);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Unknown non-prologue instruction - stop scanning
|
||||
break;
|
||||
}
|
||||
|
||||
address = m_cur_insn;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------------------------
|
||||
// UnwindAssemblyParser_x86 method definitions
|
||||
//-----------------------------------------------------------------------------------------------
|
||||
|
||||
bool
|
||||
UnwindAssemblyProfiler_x86::GetNonCallSiteUnwindPlanFromAssembly (AddressRange& func, Thread& thread, UnwindPlan& unwind_plan)
|
||||
{
|
||||
AssemblyParse_x86 asm_parse(thread.GetProcess().GetTarget(), &thread, m_cpu, func);
|
||||
return asm_parse.get_non_call_site_unwind_plan (unwind_plan);
|
||||
}
|
||||
|
||||
bool
|
||||
UnwindAssemblyProfiler_x86::GetFastUnwindPlan (AddressRange& func, Thread& thread, UnwindPlan &unwind_plan)
|
||||
{
|
||||
AssemblyParse_x86 asm_parse(thread.GetProcess().GetTarget(), &thread, m_cpu, func);
|
||||
return asm_parse.get_fast_unwind_plan (unwind_plan);
|
||||
}
|
||||
|
||||
bool
|
||||
UnwindAssemblyProfiler_x86::FirstNonPrologueInsn (AddressRange& func, Target& target, Thread* thread, Address& first_non_prologue_insn)
|
||||
{
|
||||
AssemblyParse_x86 asm_parse(target, thread, m_cpu, func);
|
||||
return asm_parse.find_first_non_prologue_insn (first_non_prologue_insn);
|
||||
}
|
||||
|
||||
lldb_private::UnwindAssemblyProfiler *
|
||||
UnwindAssemblyProfiler_x86::CreateInstance (const lldb_private::ArchSpec &arch)
|
||||
{
|
||||
uint32_t cpu = arch.GetCPUType ();
|
||||
if (cpu != CPU_TYPE_X86_64 && cpu != CPU_TYPE_I386)
|
||||
return NULL;
|
||||
|
||||
return new UnwindAssemblyProfiler_x86 (cpu == CPU_TYPE_X86_64 ? k_x86_64 : k_i386);
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// PluginInterface protocol in UnwindAssemblyParser_x86
|
||||
//------------------------------------------------------------------
|
||||
|
||||
const char *
|
||||
UnwindAssemblyProfiler_x86::GetPluginName()
|
||||
{
|
||||
return "UnwindAssemblyProfiler_x86";
|
||||
}
|
||||
|
||||
const char *
|
||||
UnwindAssemblyProfiler_x86::GetShortPluginName()
|
||||
{
|
||||
return "unwindassemblyprofiler.x86";
|
||||
}
|
||||
|
||||
|
||||
uint32_t
|
||||
UnwindAssemblyProfiler_x86::GetPluginVersion()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
UnwindAssemblyProfiler_x86::GetPluginCommandHelp (const char *command, Stream *strm)
|
||||
{
|
||||
}
|
||||
|
||||
Error
|
||||
UnwindAssemblyProfiler_x86::ExecutePluginCommand (Args &command, Stream *strm)
|
||||
{
|
||||
Error error;
|
||||
error.SetErrorString("No plug-in command are currently supported.");
|
||||
return error;
|
||||
}
|
||||
|
||||
Log *
|
||||
UnwindAssemblyProfiler_x86::EnablePluginLogging (Stream *strm, Args &command)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
UnwindAssemblyProfiler_x86::Initialize()
|
||||
{
|
||||
PluginManager::RegisterPlugin (GetPluginNameStatic(),
|
||||
GetPluginDescriptionStatic(),
|
||||
CreateInstance);
|
||||
}
|
||||
|
||||
void
|
||||
UnwindAssemblyProfiler_x86::Terminate()
|
||||
{
|
||||
PluginManager::UnregisterPlugin (CreateInstance);
|
||||
}
|
||||
|
||||
|
||||
const char *
|
||||
UnwindAssemblyProfiler_x86::GetPluginNameStatic()
|
||||
{
|
||||
return "UnwindAssemblyProfiler_x86";
|
||||
}
|
||||
|
||||
const char *
|
||||
UnwindAssemblyProfiler_x86::GetPluginDescriptionStatic()
|
||||
{
|
||||
return "i386 and x86_64 assembly language profiler plugin.";
|
||||
}
|
@ -0,0 +1,82 @@
|
||||
//===-- UnwindAssemblyProfiler-x86.h ----------------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef liblldb_UnwindAssemblyProfiler_x86_h_
|
||||
#define liblldb_UnwindAssemblyProfiler_x86_h_
|
||||
|
||||
#include "lldb/lldb-private.h"
|
||||
#include "lldb/Utility/UnwindAssemblyProfiler.h"
|
||||
#include "lldb/Target/Thread.h"
|
||||
|
||||
namespace lldb_private {
|
||||
|
||||
class UnwindAssemblyProfiler_x86 : public lldb_private::UnwindAssemblyProfiler
|
||||
{
|
||||
public:
|
||||
|
||||
~UnwindAssemblyProfiler_x86 () { }
|
||||
|
||||
virtual bool
|
||||
GetNonCallSiteUnwindPlanFromAssembly (AddressRange& func, lldb_private::Thread& thread, UnwindPlan& unwind_plan);
|
||||
|
||||
virtual bool
|
||||
GetFastUnwindPlan (AddressRange& func, lldb_private::Thread& thread, UnwindPlan &unwind_plan);
|
||||
|
||||
// thread may be NULL in which case we only use the Target (e.g. if this is called pre-process-launch).
|
||||
virtual bool
|
||||
FirstNonPrologueInsn (AddressRange& func, lldb_private::Target& target, lldb_private::Thread* thread, Address& first_non_prologue_insn);
|
||||
|
||||
static lldb_private::UnwindAssemblyProfiler *
|
||||
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:
|
||||
UnwindAssemblyProfiler_x86(int cpu) :
|
||||
lldb_private::UnwindAssemblyProfiler(), m_cpu(cpu) { } // Call CreateInstance instead.
|
||||
|
||||
int m_cpu;
|
||||
};
|
||||
|
||||
|
||||
} // namespace lldb_private
|
||||
|
||||
#endif // liblldb_UnwindAssemblyProfiler_x86_h_
|
@ -416,83 +416,83 @@ GDBRemoteDynamicRegisterInfo::HardcodeARMRegisters()
|
||||
static lldb::RegisterInfo
|
||||
g_register_infos[] =
|
||||
{
|
||||
// NAME ALT SZ OFF ENCODING FORMAT NUM COMPILER DWARF GENERIC
|
||||
// ====== ======= == ==== ============= ============ === =============== =============== =========
|
||||
{ "r0", NULL, 4, 0, eEncodingUint, eFormatHex, 0, { gcc_r0, dwarf_r0, LLDB_INVALID_REGNUM }},
|
||||
{ "r1", NULL, 4, 4, eEncodingUint, eFormatHex, 1, { gcc_r1, dwarf_r1, LLDB_INVALID_REGNUM }},
|
||||
{ "r2", NULL, 4, 8, eEncodingUint, eFormatHex, 2, { gcc_r2, dwarf_r2, LLDB_INVALID_REGNUM }},
|
||||
{ "r3", NULL, 4, 12, eEncodingUint, eFormatHex, 3, { gcc_r3, dwarf_r3, LLDB_INVALID_REGNUM }},
|
||||
{ "r4", NULL, 4, 16, eEncodingUint, eFormatHex, 4, { gcc_r4, dwarf_r4, LLDB_INVALID_REGNUM }},
|
||||
{ "r5", NULL, 4, 20, eEncodingUint, eFormatHex, 5, { gcc_r5, dwarf_r5, LLDB_INVALID_REGNUM }},
|
||||
{ "r6", NULL, 4, 24, eEncodingUint, eFormatHex, 6, { gcc_r6, dwarf_r6, LLDB_INVALID_REGNUM }},
|
||||
{ "r7", NULL, 4, 28, eEncodingUint, eFormatHex, 7, { gcc_r7, dwarf_r7, LLDB_REGNUM_GENERIC_FP }},
|
||||
{ "r8", NULL, 4, 32, eEncodingUint, eFormatHex, 8, { gcc_r8, dwarf_r8, LLDB_INVALID_REGNUM }},
|
||||
{ "r9", NULL, 4, 36, eEncodingUint, eFormatHex, 9, { gcc_r9, dwarf_r9, LLDB_INVALID_REGNUM }},
|
||||
{ "r10", NULL, 4, 40, eEncodingUint, eFormatHex, 10, { gcc_r10, dwarf_r10, LLDB_INVALID_REGNUM }},
|
||||
{ "r11", NULL, 4, 44, eEncodingUint, eFormatHex, 11, { gcc_r11, dwarf_r11, LLDB_INVALID_REGNUM }},
|
||||
{ "r12", NULL, 4, 48, eEncodingUint, eFormatHex, 12, { gcc_r12, dwarf_r12, LLDB_INVALID_REGNUM }},
|
||||
{ "sp", "r13", 4, 52, eEncodingUint, eFormatHex, 13, { gcc_sp, dwarf_sp, LLDB_REGNUM_GENERIC_SP }},
|
||||
{ "lr", "r14", 4, 56, eEncodingUint, eFormatHex, 14, { gcc_lr, dwarf_lr, LLDB_REGNUM_GENERIC_RA }},
|
||||
{ "pc", "r15", 4, 60, eEncodingUint, eFormatHex, 15, { gcc_pc, dwarf_pc, LLDB_REGNUM_GENERIC_PC }},
|
||||
{ NULL, NULL, 12, 64, eEncodingIEEE754, eFormatFloat, 16, { LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS }},
|
||||
{ NULL, NULL, 12, 76, eEncodingIEEE754, eFormatFloat, 17, { LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS }},
|
||||
{ NULL, NULL, 12, 88, eEncodingIEEE754, eFormatFloat, 18, { LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS }},
|
||||
{ NULL, NULL, 12, 100, eEncodingIEEE754, eFormatFloat, 19, { LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS }},
|
||||
{ NULL, NULL, 12, 112, eEncodingIEEE754, eFormatFloat, 20, { LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS }},
|
||||
{ NULL, NULL, 12, 124, eEncodingIEEE754, eFormatFloat, 21, { LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS }},
|
||||
{ NULL, NULL, 12, 136, eEncodingIEEE754, eFormatFloat, 22, { LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS }},
|
||||
{ NULL, NULL, 12, 148, eEncodingIEEE754, eFormatFloat, 23, { LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS }},
|
||||
{ NULL, NULL, 12, 160, eEncodingIEEE754, eFormatFloat, 24, { LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS }},
|
||||
{ "cpsr", "psr", 4, 172, eEncodingUint, eFormatHex, 25, { gcc_cpsr, dwarf_cpsr, LLDB_REGNUM_GENERIC_FLAGS }},
|
||||
{ "s0", NULL, 4, 176, eEncodingIEEE754, eFormatFloat, 26, { LLDB_INVALID_REGNUM, dwarf_s0, LLDB_INVALID_REGNUM }},
|
||||
{ "s1", NULL, 4, 180, eEncodingIEEE754, eFormatFloat, 27, { LLDB_INVALID_REGNUM, dwarf_s1, LLDB_INVALID_REGNUM }},
|
||||
{ "s2", NULL, 4, 184, eEncodingIEEE754, eFormatFloat, 28, { LLDB_INVALID_REGNUM, dwarf_s2, LLDB_INVALID_REGNUM }},
|
||||
{ "s3", NULL, 4, 188, eEncodingIEEE754, eFormatFloat, 29, { LLDB_INVALID_REGNUM, dwarf_s3, LLDB_INVALID_REGNUM }},
|
||||
{ "s4", NULL, 4, 192, eEncodingIEEE754, eFormatFloat, 30, { LLDB_INVALID_REGNUM, dwarf_s4, LLDB_INVALID_REGNUM }},
|
||||
{ "s5", NULL, 4, 196, eEncodingIEEE754, eFormatFloat, 31, { LLDB_INVALID_REGNUM, dwarf_s5, LLDB_INVALID_REGNUM }},
|
||||
{ "s6", NULL, 4, 200, eEncodingIEEE754, eFormatFloat, 32, { LLDB_INVALID_REGNUM, dwarf_s6, LLDB_INVALID_REGNUM }},
|
||||
{ "s7", NULL, 4, 204, eEncodingIEEE754, eFormatFloat, 33, { LLDB_INVALID_REGNUM, dwarf_s7, LLDB_INVALID_REGNUM }},
|
||||
{ "s8", NULL, 4, 208, eEncodingIEEE754, eFormatFloat, 34, { LLDB_INVALID_REGNUM, dwarf_s8, LLDB_INVALID_REGNUM }},
|
||||
{ "s9", NULL, 4, 212, eEncodingIEEE754, eFormatFloat, 35, { LLDB_INVALID_REGNUM, dwarf_s9, LLDB_INVALID_REGNUM }},
|
||||
{ "s10", NULL, 4, 216, eEncodingIEEE754, eFormatFloat, 36, { LLDB_INVALID_REGNUM, dwarf_s10, LLDB_INVALID_REGNUM }},
|
||||
{ "s11", NULL, 4, 220, eEncodingIEEE754, eFormatFloat, 37, { LLDB_INVALID_REGNUM, dwarf_s11, LLDB_INVALID_REGNUM }},
|
||||
{ "s12", NULL, 4, 224, eEncodingIEEE754, eFormatFloat, 38, { LLDB_INVALID_REGNUM, dwarf_s12, LLDB_INVALID_REGNUM }},
|
||||
{ "s13", NULL, 4, 228, eEncodingIEEE754, eFormatFloat, 39, { LLDB_INVALID_REGNUM, dwarf_s13, LLDB_INVALID_REGNUM }},
|
||||
{ "s14", NULL, 4, 232, eEncodingIEEE754, eFormatFloat, 40, { LLDB_INVALID_REGNUM, dwarf_s14, LLDB_INVALID_REGNUM }},
|
||||
{ "s15", NULL, 4, 236, eEncodingIEEE754, eFormatFloat, 41, { LLDB_INVALID_REGNUM, dwarf_s15, LLDB_INVALID_REGNUM }},
|
||||
{ "s16", NULL, 4, 240, eEncodingIEEE754, eFormatFloat, 42, { LLDB_INVALID_REGNUM, dwarf_s16, LLDB_INVALID_REGNUM }},
|
||||
{ "s17", NULL, 4, 244, eEncodingIEEE754, eFormatFloat, 43, { LLDB_INVALID_REGNUM, dwarf_s17, LLDB_INVALID_REGNUM }},
|
||||
{ "s18", NULL, 4, 248, eEncodingIEEE754, eFormatFloat, 44, { LLDB_INVALID_REGNUM, dwarf_s18, LLDB_INVALID_REGNUM }},
|
||||
{ "s19", NULL, 4, 252, eEncodingIEEE754, eFormatFloat, 45, { LLDB_INVALID_REGNUM, dwarf_s19, LLDB_INVALID_REGNUM }},
|
||||
{ "s20", NULL, 4, 256, eEncodingIEEE754, eFormatFloat, 46, { LLDB_INVALID_REGNUM, dwarf_s20, LLDB_INVALID_REGNUM }},
|
||||
{ "s21", NULL, 4, 260, eEncodingIEEE754, eFormatFloat, 47, { LLDB_INVALID_REGNUM, dwarf_s21, LLDB_INVALID_REGNUM }},
|
||||
{ "s22", NULL, 4, 264, eEncodingIEEE754, eFormatFloat, 48, { LLDB_INVALID_REGNUM, dwarf_s22, LLDB_INVALID_REGNUM }},
|
||||
{ "s23", NULL, 4, 268, eEncodingIEEE754, eFormatFloat, 49, { LLDB_INVALID_REGNUM, dwarf_s23, LLDB_INVALID_REGNUM }},
|
||||
{ "s24", NULL, 4, 272, eEncodingIEEE754, eFormatFloat, 50, { LLDB_INVALID_REGNUM, dwarf_s24, LLDB_INVALID_REGNUM }},
|
||||
{ "s25", NULL, 4, 276, eEncodingIEEE754, eFormatFloat, 51, { LLDB_INVALID_REGNUM, dwarf_s25, LLDB_INVALID_REGNUM }},
|
||||
{ "s26", NULL, 4, 280, eEncodingIEEE754, eFormatFloat, 52, { LLDB_INVALID_REGNUM, dwarf_s26, LLDB_INVALID_REGNUM }},
|
||||
{ "s27", NULL, 4, 284, eEncodingIEEE754, eFormatFloat, 53, { LLDB_INVALID_REGNUM, dwarf_s27, LLDB_INVALID_REGNUM }},
|
||||
{ "s28", NULL, 4, 288, eEncodingIEEE754, eFormatFloat, 54, { LLDB_INVALID_REGNUM, dwarf_s28, LLDB_INVALID_REGNUM }},
|
||||
{ "s29", NULL, 4, 292, eEncodingIEEE754, eFormatFloat, 55, { LLDB_INVALID_REGNUM, dwarf_s29, LLDB_INVALID_REGNUM }},
|
||||
{ "s30", NULL, 4, 296, eEncodingIEEE754, eFormatFloat, 56, { LLDB_INVALID_REGNUM, dwarf_s30, LLDB_INVALID_REGNUM }},
|
||||
{ "s31", NULL, 4, 300, eEncodingIEEE754, eFormatFloat, 57, { LLDB_INVALID_REGNUM, dwarf_s31, LLDB_INVALID_REGNUM }},
|
||||
{ "fpscr", NULL, 4, 304, eEncodingUint, eFormatHex, 58, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,LLDB_INVALID_REGNUM }},
|
||||
{ "d16", NULL, 8, 308, eEncodingIEEE754, eFormatFloat, 59, { LLDB_INVALID_REGNUM, dwarf_d16, LLDB_INVALID_REGNUM }},
|
||||
{ "d17", NULL, 8, 316, eEncodingIEEE754, eFormatFloat, 60, { LLDB_INVALID_REGNUM, dwarf_d17, LLDB_INVALID_REGNUM }},
|
||||
{ "d18", NULL, 8, 324, eEncodingIEEE754, eFormatFloat, 61, { LLDB_INVALID_REGNUM, dwarf_d18, LLDB_INVALID_REGNUM }},
|
||||
{ "d19", NULL, 8, 332, eEncodingIEEE754, eFormatFloat, 62, { LLDB_INVALID_REGNUM, dwarf_d19, LLDB_INVALID_REGNUM }},
|
||||
{ "d20", NULL, 8, 340, eEncodingIEEE754, eFormatFloat, 63, { LLDB_INVALID_REGNUM, dwarf_d20, LLDB_INVALID_REGNUM }},
|
||||
{ "d21", NULL, 8, 348, eEncodingIEEE754, eFormatFloat, 64, { LLDB_INVALID_REGNUM, dwarf_d21, LLDB_INVALID_REGNUM }},
|
||||
{ "d22", NULL, 8, 356, eEncodingIEEE754, eFormatFloat, 65, { LLDB_INVALID_REGNUM, dwarf_d22, LLDB_INVALID_REGNUM }},
|
||||
{ "d23", NULL, 8, 364, eEncodingIEEE754, eFormatFloat, 66, { LLDB_INVALID_REGNUM, dwarf_d23, LLDB_INVALID_REGNUM }},
|
||||
{ "d24", NULL, 8, 372, eEncodingIEEE754, eFormatFloat, 67, { LLDB_INVALID_REGNUM, dwarf_d24, LLDB_INVALID_REGNUM }},
|
||||
{ "d25", NULL, 8, 380, eEncodingIEEE754, eFormatFloat, 68, { LLDB_INVALID_REGNUM, dwarf_d25, LLDB_INVALID_REGNUM }},
|
||||
{ "d26", NULL, 8, 388, eEncodingIEEE754, eFormatFloat, 69, { LLDB_INVALID_REGNUM, dwarf_d26, LLDB_INVALID_REGNUM }},
|
||||
{ "d27", NULL, 8, 396, eEncodingIEEE754, eFormatFloat, 70, { LLDB_INVALID_REGNUM, dwarf_d27, LLDB_INVALID_REGNUM }},
|
||||
{ "d28", NULL, 8, 404, eEncodingIEEE754, eFormatFloat, 71, { LLDB_INVALID_REGNUM, dwarf_d28, LLDB_INVALID_REGNUM }},
|
||||
{ "d29", NULL, 8, 412, eEncodingIEEE754, eFormatFloat, 72, { LLDB_INVALID_REGNUM, dwarf_d29, LLDB_INVALID_REGNUM }},
|
||||
{ "d30", NULL, 8, 420, eEncodingIEEE754, eFormatFloat, 73, { LLDB_INVALID_REGNUM, dwarf_d30, LLDB_INVALID_REGNUM }},
|
||||
{ "d31", NULL, 8, 428, eEncodingIEEE754, eFormatFloat, 74, { LLDB_INVALID_REGNUM, dwarf_d31, LLDB_INVALID_REGNUM }},
|
||||
// NAME ALT SZ OFF ENCODING FORMAT COMPILER DWARF GENERIC GDB LLDB NATIVE
|
||||
// ====== ======= == ==== ============= ============ =============== =============== ========= ===== ===========
|
||||
{ "r0", NULL, 4, 0, eEncodingUint, eFormatHex, { gcc_r0, dwarf_r0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 0 }},
|
||||
{ "r1", NULL, 4, 4, eEncodingUint, eFormatHex, { gcc_r1, dwarf_r1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 1 }},
|
||||
{ "r2", NULL, 4, 8, eEncodingUint, eFormatHex, { gcc_r2, dwarf_r2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 2 }},
|
||||
{ "r3", NULL, 4, 12, eEncodingUint, eFormatHex, { gcc_r3, dwarf_r3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 3 }},
|
||||
{ "r4", NULL, 4, 16, eEncodingUint, eFormatHex, { gcc_r4, dwarf_r4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 4 }},
|
||||
{ "r5", NULL, 4, 20, eEncodingUint, eFormatHex, { gcc_r5, dwarf_r5, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 5 }},
|
||||
{ "r6", NULL, 4, 24, eEncodingUint, eFormatHex, { gcc_r6, dwarf_r6, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 6 }},
|
||||
{ "r7", NULL, 4, 28, eEncodingUint, eFormatHex, { gcc_r7, dwarf_r7, LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM, 7 }},
|
||||
{ "r8", NULL, 4, 32, eEncodingUint, eFormatHex, { gcc_r8, dwarf_r8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 8 }},
|
||||
{ "r9", NULL, 4, 36, eEncodingUint, eFormatHex, { gcc_r9, dwarf_r9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 9 }},
|
||||
{ "r10", NULL, 4, 40, eEncodingUint, eFormatHex, { gcc_r10, dwarf_r10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 10 }},
|
||||
{ "r11", NULL, 4, 44, eEncodingUint, eFormatHex, { gcc_r11, dwarf_r11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 11 }},
|
||||
{ "r12", NULL, 4, 48, eEncodingUint, eFormatHex, { gcc_r12, dwarf_r12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 12 }},
|
||||
{ "sp", "r13", 4, 52, eEncodingUint, eFormatHex, { gcc_sp, dwarf_sp, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM, 13 }},
|
||||
{ "lr", "r14", 4, 56, eEncodingUint, eFormatHex, { gcc_lr, dwarf_lr, LLDB_REGNUM_GENERIC_RA, LLDB_INVALID_REGNUM, 14 }},
|
||||
{ "pc", "r15", 4, 60, eEncodingUint, eFormatHex, { gcc_pc, dwarf_pc, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM, 15 }},
|
||||
{ NULL, NULL, 12, 64, eEncodingIEEE754, eFormatFloat, { LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, 16 }},
|
||||
{ NULL, NULL, 12, 76, eEncodingIEEE754, eFormatFloat, { LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, 17 }},
|
||||
{ NULL, NULL, 12, 88, eEncodingIEEE754, eFormatFloat, { LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, 18 }},
|
||||
{ NULL, NULL, 12, 100, eEncodingIEEE754, eFormatFloat, { LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, 19 }},
|
||||
{ NULL, NULL, 12, 112, eEncodingIEEE754, eFormatFloat, { LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, 20 }},
|
||||
{ NULL, NULL, 12, 124, eEncodingIEEE754, eFormatFloat, { LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, 21 }},
|
||||
{ NULL, NULL, 12, 136, eEncodingIEEE754, eFormatFloat, { LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, 22 }},
|
||||
{ NULL, NULL, 12, 148, eEncodingIEEE754, eFormatFloat, { LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, 23 }},
|
||||
{ NULL, NULL, 12, 160, eEncodingIEEE754, eFormatFloat, { LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, 24 }},
|
||||
{ "cpsr", "psr", 4, 172, eEncodingUint, eFormatHex, { gcc_cpsr, dwarf_cpsr, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, 25 }},
|
||||
{ "s0", NULL, 4, 176, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 26 }},
|
||||
{ "s1", NULL, 4, 180, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 27 }},
|
||||
{ "s2", NULL, 4, 184, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 28 }},
|
||||
{ "s3", NULL, 4, 188, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 29 }},
|
||||
{ "s4", NULL, 4, 192, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s4, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 30 }},
|
||||
{ "s5", NULL, 4, 196, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s5, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 31 }},
|
||||
{ "s6", NULL, 4, 200, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s6, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 32 }},
|
||||
{ "s7", NULL, 4, 204, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s7, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 33 }},
|
||||
{ "s8", NULL, 4, 208, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 34 }},
|
||||
{ "s9", NULL, 4, 212, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 35 }},
|
||||
{ "s10", NULL, 4, 216, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 36 }},
|
||||
{ "s11", NULL, 4, 220, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 37 }},
|
||||
{ "s12", NULL, 4, 224, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 38 }},
|
||||
{ "s13", NULL, 4, 228, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s13, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 39 }},
|
||||
{ "s14", NULL, 4, 232, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s14, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 40 }},
|
||||
{ "s15", NULL, 4, 236, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s15, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 41 }},
|
||||
{ "s16", NULL, 4, 240, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s16, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 42 }},
|
||||
{ "s17", NULL, 4, 244, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s17, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 43 }},
|
||||
{ "s18", NULL, 4, 248, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s18, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 44 }},
|
||||
{ "s19", NULL, 4, 252, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s19, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 45 }},
|
||||
{ "s20", NULL, 4, 256, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s20, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 46 }},
|
||||
{ "s21", NULL, 4, 260, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s21, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 47 }},
|
||||
{ "s22", NULL, 4, 264, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s22, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 48 }},
|
||||
{ "s23", NULL, 4, 268, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s23, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 49 }},
|
||||
{ "s24", NULL, 4, 272, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s24, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 50 }},
|
||||
{ "s25", NULL, 4, 276, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s25, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 51 }},
|
||||
{ "s26", NULL, 4, 280, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s26, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 52 }},
|
||||
{ "s27", NULL, 4, 284, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s27, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 53 }},
|
||||
{ "s28", NULL, 4, 288, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s28, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 54 }},
|
||||
{ "s29", NULL, 4, 292, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s29, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 55 }},
|
||||
{ "s30", NULL, 4, 296, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s30, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 56 }},
|
||||
{ "s31", NULL, 4, 300, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s31, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 57 }},
|
||||
{ "fpscr", NULL, 4, 304, eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 58 }},
|
||||
{ "d16", NULL, 8, 308, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d16, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 59 }},
|
||||
{ "d17", NULL, 8, 316, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d17, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 60 }},
|
||||
{ "d18", NULL, 8, 324, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d18, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 61 }},
|
||||
{ "d19", NULL, 8, 332, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d19, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 62 }},
|
||||
{ "d20", NULL, 8, 340, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d20, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 63 }},
|
||||
{ "d21", NULL, 8, 348, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d21, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 64 }},
|
||||
{ "d22", NULL, 8, 356, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d22, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 65 }},
|
||||
{ "d23", NULL, 8, 364, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d23, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 66 }},
|
||||
{ "d24", NULL, 8, 372, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d24, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 67 }},
|
||||
{ "d25", NULL, 8, 380, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d25, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 68 }},
|
||||
{ "d26", NULL, 8, 388, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d26, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 69 }},
|
||||
{ "d27", NULL, 8, 396, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d27, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 70 }},
|
||||
{ "d28", NULL, 8, 404, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d28, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 71 }},
|
||||
{ "d29", NULL, 8, 412, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d29, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 72 }},
|
||||
{ "d30", NULL, 8, 420, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d30, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 73 }},
|
||||
{ "d31", NULL, 8, 428, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d31, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 74 }},
|
||||
};
|
||||
static const uint32_t num_registers = sizeof (g_register_infos)/sizeof (lldb::RegisterInfo);
|
||||
static ConstString gpr_reg_set ("General Purpose Registers");
|
||||
|
@ -17,6 +17,7 @@
|
||||
// Other libraries and framework includes
|
||||
// Project includes
|
||||
#include "lldb/lldb-private.h"
|
||||
#include "lldb/lldb-enumerations.h"
|
||||
#include "lldb/Core/ConstString.h"
|
||||
#include "lldb/Core/DataExtractor.h"
|
||||
#include "lldb/Target/RegisterContext.h"
|
||||
|
@ -214,12 +214,12 @@ ProcessGDBRemote::BuildDynamicRegisterInfo ()
|
||||
reg_offset, // offset
|
||||
eEncodingUint, // encoding
|
||||
eFormatHex, // formate
|
||||
reg_num, // native register number
|
||||
{
|
||||
LLDB_INVALID_REGNUM, // GCC reg num
|
||||
LLDB_INVALID_REGNUM, // DWARF reg num
|
||||
LLDB_INVALID_REGNUM, // generic reg num
|
||||
reg_num // GDB reg num
|
||||
reg_num, // GDB reg num
|
||||
reg_num // native register number
|
||||
}
|
||||
};
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
126
lldb/source/Symbol/FuncUnwinders.cpp
Normal file
126
lldb/source/Symbol/FuncUnwinders.cpp
Normal file
@ -0,0 +1,126 @@
|
||||
//===-- FuncUnwinders.cpp ----------------------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "lldb/lldb-private.h"
|
||||
#include "lldb/Symbol/FuncUnwinders.h"
|
||||
#include "lldb/Symbol/ObjectFile.h"
|
||||
#include "lldb/Symbol/UnwindPlan.h"
|
||||
#include "lldb/Core/AddressRange.h"
|
||||
#include "lldb/Core/Address.h"
|
||||
#include "lldb/Symbol/UnwindTable.h"
|
||||
#include "lldb/Utility/UnwindAssemblyProfiler.h"
|
||||
#include "lldb/Utility/ArchDefaultUnwindPlan.h"
|
||||
#include "lldb/Symbol/DWARFCallFrameInfo.h"
|
||||
#include "lldb/Target/Thread.h"
|
||||
#include "lldb/Target/Target.h"
|
||||
|
||||
using namespace lldb;
|
||||
using namespace lldb_private;
|
||||
|
||||
|
||||
FuncUnwinders::FuncUnwinders (UnwindTable& unwind_table, UnwindAssemblyProfiler *assembly_profiler, AddressRange range) :
|
||||
m_unwind_table(unwind_table),
|
||||
m_assembly_profiler(assembly_profiler),
|
||||
m_range(range),
|
||||
m_unwind_at_call_site(NULL),
|
||||
m_unwind_at_non_call_site(NULL),
|
||||
m_fast_unwind(NULL),
|
||||
m_arch_default_unwind(NULL),
|
||||
m_first_non_prologue_insn() { }
|
||||
|
||||
FuncUnwinders::~FuncUnwinders ()
|
||||
{
|
||||
if (m_unwind_at_call_site)
|
||||
delete m_unwind_at_call_site;
|
||||
if (m_unwind_at_non_call_site)
|
||||
delete m_unwind_at_non_call_site;
|
||||
if (m_fast_unwind)
|
||||
delete m_fast_unwind;
|
||||
if (m_arch_default_unwind)
|
||||
delete m_arch_default_unwind;
|
||||
}
|
||||
|
||||
UnwindPlan*
|
||||
FuncUnwinders::GetUnwindPlanAtCallSite ()
|
||||
{
|
||||
if (m_unwind_at_call_site != NULL)
|
||||
return m_unwind_at_call_site;
|
||||
if (!m_range.GetBaseAddress().IsValid())
|
||||
return NULL;
|
||||
|
||||
DWARFCallFrameInfo *eh_frame = m_unwind_table.GetEHFrameInfo();
|
||||
if (eh_frame)
|
||||
{
|
||||
UnwindPlan *up = new UnwindPlan;
|
||||
if (eh_frame->GetUnwindPlan (m_range.GetBaseAddress (), *up) == true)
|
||||
{
|
||||
m_unwind_at_call_site = up;
|
||||
return m_unwind_at_call_site;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
UnwindPlan*
|
||||
FuncUnwinders::GetUnwindPlanAtNonCallSite (Thread& thread)
|
||||
{
|
||||
if (m_unwind_at_non_call_site != NULL)
|
||||
m_unwind_at_non_call_site;
|
||||
m_unwind_at_non_call_site = new UnwindPlan;
|
||||
m_assembly_profiler->GetNonCallSiteUnwindPlanFromAssembly (m_range, thread, *m_unwind_at_non_call_site);
|
||||
return m_unwind_at_non_call_site;
|
||||
}
|
||||
|
||||
UnwindPlan*
|
||||
FuncUnwinders::GetUnwindPlanFastUnwind (Thread& thread)
|
||||
{
|
||||
if (m_fast_unwind != NULL)
|
||||
return m_fast_unwind;
|
||||
m_fast_unwind = new UnwindPlan;
|
||||
m_assembly_profiler->GetFastUnwindPlan (m_range, thread, *m_fast_unwind);
|
||||
return m_fast_unwind;
|
||||
}
|
||||
|
||||
UnwindPlan*
|
||||
FuncUnwinders::GetUnwindPlanArchitectureDefault (Thread& thread)
|
||||
{
|
||||
if (m_arch_default_unwind != NULL)
|
||||
return m_arch_default_unwind;
|
||||
|
||||
Address current_pc;
|
||||
Target *target = thread.CalculateTarget();
|
||||
ArchSpec arch;
|
||||
if (target)
|
||||
{
|
||||
ArchSpec arch = target->GetArchitecture ();
|
||||
ArchDefaultUnwindPlan *arch_default = ArchDefaultUnwindPlan::FindPlugin (arch);
|
||||
if (arch_default)
|
||||
{
|
||||
m_arch_default_unwind = arch_default->GetArchDefaultUnwindPlan (thread, current_pc);
|
||||
}
|
||||
}
|
||||
|
||||
return m_arch_default_unwind;
|
||||
}
|
||||
|
||||
Address&
|
||||
FuncUnwinders::GetFirstNonPrologueInsn (Target& target)
|
||||
{
|
||||
if (m_first_non_prologue_insn.IsValid())
|
||||
return m_first_non_prologue_insn;
|
||||
m_assembly_profiler->FirstNonPrologueInsn (m_range, target, NULL, m_first_non_prologue_insn);
|
||||
return m_first_non_prologue_insn;
|
||||
}
|
||||
|
||||
const Address&
|
||||
FuncUnwinders::GetFunctionStartAddress () const
|
||||
{
|
||||
return m_range.GetBaseAddress();
|
||||
}
|
||||
|
309
lldb/source/Symbol/UnwindPlan.cpp
Normal file
309
lldb/source/Symbol/UnwindPlan.cpp
Normal file
@ -0,0 +1,309 @@
|
||||
//===-- UnwindPlan.cpp ----------------------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "lldb/Symbol/UnwindPlan.h"
|
||||
#include "lldb/Target/Thread.h"
|
||||
#include "lldb/Target/RegisterContext.h"
|
||||
|
||||
using namespace lldb;
|
||||
using namespace lldb_private;
|
||||
|
||||
bool
|
||||
UnwindPlan::Row::RegisterLocation::operator == (const UnwindPlan::Row::RegisterLocation& rhs) const
|
||||
{
|
||||
if (m_type != rhs.m_type)
|
||||
return false;
|
||||
if (m_type == atCFAPlusOffset || m_type == isCFAPlusOffset)
|
||||
return m_location.offset == rhs.m_location.offset;
|
||||
if (m_type == inOtherRegister)
|
||||
return m_location.reg_num == rhs.m_location.reg_num;
|
||||
if (m_type == atDWARFExpression || m_type == isDWARFExpression)
|
||||
if (m_location.expr.length == rhs.m_location.expr.length)
|
||||
return !memcmp (m_location.expr.opcodes, rhs.m_location.expr.opcodes, m_location.expr.length);
|
||||
return false;
|
||||
}
|
||||
|
||||
// This function doesn't copy the dwarf expression bytes; they must remain in allocated
|
||||
// memory for the lifespan of this UnwindPlan object.
|
||||
void
|
||||
UnwindPlan::Row::RegisterLocation::SetAtDWARFExpression (const uint8_t *opcodes, uint32_t len)
|
||||
{
|
||||
m_type = atDWARFExpression;
|
||||
m_location.expr.opcodes = opcodes;
|
||||
m_location.expr.length = len;
|
||||
}
|
||||
|
||||
// This function doesn't copy the dwarf expression bytes; they must remain in allocated
|
||||
// memory for the lifespan of this UnwindPlan object.
|
||||
void
|
||||
UnwindPlan::Row::RegisterLocation::SetIsDWARFExpression (const uint8_t *opcodes, uint32_t len)
|
||||
{
|
||||
m_type = isDWARFExpression;
|
||||
m_location.expr.opcodes = opcodes;
|
||||
m_location.expr.length = len;
|
||||
}
|
||||
|
||||
void
|
||||
UnwindPlan::Row::RegisterLocation::SetUnspecified ()
|
||||
{
|
||||
m_type = unspecified;
|
||||
}
|
||||
|
||||
void
|
||||
UnwindPlan::Row::RegisterLocation::SetUndefined ()
|
||||
{
|
||||
m_type = isUndefined;
|
||||
}
|
||||
|
||||
void
|
||||
UnwindPlan::Row::RegisterLocation::SetSame ()
|
||||
{
|
||||
m_type = isSame;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
UnwindPlan::Row::RegisterLocation::SetAtCFAPlusOffset (int32_t offset)
|
||||
{
|
||||
m_type = atCFAPlusOffset;
|
||||
m_location.offset = offset;
|
||||
}
|
||||
|
||||
void
|
||||
UnwindPlan::Row::RegisterLocation::SetIsCFAPlusOffset (int32_t offset)
|
||||
{
|
||||
m_type = isCFAPlusOffset;
|
||||
m_location.offset = offset;
|
||||
}
|
||||
|
||||
void
|
||||
UnwindPlan::Row::RegisterLocation::SetInRegister (uint32_t reg_num)
|
||||
{
|
||||
m_type = inOtherRegister;
|
||||
m_location.reg_num = reg_num;
|
||||
}
|
||||
|
||||
void
|
||||
UnwindPlan::Row::RegisterLocation::Dump (Stream &s) const
|
||||
{
|
||||
switch (m_type)
|
||||
{
|
||||
case unspecified:
|
||||
s.Printf ("unspecified");
|
||||
break;
|
||||
case isUndefined:
|
||||
s.Printf ("isUndefined");
|
||||
break;
|
||||
case isSame:
|
||||
s.Printf ("isSame");
|
||||
break;
|
||||
case atCFAPlusOffset:
|
||||
s.Printf ("atCFAPlusOffset %d", m_location.offset);
|
||||
break;
|
||||
case isCFAPlusOffset:
|
||||
s.Printf ("isCFAPlusOffset %d", m_location.offset);
|
||||
break;
|
||||
case inOtherRegister:
|
||||
s.Printf ("inOtherRegister %d", m_location.reg_num);
|
||||
break;
|
||||
case atDWARFExpression:
|
||||
s.Printf ("atDWARFExpression");
|
||||
break;
|
||||
case isDWARFExpression:
|
||||
s.Printf ("isDWARFExpression");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
UnwindPlan::Row::Clear ()
|
||||
{
|
||||
m_offset = 0;
|
||||
m_cfa_reg_num = 0;
|
||||
m_cfa_offset = 0;
|
||||
m_register_locations.clear();
|
||||
}
|
||||
|
||||
void
|
||||
UnwindPlan::Row::Dump (Stream& s, int register_kind, Thread* thread) const
|
||||
{
|
||||
RegisterContext *rctx = NULL;
|
||||
const RegisterInfo *rinfo = NULL;
|
||||
int translated_regnum;
|
||||
if (thread && thread->GetRegisterContext())
|
||||
{
|
||||
rctx = thread->GetRegisterContext();
|
||||
}
|
||||
s.Printf ("offset %ld, CFA reg ", (long) GetOffset());
|
||||
if (rctx
|
||||
&& (translated_regnum = rctx->ConvertRegisterKindToRegisterNumber (register_kind, GetCFARegister())) != -1
|
||||
&& (rinfo = rctx->GetRegisterInfoAtIndex (translated_regnum)) != NULL
|
||||
&& rinfo->name != NULL
|
||||
&& rinfo->name[0] != '\0')
|
||||
{
|
||||
s.Printf ("%s, ", rinfo->name);
|
||||
}
|
||||
else
|
||||
{
|
||||
s.Printf ("%d, ", (int)(int) GetCFARegister());
|
||||
}
|
||||
s.Printf ("CFA offset %d", (int) GetCFAOffset ());
|
||||
for (collection::const_iterator idx = m_register_locations.begin (); idx != m_register_locations.end (); ++idx)
|
||||
{
|
||||
s.Printf (" [");
|
||||
bool printed_name = false;
|
||||
if (thread && thread->GetRegisterContext())
|
||||
{
|
||||
rctx = thread->GetRegisterContext();
|
||||
translated_regnum = rctx->ConvertRegisterKindToRegisterNumber (register_kind, idx->first);
|
||||
rinfo = rctx->GetRegisterInfoAtIndex (translated_regnum);
|
||||
if (rinfo && rinfo->name)
|
||||
{
|
||||
s.Printf ("%s ", rinfo->name);
|
||||
printed_name = true;
|
||||
}
|
||||
}
|
||||
if (!printed_name)
|
||||
{
|
||||
s.Printf ("reg %d ", idx->first);
|
||||
}
|
||||
idx->second.Dump(s);
|
||||
s.Printf ("]");
|
||||
}
|
||||
s.Printf ("\n");
|
||||
}
|
||||
|
||||
UnwindPlan::Row::Row() :
|
||||
m_offset(0),
|
||||
m_cfa_reg_num(0),
|
||||
m_cfa_offset(0),
|
||||
m_register_locations()
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
UnwindPlan::Row::GetRegisterInfo (uint32_t reg_num, UnwindPlan::Row::RegisterLocation& register_location) const
|
||||
{
|
||||
collection::const_iterator pos = m_register_locations.find(reg_num);
|
||||
if (pos != m_register_locations.end())
|
||||
{
|
||||
register_location = pos->second;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
UnwindPlan::Row::SetRegisterInfo (uint32_t reg_num, const UnwindPlan::Row::RegisterLocation register_location)
|
||||
{
|
||||
m_register_locations[reg_num] = register_location;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
UnwindPlan::AppendRow (const UnwindPlan::Row &row)
|
||||
{
|
||||
if (m_row_list.empty() || m_row_list.back().GetOffset() != row.GetOffset())
|
||||
m_row_list.push_back(row);
|
||||
else
|
||||
m_row_list.back() = row;
|
||||
}
|
||||
|
||||
const UnwindPlan::Row *
|
||||
UnwindPlan::GetRowForFunctionOffset (int offset) const
|
||||
{
|
||||
const UnwindPlan::Row *rowp = NULL;
|
||||
for (int i = 0; i < m_row_list.size(); ++i)
|
||||
{
|
||||
if (m_row_list[i].GetOffset() <= offset)
|
||||
{
|
||||
rowp = &m_row_list[i];
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
return rowp;
|
||||
}
|
||||
|
||||
bool
|
||||
UnwindPlan::IsValidRowIndex (uint32_t idx) const
|
||||
{
|
||||
return idx < m_row_list.size();
|
||||
}
|
||||
|
||||
const UnwindPlan::Row&
|
||||
UnwindPlan::GetRowAtIndex (uint32_t idx) const
|
||||
{
|
||||
// You must call IsValidRowIndex(idx) first before calling this!!!
|
||||
return m_row_list[idx];
|
||||
}
|
||||
|
||||
int
|
||||
UnwindPlan::GetRowCount () const
|
||||
{
|
||||
return m_row_list.size ();
|
||||
}
|
||||
|
||||
void
|
||||
UnwindPlan::SetRegisterKind (uint32_t rk)
|
||||
{
|
||||
m_register_kind = rk;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
UnwindPlan::GetRegisterKind (void) const
|
||||
{
|
||||
return m_register_kind;
|
||||
}
|
||||
|
||||
void
|
||||
UnwindPlan::SetPlanValidAddressRange (const AddressRange& range)
|
||||
{
|
||||
m_plan_valid_address_range = range;
|
||||
// .GetBaseAddress() = addr;
|
||||
// m_plan_valid_address_range.SetByteSize (range.GetByteSize());
|
||||
}
|
||||
|
||||
bool
|
||||
UnwindPlan::PlanValidAtAddress (Address addr)
|
||||
{
|
||||
if (!m_plan_valid_address_range.GetBaseAddress().IsValid())
|
||||
return true;
|
||||
|
||||
if (m_plan_valid_address_range.ContainsFileAddress (addr))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
UnwindPlan::Dump (Stream& s, Process* process, Thread *thread) const
|
||||
{
|
||||
s.Printf ("Address range of this UnwindPlan: ");
|
||||
m_plan_valid_address_range.Dump (&s, process, Address::DumpStyleSectionNameOffset);
|
||||
s.Printf ("\n");
|
||||
s.Printf ("UnwindPlan register kind %d", m_register_kind);
|
||||
switch (m_register_kind)
|
||||
{
|
||||
case eRegisterKindGCC: s.Printf (" [eRegisterKindGCC]"); break;
|
||||
case eRegisterKindDWARF: s.Printf (" [eRegisterKindDWARF]"); break;
|
||||
case eRegisterKindGeneric: s.Printf (" [eRegisterKindGeneric]"); break;
|
||||
case eRegisterKindGDB: s.Printf (" [eRegisterKindGDB]"); break;
|
||||
case eRegisterKindLLDB: s.Printf (" [eRegisterKindLLDB]"); break;
|
||||
default: break;
|
||||
}
|
||||
s.Printf ("\n");
|
||||
for (int i = 0; IsValidRowIndex (i); i++)
|
||||
{
|
||||
s.Printf ("UnwindPlan row at index %d: ", i);
|
||||
m_row_list[i].Dump(s, m_register_kind, thread);
|
||||
}
|
||||
}
|
132
lldb/source/Symbol/UnwindTable.cpp
Normal file
132
lldb/source/Symbol/UnwindTable.cpp
Normal file
@ -0,0 +1,132 @@
|
||||
//===-- UnwindTable.cpp ----------------------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "lldb/Symbol/ObjectFile.h"
|
||||
|
||||
#include "lldb/Symbol/FuncUnwinders.h"
|
||||
#include "lldb/Symbol/SymbolContext.h"
|
||||
#include "lldb/Core/Section.h"
|
||||
#include "lldb/Core/Module.h"
|
||||
#include "lldb/lldb-forward.h"
|
||||
#include "lldb/Utility/UnwindAssemblyProfiler.h"
|
||||
#include "lldb/Symbol/DWARFCallFrameInfo.h"
|
||||
|
||||
#include "lldb/Symbol/UnwindTable.h"
|
||||
#include <stdio.h>
|
||||
|
||||
// There is one UnwindTable object per ObjectFile.
|
||||
// It contains a list of Unwind objects -- one per function, populated lazily -- for the ObjectFile.
|
||||
// Each Unwind object has multiple UnwindPlans for different scenarios.
|
||||
|
||||
using namespace lldb;
|
||||
using namespace lldb_private;
|
||||
|
||||
UnwindTable::UnwindTable (ObjectFile& objfile) : m_object_file(objfile),
|
||||
m_unwinds(),
|
||||
m_initialized(false),
|
||||
m_eh_frame(NULL),
|
||||
m_assembly_profiler(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
// We can't do some of this initialization when the ObjectFile is running its ctor; delay doing it
|
||||
// until needed for something.
|
||||
|
||||
void
|
||||
UnwindTable::initialize ()
|
||||
{
|
||||
if (m_initialized)
|
||||
return;
|
||||
|
||||
SectionList* sl = m_object_file.GetSectionList ();
|
||||
if (sl)
|
||||
{
|
||||
SectionSP sect = sl->FindSectionByType (eSectionTypeEHFrame, true);
|
||||
if (sect.get())
|
||||
{
|
||||
m_eh_frame = new DWARFCallFrameInfo(m_object_file, sect, eRegisterKindGCC, true);
|
||||
}
|
||||
}
|
||||
|
||||
ArchSpec arch;
|
||||
ConstString str;
|
||||
m_object_file.GetTargetTriple (str);
|
||||
arch.SetArchFromTargetTriple (str.GetCString());
|
||||
m_assembly_profiler = UnwindAssemblyProfiler::FindPlugin (arch);
|
||||
|
||||
m_initialized = true;
|
||||
}
|
||||
|
||||
UnwindTable::~UnwindTable ()
|
||||
{
|
||||
if (m_eh_frame)
|
||||
delete m_eh_frame;
|
||||
}
|
||||
|
||||
FuncUnwindersSP
|
||||
UnwindTable::GetFuncUnwindersContainingAddress (const Address& addr, SymbolContext &sc)
|
||||
{
|
||||
FuncUnwindersSP no_unwind_found;
|
||||
|
||||
initialize();
|
||||
|
||||
// Create a FuncUnwinders object for the binary search below
|
||||
AddressRange search_range(addr, 1);
|
||||
FuncUnwindersSP search_unwind(new FuncUnwinders (*this, NULL, search_range));
|
||||
|
||||
const_iterator idx;
|
||||
idx = std::lower_bound (m_unwinds.begin(), m_unwinds.end(), search_unwind);
|
||||
|
||||
bool found_match = true;
|
||||
if (m_unwinds.size() == 0)
|
||||
{
|
||||
found_match = false;
|
||||
}
|
||||
else if (idx == m_unwinds.end())
|
||||
{
|
||||
--idx;
|
||||
}
|
||||
if (idx != m_unwinds.begin() && (*idx)->GetFunctionStartAddress().GetOffset() != addr.GetOffset())
|
||||
{
|
||||
--idx;
|
||||
}
|
||||
if (found_match && (*idx)->ContainsAddress (addr))
|
||||
{
|
||||
return *idx;
|
||||
}
|
||||
|
||||
AddressRange range;
|
||||
if (sc.GetAddressRange(eSymbolContextFunction | eSymbolContextSymbol, range))
|
||||
{
|
||||
FuncUnwindersSP unw(new FuncUnwinders(*this, m_assembly_profiler, range));
|
||||
m_unwinds.push_back (unw);
|
||||
std::sort (m_unwinds.begin(), m_unwinds.end());
|
||||
return unw;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Does the eh_frame unwind info has a function bounds defined for this addr?
|
||||
if (m_eh_frame->GetAddressRange (addr, range))
|
||||
{
|
||||
FuncUnwindersSP unw(new FuncUnwinders(*this, m_assembly_profiler, range));
|
||||
m_unwinds.push_back (unw);
|
||||
std::sort (m_unwinds.begin(), m_unwinds.end());
|
||||
return unw;
|
||||
// FIXME we should create a syntheic Symbol based on the address range with a synthesized symbol name
|
||||
}
|
||||
}
|
||||
return no_unwind_found;
|
||||
}
|
||||
|
||||
DWARFCallFrameInfo *
|
||||
UnwindTable::GetEHFrameInfo ()
|
||||
{
|
||||
initialize();
|
||||
return m_eh_frame;
|
||||
}
|
@ -235,4 +235,26 @@ RegisterContext::Calculate (ExecutionContext &exe_ctx)
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
RegisterContext::ConvertBetweenRegisterKinds (int source_rk, uint32_t source_regnum, int target_rk, uint32_t target_regnum)
|
||||
{
|
||||
const uint32_t num_registers = GetRegisterCount();
|
||||
for (uint32_t reg = 0; reg < num_registers; ++reg)
|
||||
{
|
||||
const RegisterInfo * reg_info = GetRegisterInfoAtIndex (reg);
|
||||
|
||||
if (reg_info->kinds[source_rk] == source_regnum)
|
||||
{
|
||||
target_regnum = reg_info->kinds[target_rk];
|
||||
if (target_regnum == LLDB_INVALID_REGNUM)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
40
lldb/source/Utility/ArchDefaultUnwindPlan.cpp
Normal file
40
lldb/source/Utility/ArchDefaultUnwindPlan.cpp
Normal file
@ -0,0 +1,40 @@
|
||||
//===-- ArchDefaultUnwindPlan.cpp -------------------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "lldb-private.h"
|
||||
#include "lldb/Core/PluginManager.h"
|
||||
#include "lldb/Core/PluginInterface.h"
|
||||
#include "lldb/Utility/ArchDefaultUnwindPlan.h"
|
||||
|
||||
using namespace lldb;
|
||||
using namespace lldb_private;
|
||||
|
||||
ArchDefaultUnwindPlan*
|
||||
ArchDefaultUnwindPlan::FindPlugin (const ArchSpec &arch)
|
||||
{
|
||||
ArchDefaultUnwindPlanCreateInstance create_callback;
|
||||
|
||||
for (uint32_t idx = 0;
|
||||
(create_callback = PluginManager::GetArchDefaultUnwindPlanCreateCallbackAtIndex(idx)) != NULL;
|
||||
++idx)
|
||||
{
|
||||
std::auto_ptr<ArchDefaultUnwindPlan> default_unwind_plan_ap (create_callback (arch));
|
||||
if (default_unwind_plan_ap.get ())
|
||||
return default_unwind_plan_ap.release ();
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ArchDefaultUnwindPlan::ArchDefaultUnwindPlan ()
|
||||
{
|
||||
}
|
||||
|
||||
ArchDefaultUnwindPlan::~ArchDefaultUnwindPlan ()
|
||||
{
|
||||
}
|
40
lldb/source/Utility/UnwindAssemblyProfiler.cpp
Normal file
40
lldb/source/Utility/UnwindAssemblyProfiler.cpp
Normal file
@ -0,0 +1,40 @@
|
||||
//===-- UnwindAssemblyProfiler.cpp ------------------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "lldb-private.h"
|
||||
#include "lldb/Core/PluginManager.h"
|
||||
#include "lldb/Core/PluginInterface.h"
|
||||
#include "lldb/Utility/UnwindAssemblyProfiler.h"
|
||||
|
||||
using namespace lldb;
|
||||
using namespace lldb_private;
|
||||
|
||||
UnwindAssemblyProfiler*
|
||||
UnwindAssemblyProfiler::FindPlugin (const ArchSpec &arch)
|
||||
{
|
||||
UnwindAssemblyProfilerCreateInstance create_callback;
|
||||
|
||||
for (uint32_t idx = 0;
|
||||
(create_callback = PluginManager::GetUnwindAssemblyProfilerCreateCallbackAtIndex(idx)) != NULL;
|
||||
++idx)
|
||||
{
|
||||
std::auto_ptr<UnwindAssemblyProfiler> assembly_profiler_ap (create_callback (arch));
|
||||
if (assembly_profiler_ap.get ())
|
||||
return assembly_profiler_ap.release ();
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
UnwindAssemblyProfiler::UnwindAssemblyProfiler ()
|
||||
{
|
||||
}
|
||||
|
||||
UnwindAssemblyProfiler::~UnwindAssemblyProfiler ()
|
||||
{
|
||||
}
|
@ -22,6 +22,8 @@
|
||||
#include "Plugins/SymbolFile/DWARF/SymbolFileDWARF.h"
|
||||
#include "Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h"
|
||||
#include "Plugins/SymbolFile/Symtab/SymbolFileSymtab.h"
|
||||
#include "Plugins/Process/Utility/UnwindAssemblyProfiler-x86.h"
|
||||
#include "Plugins/Process/Utility/ArchDefaultUnwindPlan-x86.h"
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include "Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h"
|
||||
@ -63,6 +65,8 @@ lldb_private::Initialize ()
|
||||
SymbolFileDWARF::Initialize();
|
||||
SymbolFileDWARFDebugMap::Initialize();
|
||||
SymbolFileSymtab::Initialize();
|
||||
UnwindAssemblyProfiler_x86::Initialize();
|
||||
ArchDefaultUnwindPlan_x86::Initialize();
|
||||
|
||||
#ifdef __APPLE__
|
||||
ABIMacOSX_i386::Initialize();
|
||||
@ -99,6 +103,8 @@ lldb_private::Terminate ()
|
||||
SymbolFileDWARF::Terminate();
|
||||
SymbolFileDWARFDebugMap::Terminate();
|
||||
SymbolFileSymtab::Terminate();
|
||||
UnwindAssemblyProfiler_x86::Terminate();
|
||||
ArchDefaultUnwindPlan_x86::Terminate();
|
||||
|
||||
#ifdef __APPLE__
|
||||
DynamicLoaderMacOSXDYLD::Terminate();
|
||||
|
Loading…
Reference in New Issue
Block a user