1581ba352SKai Wang //===--- ELFAttributeParser.cpp - ELF Attribute Parser --------------------===//
2581ba352SKai Wang //
3581ba352SKai Wang // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4581ba352SKai Wang // See https://llvm.org/LICENSE.txt for license information.
5581ba352SKai Wang // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6581ba352SKai Wang //
7581ba352SKai Wang //===----------------------------------------------------------------------===//
8581ba352SKai Wang
9581ba352SKai Wang #include "llvm/Support/ELFAttributeParser.h"
10581ba352SKai Wang #include "llvm/ADT/StringExtras.h"
11581ba352SKai Wang #include "llvm/Support/Errc.h"
12581ba352SKai Wang #include "llvm/Support/ScopedPrinter.h"
13581ba352SKai Wang
14581ba352SKai Wang using namespace llvm;
15581ba352SKai Wang using namespace llvm::ELFAttrs;
16581ba352SKai Wang
1776374573SMehdi Amini static constexpr EnumEntry<unsigned> tagNames[] = {
18581ba352SKai Wang {"Tag_File", ELFAttrs::File},
19581ba352SKai Wang {"Tag_Section", ELFAttrs::Section},
20581ba352SKai Wang {"Tag_Symbol", ELFAttrs::Symbol},
21581ba352SKai Wang };
22581ba352SKai Wang
parseStringAttribute(const char * name,unsigned tag,ArrayRef<const char * > strings)23581ba352SKai Wang Error ELFAttributeParser::parseStringAttribute(const char *name, unsigned tag,
24581ba352SKai Wang ArrayRef<const char *> strings) {
25581ba352SKai Wang uint64_t value = de.getULEB128(cursor);
26581ba352SKai Wang if (value >= strings.size()) {
27581ba352SKai Wang printAttribute(tag, value, "");
28581ba352SKai Wang return createStringError(errc::invalid_argument,
29581ba352SKai Wang "unknown " + Twine(name) +
30581ba352SKai Wang " value: " + Twine(value));
31581ba352SKai Wang }
32581ba352SKai Wang printAttribute(tag, value, strings[value]);
33581ba352SKai Wang return Error::success();
34581ba352SKai Wang }
35581ba352SKai Wang
integerAttribute(unsigned tag)36581ba352SKai Wang Error ELFAttributeParser::integerAttribute(unsigned tag) {
37581ba352SKai Wang StringRef tagName =
38581ba352SKai Wang ELFAttrs::attrTypeAsString(tag, tagToStringMap, /*hasTagPrefix=*/false);
39581ba352SKai Wang uint64_t value = de.getULEB128(cursor);
40581ba352SKai Wang attributes.insert(std::make_pair(tag, value));
41581ba352SKai Wang
42581ba352SKai Wang if (sw) {
43581ba352SKai Wang DictScope scope(*sw, "Attribute");
44581ba352SKai Wang sw->printNumber("Tag", tag);
45581ba352SKai Wang if (!tagName.empty())
46581ba352SKai Wang sw->printString("TagName", tagName);
47581ba352SKai Wang sw->printNumber("Value", value);
48581ba352SKai Wang }
49581ba352SKai Wang return Error::success();
50581ba352SKai Wang }
51581ba352SKai Wang
stringAttribute(unsigned tag)52581ba352SKai Wang Error ELFAttributeParser::stringAttribute(unsigned tag) {
53581ba352SKai Wang StringRef tagName =
54581ba352SKai Wang ELFAttrs::attrTypeAsString(tag, tagToStringMap, /*hasTagPrefix=*/false);
55581ba352SKai Wang StringRef desc = de.getCStrRef(cursor);
561d66c5ebSVictor Campos setAttributeString(tag, desc);
57581ba352SKai Wang
58581ba352SKai Wang if (sw) {
59581ba352SKai Wang DictScope scope(*sw, "Attribute");
60581ba352SKai Wang sw->printNumber("Tag", tag);
61581ba352SKai Wang if (!tagName.empty())
62581ba352SKai Wang sw->printString("TagName", tagName);
63581ba352SKai Wang sw->printString("Value", desc);
64581ba352SKai Wang }
65581ba352SKai Wang return Error::success();
66581ba352SKai Wang }
67581ba352SKai Wang
printAttribute(unsigned tag,unsigned value,StringRef valueDesc)68581ba352SKai Wang void ELFAttributeParser::printAttribute(unsigned tag, unsigned value,
69581ba352SKai Wang StringRef valueDesc) {
70581ba352SKai Wang attributes.insert(std::make_pair(tag, value));
71581ba352SKai Wang
72581ba352SKai Wang if (sw) {
73581ba352SKai Wang StringRef tagName = ELFAttrs::attrTypeAsString(tag, tagToStringMap,
74581ba352SKai Wang /*hasTagPrefix=*/false);
75581ba352SKai Wang DictScope as(*sw, "Attribute");
76581ba352SKai Wang sw->printNumber("Tag", tag);
77581ba352SKai Wang sw->printNumber("Value", value);
78581ba352SKai Wang if (!tagName.empty())
79581ba352SKai Wang sw->printString("TagName", tagName);
80581ba352SKai Wang if (!valueDesc.empty())
81581ba352SKai Wang sw->printString("Description", valueDesc);
82581ba352SKai Wang }
83581ba352SKai Wang }
84581ba352SKai Wang
parseIndexList(SmallVectorImpl<uint8_t> & indexList)85581ba352SKai Wang void ELFAttributeParser::parseIndexList(SmallVectorImpl<uint8_t> &indexList) {
86581ba352SKai Wang for (;;) {
87581ba352SKai Wang uint64_t value = de.getULEB128(cursor);
88581ba352SKai Wang if (!cursor || !value)
89581ba352SKai Wang break;
90581ba352SKai Wang indexList.push_back(value);
91581ba352SKai Wang }
92581ba352SKai Wang }
93581ba352SKai Wang
parseAttributeList(uint32_t length)94581ba352SKai Wang Error ELFAttributeParser::parseAttributeList(uint32_t length) {
95581ba352SKai Wang uint64_t pos;
96581ba352SKai Wang uint64_t end = cursor.tell() + length;
97581ba352SKai Wang while ((pos = cursor.tell()) < end) {
98581ba352SKai Wang uint64_t tag = de.getULEB128(cursor);
99581ba352SKai Wang bool handled;
100581ba352SKai Wang if (Error e = handler(tag, handled))
101581ba352SKai Wang return e;
102581ba352SKai Wang
103581ba352SKai Wang if (!handled) {
104581ba352SKai Wang if (tag < 32) {
105581ba352SKai Wang return createStringError(errc::invalid_argument,
106581ba352SKai Wang "invalid tag 0x" + Twine::utohexstr(tag) +
107581ba352SKai Wang " at offset 0x" + Twine::utohexstr(pos));
108581ba352SKai Wang }
109581ba352SKai Wang
110581ba352SKai Wang if (tag % 2 == 0) {
111581ba352SKai Wang if (Error e = integerAttribute(tag))
112581ba352SKai Wang return e;
113581ba352SKai Wang } else {
114581ba352SKai Wang if (Error e = stringAttribute(tag))
115581ba352SKai Wang return e;
116581ba352SKai Wang }
117581ba352SKai Wang }
118581ba352SKai Wang }
119581ba352SKai Wang return Error::success();
120581ba352SKai Wang }
121581ba352SKai Wang
parseSubsection(uint32_t length)122581ba352SKai Wang Error ELFAttributeParser::parseSubsection(uint32_t length) {
123581ba352SKai Wang uint64_t end = cursor.tell() - sizeof(length) + length;
124581ba352SKai Wang StringRef vendorName = de.getCStrRef(cursor);
125581ba352SKai Wang if (sw) {
126581ba352SKai Wang sw->printNumber("SectionLength", length);
127581ba352SKai Wang sw->printString("Vendor", vendorName);
128581ba352SKai Wang }
129581ba352SKai Wang
130cb1d6ea8SSimon Tatham // Handle a subsection with an unrecognized vendor-name by skipping
131cb1d6ea8SSimon Tatham // over it to the next subsection. ADDENDA32 in the Arm ABI defines
132cb1d6ea8SSimon Tatham // that vendor attribute sections must not affect compatibility, so
133cb1d6ea8SSimon Tatham // this should always be safe.
134cb1d6ea8SSimon Tatham if (vendorName.lower() != vendor) {
135cb1d6ea8SSimon Tatham cursor.seek(end);
136cb1d6ea8SSimon Tatham return Error::success();
137cb1d6ea8SSimon Tatham }
138581ba352SKai Wang
139581ba352SKai Wang while (cursor.tell() < end) {
140581ba352SKai Wang /// Tag_File | Tag_Section | Tag_Symbol uleb128:byte-size
141581ba352SKai Wang uint8_t tag = de.getU8(cursor);
142581ba352SKai Wang uint32_t size = de.getU32(cursor);
143581ba352SKai Wang if (!cursor)
144581ba352SKai Wang return cursor.takeError();
145581ba352SKai Wang
146581ba352SKai Wang if (sw) {
14738818b60Sserge-sans-paille sw->printEnum("Tag", tag, ArrayRef(tagNames));
148581ba352SKai Wang sw->printNumber("Size", size);
149581ba352SKai Wang }
150581ba352SKai Wang if (size < 5)
151581ba352SKai Wang return createStringError(errc::invalid_argument,
152581ba352SKai Wang "invalid attribute size " + Twine(size) +
153581ba352SKai Wang " at offset 0x" +
154581ba352SKai Wang Twine::utohexstr(cursor.tell() - 5));
155581ba352SKai Wang
156581ba352SKai Wang StringRef scopeName, indexName;
157*1650f1b3SJay Foad SmallVector<uint8_t, 8> indices;
158581ba352SKai Wang switch (tag) {
159581ba352SKai Wang case ELFAttrs::File:
160581ba352SKai Wang scopeName = "FileAttributes";
161581ba352SKai Wang break;
162581ba352SKai Wang case ELFAttrs::Section:
163581ba352SKai Wang scopeName = "SectionAttributes";
164581ba352SKai Wang indexName = "Sections";
165*1650f1b3SJay Foad parseIndexList(indices);
166581ba352SKai Wang break;
167581ba352SKai Wang case ELFAttrs::Symbol:
168581ba352SKai Wang scopeName = "SymbolAttributes";
169581ba352SKai Wang indexName = "Symbols";
170*1650f1b3SJay Foad parseIndexList(indices);
171581ba352SKai Wang break;
172581ba352SKai Wang default:
173581ba352SKai Wang return createStringError(errc::invalid_argument,
174581ba352SKai Wang "unrecognized tag 0x" + Twine::utohexstr(tag) +
175581ba352SKai Wang " at offset 0x" +
176581ba352SKai Wang Twine::utohexstr(cursor.tell() - 5));
177581ba352SKai Wang }
178581ba352SKai Wang
179581ba352SKai Wang if (sw) {
180581ba352SKai Wang DictScope scope(*sw, scopeName);
181*1650f1b3SJay Foad if (!indices.empty())
182*1650f1b3SJay Foad sw->printList(indexName, indices);
183581ba352SKai Wang if (Error e = parseAttributeList(size - 5))
184581ba352SKai Wang return e;
185581ba352SKai Wang } else if (Error e = parseAttributeList(size - 5))
186581ba352SKai Wang return e;
187581ba352SKai Wang }
188581ba352SKai Wang return Error::success();
189581ba352SKai Wang }
190581ba352SKai Wang
parse(ArrayRef<uint8_t> section,llvm::endianness endian)191581ba352SKai Wang Error ELFAttributeParser::parse(ArrayRef<uint8_t> section,
192a9d50568SKazu Hirata llvm::endianness endian) {
193581ba352SKai Wang unsigned sectionNumber = 0;
1944a0ccfa8SKazu Hirata de = DataExtractor(section, endian == llvm::endianness::little, 0);
195581ba352SKai Wang
196581ba352SKai Wang // For early returns, we have more specific errors, consume the Error in
197581ba352SKai Wang // cursor.
198581ba352SKai Wang struct ClearCursorError {
199581ba352SKai Wang DataExtractor::Cursor &cursor;
200581ba352SKai Wang ~ClearCursorError() { consumeError(cursor.takeError()); }
201581ba352SKai Wang } clear{cursor};
202581ba352SKai Wang
203581ba352SKai Wang // Unrecognized format-version.
204581ba352SKai Wang uint8_t formatVersion = de.getU8(cursor);
205137a25f0SGeorgii Rymar if (formatVersion != ELFAttrs::Format_Version)
206581ba352SKai Wang return createStringError(errc::invalid_argument,
207581ba352SKai Wang "unrecognized format-version: 0x" +
208581ba352SKai Wang utohexstr(formatVersion));
209581ba352SKai Wang
210581ba352SKai Wang while (!de.eof(cursor)) {
211581ba352SKai Wang uint32_t sectionLength = de.getU32(cursor);
212581ba352SKai Wang if (!cursor)
213581ba352SKai Wang return cursor.takeError();
214581ba352SKai Wang
215581ba352SKai Wang if (sw) {
216581ba352SKai Wang sw->startLine() << "Section " << ++sectionNumber << " {\n";
217581ba352SKai Wang sw->indent();
218581ba352SKai Wang }
219581ba352SKai Wang
220581ba352SKai Wang if (sectionLength < 4 || cursor.tell() - 4 + sectionLength > section.size())
221581ba352SKai Wang return createStringError(errc::invalid_argument,
222501522b5SKai Wang "invalid section length " +
223581ba352SKai Wang Twine(sectionLength) + " at offset 0x" +
224581ba352SKai Wang utohexstr(cursor.tell() - 4));
225581ba352SKai Wang
226581ba352SKai Wang if (Error e = parseSubsection(sectionLength))
227581ba352SKai Wang return e;
228581ba352SKai Wang if (sw) {
229581ba352SKai Wang sw->unindent();
230581ba352SKai Wang sw->startLine() << "}\n";
231581ba352SKai Wang }
232581ba352SKai Wang }
233581ba352SKai Wang
234581ba352SKai Wang return cursor.takeError();
235581ba352SKai Wang }
236