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