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