Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/Support/ELFAttributeParser.cpp
35234 views
1
//===--- ELFAttributeParser.cpp - ELF Attribute Parser --------------------===//
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/Support/ELFAttributeParser.h"
10
#include "llvm/ADT/StringExtras.h"
11
#include "llvm/Support/Errc.h"
12
#include "llvm/Support/ScopedPrinter.h"
13
14
using namespace llvm;
15
using namespace llvm::ELFAttrs;
16
17
static constexpr EnumEntry<unsigned> tagNames[] = {
18
{"Tag_File", ELFAttrs::File},
19
{"Tag_Section", ELFAttrs::Section},
20
{"Tag_Symbol", ELFAttrs::Symbol},
21
};
22
23
Error ELFAttributeParser::parseStringAttribute(const char *name, unsigned tag,
24
ArrayRef<const char *> strings) {
25
uint64_t value = de.getULEB128(cursor);
26
if (value >= strings.size()) {
27
printAttribute(tag, value, "");
28
return createStringError(errc::invalid_argument,
29
"unknown " + Twine(name) +
30
" value: " + Twine(value));
31
}
32
printAttribute(tag, value, strings[value]);
33
return Error::success();
34
}
35
36
Error ELFAttributeParser::integerAttribute(unsigned tag) {
37
StringRef tagName =
38
ELFAttrs::attrTypeAsString(tag, tagToStringMap, /*hasTagPrefix=*/false);
39
uint64_t value = de.getULEB128(cursor);
40
attributes.insert(std::make_pair(tag, value));
41
42
if (sw) {
43
DictScope scope(*sw, "Attribute");
44
sw->printNumber("Tag", tag);
45
if (!tagName.empty())
46
sw->printString("TagName", tagName);
47
sw->printNumber("Value", value);
48
}
49
return Error::success();
50
}
51
52
Error ELFAttributeParser::stringAttribute(unsigned tag) {
53
StringRef tagName =
54
ELFAttrs::attrTypeAsString(tag, tagToStringMap, /*hasTagPrefix=*/false);
55
StringRef desc = de.getCStrRef(cursor);
56
setAttributeString(tag, desc);
57
58
if (sw) {
59
DictScope scope(*sw, "Attribute");
60
sw->printNumber("Tag", tag);
61
if (!tagName.empty())
62
sw->printString("TagName", tagName);
63
sw->printString("Value", desc);
64
}
65
return Error::success();
66
}
67
68
void ELFAttributeParser::printAttribute(unsigned tag, unsigned value,
69
StringRef valueDesc) {
70
attributes.insert(std::make_pair(tag, value));
71
72
if (sw) {
73
StringRef tagName = ELFAttrs::attrTypeAsString(tag, tagToStringMap,
74
/*hasTagPrefix=*/false);
75
DictScope as(*sw, "Attribute");
76
sw->printNumber("Tag", tag);
77
sw->printNumber("Value", value);
78
if (!tagName.empty())
79
sw->printString("TagName", tagName);
80
if (!valueDesc.empty())
81
sw->printString("Description", valueDesc);
82
}
83
}
84
85
void ELFAttributeParser::parseIndexList(SmallVectorImpl<uint8_t> &indexList) {
86
for (;;) {
87
uint64_t value = de.getULEB128(cursor);
88
if (!cursor || !value)
89
break;
90
indexList.push_back(value);
91
}
92
}
93
94
Error ELFAttributeParser::parseAttributeList(uint32_t length) {
95
uint64_t pos;
96
uint64_t end = cursor.tell() + length;
97
while ((pos = cursor.tell()) < end) {
98
uint64_t tag = de.getULEB128(cursor);
99
bool handled;
100
if (Error e = handler(tag, handled))
101
return e;
102
103
if (!handled) {
104
if (tag < 32) {
105
return createStringError(errc::invalid_argument,
106
"invalid tag 0x" + Twine::utohexstr(tag) +
107
" at offset 0x" + Twine::utohexstr(pos));
108
}
109
110
if (tag % 2 == 0) {
111
if (Error e = integerAttribute(tag))
112
return e;
113
} else {
114
if (Error e = stringAttribute(tag))
115
return e;
116
}
117
}
118
}
119
return Error::success();
120
}
121
122
Error ELFAttributeParser::parseSubsection(uint32_t length) {
123
uint64_t end = cursor.tell() - sizeof(length) + length;
124
StringRef vendorName = de.getCStrRef(cursor);
125
if (sw) {
126
sw->printNumber("SectionLength", length);
127
sw->printString("Vendor", vendorName);
128
}
129
130
// Handle a subsection with an unrecognized vendor-name by skipping
131
// over it to the next subsection. ADDENDA32 in the Arm ABI defines
132
// that vendor attribute sections must not affect compatibility, so
133
// this should always be safe.
134
if (vendorName.lower() != vendor) {
135
cursor.seek(end);
136
return Error::success();
137
}
138
139
while (cursor.tell() < end) {
140
/// Tag_File | Tag_Section | Tag_Symbol uleb128:byte-size
141
uint8_t tag = de.getU8(cursor);
142
uint32_t size = de.getU32(cursor);
143
if (!cursor)
144
return cursor.takeError();
145
146
if (sw) {
147
sw->printEnum("Tag", tag, ArrayRef(tagNames));
148
sw->printNumber("Size", size);
149
}
150
if (size < 5)
151
return createStringError(errc::invalid_argument,
152
"invalid attribute size " + Twine(size) +
153
" at offset 0x" +
154
Twine::utohexstr(cursor.tell() - 5));
155
156
StringRef scopeName, indexName;
157
SmallVector<uint8_t, 8> indices;
158
switch (tag) {
159
case ELFAttrs::File:
160
scopeName = "FileAttributes";
161
break;
162
case ELFAttrs::Section:
163
scopeName = "SectionAttributes";
164
indexName = "Sections";
165
parseIndexList(indices);
166
break;
167
case ELFAttrs::Symbol:
168
scopeName = "SymbolAttributes";
169
indexName = "Symbols";
170
parseIndexList(indices);
171
break;
172
default:
173
return createStringError(errc::invalid_argument,
174
"unrecognized tag 0x" + Twine::utohexstr(tag) +
175
" at offset 0x" +
176
Twine::utohexstr(cursor.tell() - 5));
177
}
178
179
if (sw) {
180
DictScope scope(*sw, scopeName);
181
if (!indices.empty())
182
sw->printList(indexName, indices);
183
if (Error e = parseAttributeList(size - 5))
184
return e;
185
} else if (Error e = parseAttributeList(size - 5))
186
return e;
187
}
188
return Error::success();
189
}
190
191
Error ELFAttributeParser::parse(ArrayRef<uint8_t> section,
192
llvm::endianness endian) {
193
unsigned sectionNumber = 0;
194
de = DataExtractor(section, endian == llvm::endianness::little, 0);
195
196
// For early returns, we have more specific errors, consume the Error in
197
// cursor.
198
struct ClearCursorError {
199
DataExtractor::Cursor &cursor;
200
~ClearCursorError() { consumeError(cursor.takeError()); }
201
} clear{cursor};
202
203
// Unrecognized format-version.
204
uint8_t formatVersion = de.getU8(cursor);
205
if (formatVersion != ELFAttrs::Format_Version)
206
return createStringError(errc::invalid_argument,
207
"unrecognized format-version: 0x" +
208
utohexstr(formatVersion));
209
210
while (!de.eof(cursor)) {
211
uint32_t sectionLength = de.getU32(cursor);
212
if (!cursor)
213
return cursor.takeError();
214
215
if (sw) {
216
sw->startLine() << "Section " << ++sectionNumber << " {\n";
217
sw->indent();
218
}
219
220
if (sectionLength < 4 || cursor.tell() - 4 + sectionLength > section.size())
221
return createStringError(errc::invalid_argument,
222
"invalid section length " +
223
Twine(sectionLength) + " at offset 0x" +
224
utohexstr(cursor.tell() - 4));
225
226
if (Error e = parseSubsection(sectionLength))
227
return e;
228
if (sw) {
229
sw->unindent();
230
sw->startLine() << "}\n";
231
}
232
}
233
234
return cursor.takeError();
235
}
236
237