brintos

brintos / llvm-project-archived public Read only

0
0
Text · 7.4 KiB · 14c5533 Raw
239 lines · cpp
1//===--- ELFCompactAttrParser.cpp - ELF Compact Attribute Parser ------  ===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7// ELF Compact Attribute Parser parse ELF build atrributes that are held8// in a single Build Attributes Subsection.9//10//===--------------------------------------------------------------------===//11 12#include "llvm/Support/ELFAttrParserCompact.h"13#include "llvm/ADT/StringExtras.h"14#include "llvm/Support/Errc.h"15#include "llvm/Support/ScopedPrinter.h"16 17using namespace llvm;18using namespace llvm::ELFAttrs;19 20static constexpr EnumEntry<unsigned> tagNames[] = {21    {"Tag_File", ELFAttrs::File},22    {"Tag_Section", ELFAttrs::Section},23    {"Tag_Symbol", ELFAttrs::Symbol},24};25 26Error ELFCompactAttrParser::parseStringAttribute(27    const char *name, unsigned tag, ArrayRef<const char *> strings) {28  uint64_t value = de.getULEB128(cursor);29  if (value >= strings.size()) {30    printAttribute(tag, value, "");31    return createStringError(errc::invalid_argument,32                             "unknown " + Twine(name) +33                                 " value: " + Twine(value));34  }35  printAttribute(tag, value, strings[value]);36  return Error::success();37}38 39Error ELFCompactAttrParser::integerAttribute(unsigned tag) {40  StringRef tagName =41      ELFAttrs::attrTypeAsString(tag, tagToStringMap, /*hasTagPrefix=*/false);42  uint64_t value = de.getULEB128(cursor);43  attributes.insert(std::make_pair(tag, value));44 45  if (sw) {46    DictScope scope(*sw, "Attribute");47    sw->printNumber("Tag", tag);48    if (!tagName.empty())49      sw->printString("TagName", tagName);50    sw->printNumber("Value", value);51  }52  return Error::success();53}54 55Error ELFCompactAttrParser::stringAttribute(unsigned tag) {56  StringRef tagName =57      ELFAttrs::attrTypeAsString(tag, tagToStringMap, /*hasTagPrefix=*/false);58  StringRef desc = de.getCStrRef(cursor);59  setAttributeString(tag, desc);60 61  if (sw) {62    DictScope scope(*sw, "Attribute");63    sw->printNumber("Tag", tag);64    if (!tagName.empty())65      sw->printString("TagName", tagName);66    sw->printString("Value", desc);67  }68  return Error::success();69}70 71void ELFCompactAttrParser::printAttribute(unsigned tag, unsigned value,72                                          StringRef valueDesc) {73  attributes.insert(std::make_pair(tag, value));74 75  if (sw) {76    StringRef tagName = ELFAttrs::attrTypeAsString(tag, tagToStringMap,77                                                   /*hasTagPrefix=*/false);78    DictScope as(*sw, "Attribute");79    sw->printNumber("Tag", tag);80    sw->printNumber("Value", value);81    if (!tagName.empty())82      sw->printString("TagName", tagName);83    if (!valueDesc.empty())84      sw->printString("Description", valueDesc);85  }86}87 88void ELFCompactAttrParser::parseIndexList(SmallVectorImpl<uint8_t> &indexList) {89  for (;;) {90    uint64_t value = de.getULEB128(cursor);91    if (!cursor || !value)92      break;93    indexList.push_back(value);94  }95}96 97Error ELFCompactAttrParser::parseAttributeList(uint32_t length) {98  uint64_t pos;99  uint64_t end = cursor.tell() + length;100  while ((pos = cursor.tell()) < end) {101    uint64_t tag = de.getULEB128(cursor);102    bool handled;103    if (Error e = handler(tag, handled))104      return e;105 106    if (!handled) {107      if (tag < 32) {108        return createStringError(errc::invalid_argument,109                                 "invalid tag 0x" + Twine::utohexstr(tag) +110                                     " at offset 0x" + Twine::utohexstr(pos));111      }112 113      if (tag % 2 == 0) {114        if (Error e = integerAttribute(tag))115          return e;116      } else {117        if (Error e = stringAttribute(tag))118          return e;119      }120    }121  }122  return Error::success();123}124 125Error ELFCompactAttrParser::parseSubsection(uint32_t length) {126  uint64_t end = cursor.tell() - sizeof(length) + length;127  StringRef vendorName = de.getCStrRef(cursor);128  if (sw) {129    sw->printNumber("SectionLength", length);130    sw->printString("Vendor", vendorName);131  }132 133  // Handle a subsection with an unrecognized vendor-name by skipping134  // over it to the next subsection. ADDENDA32 in the Arm ABI defines135  // that vendor attribute sections must not affect compatibility, so136  // this should always be safe.137  if (vendorName.lower() != vendor) {138    cursor.seek(end);139    return Error::success();140  }141 142  while (cursor.tell() < end) {143    /// Tag_File | Tag_Section | Tag_Symbol   uleb128:byte-size144    uint8_t tag = de.getU8(cursor);145    uint32_t size = de.getU32(cursor);146    if (!cursor)147      return cursor.takeError();148 149    if (sw) {150      sw->printEnum("Tag", tag, ArrayRef(tagNames));151      sw->printNumber("Size", size);152    }153    if (size < 5)154      return createStringError(errc::invalid_argument,155                               "invalid attribute size " + Twine(size) +156                                   " at offset 0x" +157                                   Twine::utohexstr(cursor.tell() - 5));158 159    StringRef scopeName, indexName;160    SmallVector<uint8_t, 8> indices;161    switch (tag) {162    case ELFAttrs::File:163      scopeName = "FileAttributes";164      break;165    case ELFAttrs::Section:166      scopeName = "SectionAttributes";167      indexName = "Sections";168      parseIndexList(indices);169      break;170    case ELFAttrs::Symbol:171      scopeName = "SymbolAttributes";172      indexName = "Symbols";173      parseIndexList(indices);174      break;175    default:176      return createStringError(errc::invalid_argument,177                               "unrecognized tag 0x" + Twine::utohexstr(tag) +178                                   " at offset 0x" +179                                   Twine::utohexstr(cursor.tell() - 5));180    }181 182    if (sw) {183      DictScope scope(*sw, scopeName);184      if (!indices.empty())185        sw->printList(indexName, indices);186      if (Error e = parseAttributeList(size - 5))187        return e;188    } else if (Error e = parseAttributeList(size - 5))189      return e;190  }191  return Error::success();192}193 194Error ELFCompactAttrParser::parse(ArrayRef<uint8_t> section,195                                  llvm::endianness endian) {196  unsigned sectionNumber = 0;197  de = DataExtractor(section, endian == llvm::endianness::little, 0);198 199  // For early returns, we have more specific errors, consume the Error in200  // cursor.201  struct ClearCursorError {202    DataExtractor::Cursor &cursor;203    ~ClearCursorError() { consumeError(cursor.takeError()); }204  } clear{cursor};205 206  // Unrecognized format-version.207  uint8_t formatVersion = de.getU8(cursor);208  if (formatVersion != ELFAttrs::Format_Version)209    return createStringError(errc::invalid_argument,210                             "unrecognized format-version: 0x" +211                                 utohexstr(formatVersion));212 213  while (!de.eof(cursor)) {214    uint32_t sectionLength = de.getU32(cursor);215    if (!cursor)216      return cursor.takeError();217 218    if (sw) {219      sw->startLine() << "Section " << ++sectionNumber << " {\n";220      sw->indent();221    }222 223    if (sectionLength < 4 || cursor.tell() - 4 + sectionLength > section.size())224      return createStringError(errc::invalid_argument,225                               "invalid section length " +226                                   Twine(sectionLength) + " at offset 0x" +227                                   utohexstr(cursor.tell() - 4));228 229    if (Error e = parseSubsection(sectionLength))230      return e;231    if (sw) {232      sw->unindent();233      sw->startLine() << "}\n";234    }235  }236 237  return cursor.takeError();238}239