ELFAttributeParser.cpp 7.2 KB

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