diff options
Diffstat (limited to 'lldb/source')
5 files changed, 113 insertions, 837 deletions
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp index a4281ace521..576bb3119e4 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp @@ -363,8 +363,7 @@ DWARFCompileUnit::GetFunctionAranges () m_offset); DIE()->BuildFunctionAddressRangeTable (m_dwarf2Data, this, m_func_aranges_ap.get()); const bool minimize = false; - const uint32_t fudge_size = 0; - m_func_aranges_ap->Sort(minimize, fudge_size); + m_func_aranges_ap->Sort(minimize); } return *m_func_aranges_ap.get(); } diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugArangeSet.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugArangeSet.h index e2e11877676..5c1c44e50dd 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugArangeSet.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugArangeSet.h @@ -18,21 +18,21 @@ class SymbolFileDWARF; class DWARFDebugArangeSet { public: - typedef struct HeaderTag + struct Header { uint32_t length; // The total length of the entries for that set, not including the length field itself. uint16_t version; // The DWARF version number uint32_t cu_offset; // The offset from the beginning of the .debug_info section of the compilation unit entry referenced by the table. uint8_t addr_size; // The size in bytes of an address on the target architecture. For segmented addressing, this is the size of the offset portion of the address uint8_t seg_size; // The size in bytes of a segment descriptor on the target architecture. If the target system uses a flat address space, this value is 0. - } Header; + }; - typedef struct DescriptorTag + struct Descriptor { dw_addr_t address; dw_addr_t length; dw_addr_t end_address() const { return address + length; } - } Descriptor; + }; DWARFDebugArangeSet(); @@ -55,6 +55,12 @@ public: return NULL; } + const Descriptor & + GetDescriptorRef (uint32_t i) const + { + return m_arange_descriptors[i]; + } + protected: typedef std::vector<Descriptor> DescriptorColl; diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp index 974868cfccb..d52b2f0739f 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp @@ -34,15 +34,6 @@ DWARFDebugAranges::DWARFDebugAranges() : { } - -//---------------------------------------------------------------------- -// Compare function DWARFDebugAranges::Range structures -//---------------------------------------------------------------------- -static bool RangeLessThan (const DWARFDebugAranges::Range& range1, const DWARFDebugAranges::Range& range2) -{ - return range1.lo_pc < range2.lo_pc; -} - //---------------------------------------------------------------------- // CountArangeDescriptors //---------------------------------------------------------------------- @@ -60,41 +51,6 @@ public: uint32_t& count; }; -//---------------------------------------------------------------------- -// AddArangeDescriptors -//---------------------------------------------------------------------- -class AddArangeDescriptors -{ -public: - AddArangeDescriptors (DWARFDebugAranges::RangeColl& ranges) : range_collection(ranges) {} - void operator() (const DWARFDebugArangeSet& set) - { - const DWARFDebugArangeSet::Descriptor* arange_desc_ptr; - DWARFDebugAranges::Range range; - range.offset = set.GetCompileUnitDIEOffset(); - - for (uint32_t i=0; (arange_desc_ptr = set.GetDescriptor(i)) != NULL; ++i) - { - range.lo_pc = arange_desc_ptr->address; - range.length = arange_desc_ptr->length; - - // Insert each item in increasing address order so binary searching - // can later be done! - DWARFDebugAranges::RangeColl::iterator insert_pos = lower_bound(range_collection.begin(), range_collection.end(), range, RangeLessThan); - range_collection.insert(insert_pos, range); - } - } - DWARFDebugAranges::RangeColl& range_collection; -}; - -//---------------------------------------------------------------------- -// PrintRange -//---------------------------------------------------------------------- -static void PrintRange(const DWARFDebugAranges::Range& range) -{ - // Cast the address values in case the address type is compiled as 32 bit - printf("0x%8.8x: [0x%8.8llx - 0x%8.8llx)\n", range.offset, (long long)range.lo_pc, (long long)range.hi_pc()); -} //---------------------------------------------------------------------- // Extract @@ -106,28 +62,23 @@ DWARFDebugAranges::Extract(const DataExtractor &debug_aranges_data) { uint32_t offset = 0; - typedef std::vector<DWARFDebugArangeSet> SetCollection; - typedef SetCollection::const_iterator SetCollectionIter; - SetCollection sets; - DWARFDebugArangeSet set; Range range; while (set.Extract(debug_aranges_data, &offset)) - sets.push_back(set); - - uint32_t count = 0; - - for_each(sets.begin(), sets.end(), CountArangeDescriptors(count)); - - if (count > 0) { - m_aranges.reserve(count); - AddArangeDescriptors range_adder(m_aranges); - for_each(sets.begin(), sets.end(), range_adder); + const uint32_t num_descriptors = set.NumDescriptors(); + if (num_descriptors > 0) + { + const dw_offset_t cu_offset = set.GetCompileUnitDIEOffset(); + + for (uint32_t i=0; i<num_descriptors; ++i) + { + const DWARFDebugArangeSet::Descriptor &descriptor = set.GetDescriptorRef(i); + m_aranges.Append(RangeToDIE::Entry (descriptor.address, descriptor.length, cu_offset)); + } + } + set.Clear(); } - - // puts("\n\nDWARFDebugAranges list is:\n"); - // for_each(m_aranges.begin(), m_aranges.end(), PrintRange); } return false; } @@ -161,177 +112,51 @@ DWARFDebugAranges::Dump (Log *log) const { if (log == NULL) return; - const uint32_t num_ranges = NumRanges(); - for (uint32_t i = 0; i < num_ranges; ++i) + + const size_t num_entries = m_aranges.GetNumEntries(); + for (size_t i=0; i<num_entries; ++i) { - const Range &range = m_aranges[i]; - log->Printf ("0x%8.8x: [0x%8.8llx - 0x%8.8llx)", range.offset, (uint64_t)range.lo_pc, (uint64_t)range.hi_pc()); + const RangeToDIE::Entry *entry = m_aranges.GetEntryAtIndex(i); + log->Printf ("0x%8.8x: [0x%llx - 0x%llx)", + entry->data, + entry->range.GetBase(), + entry->range.GetEnd()); } } - -void -DWARFDebugAranges::Range::Dump(Stream *s) const -{ - s->Printf("{0x%8.8x}: [0x%8.8llx - 0x%8.8llx)\n", offset, lo_pc, hi_pc()); -} - -//---------------------------------------------------------------------- -// Dump -//---------------------------------------------------------------------- -//void -//DWARFDebugAranges::Dump(SymbolFileDWARF* dwarf2Data, Stream *s) -//{ -// const DataExtractor &debug_aranges_data = dwarf2Data->get_debug_aranges_data(); -// if (debug_aranges_data.ValidOffset(0)) -// { -// uint32_t offset = 0; -// -// DWARFDebugArangeSet set; -// while (set.Extract(debug_aranges_data, &offset)) -// set.Dump(s); -// } -// else -// s->PutCString("< EMPTY >\n"); -//} -// - -//---------------------------------------------------------------------- -// AppendDebugRanges -//---------------------------------------------------------------------- -//void -//DWARFDebugAranges::AppendDebugRanges(BinaryStreamBuf& debug_ranges, dw_addr_t cu_base_addr, uint32_t addr_size) const -//{ -// if (!m_aranges.empty()) -// { -// RangeCollIterator end = m_aranges.end(); -// RangeCollIterator pos; -// RangeCollIterator lo_pos = end; -// for (pos = m_aranges.begin(); pos != end; ++pos) -// { -// if (lo_pos == end) -// lo_pos = pos; -// -// RangeCollIterator next = pos + 1; -// if (next != end) -// { -// // Check to see if we can combine two consecutive ranges? -// if (pos->hi_pc == next->lo_pc) -// continue; // We can combine them! -// } -// -// if (cu_base_addr == 0 || cu_base_addr == DW_INVALID_ADDRESS) -// { -// debug_ranges.AppendMax64(lo_pos->lo_pc, addr_size); -// debug_ranges.AppendMax64(pos->hi_pc, addr_size); -// } -// else -// { -// assert(lo_pos->lo_pc >= cu_base_addr); -// assert(pos->hi_pc >= cu_base_addr); -// debug_ranges.AppendMax64(lo_pos->lo_pc - cu_base_addr, addr_size); -// debug_ranges.AppendMax64(pos->hi_pc - cu_base_addr, addr_size); -// } -// -// // Reset the low part of the next address range -// lo_pos = end; -// } -// } -// // Terminate the .debug_ranges with two zero addresses -// debug_ranges.AppendMax64(0, addr_size); -// debug_ranges.AppendMax64(0, addr_size); -// -//} void DWARFDebugAranges::AppendRange (dw_offset_t offset, dw_addr_t low_pc, dw_addr_t high_pc) { - if (!m_aranges.empty()) - { - if (m_aranges.back().offset == offset && m_aranges.back().hi_pc() == low_pc) - { - m_aranges.back().set_hi_pc(high_pc); - return; - } - } - m_aranges.push_back (DWARFDebugAranges::Range(low_pc, high_pc, offset)); + if (high_pc > low_pc) + m_aranges.Append(RangeToDIE::Entry (low_pc, high_pc - low_pc, offset)); } void -DWARFDebugAranges::Sort (bool minimize, uint32_t n) +DWARFDebugAranges::Sort (bool minimize) { Timer scoped_timer(__PRETTY_FUNCTION__, "%s this = %p", __PRETTY_FUNCTION__, this); LogSP log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_ARANGES)); - const size_t orig_arange_size = m_aranges.size(); + size_t orig_arange_size = 0; if (log) { - log->Printf ("DWARFDebugAranges::Sort(minimize = %u, n = %u) with %zu entries", minimize, n, orig_arange_size); - Dump (log.get()); - } - - // Size of one? If so, no sorting is needed - if (orig_arange_size <= 1) - return; - // Sort our address range entries - std::stable_sort (m_aranges.begin(), m_aranges.end(), RangeLessThan); - - - if (!minimize) - return; - - // Most address ranges are contiguous from function to function - // so our new ranges will likely be smaller. We calculate the size - // of the new ranges since although std::vector objects can be resized, - // the will never reduce their allocated block size and free any excesss - // memory, so we might as well start a brand new collection so it is as - // small as possible. - - // First calculate the size of the new minimal arange vector - // so we don't have to do a bunch of re-allocations as we - // copy the new minimal stuff over to the new collection - size_t minimal_size = 1; - size_t i; - for (i=1; i<orig_arange_size; ++i) - { - if (!DWARFDebugAranges::Range::SortedOverlapCheck (m_aranges[i-1], m_aranges[i], n)) - ++minimal_size; + orig_arange_size = m_aranges.GetNumEntries(); + log->Printf ("DWARFDebugAranges::Sort(minimize = %u) with %zu entries", minimize, orig_arange_size); } - // If the sizes are the same, then no consecutive aranges can be - // combined, we are done - if (minimal_size == orig_arange_size) - return; + m_aranges.Sort(); + m_aranges.CombineConsecutiveEntriesWithEqualData(); - // Else, make a new RangeColl that _only_ contains what we need. - RangeColl minimal_aranges; - minimal_aranges.resize(minimal_size); - uint32_t j=0; - minimal_aranges[j] = m_aranges[0]; - for (i=1; i<orig_arange_size; ++i) + if (log) { - if (DWARFDebugAranges::Range::SortedOverlapCheck (minimal_aranges[j], m_aranges[i], n)) + if (minimize) { - minimal_aranges[j].set_hi_pc (m_aranges[i].hi_pc()); + const size_t new_arange_size = m_aranges.GetNumEntries(); + const size_t delta = orig_arange_size - new_arange_size; + log->Printf ("DWARFDebugAranges::Sort() %zu entries after minimizing (%zu entries combined for %zu bytes saved)", + new_arange_size, delta, delta * sizeof(Range)); } - else - { - // Only increment j if we aren't merging - minimal_aranges[++j] = m_aranges[i]; - } - } - assert (j+1 == minimal_size); - - // Now swap our new minimal aranges into place. The local - // minimal_aranges will then contian the old big collection - // which will get freed. - minimal_aranges.swap(m_aranges); - - if (log) - { - size_t delta = orig_arange_size - m_aranges.size(); - log->Printf ("DWARFDebugAranges::Sort() %zu entries after minimizing (%zu entries combined for %zu bytes saved)", - m_aranges.size(), delta, delta * sizeof(Range)); Dump (log.get()); } } @@ -342,64 +167,8 @@ DWARFDebugAranges::Sort (bool minimize, uint32_t n) dw_offset_t DWARFDebugAranges::FindAddress(dw_addr_t address) const { - if ( !m_aranges.empty() ) - { - DWARFDebugAranges::Range range(address); - DWARFDebugAranges::RangeCollIterator begin = m_aranges.begin(); - DWARFDebugAranges::RangeCollIterator end = m_aranges.end(); - DWARFDebugAranges::RangeCollIterator pos = lower_bound(begin, end, range, RangeLessThan); - - if ((pos != end) && (pos->lo_pc <= address && address < pos->hi_pc())) - { - // printf("FindAddress(1) found 0x%8.8x in compile unit: 0x%8.8x\n", address, pos->offset); - return pos->offset; - } - else if (pos != begin) - { - --pos; - if ((pos->lo_pc <= address) && (address < pos->hi_pc())) - { - // printf("FindAddress(2) found 0x%8.8x in compile unit: 0x%8.8x\n", address, pos->offset); - return (*pos).offset; - } - } - } + const RangeToDIE::Entry *entry = m_aranges.FindEntryThatContains(address); + if (entry) + return entry->data; return DW_INVALID_OFFSET; } - -//---------------------------------------------------------------------- -// AllRangesAreContiguous -//---------------------------------------------------------------------- -bool -DWARFDebugAranges::AllRangesAreContiguous(dw_addr_t& lo_pc, dw_addr_t& hi_pc) const -{ - if (m_aranges.empty()) - return false; - - DWARFDebugAranges::RangeCollIterator begin = m_aranges.begin(); - DWARFDebugAranges::RangeCollIterator end = m_aranges.end(); - DWARFDebugAranges::RangeCollIterator pos; - dw_addr_t next_addr = 0; - - for (pos = begin; pos != end; ++pos) - { - if ((pos != begin) && (pos->lo_pc != next_addr)) - return false; - next_addr = pos->hi_pc(); - } - lo_pc = m_aranges.front().lo_pc; // We checked for empty at the start of function so front() will be valid - hi_pc = m_aranges.back().hi_pc(); // We checked for empty at the start of function so back() will be valid - return true; -} - -bool -DWARFDebugAranges::GetMaxRange(dw_addr_t& lo_pc, dw_addr_t& hi_pc) const -{ - if (m_aranges.empty()) - return false; - - lo_pc = m_aranges.front().lo_pc; // We checked for empty at the start of function so front() will be valid - hi_pc = m_aranges.back().hi_pc(); // We checked for empty at the start of function so back() will be valid - return true; -} - diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.h index b6fe1439a9b..c02ea612e11 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.h @@ -13,113 +13,81 @@ #include "DWARFDebugArangeSet.h" #include <list> +#include "lldb/Core/RangeMap.h" + class SymbolFileDWARF; class DWARFDebugAranges { +protected: + typedef lldb_private::RangeMap<dw_addr_t, uint32_t, dw_offset_t> RangeToDIE; + public: - struct Range + typedef RangeToDIE::Entry Range; + typedef std::vector<RangeToDIE::Entry> RangeColl; + + DWARFDebugAranges(); + + void + Clear() { - explicit - Range (dw_addr_t lo = DW_INVALID_ADDRESS, - dw_addr_t hi = DW_INVALID_ADDRESS, - dw_offset_t off = DW_INVALID_OFFSET) : - lo_pc (lo), - length (hi-lo), - offset (off) - { - } - - void Clear() - { - lo_pc = DW_INVALID_ADDRESS; - length = 0; - offset = DW_INVALID_OFFSET; - } - - void - set_hi_pc (dw_addr_t hi_pc) - { - if (hi_pc == DW_INVALID_ADDRESS || hi_pc <= lo_pc) - length = 0; - else - length = hi_pc - lo_pc; - } - dw_addr_t - hi_pc() const - { - if (length) - return lo_pc + length; - return DW_INVALID_ADDRESS; - } - bool - ValidRange() const - { - return length > 0; - } - - static bool - SortedOverlapCheck (const Range& curr_range, const Range& next_range, uint32_t n) - { - if (curr_range.offset != next_range.offset) - return false; - return curr_range.hi_pc() + n >= next_range.lo_pc; - } - - bool Contains(const Range& range) const - { - return lo_pc <= range.lo_pc && range.hi_pc() <= hi_pc(); - } - - void Dump(lldb_private::Stream *s) const; - dw_addr_t lo_pc; // Start of address range - uint32_t length; // End of address range (not including this address) - dw_offset_t offset; // Offset of the compile unit or die - }; - - DWARFDebugAranges(); - - void Clear() { m_aranges.clear(); } - bool AllRangesAreContiguous(dw_addr_t& lo_pc, dw_addr_t& hi_pc) const; - bool GetMaxRange(dw_addr_t& lo_pc, dw_addr_t& hi_pc) const; - bool Extract(const lldb_private::DataExtractor &debug_aranges_data); - bool Generate(SymbolFileDWARF* dwarf2Data); + m_aranges.Clear(); + } + + bool + Extract(const lldb_private::DataExtractor &debug_aranges_data); + + bool + Generate(SymbolFileDWARF* dwarf2Data); // Use append range multiple times and then call sort - void AppendRange (dw_offset_t cu_offset, dw_addr_t low_pc, dw_addr_t high_pc); - void Sort (bool minimize, uint32_t n); - - const Range* RangeAtIndex(uint32_t idx) const - { - if (idx < m_aranges.size()) - return &m_aranges[idx]; - return NULL; - } - void Dump (lldb_private::Log *log) const; - dw_offset_t FindAddress(dw_addr_t address) const; - bool IsEmpty() const { return m_aranges.empty(); } -// void Dump(lldb_private::Stream *s); - uint32_t NumRanges() const - { - return m_aranges.size(); - } - - dw_offset_t OffsetAtIndex(uint32_t idx) const - { - if (idx < m_aranges.size()) - return m_aranges[idx].offset; - return DW_INVALID_OFFSET; - } -// void AppendDebugRanges(BinaryStreamBuf& debug_ranges, dw_addr_t cu_base_addr, uint32_t addr_size) const; - - static void Dump(SymbolFileDWARF* dwarf2Data, lldb_private::Stream *s); - - typedef std::vector<Range> RangeColl; - typedef RangeColl::const_iterator RangeCollIterator; + void + AppendRange (dw_offset_t cu_offset, + dw_addr_t low_pc, + dw_addr_t high_pc); + + void + Sort (bool minimize); + + const Range* + RangeAtIndex(uint32_t idx) const + { + return m_aranges.GetEntryAtIndex (idx); + } + + void + Dump (lldb_private::Log *log) const; + + dw_offset_t + FindAddress(dw_addr_t address) const; + bool + IsEmpty() const + { + return m_aranges.IsEmpty(); + } + uint32_t + GetNumRanges() const + { + return m_aranges.GetNumEntries(); + } + + dw_offset_t + OffsetAtIndex(uint32_t idx) const + { + const Range *range = m_aranges.GetEntryAtIndex (idx); + if (range) + return range->data; + return DW_INVALID_OFFSET; + } + + static void + Dump(SymbolFileDWARF* dwarf2Data, lldb_private::Stream *s); + protected: - RangeColl m_aranges; + + RangeToDIE m_aranges; }; 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) : |

