Path: blob/main/contrib/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFDebugAranges.cpp
35269 views
//===- DWARFDebugAranges.cpp ----------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "llvm/DebugInfo/DWARF/DWARFDebugAranges.h"9#include "llvm/DebugInfo/DWARF/DWARFAddressRange.h"10#include "llvm/DebugInfo/DWARF/DWARFContext.h"11#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"12#include "llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h"13#include "llvm/DebugInfo/DWARF/DWARFObject.h"14#include "llvm/DebugInfo/DWARF/DWARFUnit.h"15#include <algorithm>16#include <cassert>17#include <cstdint>18#include <set>1920using namespace llvm;2122void DWARFDebugAranges::extract(23DWARFDataExtractor DebugArangesData,24function_ref<void(Error)> RecoverableErrorHandler,25function_ref<void(Error)> WarningHandler) {26if (!DebugArangesData.isValidOffset(0))27return;28uint64_t Offset = 0;29DWARFDebugArangeSet Set;3031while (DebugArangesData.isValidOffset(Offset)) {32if (Error E = Set.extract(DebugArangesData, &Offset, WarningHandler)) {33RecoverableErrorHandler(std::move(E));34return;35}36uint64_t CUOffset = Set.getCompileUnitDIEOffset();37for (const auto &Desc : Set.descriptors()) {38uint64_t LowPC = Desc.Address;39uint64_t HighPC = Desc.getEndAddress();40appendRange(CUOffset, LowPC, HighPC);41}42ParsedCUOffsets.insert(CUOffset);43}44}4546void DWARFDebugAranges::generate(DWARFContext *CTX) {47clear();48if (!CTX)49return;5051// Extract aranges from .debug_aranges section.52DWARFDataExtractor ArangesData(CTX->getDWARFObj().getArangesSection(),53CTX->isLittleEndian(), 0);54extract(ArangesData, CTX->getRecoverableErrorHandler(),55CTX->getWarningHandler());5657// 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.60for (const auto &CU : CTX->compile_units()) {61uint64_t CUOffset = CU->getOffset();62if (ParsedCUOffsets.insert(CUOffset).second) {63Expected<DWARFAddressRangesVector> CURanges = CU->collectAddressRanges();64if (!CURanges)65CTX->getRecoverableErrorHandler()(CURanges.takeError());66else67for (const auto &R : *CURanges)68appendRange(CUOffset, R.LowPC, R.HighPC);69}70}7172construct();73}7475void DWARFDebugAranges::clear() {76Endpoints.clear();77Aranges.clear();78ParsedCUOffsets.clear();79}8081void DWARFDebugAranges::appendRange(uint64_t CUOffset, uint64_t LowPC,82uint64_t HighPC) {83if (LowPC >= HighPC)84return;85Endpoints.emplace_back(LowPC, CUOffset, true);86Endpoints.emplace_back(HighPC, CUOffset, false);87}8889void DWARFDebugAranges::construct() {90std::multiset<uint64_t> ValidCUs; // Maintain the set of CUs describing91// a current address range.92llvm::sort(Endpoints);93uint64_t PrevAddress = -1ULL;94for (const auto &E : Endpoints) {95if (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.99if (!Aranges.empty() && Aranges.back().HighPC() == PrevAddress &&100ValidCUs.find(Aranges.back().CUOffset) != ValidCUs.end()) {101Aranges.back().setHighPC(E.Address);102} else {103Aranges.emplace_back(PrevAddress, E.Address, *ValidCUs.begin());104}105}106// Update the set of valid CUs.107if (E.IsRangeStart) {108ValidCUs.insert(E.CUOffset);109} else {110auto CUPos = ValidCUs.find(E.CUOffset);111assert(CUPos != ValidCUs.end());112ValidCUs.erase(CUPos);113}114PrevAddress = E.Address;115}116assert(ValidCUs.empty());117118// Endpoints are not needed now.119Endpoints.clear();120Endpoints.shrink_to_fit();121}122123uint64_t DWARFDebugAranges::findAddress(uint64_t Address) const {124RangeCollIterator It =125partition_point(Aranges, [=](Range R) { return R.HighPC() <= Address; });126if (It != Aranges.end() && It->LowPC <= Address)127return It->CUOffset;128return -1ULL;129}130131132