blob: 08dc42e2d1d8dc7fce8a4051427c8fa57914c46b [file] [log] [blame]
//===-- DWARFCallFrameInfo.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_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"
namespace lldb_private {
//----------------------------------------------------------------------
// DWARFCallFrameInfo
//
// State that describes all register locations for a given address
// range.
//----------------------------------------------------------------------
class DWARFCallFrameInfo
{
public:
enum
{
CFI_AUG_MAX_SIZE = 8,
CFI_HEADER_SIZE = 8
};
class Row;
class RegisterLocation
{
public:
typedef 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
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;
CIE(dw_offset_t offset);
~CIE();
void
Dump(Stream *s, Thread* threadState, const ArchSpec *arch, uint32_t reg_kind) const;
};
//------------------------------------------------------------------
// Frame Description Entry (FDE)
//------------------------------------------------------------------
public:
class FDE
{
public:
typedef lldb::SharedPtr<FDE>::Type shared_ptr;
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);
};
DWARFCallFrameInfo(ObjectFile *objfile, lldb_private::Section *section, uint32_t reg_kind);
~DWARFCallFrameInfo();
bool
IsEHFrame() const;
const ArchSpec *
GetArchitecture() const;
uint32_t
GetRegisterKind () const;
void
SetRegisterKind (uint32_t reg_kind);
void
Index ();
// 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);
void
Dump(Stream *s, Thread *thread) const;
void
ParseAll();
protected:
enum
{
eFlagParsedIndex = (1 << 0)
};
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 ();
};
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
ParseCIE (const uint32_t cie_offset);
FDE::shared_ptr
ParseFDE (const uint32_t fde_offset);
};
} // namespace lldb_private
#endif // liblldb_DWARFCallFrameInfo_h_