Path: blob/main/contrib/llvm-project/llvm/lib/Support/ELFAttributeParser.cpp
35234 views
//===--- ELFAttributeParser.cpp - ELF Attribute Parser --------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "llvm/Support/ELFAttributeParser.h"9#include "llvm/ADT/StringExtras.h"10#include "llvm/Support/Errc.h"11#include "llvm/Support/ScopedPrinter.h"1213using namespace llvm;14using namespace llvm::ELFAttrs;1516static constexpr EnumEntry<unsigned> tagNames[] = {17{"Tag_File", ELFAttrs::File},18{"Tag_Section", ELFAttrs::Section},19{"Tag_Symbol", ELFAttrs::Symbol},20};2122Error ELFAttributeParser::parseStringAttribute(const char *name, unsigned tag,23ArrayRef<const char *> strings) {24uint64_t value = de.getULEB128(cursor);25if (value >= strings.size()) {26printAttribute(tag, value, "");27return createStringError(errc::invalid_argument,28"unknown " + Twine(name) +29" value: " + Twine(value));30}31printAttribute(tag, value, strings[value]);32return Error::success();33}3435Error ELFAttributeParser::integerAttribute(unsigned tag) {36StringRef tagName =37ELFAttrs::attrTypeAsString(tag, tagToStringMap, /*hasTagPrefix=*/false);38uint64_t value = de.getULEB128(cursor);39attributes.insert(std::make_pair(tag, value));4041if (sw) {42DictScope scope(*sw, "Attribute");43sw->printNumber("Tag", tag);44if (!tagName.empty())45sw->printString("TagName", tagName);46sw->printNumber("Value", value);47}48return Error::success();49}5051Error ELFAttributeParser::stringAttribute(unsigned tag) {52StringRef tagName =53ELFAttrs::attrTypeAsString(tag, tagToStringMap, /*hasTagPrefix=*/false);54StringRef desc = de.getCStrRef(cursor);55setAttributeString(tag, desc);5657if (sw) {58DictScope scope(*sw, "Attribute");59sw->printNumber("Tag", tag);60if (!tagName.empty())61sw->printString("TagName", tagName);62sw->printString("Value", desc);63}64return Error::success();65}6667void ELFAttributeParser::printAttribute(unsigned tag, unsigned value,68StringRef valueDesc) {69attributes.insert(std::make_pair(tag, value));7071if (sw) {72StringRef tagName = ELFAttrs::attrTypeAsString(tag, tagToStringMap,73/*hasTagPrefix=*/false);74DictScope as(*sw, "Attribute");75sw->printNumber("Tag", tag);76sw->printNumber("Value", value);77if (!tagName.empty())78sw->printString("TagName", tagName);79if (!valueDesc.empty())80sw->printString("Description", valueDesc);81}82}8384void ELFAttributeParser::parseIndexList(SmallVectorImpl<uint8_t> &indexList) {85for (;;) {86uint64_t value = de.getULEB128(cursor);87if (!cursor || !value)88break;89indexList.push_back(value);90}91}9293Error ELFAttributeParser::parseAttributeList(uint32_t length) {94uint64_t pos;95uint64_t end = cursor.tell() + length;96while ((pos = cursor.tell()) < end) {97uint64_t tag = de.getULEB128(cursor);98bool handled;99if (Error e = handler(tag, handled))100return e;101102if (!handled) {103if (tag < 32) {104return createStringError(errc::invalid_argument,105"invalid tag 0x" + Twine::utohexstr(tag) +106" at offset 0x" + Twine::utohexstr(pos));107}108109if (tag % 2 == 0) {110if (Error e = integerAttribute(tag))111return e;112} else {113if (Error e = stringAttribute(tag))114return e;115}116}117}118return Error::success();119}120121Error ELFAttributeParser::parseSubsection(uint32_t length) {122uint64_t end = cursor.tell() - sizeof(length) + length;123StringRef vendorName = de.getCStrRef(cursor);124if (sw) {125sw->printNumber("SectionLength", length);126sw->printString("Vendor", vendorName);127}128129// Handle a subsection with an unrecognized vendor-name by skipping130// over it to the next subsection. ADDENDA32 in the Arm ABI defines131// that vendor attribute sections must not affect compatibility, so132// this should always be safe.133if (vendorName.lower() != vendor) {134cursor.seek(end);135return Error::success();136}137138while (cursor.tell() < end) {139/// Tag_File | Tag_Section | Tag_Symbol uleb128:byte-size140uint8_t tag = de.getU8(cursor);141uint32_t size = de.getU32(cursor);142if (!cursor)143return cursor.takeError();144145if (sw) {146sw->printEnum("Tag", tag, ArrayRef(tagNames));147sw->printNumber("Size", size);148}149if (size < 5)150return createStringError(errc::invalid_argument,151"invalid attribute size " + Twine(size) +152" at offset 0x" +153Twine::utohexstr(cursor.tell() - 5));154155StringRef scopeName, indexName;156SmallVector<uint8_t, 8> indices;157switch (tag) {158case ELFAttrs::File:159scopeName = "FileAttributes";160break;161case ELFAttrs::Section:162scopeName = "SectionAttributes";163indexName = "Sections";164parseIndexList(indices);165break;166case ELFAttrs::Symbol:167scopeName = "SymbolAttributes";168indexName = "Symbols";169parseIndexList(indices);170break;171default:172return createStringError(errc::invalid_argument,173"unrecognized tag 0x" + Twine::utohexstr(tag) +174" at offset 0x" +175Twine::utohexstr(cursor.tell() - 5));176}177178if (sw) {179DictScope scope(*sw, scopeName);180if (!indices.empty())181sw->printList(indexName, indices);182if (Error e = parseAttributeList(size - 5))183return e;184} else if (Error e = parseAttributeList(size - 5))185return e;186}187return Error::success();188}189190Error ELFAttributeParser::parse(ArrayRef<uint8_t> section,191llvm::endianness endian) {192unsigned sectionNumber = 0;193de = DataExtractor(section, endian == llvm::endianness::little, 0);194195// For early returns, we have more specific errors, consume the Error in196// cursor.197struct ClearCursorError {198DataExtractor::Cursor &cursor;199~ClearCursorError() { consumeError(cursor.takeError()); }200} clear{cursor};201202// Unrecognized format-version.203uint8_t formatVersion = de.getU8(cursor);204if (formatVersion != ELFAttrs::Format_Version)205return createStringError(errc::invalid_argument,206"unrecognized format-version: 0x" +207utohexstr(formatVersion));208209while (!de.eof(cursor)) {210uint32_t sectionLength = de.getU32(cursor);211if (!cursor)212return cursor.takeError();213214if (sw) {215sw->startLine() << "Section " << ++sectionNumber << " {\n";216sw->indent();217}218219if (sectionLength < 4 || cursor.tell() - 4 + sectionLength > section.size())220return createStringError(errc::invalid_argument,221"invalid section length " +222Twine(sectionLength) + " at offset 0x" +223utohexstr(cursor.tell() - 4));224225if (Error e = parseSubsection(sectionLength))226return e;227if (sw) {228sw->unindent();229sw->startLine() << "}\n";230}231}232233return cursor.takeError();234}235236237