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