diff options
author | Greg Clayton <gclayton@apple.com> | 2010-09-15 08:33:30 +0000 |
---|---|---|
committer | Greg Clayton <gclayton@apple.com> | 2010-09-15 08:33:30 +0000 |
commit | d88d759a74f1b79cdd45b27f5c1c56cf2d0a472e (patch) | |
tree | fe6ab655ca6d1f73ed87749b6b97a65bb5e3e9e0 /lldb/source/Plugins/SymbolFile | |
parent | c288cda3d5259e5c73e29fdbc5d2499c37427364 (diff) | |
download | bcm5719-llvm-d88d759a74f1b79cdd45b27f5c1c56cf2d0a472e.tar.gz bcm5719-llvm-d88d759a74f1b79cdd45b27f5c1c56cf2d0a472e.zip |
15-20% speed improvement when parsing DWARF. I used instruments to
find the hotspots in our code when indexing the DWARF. A combination of
using SmallVector to avoid collection allocations, using fixed form
sizes when possible, and optimizing the hot loops contributed to the
speedup.
llvm-svn: 113961
Diffstat (limited to 'lldb/source/Plugins/SymbolFile')
8 files changed, 528 insertions, 298 deletions
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.h index 7959f264dfe..f748ab141af 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFAbbreviationDeclaration.h @@ -51,6 +51,10 @@ public: { m_attributes[idx].get(attr, form); } + dw_form_t GetFormByIndexUnchecked (uint32_t idx) const + { + return m_attributes[idx].get_form(); + } void CopyExcludingAddressAttributes(const DWARFAbbreviationDeclaration& abbr_decl, const uint32_t idx); void CopyChangingStringToStrp( const DWARFAbbreviationDeclaration& abbr_decl, diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp index 0a03684bbaa..c43138a0522 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp @@ -157,7 +157,7 @@ DWARFCompileUnit::ExtractDIEsIfNeeded (bool cu_die_only) uint32_t offset = GetFirstDIEOffset(); DWARFDebugInfoEntry die; // Keep a flat array of the DIE for binary lookup by DIE offset - Log *log = LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO); +// Log *log = LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO); // if (log) // log->Printf("0x%8.8x: Compile Unit: length = 0x%8.8x, version = 0x%4.4x, abbr_offset = 0x%8.8x, addr_size = 0x%2.2x", // cu->GetOffset(), @@ -169,17 +169,29 @@ DWARFCompileUnit::ExtractDIEsIfNeeded (bool cu_die_only) uint32_t depth = 0; // We are in our compile unit, parse starting at the offset // we were told to parse - while (die.Extract(m_dwarf2Data, this, &offset)) + const DataExtractor& debug_info_data = m_dwarf2Data->get_debug_info_data(); + + const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (GetAddressByteSize()); + while (die.FastExtract (debug_info_data, this, fixed_form_sizes, &offset)) { - if (log) - log->Printf("0x%8.8x: %*.*s%s%s", - die.GetOffset(), - depth * 2, depth * 2, "", - DW_TAG_value_to_name (die.Tag()), - die.HasChildren() ? " *" : ""); +// if (log) +// log->Printf("0x%8.8x: %*.*s%s%s", +// die.GetOffset(), +// depth * 2, depth * 2, "", +// DW_TAG_value_to_name (die.Tag()), +// die.HasChildren() ? " *" : ""); + + if (depth == 0) + { + uint64_t base_addr = die.GetAttributeValueAsUnsigned(m_dwarf2Data, this, DW_AT_low_pc, LLDB_INVALID_ADDRESS); + if (base_addr == LLDB_INVALID_ADDRESS) + base_addr = die.GetAttributeValueAsUnsigned(m_dwarf2Data, this, DW_AT_entry_pc, 0); + SetBaseAddress (base_addr); + } + if (cu_die_only) { - AddDIE(die); + AddDIE (die); return 1; } else if (depth == 0 && initial_die_array_size == 1) @@ -188,7 +200,7 @@ DWARFCompileUnit::ExtractDIEsIfNeeded (bool cu_die_only) } else { - AddDIE(die); + AddDIE (die); } const DWARFAbbreviationDeclaration* abbrDecl = die.GetAbbreviationDeclarationPtr(); @@ -203,7 +215,7 @@ DWARFCompileUnit::ExtractDIEsIfNeeded (bool cu_die_only) // NULL DIE. if (depth > 0) --depth; - else + if (depth == 0) break; // We are done with this compile unit! } @@ -564,6 +576,8 @@ DWARFCompileUnit::Index { const DataExtractor* debug_str = &m_dwarf2Data->get_debug_str_data(); + const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (GetAddressByteSize()); + NameToDIE::Info die_info = { cu_idx, 0 }; DWARFDebugInfoEntry::const_iterator pos; DWARFDebugInfoEntry::const_iterator begin = m_die_array.begin(); @@ -609,7 +623,7 @@ DWARFCompileUnit::Index DWARFDebugRanges::RangeList ranges; dw_offset_t specification_die_offset = DW_INVALID_OFFSET; - const size_t num_attributes = die.GetAttributes(m_dwarf2Data, this, attributes); + const size_t num_attributes = die.GetAttributes(m_dwarf2Data, this, fixed_form_sizes, attributes); if (num_attributes > 0) { uint32_t i; diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp index 50a7e9ba5ed..5ad9273d1ba 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp @@ -37,7 +37,6 @@ extern int g_verbose; DWARFDebugInfoEntry::Attributes::Attributes() : m_infos() { - m_infos.reserve(20); } DWARFDebugInfoEntry::Attributes::~Attributes() @@ -48,9 +47,9 @@ DWARFDebugInfoEntry::Attributes::~Attributes() uint32_t DWARFDebugInfoEntry::Attributes::FindAttributeIndex(dw_attr_t attr) const { - std::vector<Info>::const_iterator end = m_infos.end(); - std::vector<Info>::const_iterator beg = m_infos.begin(); - std::vector<Info>::const_iterator pos; + collection::const_iterator end = m_infos.end(); + collection::const_iterator beg = m_infos.begin(); + collection::const_iterator pos; for (pos = beg; pos != end; ++pos) { if (pos->attr == attr) @@ -102,6 +101,124 @@ DWARFDebugInfoEntry::Attributes::FormValueAsUnsignedAtIndex(SymbolFileDWARF* dwa } + +bool +DWARFDebugInfoEntry::FastExtract +( + const DataExtractor& debug_info_data, + const DWARFCompileUnit* cu, + const uint8_t *fixed_form_sizes, + uint32_t* offset_ptr +) +{ + m_offset = *offset_ptr; + + dw_uleb128_t abbrCode = debug_info_data.GetULEB128 (offset_ptr); + + assert (fixed_form_sizes); // For best performance this should be specified! + + if (abbrCode) + { + register uint32_t offset = *offset_ptr; + + m_abbrevDecl = cu->GetAbbreviations()->GetAbbreviationDeclaration(abbrCode); + + // Skip all data in the .debug_info for the attributes + const uint32_t numAttributes = m_abbrevDecl->NumAttributes(); + register uint32_t i; + register dw_form_t form; + for (i=0; i<numAttributes; ++i) + { + form = m_abbrevDecl->GetFormByIndexUnchecked(i); + + const uint8_t fixed_skip_size = fixed_form_sizes [form]; + if (fixed_skip_size) + offset += fixed_skip_size; + else + { + bool form_is_indirect = false; + do + { + register uint32_t form_size = 0; + switch (form) + { + // Blocks if inlined data that have a length field and the data bytes + // inlined in the .debug_info + case DW_FORM_block : form_size = debug_info_data.GetULEB128 (&offset); break; + case DW_FORM_block1 : form_size = debug_info_data.GetU8_unchecked (&offset); break; + case DW_FORM_block2 : form_size = debug_info_data.GetU16_unchecked (&offset);break; + case DW_FORM_block4 : form_size = debug_info_data.GetU32_unchecked (&offset);break; + + // Inlined NULL terminated C-strings + case DW_FORM_string : + debug_info_data.GetCStr (&offset); + break; + + // Compile unit address sized values + case DW_FORM_addr : + case DW_FORM_ref_addr : + form_size = cu->GetAddressByteSize(); + break; + + // 1 byte values + case DW_FORM_data1 : + case DW_FORM_flag : + case DW_FORM_ref1 : + form_size = 1; + break; + + // 2 byte values + case DW_FORM_data2 : + case DW_FORM_ref2 : + form_size = 2; + break; + + // 4 byte values + case DW_FORM_strp : + case DW_FORM_data4 : + case DW_FORM_ref4 : + form_size = 4; + break; + + // 8 byte values + case DW_FORM_data8 : + case DW_FORM_ref8 : + form_size = 8; + break; + + // signed or unsigned LEB 128 values + case DW_FORM_sdata : + case DW_FORM_udata : + case DW_FORM_ref_udata : + debug_info_data.Skip_LEB128 (&offset); + break; + + case DW_FORM_indirect : + form_is_indirect = true; + form = debug_info_data.GetULEB128 (&offset); + break; + + default: + *offset_ptr = m_offset; + return false; + } + offset += form_size; + + } while (form_is_indirect); + } + } + *offset_ptr = offset; + return true; + } + else + { + m_abbrevDecl = NULL; + return true; // NULL debug tag entry + } + + return false; +} + //---------------------------------------------------------------------- // Extract // @@ -502,254 +619,254 @@ DWARFDebugInfoEntry::DumpAncestry // DWARFDebugInfoEntry::CompareState compare_state; // int result = DWARFDebugInfoEntry::Compare(this, 0x00017ccb, 0x0001eb2b, compare_state, false, true); //---------------------------------------------------------------------- -int -DWARFDebugInfoEntry::Compare -( - SymbolFileDWARF* dwarf2Data, - dw_offset_t a_die_offset, - dw_offset_t b_die_offset, - CompareState &compare_state, - bool compare_siblings, - bool compare_children -) -{ - if (a_die_offset == b_die_offset) - return 0; - - DWARFCompileUnitSP a_cu_sp; - DWARFCompileUnitSP b_cu_sp; - const DWARFDebugInfoEntry* a_die = dwarf2Data->DebugInfo()->GetDIEPtr(a_die_offset, &a_cu_sp); - const DWARFDebugInfoEntry* b_die = dwarf2Data->DebugInfo()->GetDIEPtr(b_die_offset, &b_cu_sp); - - return Compare(dwarf2Data, a_cu_sp.get(), a_die, b_cu_sp.get(), b_die, compare_state, compare_siblings, compare_children); -} - -int -DWARFDebugInfoEntry::Compare -( - SymbolFileDWARF* dwarf2Data, - DWARFCompileUnit* a_cu, const DWARFDebugInfoEntry* a_die, - DWARFCompileUnit* b_cu, const DWARFDebugInfoEntry* b_die, - CompareState &compare_state, - bool compare_siblings, - bool compare_children -) -{ - if (a_die == b_die) - return 0; - - if (!compare_state.AddTypePair(a_die->GetOffset(), b_die->GetOffset())) - { - // We are already comparing both of these types, so let - // compares complete for the real result - return 0; - } - - //printf("DWARFDebugInfoEntry::Compare(0x%8.8x, 0x%8.8x)\n", a_die->GetOffset(), b_die->GetOffset()); - - // Do we have two valid DIEs? - if (a_die && b_die) - { - // Both DIE are valid - int result = 0; - - const dw_tag_t a_tag = a_die->Tag(); - const dw_tag_t b_tag = b_die->Tag(); - if (a_tag == 0 && b_tag == 0) - return 0; - - //printf(" comparing tags: %s and %s\n", DW_TAG_value_to_name(a_tag), DW_TAG_value_to_name(b_tag)); - - if (a_tag < b_tag) - return -1; - else if (a_tag > b_tag) - return 1; - - DWARFDebugInfoEntry::Attributes a_attrs; - DWARFDebugInfoEntry::Attributes b_attrs; - size_t a_attr_count = a_die->GetAttributes(dwarf2Data, a_cu, a_attrs); - size_t b_attr_count = b_die->GetAttributes(dwarf2Data, b_cu, b_attrs); - if (a_attr_count != b_attr_count) - { - a_attrs.RemoveAttribute(DW_AT_sibling); - b_attrs.RemoveAttribute(DW_AT_sibling); - } - - a_attr_count = a_attrs.Size(); - b_attr_count = b_attrs.Size(); - - DWARFFormValue a_form_value; - DWARFFormValue b_form_value; - - if (a_attr_count != b_attr_count) - { - uint32_t is_decl_index = a_attrs.FindAttributeIndex(DW_AT_declaration); - uint32_t a_name_index = UINT32_MAX; - uint32_t b_name_index = UINT32_MAX; - if (is_decl_index != UINT32_MAX) - { - if (a_attr_count == 2) - { - a_name_index = a_attrs.FindAttributeIndex(DW_AT_name); - b_name_index = b_attrs.FindAttributeIndex(DW_AT_name); - } - } - else - { - is_decl_index = b_attrs.FindAttributeIndex(DW_AT_declaration); - if (is_decl_index != UINT32_MAX && a_attr_count == 2) - { - a_name_index = a_attrs.FindAttributeIndex(DW_AT_name); - b_name_index = b_attrs.FindAttributeIndex(DW_AT_name); - } - } - if (a_name_index != UINT32_MAX && b_name_index != UINT32_MAX) - { - if (a_attrs.ExtractFormValueAtIndex(dwarf2Data, a_name_index, a_form_value) && - b_attrs.ExtractFormValueAtIndex(dwarf2Data, b_name_index, b_form_value)) - { - result = DWARFFormValue::Compare (a_form_value, b_form_value, a_cu, b_cu, &dwarf2Data->get_debug_str_data()); - if (result == 0) - { - a_attr_count = b_attr_count = 0; - compare_children = false; - } - } - } - } - - if (a_attr_count < b_attr_count) - return -1; - if (a_attr_count > b_attr_count) - return 1; - - - // The number of attributes are the same... - if (a_attr_count > 0) - { - const DataExtractor* debug_str_data_ptr = &dwarf2Data->get_debug_str_data(); - - uint32_t i; - for (i=0; i<a_attr_count; ++i) - { - const dw_attr_t a_attr = a_attrs.AttributeAtIndex(i); - const dw_attr_t b_attr = b_attrs.AttributeAtIndex(i); - //printf(" comparing attributes\n\t\t0x%8.8x: %s %s\t\t0x%8.8x: %s %s\n", - // a_attrs.DIEOffsetAtIndex(i), DW_FORM_value_to_name(a_attrs.FormAtIndex(i)), DW_AT_value_to_name(a_attr), - // b_attrs.DIEOffsetAtIndex(i), DW_FORM_value_to_name(b_attrs.FormAtIndex(i)), DW_AT_value_to_name(b_attr)); - - if (a_attr < b_attr) - return -1; - else if (a_attr > b_attr) - return 1; - - switch (a_attr) - { - // Since we call a form of GetAttributes which inlines the - // attributes from DW_AT_abstract_origin and DW_AT_specification - // we don't care if their values mismatch... - case DW_AT_abstract_origin: - case DW_AT_specification: - case DW_AT_sibling: - case DW_AT_containing_type: - //printf(" action = IGNORE\n"); - result = 0; - break; // ignore - - default: - if (a_attrs.ExtractFormValueAtIndex(dwarf2Data, i, a_form_value) && - b_attrs.ExtractFormValueAtIndex(dwarf2Data, i, b_form_value)) - result = DWARFFormValue::Compare (a_form_value, b_form_value, a_cu, b_cu, debug_str_data_ptr); - break; - } - - //printf("\t result = %i\n", result); - - if (result != 0) - { - // Attributes weren't equal, lets see if we care? - switch (a_attr) - { - case DW_AT_decl_file: - // TODO: add the ability to compare files in two different compile units - if (a_cu == b_cu) - { - //printf(" action = RETURN RESULT\n"); - return result; // Only return the compare results when the compile units are the same and the decl_file attributes can be compared - } - else - { - result = 0; - //printf(" action = IGNORE\n"); - } - break; - - default: - switch (a_attrs.FormAtIndex(i)) - { - case DW_FORM_ref1: - case DW_FORM_ref2: - case DW_FORM_ref4: - case DW_FORM_ref8: - case DW_FORM_ref_udata: - case DW_FORM_ref_addr: - //printf(" action = COMPARE DIEs 0x%8.8x 0x%8.8x\n", (dw_offset_t)a_form_value.Reference(a_cu), (dw_offset_t)b_form_value.Reference(b_cu)); - // These attribute values refer to other DIEs, so lets compare those instead of their DIE offsets... - result = Compare(dwarf2Data, a_form_value.Reference(a_cu), b_form_value.Reference(b_cu), compare_state, false, true); - if (result != 0) - return result; - break; - - default: - // We do care that they were different, return this result... - //printf(" action = RETURN RESULT\n"); - return result; - } - } - } - } - } - //printf(" SUCCESS\n\t\t0x%8.8x: %s\n\t\t0x%8.8x: %s\n", a_die->GetOffset(), DW_TAG_value_to_name(a_tag), b_die->GetOffset(), DW_TAG_value_to_name(b_tag)); - - if (compare_children) - { - bool a_has_children = a_die->HasChildren(); - bool b_has_children = b_die->HasChildren(); - if (a_has_children == b_has_children) - { - // Both either have kids or don't - if (a_has_children) - result = Compare( dwarf2Data, - a_cu, a_die->GetFirstChild(), - b_cu, b_die->GetFirstChild(), - compare_state, true, compare_children); - else - result = 0; - } - else if (!a_has_children) - result = -1; // A doesn't have kids, but B does - else - result = 1; // A has kids, but B doesn't - } - - if (compare_siblings) - { - result = Compare( dwarf2Data, - a_cu, a_die->GetSibling(), - b_cu, b_die->GetSibling(), - compare_state, true, compare_children); - } - - return result; - } - - if (a_die == NULL) - return -1; // a_die is NULL, yet b_die is non-NULL - else - return 1; // a_die is non-NULL, yet b_die is NULL - -} - +//int +//DWARFDebugInfoEntry::Compare +//( +// SymbolFileDWARF* dwarf2Data, +// dw_offset_t a_die_offset, +// dw_offset_t b_die_offset, +// CompareState &compare_state, +// bool compare_siblings, +// bool compare_children +//) +//{ +// if (a_die_offset == b_die_offset) +// return 0; +// +// DWARFCompileUnitSP a_cu_sp; +// DWARFCompileUnitSP b_cu_sp; +// const DWARFDebugInfoEntry* a_die = dwarf2Data->DebugInfo()->GetDIEPtr(a_die_offset, &a_cu_sp); +// const DWARFDebugInfoEntry* b_die = dwarf2Data->DebugInfo()->GetDIEPtr(b_die_offset, &b_cu_sp); +// +// return Compare(dwarf2Data, a_cu_sp.get(), a_die, b_cu_sp.get(), b_die, compare_state, compare_siblings, compare_children); +//} +// +//int +//DWARFDebugInfoEntry::Compare +//( +// SymbolFileDWARF* dwarf2Data, +// DWARFCompileUnit* a_cu, const DWARFDebugInfoEntry* a_die, +// DWARFCompileUnit* b_cu, const DWARFDebugInfoEntry* b_die, +// CompareState &compare_state, +// bool compare_siblings, +// bool compare_children +//) +//{ +// if (a_die == b_die) +// return 0; +// +// if (!compare_state.AddTypePair(a_die->GetOffset(), b_die->GetOffset())) +// { +// // We are already comparing both of these types, so let +// // compares complete for the real result +// return 0; +// } +// +// //printf("DWARFDebugInfoEntry::Compare(0x%8.8x, 0x%8.8x)\n", a_die->GetOffset(), b_die->GetOffset()); +// +// // Do we have two valid DIEs? +// if (a_die && b_die) +// { +// // Both DIE are valid +// int result = 0; +// +// const dw_tag_t a_tag = a_die->Tag(); +// const dw_tag_t b_tag = b_die->Tag(); +// if (a_tag == 0 && b_tag == 0) +// return 0; +// +// //printf(" comparing tags: %s and %s\n", DW_TAG_value_to_name(a_tag), DW_TAG_value_to_name(b_tag)); +// +// if (a_tag < b_tag) +// return -1; +// else if (a_tag > b_tag) +// return 1; +// +// DWARFDebugInfoEntry::Attributes a_attrs; +// DWARFDebugInfoEntry::Attributes b_attrs; +// size_t a_attr_count = a_die->GetAttributes(dwarf2Data, a_cu, a_attrs); +// size_t b_attr_count = b_die->GetAttributes(dwarf2Data, b_cu, b_attrs); +// if (a_attr_count != b_attr_count) +// { +// a_attrs.RemoveAttribute(DW_AT_sibling); +// b_attrs.RemoveAttribute(DW_AT_sibling); +// } +// +// a_attr_count = a_attrs.Size(); +// b_attr_count = b_attrs.Size(); +// +// DWARFFormValue a_form_value; +// DWARFFormValue b_form_value; +// +// if (a_attr_count != b_attr_count) +// { +// uint32_t is_decl_index = a_attrs.FindAttributeIndex(DW_AT_declaration); +// uint32_t a_name_index = UINT32_MAX; +// uint32_t b_name_index = UINT32_MAX; +// if (is_decl_index != UINT32_MAX) +// { +// if (a_attr_count == 2) +// { +// a_name_index = a_attrs.FindAttributeIndex(DW_AT_name); +// b_name_index = b_attrs.FindAttributeIndex(DW_AT_name); +// } +// } +// else +// { +// is_decl_index = b_attrs.FindAttributeIndex(DW_AT_declaration); +// if (is_decl_index != UINT32_MAX && a_attr_count == 2) +// { +// a_name_index = a_attrs.FindAttributeIndex(DW_AT_name); +// b_name_index = b_attrs.FindAttributeIndex(DW_AT_name); +// } +// } +// if (a_name_index != UINT32_MAX && b_name_index != UINT32_MAX) +// { +// if (a_attrs.ExtractFormValueAtIndex(dwarf2Data, a_name_index, a_form_value) && +// b_attrs.ExtractFormValueAtIndex(dwarf2Data, b_name_index, b_form_value)) +// { +// result = DWARFFormValue::Compare (a_form_value, b_form_value, a_cu, b_cu, &dwarf2Data->get_debug_str_data()); +// if (result == 0) +// { +// a_attr_count = b_attr_count = 0; +// compare_children = false; +// } +// } +// } +// } +// +// if (a_attr_count < b_attr_count) +// return -1; +// if (a_attr_count > b_attr_count) +// return 1; +// +// +// // The number of attributes are the same... +// if (a_attr_count > 0) +// { +// const DataExtractor* debug_str_data_ptr = &dwarf2Data->get_debug_str_data(); +// +// uint32_t i; +// for (i=0; i<a_attr_count; ++i) +// { +// const dw_attr_t a_attr = a_attrs.AttributeAtIndex(i); +// const dw_attr_t b_attr = b_attrs.AttributeAtIndex(i); +// //printf(" comparing attributes\n\t\t0x%8.8x: %s %s\t\t0x%8.8x: %s %s\n", +// // a_attrs.DIEOffsetAtIndex(i), DW_FORM_value_to_name(a_attrs.FormAtIndex(i)), DW_AT_value_to_name(a_attr), +// // b_attrs.DIEOffsetAtIndex(i), DW_FORM_value_to_name(b_attrs.FormAtIndex(i)), DW_AT_value_to_name(b_attr)); +// +// if (a_attr < b_attr) +// return -1; +// else if (a_attr > b_attr) +// return 1; +// +// switch (a_attr) +// { +// // Since we call a form of GetAttributes which inlines the +// // attributes from DW_AT_abstract_origin and DW_AT_specification +// // we don't care if their values mismatch... +// case DW_AT_abstract_origin: +// case DW_AT_specification: +// case DW_AT_sibling: +// case DW_AT_containing_type: +// //printf(" action = IGNORE\n"); +// result = 0; +// break; // ignore +// +// default: +// if (a_attrs.ExtractFormValueAtIndex(dwarf2Data, i, a_form_value) && +// b_attrs.ExtractFormValueAtIndex(dwarf2Data, i, b_form_value)) +// result = DWARFFormValue::Compare (a_form_value, b_form_value, a_cu, b_cu, debug_str_data_ptr); +// break; +// } +// +// //printf("\t result = %i\n", result); +// +// if (result != 0) +// { +// // Attributes weren't equal, lets see if we care? +// switch (a_attr) +// { +// case DW_AT_decl_file: +// // TODO: add the ability to compare files in two different compile units +// if (a_cu == b_cu) +// { +// //printf(" action = RETURN RESULT\n"); +// return result; // Only return the compare results when the compile units are the same and the decl_file attributes can be compared +// } +// else +// { +// result = 0; +// //printf(" action = IGNORE\n"); +// } +// break; +// +// default: +// switch (a_attrs.FormAtIndex(i)) +// { +// case DW_FORM_ref1: +// case DW_FORM_ref2: +// case DW_FORM_ref4: +// case DW_FORM_ref8: +// case DW_FORM_ref_udata: +// case DW_FORM_ref_addr: +// //printf(" action = COMPARE DIEs 0x%8.8x 0x%8.8x\n", (dw_offset_t)a_form_value.Reference(a_cu), (dw_offset_t)b_form_value.Reference(b_cu)); +// // These attribute values refer to other DIEs, so lets compare those instead of their DIE offsets... +// result = Compare(dwarf2Data, a_form_value.Reference(a_cu), b_form_value.Reference(b_cu), compare_state, false, true); +// if (result != 0) +// return result; +// break; +// +// default: +// // We do care that they were different, return this result... +// //printf(" action = RETURN RESULT\n"); +// return result; +// } +// } +// } +// } +// } +// //printf(" SUCCESS\n\t\t0x%8.8x: %s\n\t\t0x%8.8x: %s\n", a_die->GetOffset(), DW_TAG_value_to_name(a_tag), b_die->GetOffset(), DW_TAG_value_to_name(b_tag)); +// +// if (compare_children) +// { +// bool a_has_children = a_die->HasChildren(); +// bool b_has_children = b_die->HasChildren(); +// if (a_has_children == b_has_children) +// { +// // Both either have kids or don't +// if (a_has_children) +// result = Compare( dwarf2Data, +// a_cu, a_die->GetFirstChild(), +// b_cu, b_die->GetFirstChild(), +// compare_state, true, compare_children); +// else +// result = 0; +// } +// else if (!a_has_children) +// result = -1; // A doesn't have kids, but B does +// else +// result = 1; // A has kids, but B doesn't +// } +// +// if (compare_siblings) +// { +// result = Compare( dwarf2Data, +// a_cu, a_die->GetSibling(), +// b_cu, b_die->GetSibling(), +// compare_state, true, compare_children); +// } +// +// return result; +// } +// +// if (a_die == NULL) +// return -1; // a_die is NULL, yet b_die is non-NULL +// else +// return 1; // a_die is non-NULL, yet b_die is NULL +// +//} +// // //int //DWARFDebugInfoEntry::Compare @@ -1208,11 +1325,14 @@ DWARFDebugInfoEntry::GetAttributes ( SymbolFileDWARF* dwarf2Data, const DWARFCompileUnit* cu, + const uint8_t *fixed_form_sizes, DWARFDebugInfoEntry::Attributes& attributes ) const { if (m_abbrevDecl) { + if (fixed_form_sizes == NULL) + fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize(cu->GetAddressByteSize()); uint32_t offset = GetOffset(); const DataExtractor& debug_info_data = dwarf2Data->get_debug_info_data(); @@ -1239,20 +1359,24 @@ DWARFDebugInfoEntry::GetAttributes { die = const_cast<DWARFCompileUnit*>(cu)->GetDIEPtr(die_offset); if (die) - die->GetAttributes(dwarf2Data, cu, attributes); + die->GetAttributes(dwarf2Data, cu, fixed_form_sizes, attributes); } else { DWARFCompileUnitSP cu_sp_ptr; die = const_cast<SymbolFileDWARF*>(dwarf2Data)->DebugInfo()->GetDIEPtr(die_offset, &cu_sp_ptr); if (die) - die->GetAttributes(dwarf2Data, cu_sp_ptr.get(), attributes); + die->GetAttributes(dwarf2Data, cu_sp_ptr.get(), fixed_form_sizes, attributes); } } } else { - assert(DWARFFormValue::SkipValue(form, debug_info_data, &offset, cu)); + const uint8_t fixed_skip_size = fixed_form_sizes [form]; + if (fixed_skip_size) + offset += fixed_skip_size; + else + DWARFFormValue::SkipValue(form, debug_info_data, &offset, cu); } } } diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h index 8340acc427e..6e6fdf02b85 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h @@ -11,6 +11,9 @@ #define liblldb_DWARFDebugInfoEntry_h_ #include "SymbolFileDWARF.h" + +#include "llvm/ADT/SmallVector.h" + #include "DWARFAbbreviationDeclaration.h" #include "DWARFDebugRanges.h" #include <vector> @@ -76,7 +79,9 @@ public: dw_attr_t attr; dw_form_t form; }; - std::vector<Info> m_infos; + + typedef llvm::SmallVector<Info, 32> collection; + collection m_infos; }; struct CompareState @@ -116,6 +121,12 @@ public: const DWARFCompileUnit* cu, DWARFDebugAranges* debug_aranges) const; + bool FastExtract( + const lldb_private::DataExtractor& debug_info_data, + const DWARFCompileUnit* cu, + const uint8_t *fixed_form_sizes, + dw_offset_t* offset_ptr); + bool Extract( SymbolFileDWARF* dwarf2Data, const DWARFCompileUnit* cu, @@ -131,6 +142,7 @@ public: size_t GetAttributes( SymbolFileDWARF* dwarf2Data, const DWARFCompileUnit* cu, + const uint8_t *fixed_form_sizes, DWARFDebugInfoEntry::Attributes& attrs) const; dw_offset_t GetAttributeValue( @@ -196,21 +208,21 @@ public: const dw_offset_t die_offset, lldb_private::Stream *s); - static int Compare( - SymbolFileDWARF* dwarf2Data, - dw_offset_t a_die_offset, - dw_offset_t b_die_offset, - CompareState &compare_state, - bool compare_siblings, - bool compare_children); - - static int Compare( - SymbolFileDWARF* dwarf2Data, - DWARFCompileUnit* a_cu, const DWARFDebugInfoEntry* a_die, - DWARFCompileUnit* b_cu, const DWARFDebugInfoEntry* b_die, - CompareState &compare_state, - bool compare_siblings, - bool compare_children); +// static int Compare( +// SymbolFileDWARF* dwarf2Data, +// dw_offset_t a_die_offset, +// dw_offset_t b_die_offset, +// CompareState &compare_state, +// bool compare_siblings, +// bool compare_children); +// +// static int Compare( +// SymbolFileDWARF* dwarf2Data, +// DWARFCompileUnit* a_cu, const DWARFDebugInfoEntry* a_die, +// DWARFCompileUnit* b_cu, const DWARFDebugInfoEntry* b_die, +// CompareState &compare_state, +// bool compare_siblings, +// bool compare_children); static bool OffsetLessThan ( const DWARFDebugInfoEntry& a, diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugPubnames.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugPubnames.cpp index 27460d4082f..f3f8b0f2c67 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugPubnames.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugPubnames.cpp @@ -85,6 +85,8 @@ DWARFDebugPubnames::GeneratePubnames(SymbolFileDWARF* dwarf2Data) DWARFCompileUnit* cu = debug_info->GetCompileUnitAtIndex(cu_idx); + const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (cu->GetAddressByteSize()); + bool clear_dies = cu->ExtractDIEsIfNeeded (false) > 1; DWARFDIECollection dies; @@ -103,7 +105,7 @@ DWARFDebugPubnames::GeneratePubnames(SymbolFileDWARF* dwarf2Data) const char *mangled = NULL; bool add_die = false; bool is_variable = false; - const size_t num_attributes = die->GetAttributes(dwarf2Data, cu, attributes); + const size_t num_attributes = die->GetAttributes(dwarf2Data, cu, fixed_form_sizes, attributes); if (num_attributes > 0) { uint32_t i; diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp index d2c137bd7df..8d0e8ddce96 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.cpp @@ -19,6 +19,73 @@ class DWARFCompileUnit; using namespace lldb_private; + +static uint8_t g_form_sizes_addr4[] = +{ + 0, // 0x00 unused + 4, // 0x01 DW_FORM_addr + 0, // 0x02 unused + 0, // 0x03 DW_FORM_block2 + 0, // 0x04 DW_FORM_block4 + 2, // 0x05 DW_FORM_data2 + 4, // 0x06 DW_FORM_data4 + 8, // 0x07 DW_FORM_data8 + 0, // 0x08 DW_FORM_string + 0, // 0x09 DW_FORM_block + 0, // 0x0a DW_FORM_block1 + 1, // 0x0b DW_FORM_data1 + 1, // 0x0c DW_FORM_flag + 0, // 0x0d DW_FORM_sdata + 4, // 0x0e DW_FORM_strp + 0, // 0x0f DW_FORM_udata + 4, // 0x10 DW_FORM_ref_addr + 1, // 0x11 DW_FORM_ref1 + 2, // 0x12 DW_FORM_ref2 + 4, // 0x13 DW_FORM_ref4 + 8, // 0x14 DW_FORM_ref8 + 0, // 0x15 DW_FORM_ref_udata + 0, // 0x16 DW_FORM_indirect +}; + +static uint8_t +g_form_sizes_addr8[] = +{ + 0, // 0x00 unused + 8, // 0x01 DW_FORM_addr + 0, // 0x02 unused + 0, // 0x03 DW_FORM_block2 + 0, // 0x04 DW_FORM_block4 + 2, // 0x05 DW_FORM_data2 + 4, // 0x06 DW_FORM_data4 + 8, // 0x07 DW_FORM_data8 + 0, // 0x08 DW_FORM_string + 0, // 0x09 DW_FORM_block + 0, // 0x0a DW_FORM_block1 + 1, // 0x0b DW_FORM_data1 + 1, // 0x0c DW_FORM_flag + 0, // 0x0d DW_FORM_sdata + 4, // 0x0e DW_FORM_strp + 0, // 0x0f DW_FORM_udata + 8, // 0x10 DW_FORM_ref_addr + 1, // 0x11 DW_FORM_ref1 + 2, // 0x12 DW_FORM_ref2 + 4, // 0x13 DW_FORM_ref4 + 8, // 0x14 DW_FORM_ref8 + 0, // 0x15 DW_FORM_ref_udata + 0, // 0x16 DW_FORM_indirect +}; + +const uint8_t * +DWARFFormValue::GetFixedFormSizesForAddressSize (uint8_t addr_size) +{ + switch (addr_size) + { + case 4: return g_form_sizes_addr4; + case 8: return g_form_sizes_addr8; + } + return NULL; +} + DWARFFormValue::DWARFFormValue(dw_form_t form) : m_form(form), m_value() diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h index 72dedaee776..49fabdcbd94 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFFormValue.h @@ -70,7 +70,7 @@ public: // static bool PutUnsigned(dw_form_t form, dw_offset_t offset, uint64_t value, BinaryStreamBuf& out_buff, const DWARFCompileUnit* cu, bool fixup_cu_relative_refs); static bool IsBlockForm(const dw_form_t form); static bool IsDataForm(const dw_form_t form); - + static const uint8_t * GetFixedFormSizesForAddressSize (uint8_t addr_size); static int Compare (const DWARFFormValue& a, const DWARFFormValue& b, const DWARFCompileUnit* a_cu, const DWARFCompileUnit* b_cu, const lldb_private::DataExtractor* debug_str_data_ptr); protected: dw_form_t m_form; // Form for this value diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp index d388d543503..2c8977528be 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -1024,6 +1024,8 @@ SymbolFileDWARF::ParseChildMembers size_t count = 0; const DWARFDebugInfoEntry *die; + const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (dwarf_cu->GetAddressByteSize()); + for (die = parent_die->GetFirstChild(); die != NULL; die = die->GetSibling()) { dw_tag_t tag = die->Tag(); @@ -1033,7 +1035,7 @@ SymbolFileDWARF::ParseChildMembers case DW_TAG_member: { DWARFDebugInfoEntry::Attributes attributes; - const size_t num_attributes = die->GetAttributes(this, dwarf_cu, attributes); + const size_t num_attributes = die->GetAttributes(this, dwarf_cu, fixed_form_sizes, attributes); if (num_attributes > 0) { Declaration decl; @@ -1124,7 +1126,7 @@ SymbolFileDWARF::ParseChildMembers default_accessibility = eAccessPrivate; // TODO: implement DW_TAG_inheritance type parsing DWARFDebugInfoEntry::Attributes attributes; - const size_t num_attributes = die->GetAttributes(this, dwarf_cu, attributes); + const size_t num_attributes = die->GetAttributes(this, dwarf_cu, fixed_form_sizes, attributes); if (num_attributes > 0) { Declaration decl; @@ -1915,6 +1917,8 @@ SymbolFileDWARF::ParseChildParameters if (parent_die == NULL) return 0; + const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (dwarf_cu->GetAddressByteSize()); + size_t count = 0; const DWARFDebugInfoEntry *die; for (die = parent_die->GetFirstChild(); die != NULL; die = die->GetSibling()) @@ -1925,7 +1929,7 @@ SymbolFileDWARF::ParseChildParameters case DW_TAG_formal_parameter: { DWARFDebugInfoEntry::Attributes attributes; - const size_t num_attributes = die->GetAttributes(this, dwarf_cu, attributes); + const size_t num_attributes = die->GetAttributes(this, dwarf_cu, fixed_form_sizes, attributes); if (num_attributes > 0) { const char *name = NULL; @@ -2010,13 +2014,15 @@ SymbolFileDWARF::ParseChildEnumerators size_t enumerators_added = 0; const DWARFDebugInfoEntry *die; + const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (dwarf_cu->GetAddressByteSize()); + for (die = parent_die->GetFirstChild(); die != NULL; die = die->GetSibling()) { const dw_tag_t tag = die->Tag(); if (tag == DW_TAG_enumerator) { DWARFDebugInfoEntry::Attributes attributes; - const size_t num_child_attributes = die->GetAttributes(this, dwarf_cu, attributes); + const size_t num_child_attributes = die->GetAttributes(this, dwarf_cu, fixed_form_sizes, attributes); if (num_child_attributes > 0) { const char *name = NULL; @@ -2081,6 +2087,7 @@ SymbolFileDWARF::ParseChildArrayInfo return; const DWARFDebugInfoEntry *die; + const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (dwarf_cu->GetAddressByteSize()); for (die = parent_die->GetFirstChild(); die != NULL; die = die->GetSibling()) { const dw_tag_t tag = die->Tag(); @@ -2089,7 +2096,7 @@ SymbolFileDWARF::ParseChildArrayInfo case DW_TAG_enumerator: { DWARFDebugInfoEntry::Attributes attributes; - const size_t num_child_attributes = die->GetAttributes(this, dwarf_cu, attributes); + const size_t num_child_attributes = die->GetAttributes(this, dwarf_cu, fixed_form_sizes, attributes); if (num_child_attributes > 0) { const char *name = NULL; @@ -2131,7 +2138,7 @@ SymbolFileDWARF::ParseChildArrayInfo case DW_TAG_subrange_type: { DWARFDebugInfoEntry::Attributes attributes; - const size_t num_child_attributes = die->GetAttributes(this, dwarf_cu, attributes); + const size_t num_child_attributes = die->GetAttributes(this, dwarf_cu, fixed_form_sizes, attributes); if (num_child_attributes > 0) { const char *name = NULL; @@ -2354,7 +2361,7 @@ SymbolFileDWARF::ParseType(const SymbolContext& sc, const DWARFCompileUnit* dwar // Set a bit that lets us know that we are currently parsing this const_cast<DWARFDebugInfoEntry*>(die)->SetUserData(DIE_IS_BEING_PARSED); - const size_t num_attributes = die->GetAttributes(this, dwarf_cu, attributes); + const size_t num_attributes = die->GetAttributes(this, dwarf_cu, NULL, attributes); Declaration decl; uint32_t encoding = 0; size_t byte_size = 0; @@ -2482,7 +2489,7 @@ SymbolFileDWARF::ParseType(const SymbolContext& sc, const DWARFCompileUnit* dwar LanguageType class_language = eLanguageTypeUnknown; //bool struct_is_class = false; Declaration decl; - const size_t num_attributes = die->GetAttributes(this, dwarf_cu, attributes); + const size_t num_attributes = die->GetAttributes(this, dwarf_cu, NULL, attributes); if (num_attributes > 0) { uint32_t i; @@ -2637,7 +2644,7 @@ SymbolFileDWARF::ParseType(const SymbolContext& sc, const DWARFCompileUnit* dwar lldb::user_id_t encoding_uid = DW_INVALID_OFFSET; Declaration decl; - const size_t num_attributes = die->GetAttributes(this, dwarf_cu, attributes); + const size_t num_attributes = die->GetAttributes(this, dwarf_cu, NULL, attributes); if (num_attributes > 0) { uint32_t i; @@ -2712,7 +2719,7 @@ SymbolFileDWARF::ParseType(const SymbolContext& sc, const DWARFCompileUnit* dwar clang::FunctionDecl::StorageClass storage = clang::FunctionDecl::None;//, Extern, Static, PrivateExtern - const size_t num_attributes = die->GetAttributes(this, dwarf_cu, attributes); + const size_t num_attributes = die->GetAttributes(this, dwarf_cu, NULL, attributes); if (num_attributes > 0) { uint32_t i; @@ -2826,7 +2833,7 @@ SymbolFileDWARF::ParseType(const SymbolContext& sc, const DWARFCompileUnit* dwar int64_t first_index = 0; uint32_t byte_stride = 0; uint32_t bit_stride = 0; - const size_t num_attributes = die->GetAttributes(this, dwarf_cu, attributes); + const size_t num_attributes = die->GetAttributes(this, dwarf_cu, NULL, attributes); if (num_attributes > 0) { @@ -2904,7 +2911,7 @@ SymbolFileDWARF::ParseType(const SymbolContext& sc, const DWARFCompileUnit* dwar dw_offset_t type_die_offset = DW_INVALID_OFFSET; dw_offset_t containing_type_die_offset = DW_INVALID_OFFSET; - const size_t num_attributes = die->GetAttributes(this, dwarf_cu, attributes); + const size_t num_attributes = die->GetAttributes(this, dwarf_cu, NULL, attributes); if (num_attributes > 0) { uint32_t i; @@ -3173,7 +3180,7 @@ SymbolFileDWARF::ParseVariableDIE const dw_tag_t tag = die->Tag(); DWARFDebugInfoEntry::Attributes attributes; - const size_t num_attributes = die->GetAttributes(this, dwarf_cu, attributes); + const size_t num_attributes = die->GetAttributes(this, dwarf_cu, NULL, attributes); if (num_attributes > 0) { const char *name = NULL; |