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