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 DWARFDataExtractor &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 uint32_t cu_idx = 0; 97 const uint32_t num_compile_units = dwarf2Data->GetNumCompileUnits(); 98 for (cu_idx = 0; cu_idx < num_compile_units; ++cu_idx) 99 { 100 DWARFCompileUnit* cu = debug_info->GetCompileUnitAtIndex(cu_idx); 101 if (cu) 102 cu->BuildAddressRangeTable(dwarf2Data, this); 103 } 104 } 105 return !IsEmpty(); 106 } 107 108 109 void 110 DWARFDebugAranges::Dump (Log *log) const 111 { 112 if (log == NULL) 113 return; 114 115 const size_t num_entries = m_aranges.GetSize(); 116 for (size_t i=0; i<num_entries; ++i) 117 { 118 const RangeToDIE::Entry *entry = m_aranges.GetEntryAtIndex(i); 119 if (entry) 120 log->Printf ("0x%8.8x: [0x%" PRIx64 " - 0x%" PRIx64 ")", 121 entry->data, 122 entry->GetRangeBase(), 123 entry->GetRangeEnd()); 124 } 125 } 126 127 void 128 DWARFDebugAranges::AppendRange (dw_offset_t offset, dw_addr_t low_pc, dw_addr_t high_pc) 129 { 130 if (high_pc > low_pc) 131 m_aranges.Append(RangeToDIE::Entry (low_pc, high_pc - low_pc, offset)); 132 } 133 134 void 135 DWARFDebugAranges::Sort (bool minimize) 136 { 137 Timer scoped_timer(__PRETTY_FUNCTION__, "%s this = %p", 138 __PRETTY_FUNCTION__, static_cast<void*>(this)); 139 140 Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_ARANGES)); 141 size_t orig_arange_size = 0; 142 if (log) 143 { 144 orig_arange_size = m_aranges.GetSize(); 145 log->Printf ("DWARFDebugAranges::Sort(minimize = %u) with %" PRIu64 " entries", minimize, (uint64_t)orig_arange_size); 146 } 147 148 m_aranges.Sort(); 149 m_aranges.CombineConsecutiveEntriesWithEqualData(); 150 151 if (log) 152 { 153 if (minimize) 154 { 155 const size_t new_arange_size = m_aranges.GetSize(); 156 const size_t delta = orig_arange_size - new_arange_size; 157 log->Printf ("DWARFDebugAranges::Sort() %" PRIu64 " entries after minimizing (%" PRIu64 " entries combined for %" PRIu64 " bytes saved)", 158 (uint64_t)new_arange_size, 159 (uint64_t)delta, 160 (uint64_t)delta * sizeof(Range)); 161 } 162 Dump (log); 163 } 164 } 165 166 //---------------------------------------------------------------------- 167 // FindAddress 168 //---------------------------------------------------------------------- 169 dw_offset_t 170 DWARFDebugAranges::FindAddress(dw_addr_t address) const 171 { 172 const RangeToDIE::Entry *entry = m_aranges.FindEntryThatContains(address); 173 if (entry) 174 return entry->data; 175 return DW_INVALID_OFFSET; 176 } 177