215 lines · cpp
1//===-ELFAttrParserExtended.cpp-ELF Extended Attribute Information Printer-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM4// Exceptions.5// See https://llvm.org/LICENSE.txt for license information.6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception7//8//===------------------------------------------------------------------===//9 10#include "llvm/Support/ELFAttrParserExtended.h"11#include "llvm/ADT/StringExtras.h"12#include "llvm/ADT/StringRef.h"13#include "llvm/Support/ELFAttributes.h"14#include "llvm/Support/Errc.h"15#include "llvm/Support/Error.h"16#include "llvm/Support/ScopedPrinter.h"17#include "llvm/Support/raw_ostream.h"18#include <cstdint>19 20using namespace llvm;21using namespace ELFAttrs;22 23std::optional<unsigned>24ELFExtendedAttrParser::getAttributeValue(unsigned Tag) const {25 assert(26 0 &&27 "use getAttributeValue overloaded version accepting Stringref, unsigned");28 return std::nullopt;29}30 31std::optional<unsigned>32ELFExtendedAttrParser::getAttributeValue(StringRef BuildAttrSubsectionName,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>45ELFExtendedAttrParser::getAttributeString(unsigned Tag) const {46 assert(47 0 &&48 "use getAttributeValue overloaded version accepting Stringref, unsigned");49 return std::nullopt;50}51 52std::optional<StringRef>53ELFExtendedAttrParser::getAttributeString(StringRef BuildAttrSubsectionName,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 65StringRef66ELFExtendedAttrParser::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 76Error ELFExtendedAttrParser::parse(ArrayRef<uint8_t> Section,77 llvm::endianness Endian) {78 79 unsigned SectionNumber = 0;80 De = DataExtractor(Section, Endian == llvm::endianness::little, 0);81 82 // Early returns have specific errors. Consume the Error in Cursor.83 struct ClearCursorError {84 DataExtractor::Cursor &Cursor;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 the93 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 of100 <parameter type>.101 */102 103 // Get format-version104 uint8_t FormatVersion = De.getU8(Cursor);105 if (!Cursor)106 return Cursor.takeError();107 if (ELFAttrs::Format_Version != FormatVersion)108 return createStringError(errc::invalid_argument,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 at117 // least 8: length(4) name(at least a single char + null) optionality(1) and118 // 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(123 errc::invalid_argument,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(135 errc::invalid_argument,136 "\ninvalid Optionality at offset " + utohexstr(Cursor.tell() - 4) +137 ": " + utohexstr(IsOptional) + " (Options are 1|0)");138 StringRef IsOptionalStr = IsOptional ? "optional" : "required";139 uint8_t Type = De.getU8(Cursor);140 if (!Cursor)141 return Cursor.takeError();142 if (!(0 == Type || 1 == Type))143 return createStringError(errc::invalid_argument,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" << ": " << VendorName159 << " Optionality: " << IsOptionalStr160 << " Type: " << TypeStr << "\n";161 Sw->startLine() << "Attributes {\n";162 Sw->indent();163 }164 165 // Offset in Section166 uint64_t OffsetInSection = Cursor.tell();167 // Size: 4 bytes, Vendor Name: VendorName.size() + 1 (null termination),168 // optionality: 1, type: 1169 uint32_t BytesAllButAttributes = 4 + (VendorName.size() + 1) + 1 + 1;170 while (Cursor.tell() <171 (OffsetInSection + ExtBASubsectionLength - BytesAllButAttributes)) {172 173 uint64_t Tag = De.getULEB128(Cursor);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 --> ntbs182 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 --> uleb128188 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 structure196 BuildAttributeItem BAItem(static_cast<BuildAttributeItem::Types>(Type),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 structure210 SubSectionVec.push_back(BASubSection);211 }212 213 return Cursor.takeError();214}215