diff options
| author | Greg Clayton <gclayton@apple.com> | 2011-10-07 03:58:56 +0000 |
|---|---|---|
| committer | Greg Clayton <gclayton@apple.com> | 2011-10-07 03:58:56 +0000 |
| commit | c26e4454035a4160cffc3c865cf83be194ca38c4 (patch) | |
| tree | 5be2bfb2b3363cd70923d009909c4c9b377385a7 /lldb/source/Plugins | |
| parent | 779b8b0f33933e3b7bedaf7163a25143bedf428e (diff) | |
| download | bcm5719-llvm-c26e4454035a4160cffc3c865cf83be194ca38c4.tar.gz bcm5719-llvm-c26e4454035a4160cffc3c865cf83be194ca38c4.zip | |
Since we use address ranges a lot I added a templatized class that allows us to easily control the base address type, the size type, and the data that is stored with each range. It is designed to be populated by appending all needed items, then sorting the resulting list, and optionally minimizing the list when done. I adopted this new list in the DWARFDebugAranges for even further memory savings.
llvm-svn: 141352
Diffstat (limited to 'lldb/source/Plugins')
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) : |

