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 using namespace llvm;
14 
DWARFAbbreviationDeclarationSet()15 DWARFAbbreviationDeclarationSet::DWARFAbbreviationDeclarationSet() {
16   clear();
17 }
18 
clear()19 void DWARFAbbreviationDeclarationSet::clear() {
20   Offset = 0;
21   FirstAbbrCode = 0;
22   Decls.clear();
23 }
24 
extract(DataExtractor Data,uint32_t * OffsetPtr)25 bool DWARFAbbreviationDeclarationSet::extract(DataExtractor Data,
26                                               uint32_t *OffsetPtr) {
27   clear();
28   const uint32_t BeginOffset = *OffsetPtr;
29   Offset = BeginOffset;
30   DWARFAbbreviationDeclaration AbbrDecl;
31   uint32_t PrevAbbrCode = 0;
32   while (AbbrDecl.extract(Data, OffsetPtr)) {
33     if (FirstAbbrCode == 0) {
34       FirstAbbrCode = AbbrDecl.getCode();
35     } else {
36       if (PrevAbbrCode + 1 != AbbrDecl.getCode()) {
37         // Codes are not consecutive, can't do O(1) lookups.
38         FirstAbbrCode = UINT32_MAX;
39       }
40     }
41     PrevAbbrCode = AbbrDecl.getCode();
42     Decls.push_back(std::move(AbbrDecl));
43   }
44   return BeginOffset != *OffsetPtr;
45 }
46 
dump(raw_ostream & OS) const47 void DWARFAbbreviationDeclarationSet::dump(raw_ostream &OS) const {
48   for (const auto &Decl : Decls)
49     Decl.dump(OS);
50 }
51 
52 const DWARFAbbreviationDeclaration *
getAbbreviationDeclaration(uint32_t AbbrCode) const53 DWARFAbbreviationDeclarationSet::getAbbreviationDeclaration(
54     uint32_t AbbrCode) const {
55   if (FirstAbbrCode == UINT32_MAX) {
56     for (const auto &Decl : Decls) {
57       if (Decl.getCode() == AbbrCode)
58         return &Decl;
59     }
60     return nullptr;
61   }
62   if (AbbrCode < FirstAbbrCode || AbbrCode >= FirstAbbrCode + Decls.size())
63     return nullptr;
64   return &Decls[AbbrCode - FirstAbbrCode];
65 }
66 
DWARFDebugAbbrev()67 DWARFDebugAbbrev::DWARFDebugAbbrev() {
68   clear();
69 }
70 
clear()71 void DWARFDebugAbbrev::clear() {
72   AbbrDeclSets.clear();
73   PrevAbbrOffsetPos = AbbrDeclSets.end();
74 }
75 
extract(DataExtractor Data)76 void DWARFDebugAbbrev::extract(DataExtractor Data) {
77   clear();
78 
79   uint32_t Offset = 0;
80   DWARFAbbreviationDeclarationSet AbbrDecls;
81   while (Data.isValidOffset(Offset)) {
82     uint32_t CUAbbrOffset = Offset;
83     if (!AbbrDecls.extract(Data, &Offset))
84       break;
85     AbbrDeclSets[CUAbbrOffset] = std::move(AbbrDecls);
86   }
87 }
88 
dump(raw_ostream & OS) const89 void DWARFDebugAbbrev::dump(raw_ostream &OS) const {
90   if (AbbrDeclSets.empty()) {
91     OS << "< EMPTY >\n";
92     return;
93   }
94 
95   for (const auto &I : AbbrDeclSets) {
96     OS << format("Abbrev table for offset: 0x%8.8" PRIx64 "\n", I.first);
97     I.second.dump(OS);
98   }
99 }
100 
101 const DWARFAbbreviationDeclarationSet*
getAbbreviationDeclarationSet(uint64_t CUAbbrOffset) const102 DWARFDebugAbbrev::getAbbreviationDeclarationSet(uint64_t CUAbbrOffset) const {
103   const auto End = AbbrDeclSets.end();
104   if (PrevAbbrOffsetPos != End && PrevAbbrOffsetPos->first == CUAbbrOffset) {
105     return &(PrevAbbrOffsetPos->second);
106   }
107 
108   const auto Pos = AbbrDeclSets.find(CUAbbrOffset);
109   if (Pos != End) {
110     PrevAbbrOffsetPos = Pos;
111     return &(Pos->second);
112   }
113 
114   return nullptr;
115 }
116