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