summaryrefslogtreecommitdiff
path: root/llvm/lib/Support/ELFAttributeParser.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Support/ELFAttributeParser.cpp')
-rw-r--r--llvm/lib/Support/ELFAttributeParser.cpp233
1 files changed, 233 insertions, 0 deletions
diff --git a/llvm/lib/Support/ELFAttributeParser.cpp b/llvm/lib/Support/ELFAttributeParser.cpp
new file mode 100644
index 0000000000000..df955cdf5d30a
--- /dev/null
+++ b/llvm/lib/Support/ELFAttributeParser.cpp
@@ -0,0 +1,233 @@
+//===--- ELFAttributeParser.cpp - ELF Attribute Parser --------------------===//
+//
+// 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/ELFAttributeParser.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/Support/Errc.h"
+#include "llvm/Support/LEB128.h"
+#include "llvm/Support/ScopedPrinter.h"
+
+using namespace llvm;
+using namespace llvm::ELFAttrs;
+
+static const EnumEntry<unsigned> tagNames[] = {
+ {"Tag_File", ELFAttrs::File},
+ {"Tag_Section", ELFAttrs::Section},
+ {"Tag_Symbol", ELFAttrs::Symbol},
+};
+
+Error ELFAttributeParser::parseStringAttribute(const char *name, unsigned tag,
+ ArrayRef<const char *> strings) {
+ uint64_t value = de.getULEB128(cursor);
+ if (value >= strings.size()) {
+ printAttribute(tag, value, "");
+ return createStringError(errc::invalid_argument,
+ "unknown " + Twine(name) +
+ " value: " + Twine(value));
+ }
+ printAttribute(tag, value, strings[value]);
+ return Error::success();
+}
+
+Error ELFAttributeParser::integerAttribute(unsigned tag) {
+ StringRef tagName =
+ ELFAttrs::attrTypeAsString(tag, tagToStringMap, /*hasTagPrefix=*/false);
+ uint64_t value = de.getULEB128(cursor);
+ attributes.insert(std::make_pair(tag, value));
+
+ if (sw) {
+ DictScope scope(*sw, "Attribute");
+ sw->printNumber("Tag", tag);
+ if (!tagName.empty())
+ sw->printString("TagName", tagName);
+ sw->printNumber("Value", value);
+ }
+ return Error::success();
+}
+
+Error ELFAttributeParser::stringAttribute(unsigned tag) {
+ StringRef tagName =
+ ELFAttrs::attrTypeAsString(tag, tagToStringMap, /*hasTagPrefix=*/false);
+ StringRef desc = de.getCStrRef(cursor);
+ attributesStr.insert(std::make_pair(tag, desc));
+
+ if (sw) {
+ DictScope scope(*sw, "Attribute");
+ sw->printNumber("Tag", tag);
+ if (!tagName.empty())
+ sw->printString("TagName", tagName);
+ sw->printString("Value", desc);
+ }
+ return Error::success();
+}
+
+void ELFAttributeParser::printAttribute(unsigned tag, unsigned value,
+ StringRef valueDesc) {
+ attributes.insert(std::make_pair(tag, value));
+
+ if (sw) {
+ StringRef tagName = ELFAttrs::attrTypeAsString(tag, tagToStringMap,
+ /*hasTagPrefix=*/false);
+ DictScope as(*sw, "Attribute");
+ sw->printNumber("Tag", tag);
+ sw->printNumber("Value", value);
+ if (!tagName.empty())
+ sw->printString("TagName", tagName);
+ if (!valueDesc.empty())
+ sw->printString("Description", valueDesc);
+ }
+}
+
+void ELFAttributeParser::parseIndexList(SmallVectorImpl<uint8_t> &indexList) {
+ for (;;) {
+ uint64_t value = de.getULEB128(cursor);
+ if (!cursor || !value)
+ break;
+ indexList.push_back(value);
+ }
+}
+
+Error ELFAttributeParser::parseAttributeList(uint32_t length) {
+ uint64_t pos;
+ uint64_t end = cursor.tell() + length;
+ while ((pos = cursor.tell()) < end) {
+ uint64_t tag = de.getULEB128(cursor);
+ bool handled;
+ if (Error e = handler(tag, handled))
+ return e;
+
+ if (!handled) {
+ if (tag < 32) {
+ return createStringError(errc::invalid_argument,
+ "invalid tag 0x" + Twine::utohexstr(tag) +
+ " at offset 0x" + Twine::utohexstr(pos));
+ }
+
+ if (tag % 2 == 0) {
+ if (Error e = integerAttribute(tag))
+ return e;
+ } else {
+ if (Error e = stringAttribute(tag))
+ return e;
+ }
+ }
+ }
+ return Error::success();
+}
+
+Error ELFAttributeParser::parseSubsection(uint32_t length) {
+ uint64_t end = cursor.tell() - sizeof(length) + length;
+ StringRef vendorName = de.getCStrRef(cursor);
+ if (sw) {
+ sw->printNumber("SectionLength", length);
+ sw->printString("Vendor", vendorName);
+ }
+
+ // Ignore unrecognized vendor-name.
+ if (vendorName.lower() != vendor)
+ return createStringError(errc::invalid_argument,
+ "unrecognized vendor-name: " + vendorName);
+
+ while (cursor.tell() < end) {
+ /// Tag_File | Tag_Section | Tag_Symbol uleb128:byte-size
+ uint8_t tag = de.getU8(cursor);
+ uint32_t size = de.getU32(cursor);
+ if (!cursor)
+ return cursor.takeError();
+
+ if (sw) {
+ sw->printEnum("Tag", tag, makeArrayRef(tagNames));
+ sw->printNumber("Size", size);
+ }
+ if (size < 5)
+ return createStringError(errc::invalid_argument,
+ "invalid attribute size " + Twine(size) +
+ " at offset 0x" +
+ Twine::utohexstr(cursor.tell() - 5));
+
+ StringRef scopeName, indexName;
+ SmallVector<uint8_t, 8> indicies;
+ switch (tag) {
+ case ELFAttrs::File:
+ scopeName = "FileAttributes";
+ break;
+ case ELFAttrs::Section:
+ scopeName = "SectionAttributes";
+ indexName = "Sections";
+ parseIndexList(indicies);
+ break;
+ case ELFAttrs::Symbol:
+ scopeName = "SymbolAttributes";
+ indexName = "Symbols";
+ parseIndexList(indicies);
+ break;
+ default:
+ return createStringError(errc::invalid_argument,
+ "unrecognized tag 0x" + Twine::utohexstr(tag) +
+ " at offset 0x" +
+ Twine::utohexstr(cursor.tell() - 5));
+ }
+
+ if (sw) {
+ DictScope scope(*sw, scopeName);
+ if (!indicies.empty())
+ sw->printList(indexName, indicies);
+ if (Error e = parseAttributeList(size - 5))
+ return e;
+ } else if (Error e = parseAttributeList(size - 5))
+ return e;
+ }
+ return Error::success();
+}
+
+Error ELFAttributeParser::parse(ArrayRef<uint8_t> section,
+ support::endianness endian) {
+ unsigned sectionNumber = 0;
+ de = DataExtractor(section, endian == support::little, 0);
+
+ // For early returns, we have more specific errors, consume the Error in
+ // cursor.
+ struct ClearCursorError {
+ DataExtractor::Cursor &cursor;
+ ~ClearCursorError() { consumeError(cursor.takeError()); }
+ } clear{cursor};
+
+ // Unrecognized format-version.
+ uint8_t formatVersion = de.getU8(cursor);
+ if (formatVersion != 'A')
+ return createStringError(errc::invalid_argument,
+ "unrecognized format-version: 0x" +
+ utohexstr(formatVersion));
+
+ while (!de.eof(cursor)) {
+ uint32_t sectionLength = de.getU32(cursor);
+ if (!cursor)
+ return cursor.takeError();
+
+ if (sw) {
+ sw->startLine() << "Section " << ++sectionNumber << " {\n";
+ sw->indent();
+ }
+
+ if (sectionLength < 4 || cursor.tell() - 4 + sectionLength > section.size())
+ return createStringError(errc::invalid_argument,
+ "invalid section length " +
+ Twine(sectionLength) + " at offset 0x" +
+ utohexstr(cursor.tell() - 4));
+
+ if (Error e = parseSubsection(sectionLength))
+ return e;
+ if (sw) {
+ sw->unindent();
+ sw->startLine() << "}\n";
+ }
+ }
+
+ return cursor.takeError();
+}