DWARFDebugAranges.cpp revision 36b56886974eae4f9c5ebc96befd3e7bfe5de338
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#include "DWARFCompileUnit.h" 12#include "DWARFContext.h" 13#include "llvm/Support/Format.h" 14#include "llvm/Support/raw_ostream.h" 15#include <algorithm> 16#include <cassert> 17using namespace llvm; 18 19void DWARFDebugAranges::extract(DataExtractor DebugArangesData) { 20 if (!DebugArangesData.isValidOffset(0)) 21 return; 22 uint32_t Offset = 0; 23 typedef std::vector<DWARFDebugArangeSet> RangeSetColl; 24 RangeSetColl Sets; 25 DWARFDebugArangeSet Set; 26 uint32_t TotalRanges = 0; 27 28 while (Set.extract(DebugArangesData, &Offset)) { 29 Sets.push_back(Set); 30 TotalRanges += Set.getNumDescriptors(); 31 } 32 if (TotalRanges == 0) 33 return; 34 35 Aranges.reserve(TotalRanges); 36 for (const auto &I : Sets) { 37 uint32_t CUOffset = I.getCompileUnitDIEOffset(); 38 39 for (const auto &Desc : I.descriptors()) { 40 uint64_t LowPC = Desc.Address; 41 uint64_t HighPC = Desc.getEndAddress(); 42 appendRange(CUOffset, LowPC, HighPC); 43 } 44 } 45} 46 47void DWARFDebugAranges::generate(DWARFContext *CTX) { 48 clear(); 49 if (!CTX) 50 return; 51 52 // Extract aranges from .debug_aranges section. 53 DataExtractor ArangesData(CTX->getARangeSection(), CTX->isLittleEndian(), 0); 54 extract(ArangesData); 55 56 // Generate aranges from DIEs: even if .debug_aranges section is present, 57 // it may describe only a small subset of compilation units, so we need to 58 // manually build aranges for the rest of them. 59 for (const auto &CU : CTX->compile_units()) { 60 uint32_t CUOffset = CU->getOffset(); 61 if (ParsedCUOffsets.insert(CUOffset).second) 62 CU->buildAddressRangeTable(this, true, CUOffset); 63 } 64 65 sortAndMinimize(); 66} 67 68void DWARFDebugAranges::appendRange(uint32_t CUOffset, uint64_t LowPC, 69 uint64_t HighPC) { 70 if (!Aranges.empty()) { 71 if (Aranges.back().CUOffset == CUOffset && 72 Aranges.back().HighPC() == LowPC) { 73 Aranges.back().setHighPC(HighPC); 74 return; 75 } 76 } 77 Aranges.push_back(Range(LowPC, HighPC, CUOffset)); 78} 79 80void DWARFDebugAranges::sortAndMinimize() { 81 const size_t orig_arange_size = Aranges.size(); 82 // Size of one? If so, no sorting is needed 83 if (orig_arange_size <= 1) 84 return; 85 // Sort our address range entries 86 std::stable_sort(Aranges.begin(), Aranges.end()); 87 88 // Most address ranges are contiguous from function to function 89 // so our new ranges will likely be smaller. We calculate the size 90 // of the new ranges since although std::vector objects can be resized, 91 // the will never reduce their allocated block size and free any excesss 92 // memory, so we might as well start a brand new collection so it is as 93 // small as possible. 94 95 // First calculate the size of the new minimal arange vector 96 // so we don't have to do a bunch of re-allocations as we 97 // copy the new minimal stuff over to the new collection. 98 size_t minimal_size = 1; 99 for (size_t i = 1; i < orig_arange_size; ++i) { 100 if (!Range::SortedOverlapCheck(Aranges[i-1], Aranges[i])) 101 ++minimal_size; 102 } 103 104 // If the sizes are the same, then no consecutive aranges can be 105 // combined, we are done. 106 if (minimal_size == orig_arange_size) 107 return; 108 109 // Else, make a new RangeColl that _only_ contains what we need. 110 RangeColl minimal_aranges; 111 minimal_aranges.resize(minimal_size); 112 uint32_t j = 0; 113 minimal_aranges[j] = Aranges[0]; 114 for (size_t i = 1; i < orig_arange_size; ++i) { 115 if (Range::SortedOverlapCheck(minimal_aranges[j], Aranges[i])) { 116 minimal_aranges[j].setHighPC(Aranges[i].HighPC()); 117 } else { 118 // Only increment j if we aren't merging 119 minimal_aranges[++j] = Aranges[i]; 120 } 121 } 122 assert(j+1 == minimal_size); 123 124 // Now swap our new minimal aranges into place. The local 125 // minimal_aranges will then contian the old big collection 126 // which will get freed. 127 minimal_aranges.swap(Aranges); 128} 129 130uint32_t DWARFDebugAranges::findAddress(uint64_t Address) const { 131 if (!Aranges.empty()) { 132 Range range(Address); 133 RangeCollIterator begin = Aranges.begin(); 134 RangeCollIterator end = Aranges.end(); 135 RangeCollIterator pos = 136 std::lower_bound(begin, end, range); 137 138 if (pos != end && pos->containsAddress(Address)) { 139 return pos->CUOffset; 140 } else if (pos != begin) { 141 --pos; 142 if (pos->containsAddress(Address)) 143 return pos->CUOffset; 144 } 145 } 146 return -1U; 147} 148