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 26 using namespace lldb; 27 using namespace lldb_private; 28 29 //---------------------------------------------------------------------- 30 // Constructor 31 //---------------------------------------------------------------------- 32 DWARFDebugAranges::DWARFDebugAranges() : 33 m_aranges() 34 { 35 } 36 37 //---------------------------------------------------------------------- 38 // CountArangeDescriptors 39 //---------------------------------------------------------------------- 40 class CountArangeDescriptors 41 { 42 public: 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 //---------------------------------------------------------------------- 58 bool 59 DWARFDebugAranges::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 //---------------------------------------------------------------------- 89 bool 90 DWARFDebugAranges::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 110 void 111 DWARFDebugAranges::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 128 void 129 DWARFDebugAranges::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 135 void 136 DWARFDebugAranges::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 //---------------------------------------------------------------------- 170 dw_offset_t 171 DWARFDebugAranges::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