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 setAttributeString(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 // Handle a subsection with an unrecognized vendor-name by skipping 131 // over it to the next subsection. ADDENDA32 in the Arm ABI defines 132 // that vendor attribute sections must not affect compatibility, so 133 // this should always be safe. 134 if (vendorName.lower() != vendor) { 135 cursor.seek(end); 136 return Error::success(); 137 } 138 139 while (cursor.tell() < end) { 140 /// Tag_File | Tag_Section | Tag_Symbol uleb128:byte-size 141 uint8_t tag = de.getU8(cursor); 142 uint32_t size = de.getU32(cursor); 143 if (!cursor) 144 return cursor.takeError(); 145 146 if (sw) { 147 sw->printEnum("Tag", tag, ArrayRef(tagNames)); 148 sw->printNumber("Size", size); 149 } 150 if (size < 5) 151 return createStringError(errc::invalid_argument, 152 "invalid attribute size " + Twine(size) + 153 " at offset 0x" + 154 Twine::utohexstr(cursor.tell() - 5)); 155 156 StringRef scopeName, indexName; 157 SmallVector<uint8_t, 8> indicies; 158 switch (tag) { 159 case ELFAttrs::File: 160 scopeName = "FileAttributes"; 161 break; 162 case ELFAttrs::Section: 163 scopeName = "SectionAttributes"; 164 indexName = "Sections"; 165 parseIndexList(indicies); 166 break; 167 case ELFAttrs::Symbol: 168 scopeName = "SymbolAttributes"; 169 indexName = "Symbols"; 170 parseIndexList(indicies); 171 break; 172 default: 173 return createStringError(errc::invalid_argument, 174 "unrecognized tag 0x" + Twine::utohexstr(tag) + 175 " at offset 0x" + 176 Twine::utohexstr(cursor.tell() - 5)); 177 } 178 179 if (sw) { 180 DictScope scope(*sw, scopeName); 181 if (!indicies.empty()) 182 sw->printList(indexName, indicies); 183 if (Error e = parseAttributeList(size - 5)) 184 return e; 185 } else if (Error e = parseAttributeList(size - 5)) 186 return e; 187 } 188 return Error::success(); 189 } 190 191 Error ELFAttributeParser::parse(ArrayRef<uint8_t> section, 192 support::endianness endian) { 193 unsigned sectionNumber = 0; 194 de = DataExtractor(section, endian == support::little, 0); 195 196 // For early returns, we have more specific errors, consume the Error in 197 // cursor. 198 struct ClearCursorError { 199 DataExtractor::Cursor &cursor; 200 ~ClearCursorError() { consumeError(cursor.takeError()); } 201 } clear{cursor}; 202 203 // Unrecognized format-version. 204 uint8_t formatVersion = de.getU8(cursor); 205 if (formatVersion != ELFAttrs::Format_Version) 206 return createStringError(errc::invalid_argument, 207 "unrecognized format-version: 0x" + 208 utohexstr(formatVersion)); 209 210 while (!de.eof(cursor)) { 211 uint32_t sectionLength = de.getU32(cursor); 212 if (!cursor) 213 return cursor.takeError(); 214 215 if (sw) { 216 sw->startLine() << "Section " << ++sectionNumber << " {\n"; 217 sw->indent(); 218 } 219 220 if (sectionLength < 4 || cursor.tell() - 4 + sectionLength > section.size()) 221 return createStringError(errc::invalid_argument, 222 "invalid section length " + 223 Twine(sectionLength) + " at offset 0x" + 224 utohexstr(cursor.tell() - 4)); 225 226 if (Error e = parseSubsection(sectionLength)) 227 return e; 228 if (sw) { 229 sw->unindent(); 230 sw->startLine() << "}\n"; 231 } 232 } 233 234 return cursor.takeError(); 235 } 236