brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.1 KiB · 13ec7f5 Raw
170 lines · cpp
1//===- DWARFDebugAbbrev.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/DWARFDebugAbbrev.h"10#include "llvm/Support/Format.h"11#include "llvm/Support/raw_ostream.h"12#include <cinttypes>13#include <cstdint>14 15using namespace llvm;16 17DWARFAbbreviationDeclarationSet::DWARFAbbreviationDeclarationSet() {18  clear();19}20 21void DWARFAbbreviationDeclarationSet::clear() {22  Offset = 0;23  FirstAbbrCode = 0;24  Decls.clear();25}26 27Error DWARFAbbreviationDeclarationSet::extract(DataExtractor Data,28                                               uint64_t *OffsetPtr) {29  clear();30  const uint64_t BeginOffset = *OffsetPtr;31  Offset = BeginOffset;32  DWARFAbbreviationDeclaration AbbrDecl;33  uint32_t PrevAbbrCode = 0;34  while (true) {35    Expected<DWARFAbbreviationDeclaration::ExtractState> ES =36        AbbrDecl.extract(Data, OffsetPtr);37    if (!ES)38      return ES.takeError();39 40    if (*ES == DWARFAbbreviationDeclaration::ExtractState::Complete)41      break;42 43    if (FirstAbbrCode == 0) {44      FirstAbbrCode = AbbrDecl.getCode();45    } else if (PrevAbbrCode + 1 != AbbrDecl.getCode()) {46      // Codes are not consecutive, can't do O(1) lookups.47      FirstAbbrCode = UINT32_MAX;48    }49    PrevAbbrCode = AbbrDecl.getCode();50    Decls.push_back(std::move(AbbrDecl));51  }52  return Error::success();53}54 55void DWARFAbbreviationDeclarationSet::dump(raw_ostream &OS) const {56  for (const auto &Decl : Decls)57    Decl.dump(OS);58}59 60const DWARFAbbreviationDeclaration *61DWARFAbbreviationDeclarationSet::getAbbreviationDeclaration(62    uint32_t AbbrCode) const {63  if (FirstAbbrCode == UINT32_MAX) {64    for (const auto &Decl : Decls) {65      if (Decl.getCode() == AbbrCode)66        return &Decl;67    }68    return nullptr;69  }70  if (AbbrCode < FirstAbbrCode || AbbrCode >= FirstAbbrCode + Decls.size())71    return nullptr;72  return &Decls[AbbrCode - FirstAbbrCode];73}74 75std::string DWARFAbbreviationDeclarationSet::getCodeRange() const {76  // Create a sorted list of all abbrev codes.77  std::vector<uint32_t> Codes;78  Codes.reserve(Decls.size());79  for (const auto &Decl : Decls)80    Codes.push_back(Decl.getCode());81 82  std::string Buffer;83  raw_string_ostream Stream(Buffer);84  // Each iteration through this loop represents a single contiguous range in85  // the set of codes.86  for (auto Current = Codes.begin(), End = Codes.end(); Current != End;) {87    uint32_t RangeStart = *Current;88    // Add the current range start.89    Stream << *Current;90    uint32_t RangeEnd = RangeStart;91    // Find the end of the current range.92    while (++Current != End && *Current == RangeEnd + 1)93      ++RangeEnd;94    // If there is more than one value in the range, add the range end too.95    if (RangeStart != RangeEnd)96      Stream << "-" << RangeEnd;97    // If there is at least one more range, add a separator.98    if (Current != End)99      Stream << ", ";100  }101  return Buffer;102}103 104DWARFDebugAbbrev::DWARFDebugAbbrev(DataExtractor Data)105    : AbbrDeclSets(), PrevAbbrOffsetPos(AbbrDeclSets.end()), Data(Data) {}106 107Error DWARFDebugAbbrev::parse() const {108  if (!Data)109    return Error::success();110  uint64_t Offset = 0;111  auto I = AbbrDeclSets.begin();112  while (Data->isValidOffset(Offset)) {113    while (I != AbbrDeclSets.end() && I->first < Offset)114      ++I;115    uint64_t CUAbbrOffset = Offset;116    DWARFAbbreviationDeclarationSet AbbrDecls;117    if (Error Err = AbbrDecls.extract(*Data, &Offset)) {118      Data = std::nullopt;119      return Err;120    }121    AbbrDeclSets.insert(I, std::make_pair(CUAbbrOffset, std::move(AbbrDecls)));122  }123  Data = std::nullopt;124  return Error::success();125}126 127void DWARFDebugAbbrev::dump(raw_ostream &OS) const {128  if (Error Err = parse())129    // FIXME: We should propagate this error or otherwise display it.130    llvm::consumeError(std::move(Err));131 132  if (AbbrDeclSets.empty()) {133    OS << "< EMPTY >\n";134    return;135  }136 137  for (const auto &I : AbbrDeclSets) {138    OS << format("Abbrev table for offset: 0x%8.8" PRIx64 "\n", I.first);139    I.second.dump(OS);140  }141}142 143Expected<const DWARFAbbreviationDeclarationSet *>144DWARFDebugAbbrev::getAbbreviationDeclarationSet(uint64_t CUAbbrOffset) const {145  const auto End = AbbrDeclSets.end();146  if (PrevAbbrOffsetPos != End && PrevAbbrOffsetPos->first == CUAbbrOffset) {147    return &PrevAbbrOffsetPos->second;148  }149 150  const auto Pos = AbbrDeclSets.find(CUAbbrOffset);151  if (Pos != End) {152    PrevAbbrOffsetPos = Pos;153    return &Pos->second;154  }155 156  if (!Data || CUAbbrOffset >= Data->getData().size())157    return make_error<llvm::object::GenericBinaryError>(158        "the abbreviation offset into the .debug_abbrev section is not valid");159 160  uint64_t Offset = CUAbbrOffset;161  DWARFAbbreviationDeclarationSet AbbrDecls;162  if (Error Err = AbbrDecls.extract(*Data, &Offset))163    return std::move(Err);164 165  PrevAbbrOffsetPos =166      AbbrDeclSets.insert(std::make_pair(CUAbbrOffset, std::move(AbbrDecls)))167          .first;168  return &PrevAbbrOffsetPos->second;169}170