brintos

brintos / llvm-project-archived public Read only

0
0
Text · 4.3 KiB · b7ecc91 Raw
130 lines · cpp
1//===- DWARFDebugAranges.cpp ----------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "llvm/DebugInfo/DWARF/DWARFDebugAranges.h"10#include "llvm/DebugInfo/DWARF/DWARFAddressRange.h"11#include "llvm/DebugInfo/DWARF/DWARFContext.h"12#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"13#include "llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h"14#include "llvm/DebugInfo/DWARF/DWARFObject.h"15#include "llvm/DebugInfo/DWARF/DWARFUnit.h"16#include <cassert>17#include <cstdint>18#include <set>19 20using namespace llvm;21 22void DWARFDebugAranges::extract(23    DWARFDataExtractor DebugArangesData,24    function_ref<void(Error)> RecoverableErrorHandler,25    function_ref<void(Error)> WarningHandler) {26  if (!DebugArangesData.isValidOffset(0))27    return;28  uint64_t Offset = 0;29  DWARFDebugArangeSet Set;30 31  while (DebugArangesData.isValidOffset(Offset)) {32    if (Error E = Set.extract(DebugArangesData, &Offset, WarningHandler)) {33      RecoverableErrorHandler(std::move(E));34      return;35    }36    uint64_t CUOffset = Set.getCompileUnitDIEOffset();37    for (const auto &Desc : Set.descriptors()) {38      uint64_t LowPC = Desc.Address;39      uint64_t HighPC = Desc.getEndAddress();40      appendRange(CUOffset, LowPC, HighPC);41    }42    ParsedCUOffsets.insert(CUOffset);43  }44}45 46void DWARFDebugAranges::generate(DWARFContext *CTX) {47  clear();48  if (!CTX)49    return;50 51  // Extract aranges from .debug_aranges section.52  DWARFDataExtractor ArangesData(CTX->getDWARFObj().getArangesSection(),53                                 CTX->isLittleEndian(), 0);54  extract(ArangesData, CTX->getRecoverableErrorHandler(),55          CTX->getWarningHandler());56 57  // Generate aranges from DIEs: even if .debug_aranges section is present,58  // it may describe only a small subset of compilation units, so we need to59  // manually build aranges for the rest of them.60  for (const auto &CU : CTX->compile_units()) {61    uint64_t CUOffset = CU->getOffset();62    if (ParsedCUOffsets.insert(CUOffset).second) {63      Expected<DWARFAddressRangesVector> CURanges = CU->collectAddressRanges();64      if (!CURanges)65        CTX->getRecoverableErrorHandler()(CURanges.takeError());66      else67        for (const auto &R : *CURanges)68          appendRange(CUOffset, R.LowPC, R.HighPC);69    }70  }71 72  construct();73}74 75void DWARFDebugAranges::clear() {76  Endpoints.clear();77  Aranges.clear();78  ParsedCUOffsets.clear();79}80 81void DWARFDebugAranges::appendRange(uint64_t CUOffset, uint64_t LowPC,82                                    uint64_t HighPC) {83  if (LowPC >= HighPC)84    return;85  Endpoints.emplace_back(LowPC, CUOffset, true);86  Endpoints.emplace_back(HighPC, CUOffset, false);87}88 89void DWARFDebugAranges::construct() {90  std::multiset<uint64_t> ValidCUs;  // Maintain the set of CUs describing91                                     // a current address range.92  llvm::sort(Endpoints);93  uint64_t PrevAddress = -1ULL;94  for (const auto &E : Endpoints) {95    if (PrevAddress < E.Address && !ValidCUs.empty()) {96      // If the address range between two endpoints is described by some97      // CU, first try to extend the last range in Aranges. If we can't98      // do it, start a new range.99      if (!Aranges.empty() && Aranges.back().HighPC() == PrevAddress &&100          ValidCUs.find(Aranges.back().CUOffset) != ValidCUs.end()) {101        Aranges.back().setHighPC(E.Address);102      } else {103        Aranges.emplace_back(PrevAddress, E.Address, *ValidCUs.begin());104      }105    }106    // Update the set of valid CUs.107    if (E.IsRangeStart) {108      ValidCUs.insert(E.CUOffset);109    } else {110      auto CUPos = ValidCUs.find(E.CUOffset);111      assert(CUPos != ValidCUs.end());112      ValidCUs.erase(CUPos);113    }114    PrevAddress = E.Address;115  }116  assert(ValidCUs.empty());117 118  // Endpoints are not needed now.119  Endpoints.clear();120  Endpoints.shrink_to_fit();121}122 123uint64_t DWARFDebugAranges::findAddress(uint64_t Address) const {124  RangeCollIterator It =125      partition_point(Aranges, [=](Range R) { return R.HighPC() <= Address; });126  if (It != Aranges.end() && It->LowPC <= Address)127    return It->CUOffset;128  return -1ULL;129}130