brintos

brintos / llvm-project-archived public Read only

0
0
Text · 7.4 KiB · 3d9158a Raw
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