summaryrefslogtreecommitdiffstats
path: root/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp')
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp468
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) :
OpenPOWER on IntegriCloud