Home | History | Annotate | Line # | Download | only in DWARF
      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-exception
      6 //
      7 //===----------------------------------------------------------------------===//
      8 
      9 #include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h"
     10 #include "llvm/Support/Format.h"
     11 #include "llvm/Support/raw_ostream.h"
     12 #include <algorithm>
     13 #include <cinttypes>
     14 #include <cstdint>
     15 
     16 using namespace llvm;
     17 
     18 DWARFAbbreviationDeclarationSet::DWARFAbbreviationDeclarationSet() {
     19   clear();
     20 }
     21 
     22 void DWARFAbbreviationDeclarationSet::clear() {
     23   Offset = 0;
     24   FirstAbbrCode = 0;
     25   Decls.clear();
     26 }
     27 
     28 bool DWARFAbbreviationDeclarationSet::extract(DataExtractor Data,
     29                                               uint64_t *OffsetPtr) {
     30   clear();
     31   const uint64_t BeginOffset = *OffsetPtr;
     32   Offset = BeginOffset;
     33   DWARFAbbreviationDeclaration AbbrDecl;
     34   uint32_t PrevAbbrCode = 0;
     35   while (AbbrDecl.extract(Data, OffsetPtr)) {
     36     if (FirstAbbrCode == 0) {
     37       FirstAbbrCode = AbbrDecl.getCode();
     38     } else {
     39       if (PrevAbbrCode + 1 != AbbrDecl.getCode()) {
     40         // Codes are not consecutive, can't do O(1) lookups.
     41         FirstAbbrCode = UINT32_MAX;
     42       }
     43     }
     44     PrevAbbrCode = AbbrDecl.getCode();
     45     Decls.push_back(std::move(AbbrDecl));
     46   }
     47   return BeginOffset != *OffsetPtr;
     48 }
     49 
     50 void DWARFAbbreviationDeclarationSet::dump(raw_ostream &OS) const {
     51   for (const auto &Decl : Decls)
     52     Decl.dump(OS);
     53 }
     54 
     55 const DWARFAbbreviationDeclaration *
     56 DWARFAbbreviationDeclarationSet::getAbbreviationDeclaration(
     57     uint32_t AbbrCode) const {
     58   if (FirstAbbrCode == UINT32_MAX) {
     59     for (const auto &Decl : Decls) {
     60       if (Decl.getCode() == AbbrCode)
     61         return &Decl;
     62     }
     63     return nullptr;
     64   }
     65   if (AbbrCode < FirstAbbrCode || AbbrCode >= FirstAbbrCode + Decls.size())
     66     return nullptr;
     67   return &Decls[AbbrCode - FirstAbbrCode];
     68 }
     69 
     70 DWARFDebugAbbrev::DWARFDebugAbbrev() { clear(); }
     71 
     72 void DWARFDebugAbbrev::clear() {
     73   AbbrDeclSets.clear();
     74   PrevAbbrOffsetPos = AbbrDeclSets.end();
     75 }
     76 
     77 void DWARFDebugAbbrev::extract(DataExtractor Data) {
     78   clear();
     79   this->Data = Data;
     80 }
     81 
     82 void DWARFDebugAbbrev::parse() const {
     83   if (!Data)
     84     return;
     85   uint64_t Offset = 0;
     86   auto I = AbbrDeclSets.begin();
     87   while (Data->isValidOffset(Offset)) {
     88     while (I != AbbrDeclSets.end() && I->first < Offset)
     89       ++I;
     90     uint64_t CUAbbrOffset = Offset;
     91     DWARFAbbreviationDeclarationSet AbbrDecls;
     92     if (!AbbrDecls.extract(*Data, &Offset))
     93       break;
     94     AbbrDeclSets.insert(I, std::make_pair(CUAbbrOffset, std::move(AbbrDecls)));
     95   }
     96   Data = None;
     97 }
     98 
     99 void DWARFDebugAbbrev::dump(raw_ostream &OS) const {
    100   parse();
    101 
    102   if (AbbrDeclSets.empty()) {
    103     OS << "< EMPTY >\n";
    104     return;
    105   }
    106 
    107   for (const auto &I : AbbrDeclSets) {
    108     OS << format("Abbrev table for offset: 0x%8.8" PRIx64 "\n", I.first);
    109     I.second.dump(OS);
    110   }
    111 }
    112 
    113 const DWARFAbbreviationDeclarationSet*
    114 DWARFDebugAbbrev::getAbbreviationDeclarationSet(uint64_t CUAbbrOffset) const {
    115   const auto End = AbbrDeclSets.end();
    116   if (PrevAbbrOffsetPos != End && PrevAbbrOffsetPos->first == CUAbbrOffset) {
    117     return &(PrevAbbrOffsetPos->second);
    118   }
    119 
    120   const auto Pos = AbbrDeclSets.find(CUAbbrOffset);
    121   if (Pos != End) {
    122     PrevAbbrOffsetPos = Pos;
    123     return &(Pos->second);
    124   }
    125 
    126   if (Data && CUAbbrOffset < Data->getData().size()) {
    127     uint64_t Offset = CUAbbrOffset;
    128     DWARFAbbreviationDeclarationSet AbbrDecls;
    129     if (!AbbrDecls.extract(*Data, &Offset))
    130       return nullptr;
    131     PrevAbbrOffsetPos =
    132         AbbrDeclSets.insert(std::make_pair(CUAbbrOffset, std::move(AbbrDecls)))
    133             .first;
    134     return &PrevAbbrOffsetPos->second;
    135   }
    136 
    137   return nullptr;
    138 }
    139