Path: blob/main/contrib/llvm-project/llvm/lib/DebugInfo/DWARF/DWARFDebugAbbrev.cpp
35294 views
//===- DWARFDebugAbbrev.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/DWARFDebugAbbrev.h"9#include "llvm/Support/Format.h"10#include "llvm/Support/raw_ostream.h"11#include <algorithm>12#include <cinttypes>13#include <cstdint>1415using namespace llvm;1617DWARFAbbreviationDeclarationSet::DWARFAbbreviationDeclarationSet() {18clear();19}2021void DWARFAbbreviationDeclarationSet::clear() {22Offset = 0;23FirstAbbrCode = 0;24Decls.clear();25}2627Error DWARFAbbreviationDeclarationSet::extract(DataExtractor Data,28uint64_t *OffsetPtr) {29clear();30const uint64_t BeginOffset = *OffsetPtr;31Offset = BeginOffset;32DWARFAbbreviationDeclaration AbbrDecl;33uint32_t PrevAbbrCode = 0;34while (true) {35Expected<DWARFAbbreviationDeclaration::ExtractState> ES =36AbbrDecl.extract(Data, OffsetPtr);37if (!ES)38return ES.takeError();3940if (*ES == DWARFAbbreviationDeclaration::ExtractState::Complete)41break;4243if (FirstAbbrCode == 0) {44FirstAbbrCode = AbbrDecl.getCode();45} else if (PrevAbbrCode + 1 != AbbrDecl.getCode()) {46// Codes are not consecutive, can't do O(1) lookups.47FirstAbbrCode = UINT32_MAX;48}49PrevAbbrCode = AbbrDecl.getCode();50Decls.push_back(std::move(AbbrDecl));51}52return Error::success();53}5455void DWARFAbbreviationDeclarationSet::dump(raw_ostream &OS) const {56for (const auto &Decl : Decls)57Decl.dump(OS);58}5960const DWARFAbbreviationDeclaration *61DWARFAbbreviationDeclarationSet::getAbbreviationDeclaration(62uint32_t AbbrCode) const {63if (FirstAbbrCode == UINT32_MAX) {64for (const auto &Decl : Decls) {65if (Decl.getCode() == AbbrCode)66return &Decl;67}68return nullptr;69}70if (AbbrCode < FirstAbbrCode || AbbrCode >= FirstAbbrCode + Decls.size())71return nullptr;72return &Decls[AbbrCode - FirstAbbrCode];73}7475std::string DWARFAbbreviationDeclarationSet::getCodeRange() const {76// Create a sorted list of all abbrev codes.77std::vector<uint32_t> Codes;78Codes.reserve(Decls.size());79for (const auto &Decl : Decls)80Codes.push_back(Decl.getCode());8182std::string Buffer;83raw_string_ostream Stream(Buffer);84// Each iteration through this loop represents a single contiguous range in85// the set of codes.86for (auto Current = Codes.begin(), End = Codes.end(); Current != End;) {87uint32_t RangeStart = *Current;88// Add the current range start.89Stream << *Current;90uint32_t RangeEnd = RangeStart;91// Find the end of the current range.92while (++Current != End && *Current == RangeEnd + 1)93++RangeEnd;94// If there is more than one value in the range, add the range end too.95if (RangeStart != RangeEnd)96Stream << "-" << RangeEnd;97// If there is at least one more range, add a separator.98if (Current != End)99Stream << ", ";100}101return Buffer;102}103104DWARFDebugAbbrev::DWARFDebugAbbrev(DataExtractor Data)105: AbbrDeclSets(), PrevAbbrOffsetPos(AbbrDeclSets.end()), Data(Data) {}106107Error DWARFDebugAbbrev::parse() const {108if (!Data)109return Error::success();110uint64_t Offset = 0;111auto I = AbbrDeclSets.begin();112while (Data->isValidOffset(Offset)) {113while (I != AbbrDeclSets.end() && I->first < Offset)114++I;115uint64_t CUAbbrOffset = Offset;116DWARFAbbreviationDeclarationSet AbbrDecls;117if (Error Err = AbbrDecls.extract(*Data, &Offset)) {118Data = std::nullopt;119return Err;120}121AbbrDeclSets.insert(I, std::make_pair(CUAbbrOffset, std::move(AbbrDecls)));122}123Data = std::nullopt;124return Error::success();125}126127void DWARFDebugAbbrev::dump(raw_ostream &OS) const {128if (Error Err = parse())129// FIXME: We should propagate this error or otherwise display it.130llvm::consumeError(std::move(Err));131132if (AbbrDeclSets.empty()) {133OS << "< EMPTY >\n";134return;135}136137for (const auto &I : AbbrDeclSets) {138OS << format("Abbrev table for offset: 0x%8.8" PRIx64 "\n", I.first);139I.second.dump(OS);140}141}142143Expected<const DWARFAbbreviationDeclarationSet *>144DWARFDebugAbbrev::getAbbreviationDeclarationSet(uint64_t CUAbbrOffset) const {145const auto End = AbbrDeclSets.end();146if (PrevAbbrOffsetPos != End && PrevAbbrOffsetPos->first == CUAbbrOffset) {147return &PrevAbbrOffsetPos->second;148}149150const auto Pos = AbbrDeclSets.find(CUAbbrOffset);151if (Pos != End) {152PrevAbbrOffsetPos = Pos;153return &Pos->second;154}155156if (!Data || CUAbbrOffset >= Data->getData().size())157return make_error<llvm::object::GenericBinaryError>(158"the abbreviation offset into the .debug_abbrev section is not valid");159160uint64_t Offset = CUAbbrOffset;161DWARFAbbreviationDeclarationSet AbbrDecls;162if (Error Err = AbbrDecls.extract(*Data, &Offset))163return std::move(Err);164165PrevAbbrOffsetPos =166AbbrDeclSets.insert(std::make_pair(CUAbbrOffset, std::move(AbbrDecls)))167.first;168return &PrevAbbrOffsetPos->second;169}170171172