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