DWARFDebugAranges.cpp revision 344779
1//===- DWARFDebugAranges.cpp ----------------------------------------------===// 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 "llvm/DebugInfo/DWARF/DWARFDebugAranges.h" 11#include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h" 12#include "llvm/DebugInfo/DWARF/DWARFContext.h" 13#include "llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h" 14#include "llvm/Support/DataExtractor.h" 15#include "llvm/Support/WithColor.h" 16#include <algorithm> 17#include <cassert> 18#include <cstdint> 19#include <set> 20#include <vector> 21 22using namespace llvm; 23 24void DWARFDebugAranges::extract(DataExtractor DebugArangesData) { 25 if (!DebugArangesData.isValidOffset(0)) 26 return; 27 uint32_t Offset = 0; 28 DWARFDebugArangeSet Set; 29 30 while (Set.extract(DebugArangesData, &Offset)) { 31 uint32_t CUOffset = Set.getCompileUnitDIEOffset(); 32 for (const auto &Desc : Set.descriptors()) { 33 uint64_t LowPC = Desc.Address; 34 uint64_t HighPC = Desc.getEndAddress(); 35 appendRange(CUOffset, LowPC, HighPC); 36 } 37 ParsedCUOffsets.insert(CUOffset); 38 } 39} 40 41void DWARFDebugAranges::generate(DWARFContext *CTX) { 42 clear(); 43 if (!CTX) 44 return; 45 46 // Extract aranges from .debug_aranges section. 47 DataExtractor ArangesData(CTX->getDWARFObj().getARangeSection(), 48 CTX->isLittleEndian(), 0); 49 extract(ArangesData); 50 51 // Generate aranges from DIEs: even if .debug_aranges section is present, 52 // it may describe only a small subset of compilation units, so we need to 53 // manually build aranges for the rest of them. 54 for (const auto &CU : CTX->compile_units()) { 55 uint32_t CUOffset = CU->getOffset(); 56 if (ParsedCUOffsets.insert(CUOffset).second) { 57 Expected<DWARFAddressRangesVector> CURanges = CU->collectAddressRanges(); 58 if (!CURanges) 59 WithColor::error() << toString(CURanges.takeError()) << '\n'; 60 else 61 for (const auto &R : *CURanges) 62 appendRange(CUOffset, R.LowPC, R.HighPC); 63 } 64 } 65 66 construct(); 67} 68 69void DWARFDebugAranges::clear() { 70 Endpoints.clear(); 71 Aranges.clear(); 72 ParsedCUOffsets.clear(); 73} 74 75void DWARFDebugAranges::appendRange(uint32_t CUOffset, uint64_t LowPC, 76 uint64_t HighPC) { 77 if (LowPC >= HighPC) 78 return; 79 Endpoints.emplace_back(LowPC, CUOffset, true); 80 Endpoints.emplace_back(HighPC, CUOffset, false); 81} 82 83void DWARFDebugAranges::construct() { 84 std::multiset<uint32_t> ValidCUs; // Maintain the set of CUs describing 85 // a current address range. 86 llvm::sort(Endpoints); 87 uint64_t PrevAddress = -1ULL; 88 for (const auto &E : Endpoints) { 89 if (PrevAddress < E.Address && !ValidCUs.empty()) { 90 // If the address range between two endpoints is described by some 91 // CU, first try to extend the last range in Aranges. If we can't 92 // do it, start a new range. 93 if (!Aranges.empty() && Aranges.back().HighPC() == PrevAddress && 94 ValidCUs.find(Aranges.back().CUOffset) != ValidCUs.end()) { 95 Aranges.back().setHighPC(E.Address); 96 } else { 97 Aranges.emplace_back(PrevAddress, E.Address, *ValidCUs.begin()); 98 } 99 } 100 // Update the set of valid CUs. 101 if (E.IsRangeStart) { 102 ValidCUs.insert(E.CUOffset); 103 } else { 104 auto CUPos = ValidCUs.find(E.CUOffset); 105 assert(CUPos != ValidCUs.end()); 106 ValidCUs.erase(CUPos); 107 } 108 PrevAddress = E.Address; 109 } 110 assert(ValidCUs.empty()); 111 112 // Endpoints are not needed now. 113 Endpoints.clear(); 114 Endpoints.shrink_to_fit(); 115} 116 117uint32_t DWARFDebugAranges::findAddress(uint64_t Address) const { 118 if (!Aranges.empty()) { 119 Range range(Address); 120 RangeCollIterator begin = Aranges.begin(); 121 RangeCollIterator end = Aranges.end(); 122 RangeCollIterator pos = 123 std::lower_bound(begin, end, range); 124 125 if (pos != end && pos->containsAddress(Address)) { 126 return pos->CUOffset; 127 } else if (pos != begin) { 128 --pos; 129 if (pos->containsAddress(Address)) 130 return pos->CUOffset; 131 } 132 } 133 return -1U; 134} 135