LLVM 22.0.0git
ELFAttrParserExtended.cpp
Go to the documentation of this file.
1//===-ELFAttrParserExtended.cpp-ELF Extended Attribute Information Printer-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM
4// Exceptions.
5// See https://llvm.org/LICENSE.txt for license information.
6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7//
8//===------------------------------------------------------------------===//
9
12#include "llvm/ADT/StringRef.h"
14#include "llvm/Support/Errc.h"
15#include "llvm/Support/Error.h"
18#include <cstdint>
19
20using namespace llvm;
21using namespace ELFAttrs;
22
23std::optional<unsigned>
25 assert(
26 0 &&
27 "use getAttributeValue overloaded version accepting Stringref, unsigned");
28 return std::nullopt;
29}
30
31std::optional<unsigned>
33 unsigned Tag) const {
34 for (const auto &SubSection : SubSectionVec) {
35 if (BuildAttrSubsectionName == SubSection.Name)
36 for (const auto &BAItem : SubSection.Content) {
37 if (Tag == BAItem.Tag)
38 return std::optional<unsigned>(BAItem.IntValue);
39 }
40 }
41 return std::nullopt;
42}
43
44std::optional<StringRef>
46 assert(
47 0 &&
48 "use getAttributeValue overloaded version accepting Stringref, unsigned");
49 return std::nullopt;
50}
51
52std::optional<StringRef>
54 unsigned Tag) const {
55 for (const auto &SubSection : SubSectionVec) {
56 if (BuildAttrSubsectionName == SubSection.Name)
57 for (const auto &BAItem : SubSection.Content) {
58 if (Tag == BAItem.Tag)
59 return std::optional<StringRef>(BAItem.StringValue);
60 }
61 }
62 return std::nullopt;
63}
64
66ELFExtendedAttrParser::getTagName(const StringRef &BuildAttrSubsectionName,
67 const unsigned Tag) {
68 for (const auto &Entry : TagsNamesMap) {
69 if (BuildAttrSubsectionName == Entry.SubsectionName)
70 if (Tag == Entry.Tag)
71 return Entry.TagName;
72 }
73 return "";
74}
75
77 llvm::endianness Endian) {
78
79 unsigned SectionNumber = 0;
81
82 // Early returns have specific errors. Consume the Error in Cursor.
83 struct ClearCursorError {
85 ~ClearCursorError() { consumeError(Cursor.takeError()); }
86 } Clear{Cursor};
87
88 /*
89 ELF Extended Build Attributes Layout:
90 <format-version: ‘A’> --> Currently, there is only one version: 'A' (0x41)
91 [ <uint32: subsection-length> <NTBS: vendor-name> <bytes: vendor-data> ]
92 --> subsection-length: Offset from the start of this subsection to the
93 start of the next one.
94 --> vendor-name: Null-terminated byte string.
95 --> vendor-data expands to:
96 [ <uint8: optional> <uint8: parameter type> <attribute>* ]
97 --> optional: 0 = required, 1 = optional.
98 --> parameter type: 0 = ULEB128, 1 = NTBS.
99 --> attribute: <tag, value>* pair. Tag is ULEB128, value is of
100 <parameter type>.
101 */
102
103 // Get format-version
104 uint8_t FormatVersion = De.getU8(Cursor);
105 if (!Cursor)
106 return Cursor.takeError();
107 if (ELFAttrs::Format_Version != FormatVersion)
109 "unrecognized format-version: 0x" +
110 utohexstr(FormatVersion));
111
112 while (!De.eof(Cursor)) {
113 uint32_t ExtBASubsectionLength = De.getU32(Cursor);
114 if (!Cursor)
115 return Cursor.takeError();
116 // Minimal valid Extended Build Attributes subsection size is at
117 // least 8: length(4) name(at least a single char + null) optionality(1) and
118 // type(1)
119 // Extended Build Attributes subsection has to fit inside the section.
120 if (ExtBASubsectionLength < 8 ||
121 ExtBASubsectionLength > (Section.size() - Cursor.tell() + 4))
122 return createStringError(
124 "invalid Extended Build Attributes subsection size at offset: " +
125 utohexstr(Cursor.tell() - 4));
126
127 StringRef VendorName = De.getCStrRef(Cursor);
128 if (!Cursor)
129 return Cursor.takeError();
130 uint8_t IsOptional = De.getU8(Cursor);
131 if (!Cursor)
132 return Cursor.takeError();
133 if (!(0 == IsOptional || 1 == IsOptional))
134 return createStringError(
136 "\ninvalid Optionality at offset " + utohexstr(Cursor.tell() - 4) +
137 ": " + utohexstr(IsOptional) + " (Options are 1|0)");
138 StringRef IsOptionalStr = IsOptional ? "optional" : "required";
140 if (!Cursor)
141 return Cursor.takeError();
142 if (!(0 == Type || 1 == Type))
144 "\ninvalid Type at offset " +
145 utohexstr(Cursor.tell() - 4) + ": " +
146 utohexstr(Type) + " (Options are 1|0)");
147 StringRef TypeStr = Type ? "ntbs" : "uleb128";
148
149 BuildAttributeSubSection BASubSection;
150 BASubSection.Name = VendorName;
151 BASubSection.IsOptional = IsOptional;
152 BASubSection.ParameterType = Type;
153
154 if (Sw) {
155 Sw->startLine() << "Section " << ++SectionNumber << " {\n";
156 Sw->indent();
157 Sw->printNumber("SectionLength", ExtBASubsectionLength);
158 Sw->startLine() << "VendorName" << ": " << VendorName
159 << " Optionality: " << IsOptionalStr
160 << " Type: " << TypeStr << "\n";
161 Sw->startLine() << "Attributes {\n";
162 Sw->indent();
163 }
164
165 // Offset in Section
166 uint64_t OffsetInSection = Cursor.tell();
167 // Size: 4 bytes, Vendor Name: VendorName.size() + 1 (null termination),
168 // optionality: 1, type: 1
169 uint32_t BytesAllButAttributes = 4 + (VendorName.size() + 1) + 1 + 1;
170 while (Cursor.tell() <
171 (OffsetInSection + ExtBASubsectionLength - BytesAllButAttributes)) {
172
174 if (!Cursor)
175 return Cursor.takeError();
176
177 StringRef TagName = getTagName(VendorName, Tag);
178
179 uint64_t ValueInt = 0;
180 std::string ValueStr = "";
181 if (Type) { // type==1 --> ntbs
182 ValueStr = De.getCStrRef(Cursor);
183 if (!Cursor)
184 return Cursor.takeError();
185 if (Sw)
186 Sw->printString("" != TagName ? TagName : utostr(Tag), ValueStr);
187 } else { // type==0 --> uleb128
188 ValueInt = De.getULEB128(Cursor);
189 if (!Cursor)
190 return Cursor.takeError();
191 if (Sw)
192 Sw->printNumber("" != TagName ? TagName : utostr(Tag), ValueInt);
193 }
194
195 // populate data structure
197 Tag, ValueInt, ValueStr);
198 BASubSection.Content.push_back(BAItem);
199 }
200 if (Sw) {
201 // Close 'Attributes'
202 Sw->unindent();
203 Sw->startLine() << "}\n";
204 // Close 'Section'
205 Sw->unindent();
206 Sw->startLine() << "}\n";
207 }
208
209 // populate data structure
210 SubSectionVec.push_back(BASubSection);
211 }
212
213 return Cursor.takeError();
214}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
endianness Endian
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
A class representing a position in a DataExtractor, as well as any error encountered during extractio...
Definition: DataExtractor.h:55
uint64_t tell() const
Return the current position of this Cursor.
Definition: DataExtractor.h:72
Error takeError()
Return error contained inside this Cursor, if any.
Definition: DataExtractor.h:79
LLVM_ABI 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.
LLVM_ABI StringRef getCStrRef(uint64_t *OffsetPtr, Error *Err=nullptr) const
Extract a C string from *offset_ptr.
LLVM_ABI uint8_t getU8(uint64_t *offset_ptr, Error *Err=nullptr) const
Extract a uint8_t value from *offset_ptr.
LLVM_ABI uint64_t getULEB128(uint64_t *offset_ptr, llvm::Error *Err=nullptr) const
Extract a unsigned LEB128 value from *offset_ptr.
const std::vector< SubsectionAndTagToTagName > TagsNamesMap
Error parse(ArrayRef< uint8_t > Section, llvm::endianness Endian) override
std::optional< StringRef > getAttributeString(unsigned Tag) const override
StringRef getTagName(const StringRef &BuildAttrSubsectionName, const unsigned Tag)
SmallVector< BuildAttributeSubSection, 8 > SubSectionVec
std::optional< unsigned > getAttributeValue(unsigned Tag) const override
Lightweight error class with error context and mandatory checking.
Definition: Error.h:159
virtual void printString(StringRef Value)
void indent(int Levels=1)
void unindent(int Levels=1)
virtual raw_ostream & startLine()
virtual void printNumber(StringRef Label, char Value)
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:55
constexpr size_t size() const
size - Get the string size.
Definition: StringRef.h:154
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:45
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
Definition: Error.h:1305
endianness
Definition: bit.h:71
void consumeError(Error Err)
Consume a Error without doing anything.
Definition: Error.h:1083
SmallVector< BuildAttributeItem, 64 > Content
Definition: ELFAttributes.h:43