mirror of
https://github.com/intel/llvm.git
synced 2026-01-16 05:32:28 +08:00
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:
@@ -23,6 +23,7 @@ add_lldb_library(lldbPluginSymbolFileDWARF PLUGIN
|
||||
DWARFDIE.cpp
|
||||
DWARFDIECollection.cpp
|
||||
DWARFFormValue.cpp
|
||||
DWARFUnit.cpp
|
||||
HashedNameToDIE.cpp
|
||||
LogChannelDWARF.cpp
|
||||
NameToDIE.cpp
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
630
lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
Normal file
630
lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
159
lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h
Normal file
159
lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h
Normal 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_
|
||||
Reference in New Issue
Block a user