DWARFUnit split out of DWARFCompileUnit

DW_TAG_partial_unit for DWZ can be then presented by DWARFPartialUnit also
inherited from DWARFUnit.

Differential revision: https://reviews.llvm.org/D40466

llvm-svn: 327809
This commit is contained in:
Jan Kratochvil
2018-03-18 20:09:02 +00:00
parent e1d6a4df1c
commit 2ccddfe3c6
5 changed files with 796 additions and 561 deletions

View File

@@ -23,6 +23,7 @@ add_lldb_library(lldbPluginSymbolFileDWARF PLUGIN
DWARFDIE.cpp
DWARFDIECollection.cpp
DWARFFormValue.cpp
DWARFUnit.cpp
HashedNameToDIE.cpp
LogChannelDWARF.cpp
NameToDIE.cpp

View File

@@ -9,7 +9,6 @@
#include "DWARFCompileUnit.h"
#include "Plugins/Language/ObjC/ObjCLanguage.h"
#include "lldb/Core/DumpDataExtractor.h"
#include "lldb/Core/Mangled.h"
#include "lldb/Core/Module.h"
@@ -41,8 +40,6 @@ extern int g_verbose;
DWARFCompileUnit::DWARFCompileUnit(SymbolFileDWARF *dwarf2Data)
: m_dwarf2Data(dwarf2Data) {}
DWARFCompileUnit::~DWARFCompileUnit() {}
DWARFCompileUnitSP DWARFCompileUnit::Extract(SymbolFileDWARF *dwarf2Data,
lldb::offset_t *offset_ptr) {
DWARFCompileUnitSP cu_sp(new DWARFCompileUnit(dwarf2Data));
@@ -344,28 +341,6 @@ void DWARFCompileUnit::Dump(Stream *s) const {
GetNextCompileUnitOffset());
}
static uint8_t g_default_addr_size = 4;
uint8_t DWARFCompileUnit::GetAddressByteSize(const DWARFCompileUnit *cu) {
if (cu)
return cu->GetAddressByteSize();
return DWARFCompileUnit::GetDefaultAddressSize();
}
bool DWARFCompileUnit::IsDWARF64(const DWARFCompileUnit *cu) {
if (cu)
return cu->IsDWARF64();
return false;
}
uint8_t DWARFCompileUnit::GetDefaultAddressSize() {
return g_default_addr_size;
}
void DWARFCompileUnit::SetDefaultAddressSize(uint8_t addr_size) {
g_default_addr_size = addr_size;
}
lldb::user_id_t DWARFCompileUnit::GetID() const {
dw_offset_t local_id =
m_base_obj_offset != DW_INVALID_OFFSET ? m_base_obj_offset : m_offset;
@@ -516,47 +491,6 @@ DWARFCompileUnit::LookupAddress(const dw_addr_t address) {
return DWARFDIE();
}
//----------------------------------------------------------------------
// Compare function DWARFDebugAranges::Range structures
//----------------------------------------------------------------------
static bool CompareDIEOffset(const DWARFDebugInfoEntry &die,
const dw_offset_t die_offset) {
return die.GetOffset() < die_offset;
}
//----------------------------------------------------------------------
// GetDIE()
//
// Get the DIE (Debug Information Entry) with the specified offset by
// first checking if the DIE is contained within this compile unit and
// grabbing the DIE from this compile unit. Otherwise we grab the DIE
// from the DWARF file.
//----------------------------------------------------------------------
DWARFDIE
DWARFCompileUnit::GetDIE(dw_offset_t die_offset) {
if (die_offset != DW_INVALID_OFFSET) {
if (m_dwo_symbol_file)
return m_dwo_symbol_file->GetCompileUnit()->GetDIE(die_offset);
if (ContainsDIEOffset(die_offset)) {
ExtractDIEsIfNeeded(false);
DWARFDebugInfoEntry::iterator end = m_die_array.end();
DWARFDebugInfoEntry::iterator pos =
lower_bound(m_die_array.begin(), end, die_offset, CompareDIEOffset);
if (pos != end) {
if (die_offset == (*pos).GetOffset())
return DWARFDIE(this, &(*pos));
}
} else {
// Don't specify the compile unit offset as we don't know it because the
// DIE belongs to
// a different compile unit in the same symbol file.
return m_dwarf2Data->DebugInfo()->GetDIEForDIEOffset(die_offset);
}
}
return DWARFDIE(); // Not found
}
size_t DWARFCompileUnit::AppendDIEsWithTag(const dw_tag_t tag,
DWARFDIECollection &dies,
uint32_t depth) const {
@@ -594,381 +528,6 @@ size_t DWARFCompileUnit::AppendDIEsWithTag(const dw_tag_t tag,
// m_global_die_indexes.push_back (die - first_die);
//}
void DWARFCompileUnit::Index(NameToDIE &func_basenames,
NameToDIE &func_fullnames, NameToDIE &func_methods,
NameToDIE &func_selectors,
NameToDIE &objc_class_selectors,
NameToDIE &globals, NameToDIE &types,
NameToDIE &namespaces) {
assert(!m_dwarf2Data->GetBaseCompileUnit() &&
"DWARFCompileUnit associated with .dwo or .dwp "
"should not be indexed directly");
Log *log(LogChannelDWARF::GetLogIfAll(DWARF_LOG_LOOKUPS));
if (log) {
m_dwarf2Data->GetObjectFile()->GetModule()->LogMessage(
log,
"DWARFCompileUnit::Index() for compile unit at .debug_info[0x%8.8x]",
GetOffset());
}
const LanguageType cu_language = GetLanguageType();
DWARFFormValue::FixedFormSizes fixed_form_sizes =
DWARFFormValue::GetFixedFormSizesForAddressSize(GetAddressByteSize(),
m_is_dwarf64);
IndexPrivate(this, cu_language, fixed_form_sizes, GetOffset(), func_basenames,
func_fullnames, func_methods, func_selectors,
objc_class_selectors, globals, types, namespaces);
SymbolFileDWARFDwo *dwo_symbol_file = GetDwoSymbolFile();
if (dwo_symbol_file) {
IndexPrivate(dwo_symbol_file->GetCompileUnit(), cu_language,
fixed_form_sizes, GetOffset(), func_basenames, func_fullnames,
func_methods, func_selectors, objc_class_selectors, globals,
types, namespaces);
}
}
void DWARFCompileUnit::IndexPrivate(
DWARFCompileUnit *dwarf_cu, const LanguageType cu_language,
const DWARFFormValue::FixedFormSizes &fixed_form_sizes,
const dw_offset_t cu_offset, NameToDIE &func_basenames,
NameToDIE &func_fullnames, NameToDIE &func_methods,
NameToDIE &func_selectors, NameToDIE &objc_class_selectors,
NameToDIE &globals, NameToDIE &types, NameToDIE &namespaces) {
DWARFDebugInfoEntry::const_iterator pos;
DWARFDebugInfoEntry::const_iterator begin = dwarf_cu->m_die_array.begin();
DWARFDebugInfoEntry::const_iterator end = dwarf_cu->m_die_array.end();
for (pos = begin; pos != end; ++pos) {
const DWARFDebugInfoEntry &die = *pos;
const dw_tag_t tag = die.Tag();
switch (tag) {
case DW_TAG_array_type:
case DW_TAG_base_type:
case DW_TAG_class_type:
case DW_TAG_constant:
case DW_TAG_enumeration_type:
case DW_TAG_inlined_subroutine:
case DW_TAG_namespace:
case DW_TAG_string_type:
case DW_TAG_structure_type:
case DW_TAG_subprogram:
case DW_TAG_subroutine_type:
case DW_TAG_typedef:
case DW_TAG_union_type:
case DW_TAG_unspecified_type:
case DW_TAG_variable:
break;
default:
continue;
}
DWARFAttributes attributes;
const char *name = NULL;
const char *mangled_cstr = NULL;
bool is_declaration = false;
// bool is_artificial = false;
bool has_address = false;
bool has_location_or_const_value = false;
bool is_global_or_static_variable = false;
DWARFFormValue specification_die_form;
const size_t num_attributes =
die.GetAttributes(dwarf_cu, fixed_form_sizes, attributes);
if (num_attributes > 0) {
for (uint32_t i = 0; i < num_attributes; ++i) {
dw_attr_t attr = attributes.AttributeAtIndex(i);
DWARFFormValue form_value;
switch (attr) {
case DW_AT_name:
if (attributes.ExtractFormValueAtIndex(i, form_value))
name = form_value.AsCString();
break;
case DW_AT_declaration:
if (attributes.ExtractFormValueAtIndex(i, form_value))
is_declaration = form_value.Unsigned() != 0;
break;
// case DW_AT_artificial:
// if (attributes.ExtractFormValueAtIndex(i,
// form_value))
// is_artificial = form_value.Unsigned() != 0;
// break;
case DW_AT_MIPS_linkage_name:
case DW_AT_linkage_name:
if (attributes.ExtractFormValueAtIndex(i, form_value))
mangled_cstr = form_value.AsCString();
break;
case DW_AT_low_pc:
case DW_AT_high_pc:
case DW_AT_ranges:
has_address = true;
break;
case DW_AT_entry_pc:
has_address = true;
break;
case DW_AT_location:
case DW_AT_const_value:
has_location_or_const_value = true;
if (tag == DW_TAG_variable) {
const DWARFDebugInfoEntry *parent_die = die.GetParent();
while (parent_die != NULL) {
switch (parent_die->Tag()) {
case DW_TAG_subprogram:
case DW_TAG_lexical_block:
case DW_TAG_inlined_subroutine:
// Even if this is a function level static, we don't add it. We
// could theoretically
// add these if we wanted to by introspecting into the
// DW_AT_location and seeing
// if the location describes a hard coded address, but we dont
// want the performance
// penalty of that right now.
is_global_or_static_variable = false;
// if
// (attributes.ExtractFormValueAtIndex(dwarf2Data,
// i, form_value))
// {
// // If we have valid block
// data, then we have location
// expression bytes
// // that are fixed (not a
// location list).
// const uint8_t *block_data =
// form_value.BlockData();
// if (block_data)
// {
// uint32_t block_length =
// form_value.Unsigned();
// if (block_length == 1 +
// attributes.CompileUnitAtIndex(i)->GetAddressByteSize())
// {
// if (block_data[0] ==
// DW_OP_addr)
// add_die = true;
// }
// }
// }
parent_die = NULL; // Terminate the while loop.
break;
case DW_TAG_compile_unit:
is_global_or_static_variable = true;
parent_die = NULL; // Terminate the while loop.
break;
default:
parent_die =
parent_die->GetParent(); // Keep going in the while loop.
break;
}
}
}
break;
case DW_AT_specification:
if (attributes.ExtractFormValueAtIndex(i, form_value))
specification_die_form = form_value;
break;
}
}
}
switch (tag) {
case DW_TAG_subprogram:
if (has_address) {
if (name) {
ObjCLanguage::MethodName objc_method(name, true);
if (objc_method.IsValid(true)) {
ConstString objc_class_name_with_category(
objc_method.GetClassNameWithCategory());
ConstString objc_selector_name(objc_method.GetSelector());
ConstString objc_fullname_no_category_name(
objc_method.GetFullNameWithoutCategory(true));
ConstString objc_class_name_no_category(objc_method.GetClassName());
func_fullnames.Insert(ConstString(name),
DIERef(cu_offset, die.GetOffset()));
if (objc_class_name_with_category)
objc_class_selectors.Insert(objc_class_name_with_category,
DIERef(cu_offset, die.GetOffset()));
if (objc_class_name_no_category &&
objc_class_name_no_category != objc_class_name_with_category)
objc_class_selectors.Insert(objc_class_name_no_category,
DIERef(cu_offset, die.GetOffset()));
if (objc_selector_name)
func_selectors.Insert(objc_selector_name,
DIERef(cu_offset, die.GetOffset()));
if (objc_fullname_no_category_name)
func_fullnames.Insert(objc_fullname_no_category_name,
DIERef(cu_offset, die.GetOffset()));
}
// If we have a mangled name, then the DW_AT_name attribute
// is usually the method name without the class or any parameters
const DWARFDebugInfoEntry *parent = die.GetParent();
bool is_method = false;
if (parent) {
dw_tag_t parent_tag = parent->Tag();
if (parent_tag == DW_TAG_class_type ||
parent_tag == DW_TAG_structure_type) {
is_method = true;
} else {
if (specification_die_form.IsValid()) {
DWARFDIE specification_die =
dwarf_cu->GetSymbolFileDWARF()->DebugInfo()->GetDIE(
DIERef(specification_die_form));
if (specification_die.GetParent().IsStructOrClass())
is_method = true;
}
}
}
if (is_method)
func_methods.Insert(ConstString(name),
DIERef(cu_offset, die.GetOffset()));
else
func_basenames.Insert(ConstString(name),
DIERef(cu_offset, die.GetOffset()));
if (!is_method && !mangled_cstr && !objc_method.IsValid(true))
func_fullnames.Insert(ConstString(name),
DIERef(cu_offset, die.GetOffset()));
}
if (mangled_cstr) {
// Make sure our mangled name isn't the same string table entry
// as our name. If it starts with '_', then it is ok, else compare
// the string to make sure it isn't the same and we don't end up
// with duplicate entries
if (name && name != mangled_cstr &&
((mangled_cstr[0] == '_') ||
(::strcmp(name, mangled_cstr) != 0))) {
Mangled mangled(ConstString(mangled_cstr), true);
func_fullnames.Insert(mangled.GetMangledName(),
DIERef(cu_offset, die.GetOffset()));
ConstString demangled = mangled.GetDemangledName(cu_language);
if (demangled)
func_fullnames.Insert(demangled,
DIERef(cu_offset, die.GetOffset()));
}
}
}
break;
case DW_TAG_inlined_subroutine:
if (has_address) {
if (name)
func_basenames.Insert(ConstString(name),
DIERef(cu_offset, die.GetOffset()));
if (mangled_cstr) {
// Make sure our mangled name isn't the same string table entry
// as our name. If it starts with '_', then it is ok, else compare
// the string to make sure it isn't the same and we don't end up
// with duplicate entries
if (name && name != mangled_cstr &&
((mangled_cstr[0] == '_') ||
(::strcmp(name, mangled_cstr) != 0))) {
Mangled mangled(ConstString(mangled_cstr), true);
func_fullnames.Insert(mangled.GetMangledName(),
DIERef(cu_offset, die.GetOffset()));
ConstString demangled = mangled.GetDemangledName(cu_language);
if (demangled)
func_fullnames.Insert(demangled,
DIERef(cu_offset, die.GetOffset()));
}
} else
func_fullnames.Insert(ConstString(name),
DIERef(cu_offset, die.GetOffset()));
}
break;
case DW_TAG_array_type:
case DW_TAG_base_type:
case DW_TAG_class_type:
case DW_TAG_constant:
case DW_TAG_enumeration_type:
case DW_TAG_string_type:
case DW_TAG_structure_type:
case DW_TAG_subroutine_type:
case DW_TAG_typedef:
case DW_TAG_union_type:
case DW_TAG_unspecified_type:
if (name && !is_declaration)
types.Insert(ConstString(name), DIERef(cu_offset, die.GetOffset()));
if (mangled_cstr && !is_declaration)
types.Insert(ConstString(mangled_cstr),
DIERef(cu_offset, die.GetOffset()));
break;
case DW_TAG_namespace:
if (name)
namespaces.Insert(ConstString(name),
DIERef(cu_offset, die.GetOffset()));
break;
case DW_TAG_variable:
if (name && has_location_or_const_value && is_global_or_static_variable) {
globals.Insert(ConstString(name), DIERef(cu_offset, die.GetOffset()));
// Be sure to include variables by their mangled and demangled
// names if they have any since a variable can have a basename
// "i", a mangled named "_ZN12_GLOBAL__N_11iE" and a demangled
// mangled name "(anonymous namespace)::i"...
// Make sure our mangled name isn't the same string table entry
// as our name. If it starts with '_', then it is ok, else compare
// the string to make sure it isn't the same and we don't end up
// with duplicate entries
if (mangled_cstr && name != mangled_cstr &&
((mangled_cstr[0] == '_') || (::strcmp(name, mangled_cstr) != 0))) {
Mangled mangled(ConstString(mangled_cstr), true);
globals.Insert(mangled.GetMangledName(),
DIERef(cu_offset, die.GetOffset()));
ConstString demangled = mangled.GetDemangledName(cu_language);
if (demangled)
globals.Insert(demangled, DIERef(cu_offset, die.GetOffset()));
}
}
break;
default:
continue;
}
}
}
bool DWARFCompileUnit::Supports_unnamed_objc_bitfields() {
if (GetProducer() == eProducerClang) {
const uint32_t major_version = GetProducerVersionMajor();
if (major_version > 425 ||
(major_version == 425 && GetProducerVersionUpdate() >= 13))
return true;
else
return false;
}
return true; // Assume all other compilers didn't have incorrect ObjC bitfield
// info
}
bool DWARFCompileUnit::Supports_DW_AT_APPLE_objc_complete_type() {
if (GetProducer() == eProducerLLVMGCC)
return false;
return true;
}
bool DWARFCompileUnit::DW_AT_decl_file_attributes_are_invalid() {
// llvm-gcc makes completely invalid decl file attributes and won't ever
// be fixed, so we need to know to ignore these.
return GetProducer() == eProducerLLVMGCC;
}
void DWARFCompileUnit::ParseProducerInfo() {
m_producer_version_major = UINT32_MAX;
m_producer_version_minor = UINT32_MAX;
@@ -1036,19 +595,6 @@ uint32_t DWARFCompileUnit::GetProducerVersionUpdate() {
return m_producer_version_update;
}
LanguageType DWARFCompileUnit::LanguageTypeFromDWARF(uint64_t val) {
// Note: user languages between lo_user and hi_user
// must be handled explicitly here.
switch (val) {
case DW_LANG_Mips_Assembler:
return eLanguageTypeMipsAssembler;
case DW_LANG_GOOGLE_RenderScript:
return eLanguageTypeExtRenderScript;
default:
return static_cast<LanguageType>(val);
}
}
LanguageType DWARFCompileUnit::GetLanguageType() {
if (m_language_type != eLanguageTypeUnknown)
return m_language_type;
@@ -1060,8 +606,6 @@ LanguageType DWARFCompileUnit::GetLanguageType() {
return m_language_type;
}
bool DWARFCompileUnit::IsDWARF64() const { return m_is_dwarf64; }
bool DWARFCompileUnit::GetIsOptimized() {
if (m_is_optimized == eLazyBoolCalculate) {
const DWARFDebugInfoEntry *die = GetCompileUnitDIEPtrOnly();
@@ -1080,11 +624,6 @@ bool DWARFCompileUnit::GetIsOptimized() {
}
}
DWARFFormValue::FixedFormSizes DWARFCompileUnit::GetFixedFormSizes() {
return DWARFFormValue::GetFixedFormSizesForAddressSize(GetAddressByteSize(),
IsDWARF64());
}
TypeSystem *DWARFCompileUnit::GetTypeSystem() {
if (m_dwarf2Data)
return m_dwarf2Data->GetTypeSystemForLanguage(GetLanguageType());
@@ -1105,7 +644,3 @@ void DWARFCompileUnit::SetAddrBase(dw_addr_t addr_base,
m_ranges_base = ranges_base;
m_base_obj_offset = base_obj_offset;
}
lldb::ByteOrder DWARFCompileUnit::GetByteOrder() const {
return m_dwarf2Data->GetObjectFile()->GetByteOrder();
}

View File

@@ -10,29 +10,16 @@
#ifndef SymbolFileDWARF_DWARFCompileUnit_h_
#define SymbolFileDWARF_DWARFCompileUnit_h_
#include "DWARFDIE.h"
#include "DWARFDebugInfoEntry.h"
#include "lldb/lldb-enumerations.h"
class NameToDIE;
class SymbolFileDWARF;
class SymbolFileDWARFDwo;
#include "DWARFUnit.h"
typedef std::shared_ptr<DWARFCompileUnit> DWARFCompileUnitSP;
enum DWARFProducer {
eProducerInvalid = 0,
eProducerClang,
eProducerGCC,
eProducerLLVMGCC,
eProcucerOther
};
class DWARFCompileUnit : public DWARFUnit {
friend class DWARFUnit;
class DWARFCompileUnit {
public:
static DWARFCompileUnitSP Extract(SymbolFileDWARF *dwarf2Data,
lldb::offset_t *offset_ptr);
~DWARFCompileUnit();
size_t ExtractDIEsIfNeeded(bool cu_die_only);
DWARFDIE LookupAddress(const dw_addr_t address);
@@ -41,47 +28,15 @@ public:
uint32_t depth = UINT32_MAX) const;
bool Verify(lldb_private::Stream *s) const;
void Dump(lldb_private::Stream *s) const;
// Offset of the initial length field.
dw_offset_t GetOffset() const { return m_offset; }
lldb::user_id_t GetID() const;
// Size in bytes of the initial length + compile unit header.
uint32_t Size() const { return m_is_dwarf64 ? 23 : 11; }
bool ContainsDIEOffset(dw_offset_t die_offset) const {
return die_offset >= GetFirstDIEOffset() &&
die_offset < GetNextCompileUnitOffset();
}
dw_offset_t GetFirstDIEOffset() const { return m_offset + Size(); }
dw_offset_t GetNextCompileUnitOffset() const {
return m_offset + (m_is_dwarf64 ? 12 : 4) + m_length;
}
// Size of the CU data (without initial length and without header).
size_t GetDebugInfoSize() const {
return (m_is_dwarf64 ? 12 : 4) + m_length - Size();
}
// Size of the CU data incl. header but without initial length.
uint32_t GetLength() const { return m_length; }
uint16_t GetVersion() const { return m_version; }
const DWARFAbbreviationDeclarationSet *GetAbbreviations() const {
return m_abbrevs;
}
dw_offset_t GetAbbrevOffset() const;
uint8_t GetAddressByteSize() const { return m_addr_size; }
dw_addr_t GetBaseAddress() const { return m_base_addr; }
dw_addr_t GetAddrBase() const { return m_addr_base; }
dw_addr_t GetRangesBase() const { return m_ranges_base; }
void SetAddrBase(dw_addr_t addr_base, dw_addr_t ranges_base, dw_offset_t base_obj_offset);
void ClearDIEs(bool keep_compile_unit_die);
void BuildAddressRangeTable(SymbolFileDWARF *dwarf2Data,
DWARFDebugAranges *debug_aranges);
lldb::ByteOrder GetByteOrder() const;
lldb_private::TypeSystem *GetTypeSystem();
DWARFFormValue::FixedFormSizes GetFixedFormSizes();
void SetBaseAddress(dw_addr_t base_addr) { m_base_addr = base_addr; }
DWARFDIE
GetCompileUnitDIEOnly() { return DWARFDIE(this, GetCompileUnitDIEPtrOnly()); }
@@ -105,38 +60,10 @@ public:
void AddCompileUnitDIE(DWARFDebugInfoEntry &die);
bool HasDIEsParsed() const { return m_die_array.size() > 1; }
DWARFDIE
GetDIE(dw_offset_t die_offset);
static uint8_t GetAddressByteSize(const DWARFCompileUnit *cu);
static bool IsDWARF64(const DWARFCompileUnit *cu);
static uint8_t GetDefaultAddressSize();
static void SetDefaultAddressSize(uint8_t addr_size);
void *GetUserData() const { return m_user_data; }
void SetUserData(void *d);
bool Supports_DW_AT_APPLE_objc_complete_type();
bool DW_AT_decl_file_attributes_are_invalid();
bool Supports_unnamed_objc_bitfields();
void Index(NameToDIE &func_basenames, NameToDIE &func_fullnames,
NameToDIE &func_methods, NameToDIE &func_selectors,
NameToDIE &objc_class_selectors, NameToDIE &globals,
NameToDIE &types, NameToDIE &namespaces);
const DWARFDebugAranges &GetFunctionAranges();
SymbolFileDWARF *GetSymbolFileDWARF() const { return m_dwarf2Data; }
DWARFProducer GetProducer();
uint32_t GetProducerVersionMajor();
@@ -145,21 +72,14 @@ public:
uint32_t GetProducerVersionUpdate();
static lldb::LanguageType LanguageTypeFromDWARF(uint64_t val);
lldb::LanguageType GetLanguageType();
bool IsDWARF64() const;
bool GetIsOptimized();
SymbolFileDWARFDwo *GetDwoSymbolFile() const {
return m_dwo_symbol_file.get();
}
dw_offset_t GetBaseObjOffset() const { return m_base_obj_offset; }
protected:
virtual DWARFCompileUnit &Data() override { return *this; }
virtual const DWARFCompileUnit &Data() const override { return *this; }
SymbolFileDWARF *m_dwarf2Data;
std::unique_ptr<SymbolFileDWARFDwo> m_dwo_symbol_file;
const DWARFAbbreviationDeclarationSet *m_abbrevs;
@@ -173,8 +93,6 @@ protected:
// DW_TAG_subprogram
// DIEs
dw_addr_t m_base_addr = 0;
// Offset of the initial length field.
dw_offset_t m_offset;
dw_offset_t m_length;
uint16_t m_version;
uint8_t m_addr_size;
@@ -193,14 +111,6 @@ protected:
void ParseProducerInfo();
static void
IndexPrivate(DWARFCompileUnit *dwarf_cu, const lldb::LanguageType cu_language,
const DWARFFormValue::FixedFormSizes &fixed_form_sizes,
const dw_offset_t cu_offset, NameToDIE &func_basenames,
NameToDIE &func_fullnames, NameToDIE &func_methods,
NameToDIE &func_selectors, NameToDIE &objc_class_selectors,
NameToDIE &globals, NameToDIE &types, NameToDIE &namespaces);
private:
DWARFCompileUnit(SymbolFileDWARF *dwarf2Data);

View File

@@ -0,0 +1,630 @@
//===-- DWARFUnit.cpp -------------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "DWARFUnit.h"
#include "Plugins/Language/ObjC/ObjCLanguage.h"
#include "lldb/Core/Module.h"
#include "lldb/Symbol/ObjectFile.h"
#include "DWARFCompileUnit.h"
#include "DWARFDebugInfo.h"
#include "LogChannelDWARF.h"
#include "SymbolFileDWARFDwo.h"
using namespace lldb;
using namespace lldb_private;
using namespace std;
extern int g_verbose;
DWARFUnit::DWARFUnit() {}
DWARFUnit::~DWARFUnit() {}
size_t DWARFUnit::ExtractDIEsIfNeeded(bool cu_die_only) {
return Data().ExtractDIEsIfNeeded(cu_die_only);
}
DWARFDIE DWARFUnit::LookupAddress(const dw_addr_t address) {
return Data().LookupAddress(address);
}
size_t DWARFUnit::AppendDIEsWithTag(const dw_tag_t tag,
DWARFDIECollection &dies,
uint32_t depth) const {
return Data().AppendDIEsWithTag(tag, dies, depth);
}
bool DWARFUnit::Verify(Stream *s) const {
return Data().Verify(s);
}
void DWARFUnit::Dump(Stream *s) const {
Data().Dump(s);
}
lldb::user_id_t DWARFUnit::GetID() const {
return Data().GetID();
}
uint32_t DWARFUnit::Size() const { return IsDWARF64() ? 23 : 11; }
dw_offset_t DWARFUnit::GetNextCompileUnitOffset() const {
return m_offset + (IsDWARF64() ? 12 : 4) + GetLength();
}
size_t DWARFUnit::GetDebugInfoSize() const {
return (IsDWARF64() ? 12 : 4) + GetLength() - Size();
}
uint32_t DWARFUnit::GetLength() const { return Data().m_length; }
uint16_t DWARFUnit::GetVersion() const { return Data().m_version; }
const DWARFAbbreviationDeclarationSet *DWARFUnit::GetAbbreviations() const {
return Data().m_abbrevs;
}
dw_offset_t DWARFUnit::GetAbbrevOffset() const {
return Data().GetAbbrevOffset();
}
uint8_t DWARFUnit::GetAddressByteSize() const { return Data().m_addr_size; }
dw_addr_t DWARFUnit::GetBaseAddress() const { return Data().m_base_addr; }
dw_addr_t DWARFUnit::GetAddrBase() const { return Data().m_addr_base; }
dw_addr_t DWARFUnit::GetRangesBase() const { return Data().m_ranges_base; }
void DWARFUnit::SetAddrBase(dw_addr_t addr_base,
dw_addr_t ranges_base,
dw_offset_t base_obj_offset) {
Data().SetAddrBase(addr_base, ranges_base, base_obj_offset);
}
void DWARFUnit::ClearDIEs(bool keep_compile_unit_die) {
Data().ClearDIEs(keep_compile_unit_die);
}
void DWARFUnit::BuildAddressRangeTable(SymbolFileDWARF *dwarf2Data,
DWARFDebugAranges *debug_aranges) {
Data().BuildAddressRangeTable(dwarf2Data, debug_aranges);
}
lldb::ByteOrder DWARFUnit::GetByteOrder() const {
return Data().m_dwarf2Data->GetObjectFile()->GetByteOrder();
}
TypeSystem *DWARFUnit::GetTypeSystem() {
return Data().GetTypeSystem();
}
DWARFFormValue::FixedFormSizes DWARFUnit::GetFixedFormSizes() {
return DWARFFormValue::GetFixedFormSizesForAddressSize(GetAddressByteSize(),
IsDWARF64());
}
void DWARFUnit::SetBaseAddress(dw_addr_t base_addr) {
Data().m_base_addr = base_addr;
}
DWARFDIE DWARFUnit::GetCompileUnitDIEOnly() {
return Data().GetCompileUnitDIEOnly();
}
DWARFDIE DWARFUnit::DIE() {
return Data().DIE();
}
bool DWARFUnit::HasDIEsParsed() const { return Data().m_die_array.size() > 1; }
//----------------------------------------------------------------------
// Compare function DWARFDebugAranges::Range structures
//----------------------------------------------------------------------
static bool CompareDIEOffset(const DWARFDebugInfoEntry &die,
const dw_offset_t die_offset) {
return die.GetOffset() < die_offset;
}
//----------------------------------------------------------------------
// GetDIE()
//
// Get the DIE (Debug Information Entry) with the specified offset by
// first checking if the DIE is contained within this compile unit and
// grabbing the DIE from this compile unit. Otherwise we grab the DIE
// from the DWARF file.
//----------------------------------------------------------------------
DWARFDIE
DWARFUnit::GetDIE(dw_offset_t die_offset) {
if (die_offset != DW_INVALID_OFFSET) {
if (GetDwoSymbolFile())
return GetDwoSymbolFile()->GetCompileUnit()->GetDIE(die_offset);
if (ContainsDIEOffset(die_offset)) {
ExtractDIEsIfNeeded(false);
DWARFDebugInfoEntry::iterator end = Data().m_die_array.end();
DWARFDebugInfoEntry::iterator pos = lower_bound(
Data().m_die_array.begin(), end, die_offset, CompareDIEOffset);
if (pos != end) {
if (die_offset == (*pos).GetOffset())
return DWARFDIE(&Data(), &(*pos));
}
} else {
// Don't specify the compile unit offset as we don't know it because the
// DIE belongs to
// a different compile unit in the same symbol file.
return Data().m_dwarf2Data->DebugInfo()->GetDIEForDIEOffset(die_offset);
}
}
return DWARFDIE(); // Not found
}
static uint8_t g_default_addr_size = 4;
uint8_t DWARFUnit::GetAddressByteSize(const DWARFUnit *cu) {
if (cu)
return cu->GetAddressByteSize();
return DWARFCompileUnit::GetDefaultAddressSize();
}
bool DWARFUnit::IsDWARF64(const DWARFUnit *cu) {
if (cu)
return cu->IsDWARF64();
return false;
}
uint8_t DWARFUnit::GetDefaultAddressSize() {
return g_default_addr_size;
}
void DWARFUnit::SetDefaultAddressSize(uint8_t addr_size) {
g_default_addr_size = addr_size;
}
void *DWARFUnit::GetUserData() const { return Data().m_user_data; }
void DWARFUnit::SetUserData(void *d) {
Data().SetUserData(d);
}
bool DWARFUnit::Supports_DW_AT_APPLE_objc_complete_type() {
if (GetProducer() == eProducerLLVMGCC)
return false;
return true;
}
bool DWARFUnit::DW_AT_decl_file_attributes_are_invalid() {
// llvm-gcc makes completely invalid decl file attributes and won't ever
// be fixed, so we need to know to ignore these.
return GetProducer() == eProducerLLVMGCC;
}
bool DWARFUnit::Supports_unnamed_objc_bitfields() {
if (GetProducer() == eProducerClang) {
const uint32_t major_version = GetProducerVersionMajor();
if (major_version > 425 ||
(major_version == 425 && GetProducerVersionUpdate() >= 13))
return true;
else
return false;
}
return true; // Assume all other compilers didn't have incorrect ObjC bitfield
// info
}
SymbolFileDWARF *DWARFUnit::GetSymbolFileDWARF() const {
return Data().m_dwarf2Data;
}
DWARFProducer DWARFUnit::GetProducer() {
return Data().GetProducer();
}
uint32_t DWARFUnit::GetProducerVersionMajor() {
return Data().GetProducerVersionMajor();
}
uint32_t DWARFUnit::GetProducerVersionMinor() {
return Data().GetProducerVersionMinor();
}
uint32_t DWARFUnit::GetProducerVersionUpdate() {
return Data().GetProducerVersionUpdate();
}
LanguageType DWARFUnit::LanguageTypeFromDWARF(uint64_t val) {
// Note: user languages between lo_user and hi_user
// must be handled explicitly here.
switch (val) {
case DW_LANG_Mips_Assembler:
return eLanguageTypeMipsAssembler;
case DW_LANG_GOOGLE_RenderScript:
return eLanguageTypeExtRenderScript;
default:
return static_cast<LanguageType>(val);
}
}
LanguageType DWARFUnit::GetLanguageType() {
return Data().GetLanguageType();
}
bool DWARFUnit::IsDWARF64() const { return Data().m_is_dwarf64; }
bool DWARFUnit::GetIsOptimized() {
return Data().GetIsOptimized();
}
SymbolFileDWARFDwo *DWARFUnit::GetDwoSymbolFile() const {
return Data().m_dwo_symbol_file.get();
}
dw_offset_t DWARFUnit::GetBaseObjOffset() const {
return Data().m_base_obj_offset;
}
const DWARFDebugInfoEntry *DWARFUnit::GetCompileUnitDIEPtrOnly() {
return Data().GetCompileUnitDIEPtrOnly();
}
const DWARFDebugInfoEntry *DWARFUnit::DIEPtr() {
return Data().DIEPtr();
}
void DWARFUnit::Index(NameToDIE &func_basenames,
NameToDIE &func_fullnames, NameToDIE &func_methods,
NameToDIE &func_selectors,
NameToDIE &objc_class_selectors,
NameToDIE &globals, NameToDIE &types,
NameToDIE &namespaces) {
assert(!Data().m_dwarf2Data->GetBaseCompileUnit() &&
"DWARFUnit associated with .dwo or .dwp "
"should not be indexed directly");
Log *log(LogChannelDWARF::GetLogIfAll(DWARF_LOG_LOOKUPS));
if (log) {
Data().m_dwarf2Data->GetObjectFile()->GetModule()->LogMessage(
log,
"DWARFUnit::Index() for compile unit at .debug_info[0x%8.8x]",
GetOffset());
}
const LanguageType cu_language = GetLanguageType();
DWARFFormValue::FixedFormSizes fixed_form_sizes =
DWARFFormValue::GetFixedFormSizesForAddressSize(GetAddressByteSize(),
IsDWARF64());
IndexPrivate(this, cu_language, fixed_form_sizes, GetOffset(), func_basenames,
func_fullnames, func_methods, func_selectors,
objc_class_selectors, globals, types, namespaces);
SymbolFileDWARFDwo *dwo_symbol_file = GetDwoSymbolFile();
if (dwo_symbol_file) {
IndexPrivate(
dwo_symbol_file->GetCompileUnit(), cu_language, fixed_form_sizes,
GetOffset(), func_basenames, func_fullnames, func_methods,
func_selectors, objc_class_selectors, globals, types, namespaces);
}
}
void DWARFUnit::IndexPrivate(
DWARFUnit *dwarf_cu, const LanguageType cu_language,
const DWARFFormValue::FixedFormSizes &fixed_form_sizes,
const dw_offset_t cu_offset, NameToDIE &func_basenames,
NameToDIE &func_fullnames, NameToDIE &func_methods,
NameToDIE &func_selectors, NameToDIE &objc_class_selectors,
NameToDIE &globals, NameToDIE &types, NameToDIE &namespaces) {
DWARFDebugInfoEntry::const_iterator pos;
DWARFDebugInfoEntry::const_iterator begin =
dwarf_cu->Data().m_die_array.begin();
DWARFDebugInfoEntry::const_iterator end = dwarf_cu->Data().m_die_array.end();
for (pos = begin; pos != end; ++pos) {
const DWARFDebugInfoEntry &die = *pos;
const dw_tag_t tag = die.Tag();
switch (tag) {
case DW_TAG_array_type:
case DW_TAG_base_type:
case DW_TAG_class_type:
case DW_TAG_constant:
case DW_TAG_enumeration_type:
case DW_TAG_inlined_subroutine:
case DW_TAG_namespace:
case DW_TAG_string_type:
case DW_TAG_structure_type:
case DW_TAG_subprogram:
case DW_TAG_subroutine_type:
case DW_TAG_typedef:
case DW_TAG_union_type:
case DW_TAG_unspecified_type:
case DW_TAG_variable:
break;
default:
continue;
}
DWARFAttributes attributes;
const char *name = NULL;
const char *mangled_cstr = NULL;
bool is_declaration = false;
// bool is_artificial = false;
bool has_address = false;
bool has_location_or_const_value = false;
bool is_global_or_static_variable = false;
DWARFFormValue specification_die_form;
const size_t num_attributes =
die.GetAttributes(&dwarf_cu->Data(), fixed_form_sizes, attributes);
if (num_attributes > 0) {
for (uint32_t i = 0; i < num_attributes; ++i) {
dw_attr_t attr = attributes.AttributeAtIndex(i);
DWARFFormValue form_value;
switch (attr) {
case DW_AT_name:
if (attributes.ExtractFormValueAtIndex(i, form_value))
name = form_value.AsCString();
break;
case DW_AT_declaration:
if (attributes.ExtractFormValueAtIndex(i, form_value))
is_declaration = form_value.Unsigned() != 0;
break;
// case DW_AT_artificial:
// if (attributes.ExtractFormValueAtIndex(i,
// form_value))
// is_artificial = form_value.Unsigned() != 0;
// break;
case DW_AT_MIPS_linkage_name:
case DW_AT_linkage_name:
if (attributes.ExtractFormValueAtIndex(i, form_value))
mangled_cstr = form_value.AsCString();
break;
case DW_AT_low_pc:
case DW_AT_high_pc:
case DW_AT_ranges:
has_address = true;
break;
case DW_AT_entry_pc:
has_address = true;
break;
case DW_AT_location:
case DW_AT_const_value:
has_location_or_const_value = true;
if (tag == DW_TAG_variable) {
const DWARFDebugInfoEntry *parent_die = die.GetParent();
while (parent_die != NULL) {
switch (parent_die->Tag()) {
case DW_TAG_subprogram:
case DW_TAG_lexical_block:
case DW_TAG_inlined_subroutine:
// Even if this is a function level static, we don't add it. We
// could theoretically
// add these if we wanted to by introspecting into the
// DW_AT_location and seeing
// if the location describes a hard coded address, but we dont
// want the performance
// penalty of that right now.
is_global_or_static_variable = false;
// if
// (attributes.ExtractFormValueAtIndex(dwarf2Data,
// i, form_value))
// {
// // If we have valid block
// data, then we have location
// expression bytes
// // that are fixed (not a
// location list).
// const uint8_t *block_data =
// form_value.BlockData();
// if (block_data)
// {
// uint32_t block_length =
// form_value.Unsigned();
// if (block_length == 1 +
// attributes.CompileUnitAtIndex(i)->GetAddressByteSize())
// {
// if (block_data[0] ==
// DW_OP_addr)
// add_die = true;
// }
// }
// }
parent_die = NULL; // Terminate the while loop.
break;
case DW_TAG_compile_unit:
is_global_or_static_variable = true;
parent_die = NULL; // Terminate the while loop.
break;
default:
parent_die =
parent_die->GetParent(); // Keep going in the while loop.
break;
}
}
}
break;
case DW_AT_specification:
if (attributes.ExtractFormValueAtIndex(i, form_value))
specification_die_form = form_value;
break;
}
}
}
switch (tag) {
case DW_TAG_subprogram:
if (has_address) {
if (name) {
ObjCLanguage::MethodName objc_method(name, true);
if (objc_method.IsValid(true)) {
ConstString objc_class_name_with_category(
objc_method.GetClassNameWithCategory());
ConstString objc_selector_name(objc_method.GetSelector());
ConstString objc_fullname_no_category_name(
objc_method.GetFullNameWithoutCategory(true));
ConstString objc_class_name_no_category(objc_method.GetClassName());
func_fullnames.Insert(ConstString(name),
DIERef(cu_offset, die.GetOffset()));
if (objc_class_name_with_category)
objc_class_selectors.Insert(objc_class_name_with_category,
DIERef(cu_offset, die.GetOffset()));
if (objc_class_name_no_category &&
objc_class_name_no_category != objc_class_name_with_category)
objc_class_selectors.Insert(objc_class_name_no_category,
DIERef(cu_offset, die.GetOffset()));
if (objc_selector_name)
func_selectors.Insert(objc_selector_name,
DIERef(cu_offset, die.GetOffset()));
if (objc_fullname_no_category_name)
func_fullnames.Insert(objc_fullname_no_category_name,
DIERef(cu_offset, die.GetOffset()));
}
// If we have a mangled name, then the DW_AT_name attribute
// is usually the method name without the class or any parameters
const DWARFDebugInfoEntry *parent = die.GetParent();
bool is_method = false;
if (parent) {
dw_tag_t parent_tag = parent->Tag();
if (parent_tag == DW_TAG_class_type ||
parent_tag == DW_TAG_structure_type) {
is_method = true;
} else {
if (specification_die_form.IsValid()) {
DWARFDIE specification_die =
dwarf_cu->GetSymbolFileDWARF()->DebugInfo()->GetDIE(
DIERef(specification_die_form));
if (specification_die.GetParent().IsStructOrClass())
is_method = true;
}
}
}
if (is_method)
func_methods.Insert(ConstString(name),
DIERef(cu_offset, die.GetOffset()));
else
func_basenames.Insert(ConstString(name),
DIERef(cu_offset, die.GetOffset()));
if (!is_method && !mangled_cstr && !objc_method.IsValid(true))
func_fullnames.Insert(ConstString(name),
DIERef(cu_offset, die.GetOffset()));
}
if (mangled_cstr) {
// Make sure our mangled name isn't the same string table entry
// as our name. If it starts with '_', then it is ok, else compare
// the string to make sure it isn't the same and we don't end up
// with duplicate entries
if (name && name != mangled_cstr &&
((mangled_cstr[0] == '_') ||
(::strcmp(name, mangled_cstr) != 0))) {
Mangled mangled(ConstString(mangled_cstr), true);
func_fullnames.Insert(mangled.GetMangledName(),
DIERef(cu_offset, die.GetOffset()));
ConstString demangled = mangled.GetDemangledName(cu_language);
if (demangled)
func_fullnames.Insert(demangled,
DIERef(cu_offset, die.GetOffset()));
}
}
}
break;
case DW_TAG_inlined_subroutine:
if (has_address) {
if (name)
func_basenames.Insert(ConstString(name),
DIERef(cu_offset, die.GetOffset()));
if (mangled_cstr) {
// Make sure our mangled name isn't the same string table entry
// as our name. If it starts with '_', then it is ok, else compare
// the string to make sure it isn't the same and we don't end up
// with duplicate entries
if (name && name != mangled_cstr &&
((mangled_cstr[0] == '_') ||
(::strcmp(name, mangled_cstr) != 0))) {
Mangled mangled(ConstString(mangled_cstr), true);
func_fullnames.Insert(mangled.GetMangledName(),
DIERef(cu_offset, die.GetOffset()));
ConstString demangled = mangled.GetDemangledName(cu_language);
if (demangled)
func_fullnames.Insert(demangled,
DIERef(cu_offset, die.GetOffset()));
}
} else
func_fullnames.Insert(ConstString(name),
DIERef(cu_offset, die.GetOffset()));
}
break;
case DW_TAG_array_type:
case DW_TAG_base_type:
case DW_TAG_class_type:
case DW_TAG_constant:
case DW_TAG_enumeration_type:
case DW_TAG_string_type:
case DW_TAG_structure_type:
case DW_TAG_subroutine_type:
case DW_TAG_typedef:
case DW_TAG_union_type:
case DW_TAG_unspecified_type:
if (name && !is_declaration)
types.Insert(ConstString(name), DIERef(cu_offset, die.GetOffset()));
if (mangled_cstr && !is_declaration)
types.Insert(ConstString(mangled_cstr),
DIERef(cu_offset, die.GetOffset()));
break;
case DW_TAG_namespace:
if (name)
namespaces.Insert(ConstString(name),
DIERef(cu_offset, die.GetOffset()));
break;
case DW_TAG_variable:
if (name && has_location_or_const_value && is_global_or_static_variable) {
globals.Insert(ConstString(name), DIERef(cu_offset, die.GetOffset()));
// Be sure to include variables by their mangled and demangled
// names if they have any since a variable can have a basename
// "i", a mangled named "_ZN12_GLOBAL__N_11iE" and a demangled
// mangled name "(anonymous namespace)::i"...
// Make sure our mangled name isn't the same string table entry
// as our name. If it starts with '_', then it is ok, else compare
// the string to make sure it isn't the same and we don't end up
// with duplicate entries
if (mangled_cstr && name != mangled_cstr &&
((mangled_cstr[0] == '_') || (::strcmp(name, mangled_cstr) != 0))) {
Mangled mangled(ConstString(mangled_cstr), true);
globals.Insert(mangled.GetMangledName(),
DIERef(cu_offset, die.GetOffset()));
ConstString demangled = mangled.GetDemangledName(cu_language);
if (demangled)
globals.Insert(demangled, DIERef(cu_offset, die.GetOffset()));
}
}
break;
default:
continue;
}
}
}

View File

@@ -0,0 +1,159 @@
//===-- DWARFUnit.h ---------------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef SymbolFileDWARF_DWARFUnit_h_
#define SymbolFileDWARF_DWARFUnit_h_
#include "DWARFDIE.h"
#include "DWARFDebugInfoEntry.h"
#include "lldb/lldb-enumerations.h"
class DWARFUnit;
class DWARFCompileUnit;
class NameToDIE;
class SymbolFileDWARF;
class SymbolFileDWARFDwo;
typedef std::shared_ptr<DWARFUnit> DWARFUnitSP;
enum DWARFProducer {
eProducerInvalid = 0,
eProducerClang,
eProducerGCC,
eProducerLLVMGCC,
eProcucerOther
};
class DWARFUnit {
public:
virtual ~DWARFUnit();
size_t ExtractDIEsIfNeeded(bool cu_die_only);
DWARFDIE LookupAddress(const dw_addr_t address);
size_t AppendDIEsWithTag(const dw_tag_t tag,
DWARFDIECollection &matching_dies,
uint32_t depth = UINT32_MAX) const;
bool Verify(lldb_private::Stream *s) const;
void Dump(lldb_private::Stream *s) const;
// Offset of the initial length field.
dw_offset_t GetOffset() const { return m_offset; }
lldb::user_id_t GetID() const;
// Size in bytes of the initial length + compile unit header.
uint32_t Size() const;
bool ContainsDIEOffset(dw_offset_t die_offset) const {
return die_offset >= GetFirstDIEOffset() &&
die_offset < GetNextCompileUnitOffset();
}
dw_offset_t GetFirstDIEOffset() const { return m_offset + Size(); }
dw_offset_t GetNextCompileUnitOffset() const;
// Size of the CU data (without initial length and without header).
size_t GetDebugInfoSize() const;
// Size of the CU data incl. header but without initial length.
uint32_t GetLength() const;
uint16_t GetVersion() const;
const DWARFAbbreviationDeclarationSet *GetAbbreviations() const;
dw_offset_t GetAbbrevOffset() const;
uint8_t GetAddressByteSize() const;
dw_addr_t GetBaseAddress() const;
dw_addr_t GetAddrBase() const;
dw_addr_t GetRangesBase() const;
void SetAddrBase(dw_addr_t addr_base, dw_addr_t ranges_base, dw_offset_t base_obj_offset);
void ClearDIEs(bool keep_compile_unit_die);
void BuildAddressRangeTable(SymbolFileDWARF *dwarf2Data,
DWARFDebugAranges *debug_aranges);
lldb::ByteOrder GetByteOrder() const;
lldb_private::TypeSystem *GetTypeSystem();
DWARFFormValue::FixedFormSizes GetFixedFormSizes();
void SetBaseAddress(dw_addr_t base_addr);
DWARFDIE
GetCompileUnitDIEOnly();
DWARFDIE
DIE();
bool HasDIEsParsed() const;
DWARFDIE GetDIE(dw_offset_t die_offset);
static uint8_t GetAddressByteSize(const DWARFUnit *cu);
static bool IsDWARF64(const DWARFUnit *cu);
static uint8_t GetDefaultAddressSize();
static void SetDefaultAddressSize(uint8_t addr_size);
void *GetUserData() const;
void SetUserData(void *d);
bool Supports_DW_AT_APPLE_objc_complete_type();
bool DW_AT_decl_file_attributes_are_invalid();
bool Supports_unnamed_objc_bitfields();
void Index(NameToDIE &func_basenames, NameToDIE &func_fullnames,
NameToDIE &func_methods, NameToDIE &func_selectors,
NameToDIE &objc_class_selectors, NameToDIE &globals,
NameToDIE &types, NameToDIE &namespaces);
SymbolFileDWARF *GetSymbolFileDWARF() const;
DWARFProducer GetProducer();
uint32_t GetProducerVersionMajor();
uint32_t GetProducerVersionMinor();
uint32_t GetProducerVersionUpdate();
static lldb::LanguageType LanguageTypeFromDWARF(uint64_t val);
lldb::LanguageType GetLanguageType();
bool IsDWARF64() const;
bool GetIsOptimized();
SymbolFileDWARFDwo *GetDwoSymbolFile() const;
dw_offset_t GetBaseObjOffset() const;
protected:
virtual DWARFCompileUnit &Data() = 0;
virtual const DWARFCompileUnit &Data() const = 0;
DWARFUnit();
static void
IndexPrivate(DWARFUnit *dwarf_cu, const lldb::LanguageType cu_language,
const DWARFFormValue::FixedFormSizes &fixed_form_sizes,
const dw_offset_t cu_offset, NameToDIE &func_basenames,
NameToDIE &func_fullnames, NameToDIE &func_methods,
NameToDIE &func_selectors, NameToDIE &objc_class_selectors,
NameToDIE &globals, NameToDIE &types, NameToDIE &namespaces);
// Offset of the initial length field.
dw_offset_t m_offset;
private:
const DWARFDebugInfoEntry *GetCompileUnitDIEPtrOnly();
const DWARFDebugInfoEntry *DIEPtr();
DISALLOW_COPY_AND_ASSIGN(DWARFUnit);
};
#endif // SymbolFileDWARF_DWARFUnit_h_