LLVM 17.0.0git
ELFAttributeParser.cpp
Go to the documentation of this file.
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
11#include "llvm/Support/Errc.h"
13
14using namespace llvm;
15using namespace llvm::ELFAttrs;
16
17static constexpr EnumEntry<unsigned> tagNames[] = {
18 {"Tag_File", ELFAttrs::File},
19 {"Tag_Section", ELFAttrs::Section},
20 {"Tag_Symbol", ELFAttrs::Symbol},
21};
22
24 ArrayRef<const char *> strings) {
26 if (value >= strings.size()) {
27 printAttribute(tag, value, "");
29 "unknown " + Twine(name) +
30 " value: " + Twine(value));
31 }
32 printAttribute(tag, value, strings[value]);
33 return Error::success();
34}
35
37 StringRef tagName =
38 ELFAttrs::attrTypeAsString(tag, tagToStringMap, /*hasTagPrefix=*/false);
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
53 StringRef tagName =
54 ELFAttrs::attrTypeAsString(tag, tagToStringMap, /*hasTagPrefix=*/false);
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
68void ELFAttributeParser::printAttribute(unsigned tag, unsigned value,
69 StringRef valueDesc) {
70 attributes.insert(std::make_pair(tag, value));
71
72 if (sw) {
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
86 for (;;) {
88 if (!cursor || !value)
89 break;
90 indexList.push_back(value);
91 }
92}
93
95 uint64_t pos;
96 uint64_t end = cursor.tell() + length;
97 while ((pos = cursor.tell()) < end) {
99 bool handled;
100 if (Error e = handler(tag, handled))
101 return e;
102
103 if (!handled) {
104 if (tag < 32) {
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
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 // Ignore unrecognized vendor-name.
131 if (vendorName.lower() != vendor)
133 "unrecognized vendor-name: " + vendorName);
134
135 while (cursor.tell() < end) {
136 /// Tag_File | Tag_Section | Tag_Symbol uleb128:byte-size
137 uint8_t tag = de.getU8(cursor);
139 if (!cursor)
140 return cursor.takeError();
141
142 if (sw) {
143 sw->printEnum("Tag", tag, ArrayRef(tagNames));
144 sw->printNumber("Size", size);
145 }
146 if (size < 5)
148 "invalid attribute size " + Twine(size) +
149 " at offset 0x" +
151
152 StringRef scopeName, indexName;
154 switch (tag) {
155 case ELFAttrs::File:
156 scopeName = "FileAttributes";
157 break;
159 scopeName = "SectionAttributes";
160 indexName = "Sections";
161 parseIndexList(indicies);
162 break;
163 case ELFAttrs::Symbol:
164 scopeName = "SymbolAttributes";
165 indexName = "Symbols";
166 parseIndexList(indicies);
167 break;
168 default:
170 "unrecognized tag 0x" + Twine::utohexstr(tag) +
171 " at offset 0x" +
173 }
174
175 if (sw) {
176 DictScope scope(*sw, scopeName);
177 if (!indicies.empty())
178 sw->printList(indexName, indicies);
179 if (Error e = parseAttributeList(size - 5))
180 return e;
181 } else if (Error e = parseAttributeList(size - 5))
182 return e;
183 }
184 return Error::success();
185}
186
189 unsigned sectionNumber = 0;
190 de = DataExtractor(section, endian == support::little, 0);
191
192 // For early returns, we have more specific errors, consume the Error in
193 // cursor.
194 struct ClearCursorError {
195 DataExtractor::Cursor &cursor;
196 ~ClearCursorError() { consumeError(cursor.takeError()); }
197 } clear{cursor};
198
199 // Unrecognized format-version.
200 uint8_t formatVersion = de.getU8(cursor);
201 if (formatVersion != ELFAttrs::Format_Version)
203 "unrecognized format-version: 0x" +
204 utohexstr(formatVersion));
205
206 while (!de.eof(cursor)) {
207 uint32_t sectionLength = de.getU32(cursor);
208 if (!cursor)
209 return cursor.takeError();
210
211 if (sw) {
212 sw->startLine() << "Section " << ++sectionNumber << " {\n";
213 sw->indent();
214 }
215
216 if (sectionLength < 4 || cursor.tell() - 4 + sectionLength > section.size())
218 "invalid section length " +
219 Twine(sectionLength) + " at offset 0x" +
220 utohexstr(cursor.tell() - 4));
221
222 if (Error e = parseSubsection(sectionLength))
223 return e;
224 if (sw) {
225 sw->unindent();
226 sw->startLine() << "}\n";
227 }
228 }
229
230 return cursor.takeError();
231}
static void clear(coro::Shape &Shape)
Definition: Coroutines.cpp:149
Given that RA is a live value
static constexpr EnumEntry< unsigned > tagNames[]
static const char * name
Definition: SMEABIPass.cpp:49
This file contains some functions that are useful when dealing with strings.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: ArrayRef.h:41
size_t size() const
size - Get the array size.
Definition: ArrayRef.h:163
A class representing a position in a DataExtractor, as well as any error encountered during extractio...
Definition: DataExtractor.h:54
uint64_t tell() const
Return the current position of this Cursor.
Definition: DataExtractor.h:71
Error takeError()
Return error contained inside this Cursor, if any.
Definition: DataExtractor.h:78
uint32_t getU32(uint64_t *offset_ptr, Error *Err=nullptr) const
Extract a uint32_t value from *offset_ptr.
bool eof(const Cursor &C) const
Return true iff the cursor is at the end of the buffer, regardless of the error state of the cursor.
StringRef getCStrRef(uint64_t *OffsetPtr, Error *Err=nullptr) const
Extract a C string from *offset_ptr.
uint8_t getU8(uint64_t *offset_ptr, Error *Err=nullptr) const
Extract a uint8_t value from *offset_ptr.
uint64_t getULEB128(uint64_t *offset_ptr, llvm::Error *Err=nullptr) const
Extract a unsigned LEB128 value from *offset_ptr.
void setAttributeString(unsigned tag, StringRef value)
Error parseSubsection(uint32_t length)
Error parse(ArrayRef< uint8_t > section, support::endianness endian)
Error integerAttribute(unsigned tag)
DataExtractor::Cursor cursor
Error stringAttribute(unsigned tag)
void parseIndexList(SmallVectorImpl< uint8_t > &indexList)
Error parseStringAttribute(const char *name, unsigned tag, ArrayRef< const char * > strings)
void printAttribute(unsigned tag, unsigned value, StringRef valueDesc)
Error parseAttributeList(uint32_t length)
Lightweight error class with error context and mandatory checking.
Definition: Error.h:156
static ErrorSuccess success()
Create a success value.
Definition: Error.h:330
virtual void printString(StringRef Value)
void indent(int Levels=1)
void unindent(int Levels=1)
void printEnum(StringRef Label, T Value, ArrayRef< EnumEntry< TEnum > > EnumValues)
virtual raw_ostream & startLine()
virtual void printNumber(StringRef Label, char Value)
void printList(StringRef Label, const ArrayRef< T > List)
bool empty() const
Definition: SmallVector.h:94
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: SmallVector.h:577
void push_back(const T &Elt)
Definition: SmallVector.h:416
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1200
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
constexpr bool empty() const
empty - Check if the string is empty.
Definition: StringRef.h:134
std::string lower() const
Definition: StringRef.cpp:111
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:81
static Twine utohexstr(const uint64_t &Val)
Definition: Twine.h:404
StringRef attrTypeAsString(unsigned attr, TagNameMap tagNameMap, bool hasTagPrefix=true)
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
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:1777
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
Definition: Error.h:1246
void consumeError(Error Err)
Consume a Error without doing anything.
Definition: Error.h:1043