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 != 'A') 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