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