LLVM 23.0.0git
ELFAttrParserCompact.cpp
Go to the documentation of this file.
1//===--- ELFCompactAttrParser.cpp - ELF Compact 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// ELF Compact Attribute Parser parse ELF build atrributes that are held
8// in a single Build Attributes Subsection.
9//
10//===--------------------------------------------------------------------===//
11
13#include "llvm/ADT/Enum.h"
15#include "llvm/Support/Errc.h"
17
18using namespace llvm;
19using namespace llvm::ELFAttrs;
20
22 const char *name, unsigned tag, ArrayRef<const char *> strings) {
23 uint64_t value = de.getULEB128(cursor);
24 if (value >= strings.size()) {
25 printAttribute(tag, value, "");
27 "unknown " + Twine(name) +
28 " value: " + Twine(value));
29 }
30 printAttribute(tag, value, strings[value]);
31 return Error::success();
32}
33
35 StringRef tagName =
36 ELFAttrs::attrTypeAsString(tag, tagToStringMap, /*hasTagPrefix=*/false);
37 uint64_t value = de.getULEB128(cursor);
38 attributes.insert(std::make_pair(tag, value));
39
40 if (sw) {
41 DictScope scope(*sw, "Attribute");
42 sw->printNumber("Tag", tag);
43 if (!tagName.empty())
44 sw->printString("TagName", tagName);
45 sw->printNumber("Value", value);
46 }
47 return Error::success();
48}
49
51 StringRef tagName =
52 ELFAttrs::attrTypeAsString(tag, tagToStringMap, /*hasTagPrefix=*/false);
53 StringRef desc = de.getCStrRef(cursor);
54 setAttributeString(tag, desc);
55
56 if (sw) {
57 DictScope scope(*sw, "Attribute");
58 sw->printNumber("Tag", tag);
59 if (!tagName.empty())
60 sw->printString("TagName", tagName);
61 sw->printString("Value", desc);
62 }
63 return Error::success();
64}
65
66void ELFCompactAttrParser::printAttribute(unsigned tag, unsigned value,
67 StringRef valueDesc) {
68 attributes.insert(std::make_pair(tag, value));
69
70 if (sw) {
72 /*hasTagPrefix=*/false);
73 DictScope as(*sw, "Attribute");
74 sw->printNumber("Tag", tag);
75 sw->printNumber("Value", value);
76 if (!tagName.empty())
77 sw->printString("TagName", tagName);
78 if (!valueDesc.empty())
79 sw->printString("Description", valueDesc);
80 }
81}
82
84 for (;;) {
85 uint64_t value = de.getULEB128(cursor);
86 if (!cursor || !value)
87 break;
88 indexList.push_back(value);
89 }
90}
91
93 uint64_t pos;
94 uint64_t end = cursor.tell() + length;
95 while ((pos = cursor.tell()) < end) {
96 uint64_t tag = de.getULEB128(cursor);
97 bool handled;
98 if (Error e = handler(tag, handled))
99 return e;
100
101 if (!handled) {
102 if (tag < 32) {
104 "invalid tag 0x" + Twine::utohexstr(tag) +
105 " at offset 0x" + Twine::utohexstr(pos));
106 }
107
108 if (tag % 2 == 0) {
109 if (Error e = integerAttribute(tag))
110 return e;
111 } else {
112 if (Error e = stringAttribute(tag))
113 return e;
114 }
115 }
116 }
117 return Error::success();
118}
119
121 uint64_t end = cursor.tell() - sizeof(length) + length;
122 StringRef vendorName = de.getCStrRef(cursor);
123 if (sw) {
124 sw->printNumber("SectionLength", length);
125 sw->printString("Vendor", vendorName);
126 }
127
128 // Handle a subsection with an unrecognized vendor-name by skipping
129 // over it to the next subsection. ADDENDA32 in the Arm ABI defines
130 // that vendor attribute sections must not affect compatibility, so
131 // this should always be safe.
132 if (vendorName.lower() != vendor) {
133 cursor.seek(end);
134 return Error::success();
135 }
136
137 while (cursor.tell() < end) {
138 /// Tag_File | Tag_Section | Tag_Symbol uleb128:byte-size
139 uint8_t tag = de.getU8(cursor);
140 uint32_t size = de.getU32(cursor);
141 if (!cursor)
142 return cursor.takeError();
143
144 if (sw) {
145 constexpr EnumStringDef<unsigned> TagNameDefs[] = {
146 {{"Tag_File"}, ELFAttrs::File},
147 {{"Tag_Section"}, ELFAttrs::Section},
148 {{"Tag_Symbol"}, ELFAttrs::Symbol},
149 };
150 static constexpr auto TagNames = BUILD_ENUM_STRINGS(TagNameDefs);
151
152 sw->printEnum("Tag", tag, EnumStrings(TagNames));
153 sw->printNumber("Size", size);
154 }
155 if (size < 5)
157 "invalid attribute size " + Twine(size) +
158 " at offset 0x" +
159 Twine::utohexstr(cursor.tell() - 5));
160
161 StringRef scopeName, indexName;
163 switch (tag) {
164 case ELFAttrs::File:
165 scopeName = "FileAttributes";
166 break;
168 scopeName = "SectionAttributes";
169 indexName = "Sections";
170 parseIndexList(indices);
171 break;
172 case ELFAttrs::Symbol:
173 scopeName = "SymbolAttributes";
174 indexName = "Symbols";
175 parseIndexList(indices);
176 break;
177 default:
179 "unrecognized tag 0x" + Twine::utohexstr(tag) +
180 " at offset 0x" +
181 Twine::utohexstr(cursor.tell() - 5));
182 }
183
184 if (sw) {
185 DictScope scope(*sw, scopeName);
186 if (!indices.empty())
187 sw->printList(indexName, indices);
188 if (Error e = parseAttributeList(size - 5))
189 return e;
190 } else if (Error e = parseAttributeList(size - 5))
191 return e;
192 }
193 return Error::success();
194}
195
198 unsigned sectionNumber = 0;
200
201 // For early returns, we have more specific errors, consume the Error in
202 // cursor.
203 struct ClearCursorError {
205 ~ClearCursorError() { consumeError(cursor.takeError()); }
206 } clear{cursor};
207
208 // Unrecognized format-version.
209 uint8_t formatVersion = de.getU8(cursor);
210 if (formatVersion != ELFAttrs::Format_Version)
212 "unrecognized format-version: 0x" +
213 utohexstr(formatVersion));
214
215 while (!de.eof(cursor)) {
216 uint32_t sectionLength = de.getU32(cursor);
217 if (!cursor)
218 return cursor.takeError();
219
220 if (sw) {
221 sw->startLine() << "Section " << ++sectionNumber << " {\n";
222 sw->indent();
223 }
224
225 if (sectionLength < 4 || cursor.tell() - 4 + sectionLength > section.size())
227 "invalid section length " +
228 Twine(sectionLength) + " at offset 0x" +
229 utohexstr(cursor.tell() - 4));
230
231 if (Error e = parseSubsection(sectionLength))
232 return e;
233 if (sw) {
234 sw->unindent();
235 sw->startLine() << "}\n";
236 }
237 }
238
239 return cursor.takeError();
240}
#define BUILD_ENUM_STRINGS(Tab)
Definition Enum.h:120
static const char * name
This file contains some functions that are useful when dealing with strings.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
size_t size() const
Get the array size.
Definition ArrayRef.h:141
A class representing a position in a DataExtractor, as well as any error encountered during extractio...
void setAttributeString(unsigned tag, StringRef value)
void parseIndexList(SmallVectorImpl< uint8_t > &indexList)
Error parseAttributeList(uint32_t length)
void printAttribute(unsigned tag, unsigned value, StringRef valueDesc)
Error parseSubsection(uint32_t length)
Error parse(ArrayRef< uint8_t > section, llvm::endianness endian) override
Error parseStringAttribute(const char *name, unsigned tag, ArrayRef< const char * > strings)
Lightweight error class with error context and mandatory checking.
Definition Error.h:159
static ErrorSuccess success()
Create a success value.
Definition Error.h:336
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
constexpr bool empty() const
Check if the string is empty.
Definition StringRef.h:141
LLVM_ABI std::string lower() const
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition Twine.h:82
static Twine utohexstr(uint64_t Val)
Definition Twine.h:385
LLVM_ABI StringRef attrTypeAsString(unsigned attr, TagNameMap tagNameMap, bool hasTagPrefix=true)
This is an optimization pass for GlobalISel generic memory operations.
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
Definition STLExtras.h:1669
std::string utohexstr(uint64_t X, bool LowerCase=false, unsigned Width=0)
EnumStrings(const EnumStringsStorage< T, NumStrs, N, StrLen > &) -> EnumStrings< T, NumStrs >
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
Definition Error.h:1321
@ invalid_argument
Definition Errc.h:56
endianness
Definition bit.h:71
void consumeError(Error Err)
Consume a Error without doing anything.
Definition Error.h:1106
Compile-time data representation of enum entries.
Definition Enum.h:47