summaryrefslogtreecommitdiffstats
path: root/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp')
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp343
1 files changed, 343 insertions, 0 deletions
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp
new file mode 100644
index 00000000000..a3213e080c3
--- /dev/null
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp
@@ -0,0 +1,343 @@
+//===-- DWARFDebugAranges.cpp -----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DWARFDebugAranges.h"
+
+#include <assert.h>
+
+#include <algorithm>
+
+#include "lldb/Core/Stream.h"
+
+#include "SymbolFileDWARF.h"
+#include "DWARFDebugInfo.h"
+#include "DWARFCompileUnit.h"
+
+using namespace lldb_private;
+
+//----------------------------------------------------------------------
+// Constructor
+//----------------------------------------------------------------------
+DWARFDebugAranges::DWARFDebugAranges() :
+ m_aranges()
+{
+}
+
+
+//----------------------------------------------------------------------
+// Compare function DWARFDebugAranges::Range structures
+//----------------------------------------------------------------------
+static bool RangeLessThan (const DWARFDebugAranges::Range& range1, const DWARFDebugAranges::Range& range2)
+{
+// printf("RangeLessThan -- 0x%8.8x < 0x%8.8x ? %d\n", range1.lo_pc, range1.lo_pc, range1.lo_pc < range2.lo_pc);
+ return range1.lo_pc < range2.lo_pc;
+}
+
+//----------------------------------------------------------------------
+// CountArangeDescriptors
+//----------------------------------------------------------------------
+class CountArangeDescriptors
+{
+public:
+ CountArangeDescriptors (uint32_t& count_ref) : count(count_ref)
+ {
+// printf("constructor CountArangeDescriptors()\n");
+ }
+ void operator() (const DWARFDebugArangeSet& set)
+ {
+ count += set.NumDescriptors();
+ }
+ 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); ++i)
+ {
+ range.lo_pc = arange_desc_ptr->address;
+ range.hi_pc = arange_desc_ptr->address + 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, (uint64_t)range.lo_pc, (uint64_t)range.hi_pc);
+}
+
+//----------------------------------------------------------------------
+// Extract
+//----------------------------------------------------------------------
+bool
+DWARFDebugAranges::Extract(const DataExtractor &debug_aranges_data)
+{
+ if (debug_aranges_data.ValidOffset(0))
+ {
+ 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);
+ }
+
+ // puts("\n\nDWARFDebugAranges list is:\n");
+ // for_each(m_aranges.begin(), m_aranges.end(), PrintRange);
+ }
+ return false;
+}
+
+//----------------------------------------------------------------------
+// Generate
+//----------------------------------------------------------------------
+bool
+DWARFDebugAranges::Generate(SymbolFileDWARF* dwarf2Data)
+{
+ Clear();
+ DWARFDebugInfo* debug_info = dwarf2Data->DebugInfo();
+ if (debug_info)
+ {
+ uint32_t cu_idx = 0;
+ const uint32_t num_compile_units = dwarf2Data->GetNumCompileUnits();
+ for (cu_idx = 0; cu_idx < num_compile_units; ++cu_idx)
+ {
+ DWARFCompileUnit* cu = debug_info->GetCompileUnitAtIndex(cu_idx);
+ if (cu)
+ cu->DIE()->BuildAddressRangeTable(dwarf2Data, cu, this);
+ }
+ }
+ return !IsEmpty();
+}
+
+
+void
+DWARFDebugAranges::Print() const
+{
+ puts("\n\nDWARFDebugAranges address range list is:\n");
+ for_each(m_aranges.begin(), m_aranges.end(), PrintRange);
+}
+
+
+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);
+//
+//}
+//
+//----------------------------------------------------------------------
+// ArangeSetContainsAddress
+//----------------------------------------------------------------------
+class ArangeSetContainsAddress
+{
+public:
+ ArangeSetContainsAddress (dw_addr_t the_address) : address(the_address), offset(DW_INVALID_OFFSET) {}
+ bool operator() (const DWARFDebugArangeSet& set)
+ {
+ offset = set.FindAddress(address);
+ return (offset != DW_INVALID_OFFSET);
+ }
+ const dw_addr_t address;
+ dw_offset_t offset;
+};
+
+
+//----------------------------------------------------------------------
+// InsertRange
+//----------------------------------------------------------------------
+void
+DWARFDebugAranges::InsertRange(dw_offset_t offset, dw_addr_t low_pc, dw_addr_t high_pc)
+{
+ // Insert each item in increasing address order so binary searching
+ // can later be done!
+ DWARFDebugAranges::Range range(low_pc, high_pc, offset);
+ InsertRange(range);
+}
+
+//----------------------------------------------------------------------
+// InsertRange
+//----------------------------------------------------------------------
+void
+DWARFDebugAranges::InsertRange(const DWARFDebugAranges::Range& range)
+{
+ // Insert each item in increasing address order so binary searching
+ // can later be done!
+ RangeColl::iterator insert_pos = lower_bound(m_aranges.begin(), m_aranges.end(), range, RangeLessThan);
+ m_aranges.insert(insert_pos, range);
+}
+
+
+//----------------------------------------------------------------------
+// FindAddress
+//----------------------------------------------------------------------
+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;
+ }
+ }
+ }
+ 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;
+}
+
OpenPOWER on IntegriCloud