
These are identified by misc-include-cleaner. I've filtered out those that break builds. Also, I'm staying away from llvm-config.h, config.h, and Compiler.h, which likely cause platform- or compiler-specific build failures.
215 lines
7.4 KiB
C++
215 lines
7.4 KiB
C++
//===-ELFAttrParserExtended.cpp-ELF Extended Attribute Information Printer-===//
|
||
//
|
||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM
|
||
// Exceptions.
|
||
// See https://llvm.org/LICENSE.txt for license information.
|
||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||
//
|
||
//===------------------------------------------------------------------===//
|
||
|
||
#include "llvm/Support/ELFAttrParserExtended.h"
|
||
#include "llvm/ADT/StringExtras.h"
|
||
#include "llvm/ADT/StringRef.h"
|
||
#include "llvm/Support/ELFAttributes.h"
|
||
#include "llvm/Support/Errc.h"
|
||
#include "llvm/Support/Error.h"
|
||
#include "llvm/Support/ScopedPrinter.h"
|
||
#include "llvm/Support/raw_ostream.h"
|
||
#include <cstdint>
|
||
|
||
using namespace llvm;
|
||
using namespace ELFAttrs;
|
||
|
||
std::optional<unsigned>
|
||
ELFExtendedAttrParser::getAttributeValue(unsigned Tag) const {
|
||
assert(
|
||
0 &&
|
||
"use getAttributeValue overloaded version accepting Stringref, unsigned");
|
||
return std::nullopt;
|
||
}
|
||
|
||
std::optional<unsigned>
|
||
ELFExtendedAttrParser::getAttributeValue(StringRef BuildAttrSubsectionName,
|
||
unsigned Tag) const {
|
||
for (const auto &SubSection : SubSectionVec) {
|
||
if (BuildAttrSubsectionName == SubSection.Name)
|
||
for (const auto &BAItem : SubSection.Content) {
|
||
if (Tag == BAItem.Tag)
|
||
return std::optional<unsigned>(BAItem.IntValue);
|
||
}
|
||
}
|
||
return std::nullopt;
|
||
}
|
||
|
||
std::optional<StringRef>
|
||
ELFExtendedAttrParser::getAttributeString(unsigned Tag) const {
|
||
assert(
|
||
0 &&
|
||
"use getAttributeValue overloaded version accepting Stringref, unsigned");
|
||
return std::nullopt;
|
||
}
|
||
|
||
std::optional<StringRef>
|
||
ELFExtendedAttrParser::getAttributeString(StringRef BuildAttrSubsectionName,
|
||
unsigned Tag) const {
|
||
for (const auto &SubSection : SubSectionVec) {
|
||
if (BuildAttrSubsectionName == SubSection.Name)
|
||
for (const auto &BAItem : SubSection.Content) {
|
||
if (Tag == BAItem.Tag)
|
||
return std::optional<StringRef>(BAItem.StringValue);
|
||
}
|
||
}
|
||
return std::nullopt;
|
||
}
|
||
|
||
StringRef
|
||
ELFExtendedAttrParser::getTagName(const StringRef &BuildAttrSubsectionName,
|
||
const unsigned Tag) {
|
||
for (const auto &Entry : TagsNamesMap) {
|
||
if (BuildAttrSubsectionName == Entry.SubsectionName)
|
||
if (Tag == Entry.Tag)
|
||
return Entry.TagName;
|
||
}
|
||
return "";
|
||
}
|
||
|
||
Error ELFExtendedAttrParser::parse(ArrayRef<uint8_t> Section,
|
||
llvm::endianness Endian) {
|
||
|
||
unsigned SectionNumber = 0;
|
||
De = DataExtractor(Section, Endian == llvm::endianness::little, 0);
|
||
|
||
// Early returns have specific errors. Consume the Error in Cursor.
|
||
struct ClearCursorError {
|
||
DataExtractor::Cursor &Cursor;
|
||
~ClearCursorError() { consumeError(Cursor.takeError()); }
|
||
} Clear{Cursor};
|
||
|
||
/*
|
||
ELF Extended Build Attributes Layout:
|
||
<format-version: ‘A’> --> Currently, there is only one version: 'A' (0x41)
|
||
[ <uint32: subsection-length> <NTBS: vendor-name> <bytes: vendor-data> ]
|
||
--> subsection-length: Offset from the start of this subsection to the
|
||
start of the next one.
|
||
--> vendor-name: Null-terminated byte string.
|
||
--> vendor-data expands to:
|
||
[ <uint8: optional> <uint8: parameter type> <attribute>* ]
|
||
--> optional: 0 = required, 1 = optional.
|
||
--> parameter type: 0 = ULEB128, 1 = NTBS.
|
||
--> attribute: <tag, value>* pair. Tag is ULEB128, value is of
|
||
<parameter type>.
|
||
*/
|
||
|
||
// Get format-version
|
||
uint8_t FormatVersion = De.getU8(Cursor);
|
||
if (!Cursor)
|
||
return Cursor.takeError();
|
||
if (ELFAttrs::Format_Version != FormatVersion)
|
||
return createStringError(errc::invalid_argument,
|
||
"unrecognized format-version: 0x" +
|
||
utohexstr(FormatVersion));
|
||
|
||
while (!De.eof(Cursor)) {
|
||
uint32_t ExtBASubsectionLength = De.getU32(Cursor);
|
||
if (!Cursor)
|
||
return Cursor.takeError();
|
||
// Minimal valid Extended Build Attributes subsection size is at
|
||
// least 8: length(4) name(at least a single char + null) optionality(1) and
|
||
// type(1)
|
||
// Extended Build Attributes subsection has to fit inside the section.
|
||
if (ExtBASubsectionLength < 8 ||
|
||
ExtBASubsectionLength > (Section.size() - Cursor.tell() + 4))
|
||
return createStringError(
|
||
errc::invalid_argument,
|
||
"invalid Extended Build Attributes subsection size at offset: " +
|
||
utohexstr(Cursor.tell() - 4));
|
||
|
||
StringRef VendorName = De.getCStrRef(Cursor);
|
||
if (!Cursor)
|
||
return Cursor.takeError();
|
||
uint8_t IsOptional = De.getU8(Cursor);
|
||
if (!Cursor)
|
||
return Cursor.takeError();
|
||
if (!(0 == IsOptional || 1 == IsOptional))
|
||
return createStringError(
|
||
errc::invalid_argument,
|
||
"\ninvalid Optionality at offset " + utohexstr(Cursor.tell() - 4) +
|
||
": " + utohexstr(IsOptional) + " (Options are 1|0)");
|
||
StringRef IsOptionalStr = IsOptional ? "optional" : "required";
|
||
uint8_t Type = De.getU8(Cursor);
|
||
if (!Cursor)
|
||
return Cursor.takeError();
|
||
if (!(0 == Type || 1 == Type))
|
||
return createStringError(errc::invalid_argument,
|
||
"\ninvalid Type at offset " +
|
||
utohexstr(Cursor.tell() - 4) + ": " +
|
||
utohexstr(Type) + " (Options are 1|0)");
|
||
StringRef TypeStr = Type ? "ntbs" : "uleb128";
|
||
|
||
BuildAttributeSubSection BASubSection;
|
||
BASubSection.Name = VendorName;
|
||
BASubSection.IsOptional = IsOptional;
|
||
BASubSection.ParameterType = Type;
|
||
|
||
if (Sw) {
|
||
Sw->startLine() << "Section " << ++SectionNumber << " {\n";
|
||
Sw->indent();
|
||
Sw->printNumber("SectionLength", ExtBASubsectionLength);
|
||
Sw->startLine() << "VendorName" << ": " << VendorName
|
||
<< " Optionality: " << IsOptionalStr
|
||
<< " Type: " << TypeStr << "\n";
|
||
Sw->startLine() << "Attributes {\n";
|
||
Sw->indent();
|
||
}
|
||
|
||
// Offset in Section
|
||
uint64_t OffsetInSection = Cursor.tell();
|
||
// Size: 4 bytes, Vendor Name: VendorName.size() + 1 (null termination),
|
||
// optionality: 1, type: 1
|
||
uint32_t BytesAllButAttributes = 4 + (VendorName.size() + 1) + 1 + 1;
|
||
while (Cursor.tell() <
|
||
(OffsetInSection + ExtBASubsectionLength - BytesAllButAttributes)) {
|
||
|
||
uint64_t Tag = De.getULEB128(Cursor);
|
||
if (!Cursor)
|
||
return Cursor.takeError();
|
||
|
||
StringRef TagName = getTagName(VendorName, Tag);
|
||
|
||
uint64_t ValueInt = 0;
|
||
std::string ValueStr = "";
|
||
if (Type) { // type==1 --> ntbs
|
||
ValueStr = De.getCStrRef(Cursor);
|
||
if (!Cursor)
|
||
return Cursor.takeError();
|
||
if (Sw)
|
||
Sw->printString("" != TagName ? TagName : utostr(Tag), ValueStr);
|
||
} else { // type==0 --> uleb128
|
||
ValueInt = De.getULEB128(Cursor);
|
||
if (!Cursor)
|
||
return Cursor.takeError();
|
||
if (Sw)
|
||
Sw->printNumber("" != TagName ? TagName : utostr(Tag), ValueInt);
|
||
}
|
||
|
||
// populate data structure
|
||
BuildAttributeItem BAItem(static_cast<BuildAttributeItem::Types>(Type),
|
||
Tag, ValueInt, ValueStr);
|
||
BASubSection.Content.push_back(BAItem);
|
||
}
|
||
if (Sw) {
|
||
// Close 'Attributes'
|
||
Sw->unindent();
|
||
Sw->startLine() << "}\n";
|
||
// Close 'Section'
|
||
Sw->unindent();
|
||
Sw->startLine() << "}\n";
|
||
}
|
||
|
||
// populate data structure
|
||
SubSectionVec.push_back(BASubSection);
|
||
}
|
||
|
||
return Cursor.takeError();
|
||
}
|