diff options
Diffstat (limited to 'lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp')
-rw-r--r-- | lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp | 343 |
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; +} + |