diff options
Diffstat (limited to 'lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp')
| -rw-r--r-- | lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp | 468 |
1 files changed, 1 insertions, 467 deletions
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp index 4dfede9a797..dbfc0a1039b 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp @@ -84,19 +84,8 @@ DWARFDebugInfo::GetCompileUnitAranges () } } - // Sort with a fudge factor of 16 to make sure if we have a lot - // of functions in the compile unit whose end address if followed - // a start address that is "fudge_size" bytes close, it will combine - // the arange entries. This currently happens a lot on x86_64. This - // will help reduce the size of the aranges since sort will sort all - // of them and combine aranges that are consecutive for ranges in the - // same compile unit and we really don't need it to be all that - // accurate since we will get exact accuracy when we search the - // actual compile unit aranges which point to the exact range and - // the exact DIE offset of the function. const bool minimize = true; - const uint32_t fudge_factor = 16; - m_cu_aranges_ap->Sort (minimize, fudge_factor); + m_cu_aranges_ap->Sort (minimize); } return *m_cu_aranges_ap.get(); } @@ -447,461 +436,6 @@ DWARFDebugInfo::Parse(SymbolFileDWARF* dwarf2Data, Callback callback, void* user } } -/* -typedef struct AddressRangeTag -{ - dw_addr_t lo_pc; - dw_addr_t hi_pc; - dw_offset_t die_offset; -} AddressRange; -*/ -struct DIERange -{ - DIERange() : - range(), - lo_die_offset(), - hi_die_offset() - { - } - - DWARFDebugAranges::Range range; - dw_offset_t lo_die_offset; - dw_offset_t hi_die_offset; -}; - -typedef struct DwarfStat -{ - DwarfStat() : count(0), byte_size(0) {} - uint32_t count; - uint32_t byte_size; -} DwarfStat; - -typedef map<dw_attr_t, DwarfStat> DwarfAttrStatMap; - -typedef struct DIEStat -{ - DIEStat() : count(0), byte_size(0), attr_stats() {} - uint32_t count; - uint32_t byte_size; - DwarfAttrStatMap attr_stats; -} DIEStat; - -typedef map<dw_tag_t, DIEStat> DIEStatMap; -struct VerifyInfo -{ - VerifyInfo(Stream* the_strm) : - strm(the_strm), - die_ranges(), - addr_range_errors(0), - sibling_errors(0), - die_stats() - { - } - - Stream* strm; - vector<DIERange> die_ranges; - uint32_t addr_range_errors; - uint32_t sibling_errors; - DIEStatMap die_stats; - - DISALLOW_COPY_AND_ASSIGN(VerifyInfo); - -}; - - -//---------------------------------------------------------------------- -// VerifyCallback -// -// A callback function for the static DWARFDebugInfo::Parse() function -// that gets called each time a compile unit header or debug information -// entry is successfully parsed. -// -// This function will verify the DWARF information is well formed by -// making sure that any DW_TAG_compile_unit tags that have valid address -// ranges (DW_AT_low_pc and DW_AT_high_pc) have no gaps in the address -// ranges of it contained DW_TAG_subprogram tags. Also the sibling chain -// and relationships are verified to make sure nothing gets hosed up -// when dead stripping occurs. -//---------------------------------------------------------------------- - -static dw_offset_t -VerifyCallback -( - SymbolFileDWARF* dwarf2Data, - DWARFCompileUnitSP& cu_sp, - DWARFDebugInfoEntry* die, - const dw_offset_t next_offset, - const uint32_t curr_depth, - void* userData -) -{ - VerifyInfo* verifyInfo = (VerifyInfo*)userData; - - const DWARFCompileUnit* cu = cu_sp.get(); - Stream *s = verifyInfo->strm; - bool verbose = s->GetVerbose(); - if (die) - { - // die->Dump(dwarf2Data, cu, f); - const DWARFAbbreviationDeclaration* abbrevDecl = die->GetAbbreviationDeclarationPtr(); - // We have a DIE entry - if (abbrevDecl) - { - const dw_offset_t die_offset = die->GetOffset(); - const dw_offset_t sibling = die->GetAttributeValueAsReference(dwarf2Data, cu, DW_AT_sibling, DW_INVALID_OFFSET); - - if (sibling != DW_INVALID_OFFSET) - { - if (sibling <= next_offset) - { - if (verifyInfo->sibling_errors++ == 0) - s->Printf("ERROR\n"); - s->Printf(" 0x%8.8x: sibling attribute (0x%8.8x) in this die is not valid: it is less than this DIE or some of its contents.\n", die->GetOffset(), sibling); - } - else if (sibling > verifyInfo->die_ranges.back().hi_die_offset) - { - if (verifyInfo->sibling_errors++ == 0) - s->Printf("ERROR\n"); - s->Printf(" 0x%8.8x: sibling attribute (0x%8.8x) in this DIE is not valid: it is greater than the end of the parent scope.\n", die->GetOffset(), sibling); - } - } - - if ((die_offset < verifyInfo->die_ranges.back().lo_die_offset) || (die_offset >= verifyInfo->die_ranges.back().hi_die_offset)) - { - if (verifyInfo->sibling_errors++ == 0) - s->Printf("ERROR\n"); - s->Printf(" 0x%8.8x: DIE offset is not within the parent DIE range {0x%8.8x}: (0x%8.8x - 0x%8.8x)\n", - die->GetOffset(), - verifyInfo->die_ranges.back().range.offset, - verifyInfo->die_ranges.back().lo_die_offset, - verifyInfo->die_ranges.back().hi_die_offset); - - } - - dw_tag_t tag = abbrevDecl->Tag(); - - // Keep some stats on this DWARF file - verifyInfo->die_stats[tag].count++; - verifyInfo->die_stats[tag].byte_size += (next_offset - die->GetOffset()); - - if (verbose) - { - DIEStat& tag_stat = verifyInfo->die_stats[tag]; - - const DataExtractor& debug_info = dwarf2Data->get_debug_info_data(); - - dw_offset_t offset = die->GetOffset(); - // Skip the abbreviation code so we are at the data for the attributes - debug_info.Skip_LEB128(&offset); - - const uint32_t numAttributes = abbrevDecl->NumAttributes(); - dw_attr_t attr; - dw_form_t form; - for (uint32_t idx = 0; idx < numAttributes; ++idx) - { - dw_offset_t start_offset = offset; - abbrevDecl->GetAttrAndFormByIndexUnchecked(idx, attr, form); - DWARFFormValue::SkipValue(form, debug_info, &offset, cu); - - if (tag_stat.attr_stats.find(attr) == tag_stat.attr_stats.end()) - { - tag_stat.attr_stats[attr].count = 0; - tag_stat.attr_stats[attr].byte_size = 0; - } - - tag_stat.attr_stats[attr].count++; - tag_stat.attr_stats[attr].byte_size += offset - start_offset; - } - } - - DWARFDebugAranges::Range range; - range.offset = die->GetOffset(); - - switch (tag) - { - case DW_TAG_compile_unit: - // Check for previous subroutines that were within a previous - // - // VerifyAddressRangesForCU(verifyInfo); - // Remember which compile unit we are dealing with so we can verify - // the address ranges within it (if any) are contiguous. The DWARF - // spec states that if a compile unit TAG has high and low PC - // attributes, there must be no gaps in the address ranges of it's - // contained subroutines. If there are gaps, the high and low PC - // must not be in the DW_TAG_compile_unit's attributes. Errors like - // this can crop up when optimized code is dead stripped and the debug - // information isn't properly fixed up for output. - range.lo_pc = die->GetAttributeValueAsUnsigned(dwarf2Data, cu, DW_AT_low_pc, DW_INVALID_ADDRESS); - if (range.lo_pc != DW_INVALID_ADDRESS) - { - range.set_hi_pc (die->GetAttributeValueAsUnsigned(dwarf2Data, cu, DW_AT_high_pc, DW_INVALID_ADDRESS)); - if (s->GetVerbose()) - { - s->Printf("\n CU "); - range.Dump(s); - } - } - else - { - range.lo_pc = die->GetAttributeValueAsUnsigned(dwarf2Data, cu, DW_AT_entry_pc, DW_INVALID_ADDRESS); - } - break; - - case DW_TAG_subprogram: - // If the DW_TAG_compile_unit that contained this function had a - // valid address range, add all of the valid subroutine address - // ranges to a collection of addresses which will be sorted - // and verified right before the next DW_TAG_compile_unit is - // processed to make sure that there are no gaps in the address - // range. - range.lo_pc = die->GetAttributeValueAsUnsigned(dwarf2Data, cu, DW_AT_low_pc, DW_INVALID_ADDRESS); - if (range.lo_pc != DW_INVALID_ADDRESS) - { - range.set_hi_pc (die->GetAttributeValueAsUnsigned(dwarf2Data, cu, DW_AT_high_pc, DW_INVALID_ADDRESS)); - if (range.hi_pc() != DW_INVALID_ADDRESS) - { - range.offset = die->GetOffset(); - bool valid = range.ValidRange(); - if (!valid || s->GetVerbose()) - { - s->Printf("\n FUNC "); - range.Dump(s); - if (!valid) - { - ++verifyInfo->addr_range_errors; - s->Printf(" ERROR: Invalid address range for function."); - } - } - } - } - break; - - case DW_TAG_lexical_block: - case DW_TAG_inlined_subroutine: - { - range.lo_pc = die->GetAttributeValueAsUnsigned(dwarf2Data, cu, DW_AT_low_pc, DW_INVALID_ADDRESS); - if (range.lo_pc != DW_INVALID_ADDRESS) - { - range.set_hi_pc (die->GetAttributeValueAsUnsigned(dwarf2Data, cu, DW_AT_high_pc, DW_INVALID_ADDRESS)); - if (range.hi_pc() != DW_INVALID_ADDRESS) - { - range.offset = die->GetOffset(); - bool valid = range.ValidRange(); - if (!valid || s->GetVerbose()) - { - s->Printf("\n BLCK "); - range.Dump(s); - if (!valid) - { - ++verifyInfo->addr_range_errors; - s->Printf(" ERROR: Invalid address range for block or inlined subroutine."); - } - } - } - } - } - break; - } - - if (range.ValidRange() && verifyInfo->die_ranges.back().range.ValidRange()) - { - if (!verifyInfo->die_ranges.back().range.Contains(range)) - { - ++verifyInfo->addr_range_errors; - s->Printf("\n "); - range.Dump(s); - s->Printf(" ERROR: Range is not in parent"); - verifyInfo->die_ranges.back().range.Dump(s); - } - } - - if (die->HasChildren()) - { - // Keep tabs on the valid address ranges for the current item to make - // sure that it all fits (make sure the sibling offsets got fixed up - // correctly if any functions were dead stripped). - DIERange die_range; - die_range.range = range; - die_range.lo_die_offset = next_offset; - die_range.hi_die_offset = sibling; - if (die_range.hi_die_offset == DW_INVALID_OFFSET) - die_range.hi_die_offset = verifyInfo->die_ranges.back().hi_die_offset; - verifyInfo->die_ranges.push_back(die_range); - } - } - else - { - // NULL entry - verifyInfo->die_ranges.pop_back(); - } - } - else - { - // cu->Dump(ostrm_ptr); // Dump the compile unit for the DIE - // We have a new compile unit header - verifyInfo->die_ranges.clear(); - DIERange die_range; - die_range.range.offset = cu->GetOffset(); - die_range.lo_die_offset = next_offset; - die_range.hi_die_offset = cu->GetNextCompileUnitOffset(); - verifyInfo->die_ranges.push_back(die_range); - } - - // Just return the current offset to parse the next CU or DIE entry - return next_offset; -} - - -class CompareDIEStatSizes -{ -public: - bool operator() (const DIEStatMap::const_iterator& pos1, const DIEStatMap::const_iterator& pos2) const - { - return pos1->second.byte_size <= pos2->second.byte_size; - } -}; - -class CompareAttrDIEStatSizes -{ -public: - bool operator() (const DwarfAttrStatMap::const_iterator& pos1, const DwarfAttrStatMap::const_iterator& pos2) const - { - return pos1->second.byte_size <= pos2->second.byte_size; - } -}; - -//---------------------------------------------------------------------- -// Verify -// -// Verifies the DWARF information is valid. -//---------------------------------------------------------------------- -void -DWARFDebugInfo::Verify(Stream *s, SymbolFileDWARF* dwarf2Data) -{ - s->Printf("Verifying Compile Unit Header chain....."); - VerifyInfo verifyInfo(s); - verifyInfo.addr_range_errors = 0; - verifyInfo.sibling_errors = 0; - - bool verbose = s->GetVerbose(); - - uint32_t offset = 0; - if (verbose) - s->EOL(); -// vector<dw_offset_t> valid_cu_offsets; - DWARFCompileUnit cu (dwarf2Data); - bool success = true; - while ( success && dwarf2Data->get_debug_info_data().ValidOffset(offset+cu.Size()) ) - { - success = cu.Extract (dwarf2Data->get_debug_info_data(), &offset); - if (!success) - s->Printf("ERROR\n"); - // else - // valid_cu_offsets.push_back(cu.GetOffset()); - - cu.Verify(verifyInfo.strm); - offset = cu.GetNextCompileUnitOffset(); - } - - if (success) - s->Printf("OK\n"); - - s->Printf("Verifying address ranges and siblings..."); - if (verbose) - s->EOL(); - DWARFDebugInfo::Parse(dwarf2Data, VerifyCallback, &verifyInfo); - -// VerifyAddressRangesForCU(&verifyInfo); - - if (verifyInfo.addr_range_errors > 0) - s->Printf("\nERRORS - %u error(s) were found.\n", verifyInfo.addr_range_errors); - else - s->Printf("OK\n"); - - uint32_t total_category_sizes[kNumTagCategories] = {0}; - uint32_t total_category_count[kNumTagCategories] = {0}; - uint32_t total_die_count = 0; - uint32_t total_die_size = 0; - - typedef set<DIEStatMap::const_iterator, CompareDIEStatSizes> DIEStatBySizeMap; - - s->PutCString( "\n" - "DWARF Statistics\n" - "Count Size Size % Tag\n" - "-------- -------- -------- -------------------------------------------\n"); - DIEStatBySizeMap statBySizeMap; - DIEStatMap::const_iterator pos; - DIEStatMap::const_iterator end_pos = verifyInfo.die_stats.end(); - for (pos = verifyInfo.die_stats.begin(); pos != end_pos; ++pos) - { - const uint32_t die_count = pos->second.count; - const uint32_t die_size = pos->second.byte_size; - - statBySizeMap.insert(pos); - total_die_count += die_count; - total_die_size += die_size; - DW_TAG_CategoryEnum category = get_tag_category(pos->first); - total_category_sizes[category] += die_size; - total_category_count[category] += die_count; - } - - float total_die_size_float = total_die_size; - - DIEStatBySizeMap::const_reverse_iterator size_pos; - DIEStatBySizeMap::const_reverse_iterator size_pos_end = statBySizeMap.rend(); - float percentage; - for (size_pos = statBySizeMap.rbegin(); size_pos != size_pos_end; ++size_pos) - { - pos = *size_pos; - - const DIEStat& tag_stat = pos->second; - - const uint32_t die_count = tag_stat.count; - const uint32_t die_size = tag_stat.byte_size; - percentage = ((float)die_size/total_die_size_float)*100.0; - s->Printf("%7u %8u %2.2f%% %s\n", die_count, die_size, percentage, DW_TAG_value_to_name(pos->first)); - - const DwarfAttrStatMap& attr_stats = tag_stat.attr_stats; - if (!attr_stats.empty()) - { - typedef set<DwarfAttrStatMap::const_iterator, CompareAttrDIEStatSizes> DwarfAttrStatBySizeMap; - DwarfAttrStatBySizeMap attrStatBySizeMap; - DwarfAttrStatMap::const_iterator attr_stat_pos; - DwarfAttrStatMap::const_iterator attr_stat_pos_end = attr_stats.end(); - for (attr_stat_pos = attr_stats.begin(); attr_stat_pos != attr_stat_pos_end; ++attr_stat_pos) - { - attrStatBySizeMap.insert(attr_stat_pos); - } - - DwarfAttrStatBySizeMap::const_reverse_iterator attr_size_pos; - DwarfAttrStatBySizeMap::const_reverse_iterator attr_size_pos_end = attrStatBySizeMap.rend(); - for (attr_size_pos = attrStatBySizeMap.rbegin(); attr_size_pos != attr_size_pos_end; ++attr_size_pos) - { - attr_stat_pos = *attr_size_pos; - percentage = ((float)attr_stat_pos->second.byte_size/die_size)*100.0; - s->Printf("%7u %8u %2.2f%% %s\n", attr_stat_pos->second.count, attr_stat_pos->second.byte_size, percentage, DW_AT_value_to_name(attr_stat_pos->first)); - } - s->EOL(); - } - } - - s->Printf("-------- -------- -------- -------------------------------------------\n"); - s->Printf("%7u %8u 100.00%% Total for all DIEs\n", total_die_count, total_die_size); - - float total_category_percentages[kNumTagCategories] = - { - ((float)total_category_sizes[TagCategoryVariable]/total_die_size_float)*100.0, - ((float)total_category_sizes[TagCategoryType]/total_die_size_float)*100.0, - ((float)total_category_sizes[TagCategoryProgram]/total_die_size_float)*100.0 - }; - - s->EOL(); - s->Printf("%7u %8u %2.2f%% %s\n", total_category_count[TagCategoryVariable], total_category_sizes[TagCategoryVariable], total_category_percentages[TagCategoryVariable], "Total for variable related DIEs"); - s->Printf("%7u %8u %2.2f%% %s\n", total_category_count[TagCategoryType], total_category_sizes[TagCategoryType], total_category_percentages[TagCategoryType], "Total for type related DIEs"); - s->Printf("%7u %8u %2.2f%% %s\n", total_category_count[TagCategoryProgram], total_category_sizes[TagCategoryProgram], total_category_percentages[TagCategoryProgram], "Total for program related DIEs"); - s->Printf("\n\n"); -} - typedef struct DumpInfo { DumpInfo(Stream* init_strm, uint32_t off, uint32_t depth) : |

