1//===-- DWARFDebugAranges.cpp -----------------------------------*- C++ -*-===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9 10#include "DWARFDebugAranges.h" 11 12#include <assert.h> 13#include <stdio.h> 14 15#include <algorithm> 16 17#include "lldb/Core/Log.h" 18#include "lldb/Core/Stream.h" 19#include "lldb/Core/Timer.h" 20 21#include "LogChannelDWARF.h" 22#include "SymbolFileDWARF.h" 23#include "DWARFDebugInfo.h" 24#include "DWARFCompileUnit.h" 25 26using namespace lldb; 27using namespace lldb_private; 28 29//---------------------------------------------------------------------- 30// Constructor 31//---------------------------------------------------------------------- 32DWARFDebugAranges::DWARFDebugAranges() : 33 m_aranges() 34{ 35} 36 37//---------------------------------------------------------------------- 38// CountArangeDescriptors 39//---------------------------------------------------------------------- 40class CountArangeDescriptors 41{ 42public: 43 CountArangeDescriptors (uint32_t& count_ref) : count(count_ref) 44 { 45// printf("constructor CountArangeDescriptors()\n"); 46 } 47 void operator() (const DWARFDebugArangeSet& set) 48 { 49 count += set.NumDescriptors(); 50 } 51 uint32_t& count; 52}; 53 54 55//---------------------------------------------------------------------- 56// Extract 57//---------------------------------------------------------------------- 58bool 59DWARFDebugAranges::Extract(const DataExtractor &debug_aranges_data) 60{ 61 if (debug_aranges_data.ValidOffset(0)) 62 { 63 lldb::offset_t offset = 0; 64 65 DWARFDebugArangeSet set; 66 Range range; 67 while (set.Extract(debug_aranges_data, &offset)) 68 { 69 const uint32_t num_descriptors = set.NumDescriptors(); 70 if (num_descriptors > 0) 71 { 72 const dw_offset_t cu_offset = set.GetCompileUnitDIEOffset(); 73 74 for (uint32_t i=0; i<num_descriptors; ++i) 75 { 76 const DWARFDebugArangeSet::Descriptor &descriptor = set.GetDescriptorRef(i); 77 m_aranges.Append(RangeToDIE::Entry (descriptor.address, descriptor.length, cu_offset)); 78 } 79 } 80 set.Clear(); 81 } 82 } 83 return false; 84} 85 86//---------------------------------------------------------------------- 87// Generate 88//---------------------------------------------------------------------- 89bool 90DWARFDebugAranges::Generate(SymbolFileDWARF* dwarf2Data) 91{ 92 Clear(); 93 DWARFDebugInfo* debug_info = dwarf2Data->DebugInfo(); 94 if (debug_info) 95 { 96 const bool clear_dies_if_already_not_parsed = true; 97 uint32_t cu_idx = 0; 98 const uint32_t num_compile_units = dwarf2Data->GetNumCompileUnits(); 99 for (cu_idx = 0; cu_idx < num_compile_units; ++cu_idx) 100 { 101 DWARFCompileUnit* cu = debug_info->GetCompileUnitAtIndex(cu_idx); 102 if (cu) 103 cu->BuildAddressRangeTable(dwarf2Data, this, clear_dies_if_already_not_parsed); 104 } 105 } 106 return !IsEmpty(); 107} 108 109 110void 111DWARFDebugAranges::Dump (Log *log) const 112{ 113 if (log == NULL) 114 return; 115 116 const size_t num_entries = m_aranges.GetSize(); 117 for (size_t i=0; i<num_entries; ++i) 118 { 119 const RangeToDIE::Entry *entry = m_aranges.GetEntryAtIndex(i); 120 if (entry) 121 log->Printf ("0x%8.8x: [0x%" PRIx64 " - 0x%" PRIx64 ")", 122 entry->data, 123 entry->GetRangeBase(), 124 entry->GetRangeEnd()); 125 } 126} 127 128void 129DWARFDebugAranges::AppendRange (dw_offset_t offset, dw_addr_t low_pc, dw_addr_t high_pc) 130{ 131 if (high_pc > low_pc) 132 m_aranges.Append(RangeToDIE::Entry (low_pc, high_pc - low_pc, offset)); 133} 134 135void 136DWARFDebugAranges::Sort (bool minimize) 137{ 138 Timer scoped_timer(__PRETTY_FUNCTION__, "%s this = %p", 139 __PRETTY_FUNCTION__, this); 140 141 Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_ARANGES)); 142 size_t orig_arange_size = 0; 143 if (log) 144 { 145 orig_arange_size = m_aranges.GetSize(); 146 log->Printf ("DWARFDebugAranges::Sort(minimize = %u) with %" PRIu64 " entries", minimize, (uint64_t)orig_arange_size); 147 } 148 149 m_aranges.Sort(); 150 m_aranges.CombineConsecutiveEntriesWithEqualData(); 151 152 if (log) 153 { 154 if (minimize) 155 { 156 const size_t new_arange_size = m_aranges.GetSize(); 157 const size_t delta = orig_arange_size - new_arange_size; 158 log->Printf ("DWARFDebugAranges::Sort() %" PRIu64 " entries after minimizing (%" PRIu64 " entries combined for %" PRIu64 " bytes saved)", 159 (uint64_t)new_arange_size, 160 (uint64_t)delta, 161 (uint64_t)delta * sizeof(Range)); 162 } 163 Dump (log); 164 } 165} 166 167//---------------------------------------------------------------------- 168// FindAddress 169//---------------------------------------------------------------------- 170dw_offset_t 171DWARFDebugAranges::FindAddress(dw_addr_t address) const 172{ 173 const RangeToDIE::Entry *entry = m_aranges.FindEntryThatContains(address); 174 if (entry) 175 return entry->data; 176 return DW_INVALID_OFFSET; 177} 178