XCOFFDumper.cpp 48 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218
  1. //===-- XCOFFDumper.cpp - XCOFF dumping utility -----------------*- C++ -*-===//
  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. // This file implements an XCOFF specific dumper for llvm-readobj.
  10. //
  11. //===----------------------------------------------------------------------===//
  12. #include "ObjDumper.h"
  13. #include "llvm-readobj.h"
  14. #include "llvm/Object/XCOFFObjectFile.h"
  15. #include "llvm/Support/FormattedStream.h"
  16. #include "llvm/Support/ScopedPrinter.h"
  17. #include <ctime>
  18. using namespace llvm;
  19. using namespace object;
  20. namespace {
  21. class XCOFFDumper : public ObjDumper {
  22. public:
  23. XCOFFDumper(const XCOFFObjectFile &Obj, ScopedPrinter &Writer)
  24. : ObjDumper(Writer, Obj.getFileName()), Obj(Obj) {}
  25. void printFileHeaders() override;
  26. void printAuxiliaryHeader() override;
  27. void printSectionHeaders() override;
  28. void printRelocations() override;
  29. void printSymbols() override;
  30. void printDynamicSymbols() override;
  31. void printUnwindInfo() override;
  32. void printStackMap() const override;
  33. void printNeededLibraries() override;
  34. void printStringTable() override;
  35. void printExceptionSection() override;
  36. void printLoaderSection(bool PrintHeader, bool PrintSymbols,
  37. bool PrintRelocations) override;
  38. ScopedPrinter &getScopedPrinter() const { return W; }
  39. private:
  40. template <typename T> void printSectionHeaders(ArrayRef<T> Sections);
  41. template <typename T> void printGenericSectionHeader(T &Sec) const;
  42. template <typename T> void printOverflowSectionHeader(T &Sec) const;
  43. template <typename T>
  44. void printExceptionSectionEntry(const T &ExceptionSectEnt) const;
  45. template <typename T> void printExceptionSectionEntries() const;
  46. template <typename T> const T *getAuxEntPtr(uintptr_t AuxAddress);
  47. void printFileAuxEnt(const XCOFFFileAuxEnt *AuxEntPtr);
  48. void printCsectAuxEnt(XCOFFCsectAuxRef AuxEntRef);
  49. void printSectAuxEntForStat(const XCOFFSectAuxEntForStat *AuxEntPtr);
  50. void printExceptionAuxEnt(const XCOFFExceptionAuxEnt *AuxEntPtr);
  51. void printFunctionAuxEnt(const XCOFFFunctionAuxEnt32 *AuxEntPtr);
  52. void printFunctionAuxEnt(const XCOFFFunctionAuxEnt64 *AuxEntPtr);
  53. void printBlockAuxEnt(const XCOFFBlockAuxEnt32 *AuxEntPtr);
  54. void printBlockAuxEnt(const XCOFFBlockAuxEnt64 *AuxEntPtr);
  55. template <typename T> void printSectAuxEntForDWARF(const T *AuxEntPtr);
  56. void printSymbol(const SymbolRef &);
  57. template <typename RelTy> void printRelocation(RelTy Reloc);
  58. template <typename Shdr, typename RelTy>
  59. void printRelocations(ArrayRef<Shdr> Sections);
  60. void printAuxiliaryHeader(const XCOFFAuxiliaryHeader32 *AuxHeader);
  61. void printAuxiliaryHeader(const XCOFFAuxiliaryHeader64 *AuxHeader);
  62. void printLoaderSectionHeader(uintptr_t LoaderSectAddr);
  63. void printLoaderSectionSymbols(uintptr_t LoaderSectAddr);
  64. template <typename LoaderSectionSymbolEntry, typename LoaderSectionHeader>
  65. void printLoaderSectionSymbolsHelper(uintptr_t LoaderSectAddr);
  66. template <typename LoadSectionRelocTy>
  67. void printLoaderSectionRelocationEntry(LoadSectionRelocTy *LoaderSecRelEntPtr,
  68. StringRef SymbolName);
  69. void printLoaderSectionRelocationEntries(uintptr_t LoaderSectAddr);
  70. template <typename LoaderSectionHeader, typename LoaderSectionSymbolEntry,
  71. typename LoaderSectionRelocationEntry>
  72. void printLoaderSectionRelocationEntriesHelper(uintptr_t LoaderSectAddr);
  73. const XCOFFObjectFile &Obj;
  74. const static int32_t FirstSymIdxOfLoaderSec = 3;
  75. };
  76. } // anonymous namespace
  77. void XCOFFDumper::printFileHeaders() {
  78. DictScope DS(W, "FileHeader");
  79. W.printHex("Magic", Obj.getMagic());
  80. W.printNumber("NumberOfSections", Obj.getNumberOfSections());
  81. // Negative timestamp values are reserved for future use.
  82. int32_t TimeStamp = Obj.getTimeStamp();
  83. if (TimeStamp > 0) {
  84. // This handling of the time stamp assumes that the host system's time_t is
  85. // compatible with AIX time_t. If a platform is not compatible, the lit
  86. // tests will let us know.
  87. time_t TimeDate = TimeStamp;
  88. char FormattedTime[21] = {};
  89. size_t BytesWritten =
  90. strftime(FormattedTime, 21, "%Y-%m-%dT%H:%M:%SZ", gmtime(&TimeDate));
  91. if (BytesWritten)
  92. W.printHex("TimeStamp", FormattedTime, TimeStamp);
  93. else
  94. W.printHex("Timestamp", TimeStamp);
  95. } else {
  96. W.printHex("TimeStamp", TimeStamp == 0 ? "None" : "Reserved Value",
  97. TimeStamp);
  98. }
  99. // The number of symbol table entries is an unsigned value in 64-bit objects
  100. // and a signed value (with negative values being 'reserved') in 32-bit
  101. // objects.
  102. if (Obj.is64Bit()) {
  103. W.printHex("SymbolTableOffset", Obj.getSymbolTableOffset64());
  104. W.printNumber("SymbolTableEntries", Obj.getNumberOfSymbolTableEntries64());
  105. } else {
  106. W.printHex("SymbolTableOffset", Obj.getSymbolTableOffset32());
  107. int32_t SymTabEntries = Obj.getRawNumberOfSymbolTableEntries32();
  108. if (SymTabEntries >= 0)
  109. W.printNumber("SymbolTableEntries", SymTabEntries);
  110. else
  111. W.printHex("SymbolTableEntries", "Reserved Value", SymTabEntries);
  112. }
  113. W.printHex("OptionalHeaderSize", Obj.getOptionalHeaderSize());
  114. W.printHex("Flags", Obj.getFlags());
  115. // TODO FIXME Add support for the auxiliary header (if any) once
  116. // XCOFFObjectFile has the necessary support.
  117. }
  118. void XCOFFDumper::printAuxiliaryHeader() {
  119. DictScope DS(W, "AuxiliaryHeader");
  120. if (Obj.is64Bit())
  121. printAuxiliaryHeader(Obj.auxiliaryHeader64());
  122. else
  123. printAuxiliaryHeader(Obj.auxiliaryHeader32());
  124. }
  125. void XCOFFDumper::printSectionHeaders() {
  126. if (Obj.is64Bit())
  127. printSectionHeaders(Obj.sections64());
  128. else
  129. printSectionHeaders(Obj.sections32());
  130. }
  131. void XCOFFDumper::printLoaderSection(bool PrintHeader, bool PrintSymbols,
  132. bool PrintRelocations) {
  133. DictScope DS(W, "Loader Section");
  134. Expected<uintptr_t> LoaderSectionAddrOrError =
  135. Obj.getSectionFileOffsetToRawData(XCOFF::STYP_LOADER);
  136. if (!LoaderSectionAddrOrError) {
  137. reportUniqueWarning(LoaderSectionAddrOrError.takeError());
  138. return;
  139. }
  140. uintptr_t LoaderSectionAddr = LoaderSectionAddrOrError.get();
  141. if (LoaderSectionAddr == 0)
  142. return;
  143. W.indent();
  144. if (PrintHeader)
  145. printLoaderSectionHeader(LoaderSectionAddr);
  146. if (PrintSymbols)
  147. printLoaderSectionSymbols(LoaderSectionAddr);
  148. if (PrintRelocations)
  149. printLoaderSectionRelocationEntries(LoaderSectionAddr);
  150. W.unindent();
  151. }
  152. void XCOFFDumper::printLoaderSectionHeader(uintptr_t LoaderSectionAddr) {
  153. DictScope DS(W, "Loader Section Header");
  154. auto PrintLoadSecHeaderCommon = [&](const auto *LDHeader) {
  155. W.printNumber("Version", LDHeader->Version);
  156. W.printNumber("NumberOfSymbolEntries", LDHeader->NumberOfSymTabEnt);
  157. W.printNumber("NumberOfRelocationEntries", LDHeader->NumberOfRelTabEnt);
  158. W.printNumber("LengthOfImportFileIDStringTable",
  159. LDHeader->LengthOfImpidStrTbl);
  160. W.printNumber("NumberOfImportFileIDs", LDHeader->NumberOfImpid);
  161. W.printHex("OffsetToImportFileIDs", LDHeader->OffsetToImpid);
  162. W.printNumber("LengthOfStringTable", LDHeader->LengthOfStrTbl);
  163. W.printHex("OffsetToStringTable", LDHeader->OffsetToStrTbl);
  164. };
  165. if (Obj.is64Bit()) {
  166. const LoaderSectionHeader64 *LoaderSec64 =
  167. reinterpret_cast<const LoaderSectionHeader64 *>(LoaderSectionAddr);
  168. PrintLoadSecHeaderCommon(LoaderSec64);
  169. W.printHex("OffsetToSymbolTable", LoaderSec64->OffsetToSymTbl);
  170. W.printHex("OffsetToRelocationEntries", LoaderSec64->OffsetToRelEnt);
  171. } else {
  172. const LoaderSectionHeader32 *LoaderSec32 =
  173. reinterpret_cast<const LoaderSectionHeader32 *>(LoaderSectionAddr);
  174. PrintLoadSecHeaderCommon(LoaderSec32);
  175. }
  176. }
  177. const EnumEntry<XCOFF::StorageClass> SymStorageClass[] = {
  178. #define ECase(X) \
  179. { #X, XCOFF::X }
  180. ECase(C_NULL), ECase(C_AUTO), ECase(C_EXT), ECase(C_STAT),
  181. ECase(C_REG), ECase(C_EXTDEF), ECase(C_LABEL), ECase(C_ULABEL),
  182. ECase(C_MOS), ECase(C_ARG), ECase(C_STRTAG), ECase(C_MOU),
  183. ECase(C_UNTAG), ECase(C_TPDEF), ECase(C_USTATIC), ECase(C_ENTAG),
  184. ECase(C_MOE), ECase(C_REGPARM), ECase(C_FIELD), ECase(C_BLOCK),
  185. ECase(C_FCN), ECase(C_EOS), ECase(C_FILE), ECase(C_LINE),
  186. ECase(C_ALIAS), ECase(C_HIDDEN), ECase(C_HIDEXT), ECase(C_BINCL),
  187. ECase(C_EINCL), ECase(C_INFO), ECase(C_WEAKEXT), ECase(C_DWARF),
  188. ECase(C_GSYM), ECase(C_LSYM), ECase(C_PSYM), ECase(C_RSYM),
  189. ECase(C_RPSYM), ECase(C_STSYM), ECase(C_TCSYM), ECase(C_BCOMM),
  190. ECase(C_ECOML), ECase(C_ECOMM), ECase(C_DECL), ECase(C_ENTRY),
  191. ECase(C_FUN), ECase(C_BSTAT), ECase(C_ESTAT), ECase(C_GTLS),
  192. ECase(C_STTLS), ECase(C_EFCN)
  193. #undef ECase
  194. };
  195. template <typename LoaderSectionSymbolEntry, typename LoaderSectionHeader>
  196. void XCOFFDumper::printLoaderSectionSymbolsHelper(uintptr_t LoaderSectionAddr) {
  197. const LoaderSectionHeader *LoadSecHeader =
  198. reinterpret_cast<const LoaderSectionHeader *>(LoaderSectionAddr);
  199. const LoaderSectionSymbolEntry *LoadSecSymEntPtr =
  200. reinterpret_cast<LoaderSectionSymbolEntry *>(
  201. LoaderSectionAddr + uintptr_t(LoadSecHeader->getOffsetToSymTbl()));
  202. for (uint32_t i = 0; i < LoadSecHeader->NumberOfSymTabEnt;
  203. ++i, ++LoadSecSymEntPtr) {
  204. if (Error E = Binary::checkOffset(
  205. Obj.getMemoryBufferRef(),
  206. LoaderSectionAddr + uintptr_t(LoadSecHeader->getOffsetToSymTbl()) +
  207. (i * sizeof(LoaderSectionSymbolEntry)),
  208. sizeof(LoaderSectionSymbolEntry))) {
  209. reportUniqueWarning(std::move(E));
  210. return;
  211. }
  212. Expected<StringRef> SymbolNameOrErr =
  213. LoadSecSymEntPtr->getSymbolName(LoadSecHeader);
  214. if (!SymbolNameOrErr) {
  215. reportUniqueWarning(SymbolNameOrErr.takeError());
  216. return;
  217. }
  218. DictScope DS(W, "Symbol");
  219. W.printString("Name", SymbolNameOrErr.get());
  220. W.printHex("Virtual Address", LoadSecSymEntPtr->Value);
  221. W.printNumber("SectionNum", LoadSecSymEntPtr->SectionNumber);
  222. W.printHex("SymbolType", LoadSecSymEntPtr->SymbolType);
  223. W.printEnum("StorageClass",
  224. static_cast<uint8_t>(LoadSecSymEntPtr->StorageClass),
  225. ArrayRef(SymStorageClass));
  226. W.printHex("ImportFileID", LoadSecSymEntPtr->ImportFileID);
  227. W.printNumber("ParameterTypeCheck", LoadSecSymEntPtr->ParameterTypeCheck);
  228. }
  229. }
  230. void XCOFFDumper::printLoaderSectionSymbols(uintptr_t LoaderSectionAddr) {
  231. DictScope DS(W, "Loader Section Symbols");
  232. if (Obj.is64Bit())
  233. printLoaderSectionSymbolsHelper<LoaderSectionSymbolEntry64,
  234. LoaderSectionHeader64>(LoaderSectionAddr);
  235. else
  236. printLoaderSectionSymbolsHelper<LoaderSectionSymbolEntry32,
  237. LoaderSectionHeader32>(LoaderSectionAddr);
  238. }
  239. const EnumEntry<XCOFF::RelocationType> RelocationTypeNameclass[] = {
  240. #define ECase(X) \
  241. { #X, XCOFF::X }
  242. ECase(R_POS), ECase(R_RL), ECase(R_RLA), ECase(R_NEG),
  243. ECase(R_REL), ECase(R_TOC), ECase(R_TRL), ECase(R_TRLA),
  244. ECase(R_GL), ECase(R_TCL), ECase(R_REF), ECase(R_BA),
  245. ECase(R_BR), ECase(R_RBA), ECase(R_RBR), ECase(R_TLS),
  246. ECase(R_TLS_IE), ECase(R_TLS_LD), ECase(R_TLS_LE), ECase(R_TLSM),
  247. ECase(R_TLSML), ECase(R_TOCU), ECase(R_TOCL)
  248. #undef ECase
  249. };
  250. // From the XCOFF specification: there are five implicit external symbols, one
  251. // each for the .text, .data, .bss, .tdata, and .tbss sections. These symbols
  252. // are referenced from the relocation table entries using symbol table index
  253. // values 0, 1, 2, -1, and -2, respectively.
  254. static const char *getImplicitLoaderSectionSymName(int SymIndx) {
  255. switch (SymIndx) {
  256. default:
  257. return "Unkown Symbol Name";
  258. case -2:
  259. return ".tbss";
  260. case -1:
  261. return ".tdata";
  262. case 0:
  263. return ".text";
  264. case 1:
  265. return ".data";
  266. case 2:
  267. return ".bss";
  268. }
  269. }
  270. template <typename LoadSectionRelocTy>
  271. void XCOFFDumper::printLoaderSectionRelocationEntry(
  272. LoadSectionRelocTy *LoaderSecRelEntPtr, StringRef SymbolName) {
  273. uint16_t Type = LoaderSecRelEntPtr->Type;
  274. if (opts::ExpandRelocs) {
  275. DictScope DS(W, "Relocation");
  276. auto IsRelocationSigned = [](uint8_t Info) {
  277. return Info & XCOFF::XR_SIGN_INDICATOR_MASK;
  278. };
  279. auto IsFixupIndicated = [](uint8_t Info) {
  280. return Info & XCOFF::XR_FIXUP_INDICATOR_MASK;
  281. };
  282. auto GetRelocatedLength = [](uint8_t Info) {
  283. // The relocation encodes the bit length being relocated minus 1. Add
  284. // back
  285. // the 1 to get the actual length being relocated.
  286. return (Info & XCOFF::XR_BIASED_LENGTH_MASK) + 1;
  287. };
  288. uint8_t Info = Type >> 8;
  289. W.printHex("Virtual Address", LoaderSecRelEntPtr->VirtualAddr);
  290. W.printNumber("Symbol", SymbolName, LoaderSecRelEntPtr->SymbolIndex);
  291. W.printString("IsSigned", IsRelocationSigned(Info) ? "Yes" : "No");
  292. W.printNumber("FixupBitValue", IsFixupIndicated(Info) ? 1 : 0);
  293. W.printNumber("Length", GetRelocatedLength(Info));
  294. W.printEnum("Type", static_cast<uint8_t>(Type),
  295. ArrayRef(RelocationTypeNameclass));
  296. W.printNumber("SectionNumber", LoaderSecRelEntPtr->SectionNum);
  297. } else {
  298. W.startLine() << format_hex(LoaderSecRelEntPtr->VirtualAddr,
  299. Obj.is64Bit() ? 18 : 10)
  300. << " " << format_hex(Type, 6) << " ("
  301. << XCOFF::getRelocationTypeString(
  302. static_cast<XCOFF::RelocationType>(Type))
  303. << ")" << format_decimal(LoaderSecRelEntPtr->SectionNum, 8)
  304. << " " << SymbolName << " ("
  305. << LoaderSecRelEntPtr->SymbolIndex << ")\n";
  306. }
  307. }
  308. template <typename LoaderSectionHeader, typename LoaderSectionSymbolEntry,
  309. typename LoaderSectionRelocationEntry>
  310. void XCOFFDumper::printLoaderSectionRelocationEntriesHelper(
  311. uintptr_t LoaderSectionAddr) {
  312. const LoaderSectionHeader *LoaderSec =
  313. reinterpret_cast<const LoaderSectionHeader *>(LoaderSectionAddr);
  314. const LoaderSectionRelocationEntry *LoaderSecRelEntPtr =
  315. reinterpret_cast<const LoaderSectionRelocationEntry *>(
  316. LoaderSectionAddr + uintptr_t(LoaderSec->getOffsetToRelEnt()));
  317. if (!opts::ExpandRelocs)
  318. W.startLine() << center_justify("Vaddr", Obj.is64Bit() ? 18 : 10)
  319. << center_justify("Type", 15) << right_justify("SecNum", 8)
  320. << center_justify("SymbolName (Index) ", 24) << "\n";
  321. for (uint32_t i = 0; i < LoaderSec->NumberOfRelTabEnt;
  322. ++i, ++LoaderSecRelEntPtr) {
  323. StringRef SymbolName;
  324. if (LoaderSecRelEntPtr->SymbolIndex >= FirstSymIdxOfLoaderSec) {
  325. // Because there are implicit symbol index values (-2, -1, 0, 1, 2),
  326. // LoaderSecRelEnt.SymbolIndex - FirstSymIdxOfLoaderSec will get the
  327. // real symbol from the symbol table.
  328. const uint64_t SymOffset =
  329. (LoaderSecRelEntPtr->SymbolIndex - FirstSymIdxOfLoaderSec) *
  330. sizeof(LoaderSectionSymbolEntry);
  331. const LoaderSectionSymbolEntry *LoaderSecRelSymEntPtr =
  332. reinterpret_cast<LoaderSectionSymbolEntry *>(
  333. LoaderSectionAddr + uintptr_t(LoaderSec->getOffsetToSymTbl()) +
  334. SymOffset);
  335. Expected<StringRef> SymbolNameOrErr =
  336. LoaderSecRelSymEntPtr->getSymbolName(LoaderSec);
  337. if (!SymbolNameOrErr) {
  338. reportUniqueWarning(SymbolNameOrErr.takeError());
  339. return;
  340. }
  341. SymbolName = SymbolNameOrErr.get();
  342. } else
  343. SymbolName =
  344. getImplicitLoaderSectionSymName(LoaderSecRelEntPtr->SymbolIndex);
  345. printLoaderSectionRelocationEntry(LoaderSecRelEntPtr, SymbolName);
  346. }
  347. }
  348. void XCOFFDumper::printLoaderSectionRelocationEntries(
  349. uintptr_t LoaderSectionAddr) {
  350. DictScope DS(W, "Loader Section Relocations");
  351. if (Obj.is64Bit())
  352. printLoaderSectionRelocationEntriesHelper<LoaderSectionHeader64,
  353. LoaderSectionSymbolEntry64,
  354. LoaderSectionRelocationEntry64>(
  355. LoaderSectionAddr);
  356. else
  357. printLoaderSectionRelocationEntriesHelper<LoaderSectionHeader32,
  358. LoaderSectionSymbolEntry32,
  359. LoaderSectionRelocationEntry32>(
  360. LoaderSectionAddr);
  361. }
  362. template <typename T>
  363. void XCOFFDumper::printExceptionSectionEntry(const T &ExceptionSectEnt) const {
  364. if (ExceptionSectEnt.getReason())
  365. W.printHex("Trap Instr Addr", ExceptionSectEnt.getTrapInstAddr());
  366. else {
  367. uint32_t SymIdx = ExceptionSectEnt.getSymbolIndex();
  368. Expected<StringRef> ErrOrSymbolName = Obj.getSymbolNameByIndex(SymIdx);
  369. if (Error E = ErrOrSymbolName.takeError()) {
  370. reportUniqueWarning(std::move(E));
  371. return;
  372. }
  373. StringRef SymName = *ErrOrSymbolName;
  374. W.printNumber("Symbol", SymName, SymIdx);
  375. }
  376. W.printNumber("LangID", ExceptionSectEnt.getLangID());
  377. W.printNumber("Reason", ExceptionSectEnt.getReason());
  378. }
  379. template <typename T> void XCOFFDumper::printExceptionSectionEntries() const {
  380. Expected<ArrayRef<T>> ExceptSectEntsOrErr = Obj.getExceptionEntries<T>();
  381. if (Error E = ExceptSectEntsOrErr.takeError()) {
  382. reportUniqueWarning(std::move(E));
  383. return;
  384. }
  385. ArrayRef<T> ExceptSectEnts = *ExceptSectEntsOrErr;
  386. DictScope DS(W, "Exception section");
  387. if (ExceptSectEnts.empty())
  388. return;
  389. for (auto &Ent : ExceptSectEnts)
  390. printExceptionSectionEntry(Ent);
  391. }
  392. void XCOFFDumper::printExceptionSection() {
  393. if (Obj.is64Bit())
  394. printExceptionSectionEntries<ExceptionSectionEntry64>();
  395. else
  396. printExceptionSectionEntries<ExceptionSectionEntry32>();
  397. }
  398. void XCOFFDumper::printRelocations() {
  399. if (Obj.is64Bit())
  400. printRelocations<XCOFFSectionHeader64, XCOFFRelocation64>(Obj.sections64());
  401. else
  402. printRelocations<XCOFFSectionHeader32, XCOFFRelocation32>(Obj.sections32());
  403. }
  404. template <typename RelTy> void XCOFFDumper::printRelocation(RelTy Reloc) {
  405. Expected<StringRef> ErrOrSymbolName =
  406. Obj.getSymbolNameByIndex(Reloc.SymbolIndex);
  407. if (Error E = ErrOrSymbolName.takeError()) {
  408. reportUniqueWarning(std::move(E));
  409. return;
  410. }
  411. StringRef SymbolName = *ErrOrSymbolName;
  412. StringRef RelocName = XCOFF::getRelocationTypeString(Reloc.Type);
  413. if (opts::ExpandRelocs) {
  414. DictScope Group(W, "Relocation");
  415. W.printHex("Virtual Address", Reloc.VirtualAddress);
  416. W.printNumber("Symbol", SymbolName, Reloc.SymbolIndex);
  417. W.printString("IsSigned", Reloc.isRelocationSigned() ? "Yes" : "No");
  418. W.printNumber("FixupBitValue", Reloc.isFixupIndicated() ? 1 : 0);
  419. W.printNumber("Length", Reloc.getRelocatedLength());
  420. W.printEnum("Type", (uint8_t)Reloc.Type, ArrayRef(RelocationTypeNameclass));
  421. } else {
  422. raw_ostream &OS = W.startLine();
  423. OS << W.hex(Reloc.VirtualAddress) << " " << RelocName << " " << SymbolName
  424. << "(" << Reloc.SymbolIndex << ") " << W.hex(Reloc.Info) << "\n";
  425. }
  426. }
  427. template <typename Shdr, typename RelTy>
  428. void XCOFFDumper::printRelocations(ArrayRef<Shdr> Sections) {
  429. ListScope LS(W, "Relocations");
  430. uint16_t Index = 0;
  431. for (const Shdr &Sec : Sections) {
  432. ++Index;
  433. // Only the .text, .data, .tdata, and STYP_DWARF sections have relocation.
  434. if (Sec.Flags != XCOFF::STYP_TEXT && Sec.Flags != XCOFF::STYP_DATA &&
  435. Sec.Flags != XCOFF::STYP_TDATA && Sec.Flags != XCOFF::STYP_DWARF)
  436. continue;
  437. Expected<ArrayRef<RelTy>> ErrOrRelocations = Obj.relocations<Shdr, RelTy>(Sec);
  438. if (Error E = ErrOrRelocations.takeError()) {
  439. reportUniqueWarning(std::move(E));
  440. continue;
  441. }
  442. const ArrayRef<RelTy> Relocations = *ErrOrRelocations;
  443. if (Relocations.empty())
  444. continue;
  445. W.startLine() << "Section (index: " << Index << ") " << Sec.getName()
  446. << " {\n";
  447. W.indent();
  448. for (const RelTy Reloc : Relocations)
  449. printRelocation(Reloc);
  450. W.unindent();
  451. W.startLine() << "}\n";
  452. }
  453. }
  454. const EnumEntry<XCOFF::CFileStringType> FileStringType[] = {
  455. #define ECase(X) \
  456. { #X, XCOFF::X }
  457. ECase(XFT_FN), ECase(XFT_CT), ECase(XFT_CV), ECase(XFT_CD)
  458. #undef ECase
  459. };
  460. const EnumEntry<XCOFF::SymbolAuxType> SymAuxType[] = {
  461. #define ECase(X) \
  462. { #X, XCOFF::X }
  463. ECase(AUX_EXCEPT), ECase(AUX_FCN), ECase(AUX_SYM), ECase(AUX_FILE),
  464. ECase(AUX_CSECT), ECase(AUX_SECT)
  465. #undef ECase
  466. };
  467. void XCOFFDumper::printFileAuxEnt(const XCOFFFileAuxEnt *AuxEntPtr) {
  468. assert((!Obj.is64Bit() || AuxEntPtr->AuxType == XCOFF::AUX_FILE) &&
  469. "Mismatched auxiliary type!");
  470. StringRef FileName =
  471. unwrapOrError(Obj.getFileName(), Obj.getCFileName(AuxEntPtr));
  472. DictScope SymDs(W, "File Auxiliary Entry");
  473. W.printNumber("Index",
  474. Obj.getSymbolIndex(reinterpret_cast<uintptr_t>(AuxEntPtr)));
  475. W.printString("Name", FileName);
  476. W.printEnum("Type", static_cast<uint8_t>(AuxEntPtr->Type),
  477. ArrayRef(FileStringType));
  478. if (Obj.is64Bit()) {
  479. W.printEnum("Auxiliary Type", static_cast<uint8_t>(AuxEntPtr->AuxType),
  480. ArrayRef(SymAuxType));
  481. }
  482. }
  483. static const EnumEntry<XCOFF::StorageMappingClass> CsectStorageMappingClass[] =
  484. {
  485. #define ECase(X) \
  486. { #X, XCOFF::X }
  487. ECase(XMC_PR), ECase(XMC_RO), ECase(XMC_DB), ECase(XMC_GL),
  488. ECase(XMC_XO), ECase(XMC_SV), ECase(XMC_SV64), ECase(XMC_SV3264),
  489. ECase(XMC_TI), ECase(XMC_TB), ECase(XMC_RW), ECase(XMC_TC0),
  490. ECase(XMC_TC), ECase(XMC_TD), ECase(XMC_DS), ECase(XMC_UA),
  491. ECase(XMC_BS), ECase(XMC_UC), ECase(XMC_TL), ECase(XMC_UL),
  492. ECase(XMC_TE)
  493. #undef ECase
  494. };
  495. const EnumEntry<XCOFF::SymbolType> CsectSymbolTypeClass[] = {
  496. #define ECase(X) \
  497. { #X, XCOFF::X }
  498. ECase(XTY_ER), ECase(XTY_SD), ECase(XTY_LD), ECase(XTY_CM)
  499. #undef ECase
  500. };
  501. void XCOFFDumper::printCsectAuxEnt(XCOFFCsectAuxRef AuxEntRef) {
  502. assert((!Obj.is64Bit() || AuxEntRef.getAuxType64() == XCOFF::AUX_CSECT) &&
  503. "Mismatched auxiliary type!");
  504. DictScope SymDs(W, "CSECT Auxiliary Entry");
  505. W.printNumber("Index", Obj.getSymbolIndex(AuxEntRef.getEntryAddress()));
  506. W.printNumber(AuxEntRef.isLabel() ? "ContainingCsectSymbolIndex"
  507. : "SectionLen",
  508. AuxEntRef.getSectionOrLength());
  509. W.printHex("ParameterHashIndex", AuxEntRef.getParameterHashIndex());
  510. W.printHex("TypeChkSectNum", AuxEntRef.getTypeChkSectNum());
  511. // Print out symbol alignment and type.
  512. W.printNumber("SymbolAlignmentLog2", AuxEntRef.getAlignmentLog2());
  513. W.printEnum("SymbolType", AuxEntRef.getSymbolType(),
  514. ArrayRef(CsectSymbolTypeClass));
  515. W.printEnum("StorageMappingClass",
  516. static_cast<uint8_t>(AuxEntRef.getStorageMappingClass()),
  517. ArrayRef(CsectStorageMappingClass));
  518. if (Obj.is64Bit()) {
  519. W.printEnum("Auxiliary Type", static_cast<uint8_t>(XCOFF::AUX_CSECT),
  520. ArrayRef(SymAuxType));
  521. } else {
  522. W.printHex("StabInfoIndex", AuxEntRef.getStabInfoIndex32());
  523. W.printHex("StabSectNum", AuxEntRef.getStabSectNum32());
  524. }
  525. }
  526. void XCOFFDumper::printSectAuxEntForStat(
  527. const XCOFFSectAuxEntForStat *AuxEntPtr) {
  528. assert(!Obj.is64Bit() && "32-bit interface called on 64-bit object file.");
  529. DictScope SymDs(W, "Sect Auxiliary Entry For Stat");
  530. W.printNumber("Index",
  531. Obj.getSymbolIndex(reinterpret_cast<uintptr_t>(AuxEntPtr)));
  532. W.printNumber("SectionLength", AuxEntPtr->SectionLength);
  533. // Unlike the corresponding fields in the section header, NumberOfRelocEnt
  534. // and NumberOfLineNum do not handle values greater than 65535.
  535. W.printNumber("NumberOfRelocEnt", AuxEntPtr->NumberOfRelocEnt);
  536. W.printNumber("NumberOfLineNum", AuxEntPtr->NumberOfLineNum);
  537. }
  538. void XCOFFDumper::printExceptionAuxEnt(const XCOFFExceptionAuxEnt *AuxEntPtr) {
  539. assert(Obj.is64Bit() && "64-bit interface called on 32-bit object file.");
  540. DictScope SymDs(W, "Exception Auxiliary Entry");
  541. W.printNumber("Index",
  542. Obj.getSymbolIndex(reinterpret_cast<uintptr_t>(AuxEntPtr)));
  543. W.printHex("OffsetToExceptionTable", AuxEntPtr->OffsetToExceptionTbl);
  544. W.printHex("SizeOfFunction", AuxEntPtr->SizeOfFunction);
  545. W.printNumber("SymbolIndexOfNextBeyond", AuxEntPtr->SymIdxOfNextBeyond);
  546. W.printEnum("Auxiliary Type", static_cast<uint8_t>(AuxEntPtr->AuxType),
  547. ArrayRef(SymAuxType));
  548. }
  549. void XCOFFDumper::printFunctionAuxEnt(const XCOFFFunctionAuxEnt32 *AuxEntPtr) {
  550. assert(!Obj.is64Bit() && "32-bit interface called on 64-bit object file.");
  551. DictScope SymDs(W, "Function Auxiliary Entry");
  552. W.printNumber("Index",
  553. Obj.getSymbolIndex(reinterpret_cast<uintptr_t>(AuxEntPtr)));
  554. W.printHex("OffsetToExceptionTable", AuxEntPtr->OffsetToExceptionTbl);
  555. W.printHex("SizeOfFunction", AuxEntPtr->SizeOfFunction);
  556. W.printHex("PointerToLineNum", AuxEntPtr->PtrToLineNum);
  557. W.printNumber("SymbolIndexOfNextBeyond", AuxEntPtr->SymIdxOfNextBeyond);
  558. }
  559. void XCOFFDumper::printFunctionAuxEnt(const XCOFFFunctionAuxEnt64 *AuxEntPtr) {
  560. assert(Obj.is64Bit() && "64-bit interface called on 32-bit object file.");
  561. DictScope SymDs(W, "Function Auxiliary Entry");
  562. W.printNumber("Index",
  563. Obj.getSymbolIndex(reinterpret_cast<uintptr_t>(AuxEntPtr)));
  564. W.printHex("SizeOfFunction", AuxEntPtr->SizeOfFunction);
  565. W.printHex("PointerToLineNum", AuxEntPtr->PtrToLineNum);
  566. W.printNumber("SymbolIndexOfNextBeyond", AuxEntPtr->SymIdxOfNextBeyond);
  567. W.printEnum("Auxiliary Type", static_cast<uint8_t>(AuxEntPtr->AuxType),
  568. ArrayRef(SymAuxType));
  569. }
  570. void XCOFFDumper::printBlockAuxEnt(const XCOFFBlockAuxEnt32 *AuxEntPtr) {
  571. assert(!Obj.is64Bit() && "32-bit interface called on 64-bit object file.");
  572. DictScope SymDs(W, "Block Auxiliary Entry");
  573. W.printNumber("Index",
  574. Obj.getSymbolIndex(reinterpret_cast<uintptr_t>(AuxEntPtr)));
  575. W.printHex("LineNumber (High 2 Bytes)", AuxEntPtr->LineNumHi);
  576. W.printHex("LineNumber (Low 2 Bytes)", AuxEntPtr->LineNumLo);
  577. }
  578. void XCOFFDumper::printBlockAuxEnt(const XCOFFBlockAuxEnt64 *AuxEntPtr) {
  579. assert(Obj.is64Bit() && "64-bit interface called on 32-bit object file.");
  580. DictScope SymDs(W, "Block Auxiliary Entry");
  581. W.printNumber("Index",
  582. Obj.getSymbolIndex(reinterpret_cast<uintptr_t>(AuxEntPtr)));
  583. W.printHex("LineNumber", AuxEntPtr->LineNum);
  584. W.printEnum("Auxiliary Type", static_cast<uint8_t>(AuxEntPtr->AuxType),
  585. ArrayRef(SymAuxType));
  586. }
  587. template <typename T>
  588. void XCOFFDumper::printSectAuxEntForDWARF(const T *AuxEntPtr) {
  589. DictScope SymDs(W, "Sect Auxiliary Entry For DWARF");
  590. W.printNumber("Index",
  591. Obj.getSymbolIndex(reinterpret_cast<uintptr_t>(AuxEntPtr)));
  592. W.printHex("LengthOfSectionPortion", AuxEntPtr->LengthOfSectionPortion);
  593. W.printNumber("NumberOfRelocEntries", AuxEntPtr->NumberOfRelocEnt);
  594. if (Obj.is64Bit())
  595. W.printEnum("Auxiliary Type", static_cast<uint8_t>(XCOFF::AUX_SECT),
  596. ArrayRef(SymAuxType));
  597. }
  598. static StringRef GetSymbolValueName(XCOFF::StorageClass SC) {
  599. switch (SC) {
  600. case XCOFF::C_EXT:
  601. case XCOFF::C_WEAKEXT:
  602. case XCOFF::C_HIDEXT:
  603. case XCOFF::C_STAT:
  604. case XCOFF::C_FCN:
  605. case XCOFF::C_BLOCK:
  606. return "Value (RelocatableAddress)";
  607. case XCOFF::C_FILE:
  608. return "Value (SymbolTableIndex)";
  609. case XCOFF::C_DWARF:
  610. return "Value (OffsetInDWARF)";
  611. case XCOFF::C_FUN:
  612. case XCOFF::C_STSYM:
  613. case XCOFF::C_BINCL:
  614. case XCOFF::C_EINCL:
  615. case XCOFF::C_INFO:
  616. case XCOFF::C_BSTAT:
  617. case XCOFF::C_LSYM:
  618. case XCOFF::C_PSYM:
  619. case XCOFF::C_RPSYM:
  620. case XCOFF::C_RSYM:
  621. case XCOFF::C_ECOML:
  622. assert(false && "This StorageClass for the symbol is not yet implemented.");
  623. return "";
  624. default:
  625. return "Value";
  626. }
  627. }
  628. const EnumEntry<XCOFF::CFileLangId> CFileLangIdClass[] = {
  629. #define ECase(X) \
  630. { #X, XCOFF::X }
  631. ECase(TB_C), ECase(TB_CPLUSPLUS)
  632. #undef ECase
  633. };
  634. const EnumEntry<XCOFF::CFileCpuId> CFileCpuIdClass[] = {
  635. #define ECase(X) \
  636. { #X, XCOFF::X }
  637. ECase(TCPU_PPC64), ECase(TCPU_COM), ECase(TCPU_970)
  638. #undef ECase
  639. };
  640. template <typename T> const T *XCOFFDumper::getAuxEntPtr(uintptr_t AuxAddress) {
  641. const T *AuxEntPtr = reinterpret_cast<const T *>(AuxAddress);
  642. Obj.checkSymbolEntryPointer(reinterpret_cast<uintptr_t>(AuxEntPtr));
  643. return AuxEntPtr;
  644. }
  645. static void printUnexpectedRawAuxEnt(ScopedPrinter &W, uintptr_t AuxAddress) {
  646. W.startLine() << "!Unexpected raw auxiliary entry data:\n";
  647. W.startLine() << format_bytes(
  648. ArrayRef<uint8_t>(
  649. reinterpret_cast<const uint8_t *>(AuxAddress),
  650. XCOFF::SymbolTableEntrySize),
  651. std::nullopt, XCOFF::SymbolTableEntrySize)
  652. << "\n";
  653. }
  654. void XCOFFDumper::printSymbol(const SymbolRef &S) {
  655. DataRefImpl SymbolDRI = S.getRawDataRefImpl();
  656. XCOFFSymbolRef SymbolEntRef = Obj.toSymbolRef(SymbolDRI);
  657. uint8_t NumberOfAuxEntries = SymbolEntRef.getNumberOfAuxEntries();
  658. DictScope SymDs(W, "Symbol");
  659. StringRef SymbolName =
  660. unwrapOrError(Obj.getFileName(), SymbolEntRef.getName());
  661. uint32_t SymbolIdx = Obj.getSymbolIndex(SymbolEntRef.getEntryAddress());
  662. XCOFF::StorageClass SymbolClass = SymbolEntRef.getStorageClass();
  663. W.printNumber("Index", SymbolIdx);
  664. W.printString("Name", SymbolName);
  665. W.printHex(GetSymbolValueName(SymbolClass), SymbolEntRef.getValue());
  666. StringRef SectionName =
  667. unwrapOrError(Obj.getFileName(), Obj.getSymbolSectionName(SymbolEntRef));
  668. W.printString("Section", SectionName);
  669. if (SymbolClass == XCOFF::C_FILE) {
  670. W.printEnum("Source Language ID", SymbolEntRef.getLanguageIdForCFile(),
  671. ArrayRef(CFileLangIdClass));
  672. W.printEnum("CPU Version ID", SymbolEntRef.getCPUTypeIddForCFile(),
  673. ArrayRef(CFileCpuIdClass));
  674. } else
  675. W.printHex("Type", SymbolEntRef.getSymbolType());
  676. W.printEnum("StorageClass", static_cast<uint8_t>(SymbolClass),
  677. ArrayRef(SymStorageClass));
  678. W.printNumber("NumberOfAuxEntries", NumberOfAuxEntries);
  679. if (NumberOfAuxEntries == 0)
  680. return;
  681. auto checkNumOfAux = [=] {
  682. if (NumberOfAuxEntries > 1)
  683. reportUniqueWarning("the " +
  684. enumToString(static_cast<uint8_t>(SymbolClass),
  685. ArrayRef(SymStorageClass)) +
  686. " symbol at index " + Twine(SymbolIdx) +
  687. " should not have more than 1 "
  688. "auxiliary entry");
  689. };
  690. switch (SymbolClass) {
  691. case XCOFF::C_FILE:
  692. // If the symbol is C_FILE and has auxiliary entries...
  693. for (int I = 1; I <= NumberOfAuxEntries; I++) {
  694. uintptr_t AuxAddress = XCOFFObjectFile::getAdvancedSymbolEntryAddress(
  695. SymbolEntRef.getEntryAddress(), I);
  696. if (Obj.is64Bit() &&
  697. *Obj.getSymbolAuxType(AuxAddress) != XCOFF::SymbolAuxType::AUX_FILE) {
  698. printUnexpectedRawAuxEnt(W, AuxAddress);
  699. continue;
  700. }
  701. const XCOFFFileAuxEnt *FileAuxEntPtr =
  702. getAuxEntPtr<XCOFFFileAuxEnt>(AuxAddress);
  703. printFileAuxEnt(FileAuxEntPtr);
  704. }
  705. break;
  706. case XCOFF::C_EXT:
  707. case XCOFF::C_WEAKEXT:
  708. case XCOFF::C_HIDEXT: {
  709. // For 32-bit objects, print the function auxiliary symbol table entry. The
  710. // last one must be a CSECT auxiliary entry.
  711. // For 64-bit objects, both a function auxiliary entry and an exception
  712. // auxiliary entry may appear, print them in the loop and skip printing the
  713. // CSECT auxiliary entry, which will be printed outside the loop.
  714. for (int I = 1; I <= NumberOfAuxEntries; I++) {
  715. if (I == NumberOfAuxEntries && !Obj.is64Bit())
  716. break;
  717. uintptr_t AuxAddress = XCOFFObjectFile::getAdvancedSymbolEntryAddress(
  718. SymbolEntRef.getEntryAddress(), I);
  719. if (Obj.is64Bit()) {
  720. XCOFF::SymbolAuxType Type = *Obj.getSymbolAuxType(AuxAddress);
  721. if (Type == XCOFF::SymbolAuxType::AUX_CSECT)
  722. continue;
  723. if (Type == XCOFF::SymbolAuxType::AUX_FCN) {
  724. const XCOFFFunctionAuxEnt64 *AuxEntPtr =
  725. getAuxEntPtr<XCOFFFunctionAuxEnt64>(AuxAddress);
  726. printFunctionAuxEnt(AuxEntPtr);
  727. } else if (Type == XCOFF::SymbolAuxType::AUX_EXCEPT) {
  728. const XCOFFExceptionAuxEnt *AuxEntPtr =
  729. getAuxEntPtr<XCOFFExceptionAuxEnt>(AuxAddress);
  730. printExceptionAuxEnt(AuxEntPtr);
  731. } else {
  732. printUnexpectedRawAuxEnt(W, AuxAddress);
  733. }
  734. } else {
  735. const XCOFFFunctionAuxEnt32 *AuxEntPtr =
  736. getAuxEntPtr<XCOFFFunctionAuxEnt32>(AuxAddress);
  737. printFunctionAuxEnt(AuxEntPtr);
  738. }
  739. }
  740. // Print the CSECT auxiliary entry.
  741. auto ErrOrCsectAuxRef = SymbolEntRef.getXCOFFCsectAuxRef();
  742. if (!ErrOrCsectAuxRef)
  743. reportUniqueWarning(ErrOrCsectAuxRef.takeError());
  744. else
  745. printCsectAuxEnt(*ErrOrCsectAuxRef);
  746. break;
  747. }
  748. case XCOFF::C_STAT: {
  749. checkNumOfAux();
  750. const XCOFFSectAuxEntForStat *StatAuxEntPtr =
  751. getAuxEntPtr<XCOFFSectAuxEntForStat>(
  752. XCOFFObjectFile::getAdvancedSymbolEntryAddress(
  753. SymbolEntRef.getEntryAddress(), 1));
  754. printSectAuxEntForStat(StatAuxEntPtr);
  755. break;
  756. }
  757. case XCOFF::C_DWARF: {
  758. checkNumOfAux();
  759. uintptr_t AuxAddress = XCOFFObjectFile::getAdvancedSymbolEntryAddress(
  760. SymbolEntRef.getEntryAddress(), 1);
  761. if (Obj.is64Bit()) {
  762. const XCOFFSectAuxEntForDWARF64 *AuxEntPtr =
  763. getAuxEntPtr<XCOFFSectAuxEntForDWARF64>(AuxAddress);
  764. printSectAuxEntForDWARF<XCOFFSectAuxEntForDWARF64>(AuxEntPtr);
  765. } else {
  766. const XCOFFSectAuxEntForDWARF32 *AuxEntPtr =
  767. getAuxEntPtr<XCOFFSectAuxEntForDWARF32>(AuxAddress);
  768. printSectAuxEntForDWARF<XCOFFSectAuxEntForDWARF32>(AuxEntPtr);
  769. }
  770. break;
  771. }
  772. case XCOFF::C_BLOCK:
  773. case XCOFF::C_FCN: {
  774. checkNumOfAux();
  775. uintptr_t AuxAddress = XCOFFObjectFile::getAdvancedSymbolEntryAddress(
  776. SymbolEntRef.getEntryAddress(), 1);
  777. if (Obj.is64Bit()) {
  778. const XCOFFBlockAuxEnt64 *AuxEntPtr =
  779. getAuxEntPtr<XCOFFBlockAuxEnt64>(AuxAddress);
  780. printBlockAuxEnt(AuxEntPtr);
  781. } else {
  782. const XCOFFBlockAuxEnt32 *AuxEntPtr =
  783. getAuxEntPtr<XCOFFBlockAuxEnt32>(AuxAddress);
  784. printBlockAuxEnt(AuxEntPtr);
  785. }
  786. break;
  787. }
  788. default:
  789. for (int i = 1; i <= NumberOfAuxEntries; i++) {
  790. printUnexpectedRawAuxEnt(W,
  791. XCOFFObjectFile::getAdvancedSymbolEntryAddress(
  792. SymbolEntRef.getEntryAddress(), i));
  793. }
  794. break;
  795. }
  796. }
  797. void XCOFFDumper::printSymbols() {
  798. ListScope Group(W, "Symbols");
  799. for (const SymbolRef &S : Obj.symbols())
  800. printSymbol(S);
  801. }
  802. void XCOFFDumper::printStringTable() {
  803. DictScope DS(W, "StringTable");
  804. StringRef StrTable = Obj.getStringTable();
  805. uint32_t StrTabSize = StrTable.size();
  806. W.printNumber("Length", StrTabSize);
  807. // Print strings from the fifth byte, since the first four bytes contain the
  808. // length (in bytes) of the string table (including the length field).
  809. if (StrTabSize > 4)
  810. printAsStringList(StrTable, 4);
  811. }
  812. void XCOFFDumper::printDynamicSymbols() {
  813. llvm_unreachable("Unimplemented functionality for XCOFFDumper");
  814. }
  815. void XCOFFDumper::printUnwindInfo() {
  816. llvm_unreachable("Unimplemented functionality for XCOFFDumper");
  817. }
  818. void XCOFFDumper::printStackMap() const {
  819. llvm_unreachable("Unimplemented functionality for XCOFFDumper");
  820. }
  821. void XCOFFDumper::printNeededLibraries() {
  822. ListScope D(W, "NeededLibraries");
  823. auto ImportFilesOrError = Obj.getImportFileTable();
  824. if (!ImportFilesOrError) {
  825. reportUniqueWarning(ImportFilesOrError.takeError());
  826. return;
  827. }
  828. StringRef ImportFileTable = ImportFilesOrError.get();
  829. const char *CurrentStr = ImportFileTable.data();
  830. const char *TableEnd = ImportFileTable.end();
  831. // Default column width for names is 13 even if no names are that long.
  832. size_t BaseWidth = 13;
  833. // Get the max width of BASE columns.
  834. for (size_t StrIndex = 0; CurrentStr < TableEnd; ++StrIndex) {
  835. size_t CurrentLen = strlen(CurrentStr);
  836. CurrentStr += strlen(CurrentStr) + 1;
  837. if (StrIndex % 3 == 1)
  838. BaseWidth = std::max(BaseWidth, CurrentLen);
  839. }
  840. auto &OS = static_cast<formatted_raw_ostream &>(W.startLine());
  841. // Each entry consists of 3 strings: the path_name, base_name and
  842. // archive_member_name. The first entry is a default LIBPATH value and other
  843. // entries have no path_name. We just dump the base_name and
  844. // archive_member_name here.
  845. OS << left_justify("BASE", BaseWidth) << " MEMBER\n";
  846. CurrentStr = ImportFileTable.data();
  847. for (size_t StrIndex = 0; CurrentStr < TableEnd;
  848. ++StrIndex, CurrentStr += strlen(CurrentStr) + 1) {
  849. if (StrIndex >= 3 && StrIndex % 3 != 0) {
  850. if (StrIndex % 3 == 1)
  851. OS << " " << left_justify(CurrentStr, BaseWidth) << " ";
  852. else
  853. OS << CurrentStr << "\n";
  854. }
  855. }
  856. }
  857. const EnumEntry<XCOFF::SectionTypeFlags> SectionTypeFlagsNames[] = {
  858. #define ECase(X) \
  859. { #X, XCOFF::X }
  860. ECase(STYP_PAD), ECase(STYP_DWARF), ECase(STYP_TEXT),
  861. ECase(STYP_DATA), ECase(STYP_BSS), ECase(STYP_EXCEPT),
  862. ECase(STYP_INFO), ECase(STYP_TDATA), ECase(STYP_TBSS),
  863. ECase(STYP_LOADER), ECase(STYP_DEBUG), ECase(STYP_TYPCHK),
  864. ECase(STYP_OVRFLO)
  865. #undef ECase
  866. };
  867. template <typename T>
  868. void XCOFFDumper::printOverflowSectionHeader(T &Sec) const {
  869. if (Obj.is64Bit()) {
  870. reportWarning(make_error<StringError>("An 64-bit XCOFF object file may not "
  871. "contain an overflow section header.",
  872. object_error::parse_failed),
  873. Obj.getFileName());
  874. }
  875. W.printString("Name", Sec.getName());
  876. W.printNumber("NumberOfRelocations", Sec.PhysicalAddress);
  877. W.printNumber("NumberOfLineNumbers", Sec.VirtualAddress);
  878. W.printHex("Size", Sec.SectionSize);
  879. W.printHex("RawDataOffset", Sec.FileOffsetToRawData);
  880. W.printHex("RelocationPointer", Sec.FileOffsetToRelocationInfo);
  881. W.printHex("LineNumberPointer", Sec.FileOffsetToLineNumberInfo);
  882. W.printNumber("IndexOfSectionOverflowed", Sec.NumberOfRelocations);
  883. W.printNumber("IndexOfSectionOverflowed", Sec.NumberOfLineNumbers);
  884. }
  885. template <typename T>
  886. void XCOFFDumper::printGenericSectionHeader(T &Sec) const {
  887. W.printString("Name", Sec.getName());
  888. W.printHex("PhysicalAddress", Sec.PhysicalAddress);
  889. W.printHex("VirtualAddress", Sec.VirtualAddress);
  890. W.printHex("Size", Sec.SectionSize);
  891. W.printHex("RawDataOffset", Sec.FileOffsetToRawData);
  892. W.printHex("RelocationPointer", Sec.FileOffsetToRelocationInfo);
  893. W.printHex("LineNumberPointer", Sec.FileOffsetToLineNumberInfo);
  894. W.printNumber("NumberOfRelocations", Sec.NumberOfRelocations);
  895. W.printNumber("NumberOfLineNumbers", Sec.NumberOfLineNumbers);
  896. }
  897. enum PrintStyle { Hex, Number };
  898. template <typename T, typename V>
  899. static void printAuxMemberHelper(PrintStyle Style, const char *MemberName,
  900. const T &Member, const V *AuxHeader,
  901. uint16_t AuxSize, uint16_t &PartialFieldOffset,
  902. const char *&PartialFieldName,
  903. ScopedPrinter &W) {
  904. ptrdiff_t Offset = reinterpret_cast<const char *>(&Member) -
  905. reinterpret_cast<const char *>(AuxHeader);
  906. if (Offset + sizeof(Member) <= AuxSize)
  907. Style == Hex ? W.printHex(MemberName, Member)
  908. : W.printNumber(MemberName, Member);
  909. else if (Offset < AuxSize) {
  910. PartialFieldOffset = Offset;
  911. PartialFieldName = MemberName;
  912. }
  913. }
  914. template <class T>
  915. void checkAndPrintAuxHeaderParseError(const char *PartialFieldName,
  916. uint16_t PartialFieldOffset,
  917. uint16_t AuxSize, T &AuxHeader,
  918. XCOFFDumper *Dumper) {
  919. if (PartialFieldOffset < AuxSize) {
  920. Dumper->reportUniqueWarning(Twine("only partial field for ") +
  921. PartialFieldName + " at offset (" +
  922. Twine(PartialFieldOffset) + ")");
  923. Dumper->getScopedPrinter().printBinary(
  924. "Raw data", "",
  925. ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(&AuxHeader) +
  926. PartialFieldOffset,
  927. AuxSize - PartialFieldOffset));
  928. } else if (sizeof(AuxHeader) < AuxSize)
  929. Dumper->getScopedPrinter().printBinary(
  930. "Extra raw data", "",
  931. ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(&AuxHeader) +
  932. sizeof(AuxHeader),
  933. AuxSize - sizeof(AuxHeader)));
  934. }
  935. void XCOFFDumper::printAuxiliaryHeader(
  936. const XCOFFAuxiliaryHeader32 *AuxHeader) {
  937. if (AuxHeader == nullptr)
  938. return;
  939. uint16_t AuxSize = Obj.getOptionalHeaderSize();
  940. uint16_t PartialFieldOffset = AuxSize;
  941. const char *PartialFieldName = nullptr;
  942. auto PrintAuxMember = [&](PrintStyle Style, const char *MemberName,
  943. auto &Member) {
  944. printAuxMemberHelper(Style, MemberName, Member, AuxHeader, AuxSize,
  945. PartialFieldOffset, PartialFieldName, W);
  946. };
  947. PrintAuxMember(Hex, "Magic", AuxHeader->AuxMagic);
  948. PrintAuxMember(Hex, "Version", AuxHeader->Version);
  949. PrintAuxMember(Hex, "Size of .text section", AuxHeader->TextSize);
  950. PrintAuxMember(Hex, "Size of .data section", AuxHeader->InitDataSize);
  951. PrintAuxMember(Hex, "Size of .bss section", AuxHeader->BssDataSize);
  952. PrintAuxMember(Hex, "Entry point address", AuxHeader->EntryPointAddr);
  953. PrintAuxMember(Hex, ".text section start address", AuxHeader->TextStartAddr);
  954. PrintAuxMember(Hex, ".data section start address", AuxHeader->DataStartAddr);
  955. PrintAuxMember(Hex, "TOC anchor address", AuxHeader->TOCAnchorAddr);
  956. PrintAuxMember(Number, "Section number of entryPoint",
  957. AuxHeader->SecNumOfEntryPoint);
  958. PrintAuxMember(Number, "Section number of .text", AuxHeader->SecNumOfText);
  959. PrintAuxMember(Number, "Section number of .data", AuxHeader->SecNumOfData);
  960. PrintAuxMember(Number, "Section number of TOC", AuxHeader->SecNumOfTOC);
  961. PrintAuxMember(Number, "Section number of loader data",
  962. AuxHeader->SecNumOfLoader);
  963. PrintAuxMember(Number, "Section number of .bss", AuxHeader->SecNumOfBSS);
  964. PrintAuxMember(Hex, "Maxium alignment of .text", AuxHeader->MaxAlignOfText);
  965. PrintAuxMember(Hex, "Maxium alignment of .data", AuxHeader->MaxAlignOfData);
  966. PrintAuxMember(Hex, "Module type", AuxHeader->ModuleType);
  967. PrintAuxMember(Hex, "CPU type of objects", AuxHeader->CpuFlag);
  968. PrintAuxMember(Hex, "(Reserved)", AuxHeader->CpuType);
  969. PrintAuxMember(Hex, "Maximum stack size", AuxHeader->MaxStackSize);
  970. PrintAuxMember(Hex, "Maximum data size", AuxHeader->MaxDataSize);
  971. PrintAuxMember(Hex, "Reserved for debugger", AuxHeader->ReservedForDebugger);
  972. PrintAuxMember(Hex, "Text page size", AuxHeader->TextPageSize);
  973. PrintAuxMember(Hex, "Data page size", AuxHeader->DataPageSize);
  974. PrintAuxMember(Hex, "Stack page size", AuxHeader->StackPageSize);
  975. if (offsetof(XCOFFAuxiliaryHeader32, FlagAndTDataAlignment) +
  976. sizeof(XCOFFAuxiliaryHeader32::FlagAndTDataAlignment) <=
  977. AuxSize) {
  978. W.printHex("Flag", AuxHeader->getFlag());
  979. W.printHex("Alignment of thread-local storage",
  980. AuxHeader->getTDataAlignment());
  981. }
  982. PrintAuxMember(Number, "Section number for .tdata", AuxHeader->SecNumOfTData);
  983. PrintAuxMember(Number, "Section number for .tbss", AuxHeader->SecNumOfTBSS);
  984. checkAndPrintAuxHeaderParseError(PartialFieldName, PartialFieldOffset,
  985. AuxSize, *AuxHeader, this);
  986. }
  987. void XCOFFDumper::printAuxiliaryHeader(
  988. const XCOFFAuxiliaryHeader64 *AuxHeader) {
  989. if (AuxHeader == nullptr)
  990. return;
  991. uint16_t AuxSize = Obj.getOptionalHeaderSize();
  992. uint16_t PartialFieldOffset = AuxSize;
  993. const char *PartialFieldName = nullptr;
  994. auto PrintAuxMember = [&](PrintStyle Style, const char *MemberName,
  995. auto &Member) {
  996. printAuxMemberHelper(Style, MemberName, Member, AuxHeader, AuxSize,
  997. PartialFieldOffset, PartialFieldName, W);
  998. };
  999. PrintAuxMember(Hex, "Magic", AuxHeader->AuxMagic);
  1000. PrintAuxMember(Hex, "Version", AuxHeader->Version);
  1001. PrintAuxMember(Hex, "Reserved for debugger", AuxHeader->ReservedForDebugger);
  1002. PrintAuxMember(Hex, ".text section start address", AuxHeader->TextStartAddr);
  1003. PrintAuxMember(Hex, ".data section start address", AuxHeader->DataStartAddr);
  1004. PrintAuxMember(Hex, "TOC anchor address", AuxHeader->TOCAnchorAddr);
  1005. PrintAuxMember(Number, "Section number of entryPoint",
  1006. AuxHeader->SecNumOfEntryPoint);
  1007. PrintAuxMember(Number, "Section number of .text", AuxHeader->SecNumOfText);
  1008. PrintAuxMember(Number, "Section number of .data", AuxHeader->SecNumOfData);
  1009. PrintAuxMember(Number, "Section number of TOC", AuxHeader->SecNumOfTOC);
  1010. PrintAuxMember(Number, "Section number of loader data",
  1011. AuxHeader->SecNumOfLoader);
  1012. PrintAuxMember(Number, "Section number of .bss", AuxHeader->SecNumOfBSS);
  1013. PrintAuxMember(Hex, "Maxium alignment of .text", AuxHeader->MaxAlignOfText);
  1014. PrintAuxMember(Hex, "Maxium alignment of .data", AuxHeader->MaxAlignOfData);
  1015. PrintAuxMember(Hex, "Module type", AuxHeader->ModuleType);
  1016. PrintAuxMember(Hex, "CPU type of objects", AuxHeader->CpuFlag);
  1017. PrintAuxMember(Hex, "(Reserved)", AuxHeader->CpuType);
  1018. PrintAuxMember(Hex, "Text page size", AuxHeader->TextPageSize);
  1019. PrintAuxMember(Hex, "Data page size", AuxHeader->DataPageSize);
  1020. PrintAuxMember(Hex, "Stack page size", AuxHeader->StackPageSize);
  1021. if (offsetof(XCOFFAuxiliaryHeader64, FlagAndTDataAlignment) +
  1022. sizeof(XCOFFAuxiliaryHeader64::FlagAndTDataAlignment) <=
  1023. AuxSize) {
  1024. W.printHex("Flag", AuxHeader->getFlag());
  1025. W.printHex("Alignment of thread-local storage",
  1026. AuxHeader->getTDataAlignment());
  1027. }
  1028. PrintAuxMember(Hex, "Size of .text section", AuxHeader->TextSize);
  1029. PrintAuxMember(Hex, "Size of .data section", AuxHeader->InitDataSize);
  1030. PrintAuxMember(Hex, "Size of .bss section", AuxHeader->BssDataSize);
  1031. PrintAuxMember(Hex, "Entry point address", AuxHeader->EntryPointAddr);
  1032. PrintAuxMember(Hex, "Maximum stack size", AuxHeader->MaxStackSize);
  1033. PrintAuxMember(Hex, "Maximum data size", AuxHeader->MaxDataSize);
  1034. PrintAuxMember(Number, "Section number for .tdata", AuxHeader->SecNumOfTData);
  1035. PrintAuxMember(Number, "Section number for .tbss", AuxHeader->SecNumOfTBSS);
  1036. PrintAuxMember(Hex, "Additional flags 64-bit XCOFF", AuxHeader->XCOFF64Flag);
  1037. checkAndPrintAuxHeaderParseError(PartialFieldName, PartialFieldOffset,
  1038. AuxSize, *AuxHeader, this);
  1039. }
  1040. template <typename T>
  1041. void XCOFFDumper::printSectionHeaders(ArrayRef<T> Sections) {
  1042. ListScope Group(W, "Sections");
  1043. uint16_t Index = 1;
  1044. for (const T &Sec : Sections) {
  1045. DictScope SecDS(W, "Section");
  1046. W.printNumber("Index", Index++);
  1047. uint16_t SectionType = Sec.getSectionType();
  1048. switch (SectionType) {
  1049. case XCOFF::STYP_OVRFLO:
  1050. printOverflowSectionHeader(Sec);
  1051. break;
  1052. case XCOFF::STYP_LOADER:
  1053. case XCOFF::STYP_EXCEPT:
  1054. case XCOFF::STYP_TYPCHK:
  1055. // TODO The interpretation of loader, exception and type check section
  1056. // headers are different from that of generic section headers. We will
  1057. // implement them later. We interpret them as generic section headers for
  1058. // now.
  1059. default:
  1060. printGenericSectionHeader(Sec);
  1061. break;
  1062. }
  1063. if (Sec.isReservedSectionType())
  1064. W.printHex("Flags", "Reserved", SectionType);
  1065. else
  1066. W.printEnum("Type", SectionType, ArrayRef(SectionTypeFlagsNames));
  1067. }
  1068. if (opts::SectionRelocations)
  1069. report_fatal_error("Dumping section relocations is unimplemented");
  1070. if (opts::SectionSymbols)
  1071. report_fatal_error("Dumping symbols is unimplemented");
  1072. if (opts::SectionData)
  1073. report_fatal_error("Dumping section data is unimplemented");
  1074. }
  1075. namespace llvm {
  1076. std::unique_ptr<ObjDumper>
  1077. createXCOFFDumper(const object::XCOFFObjectFile &XObj, ScopedPrinter &Writer) {
  1078. return std::make_unique<XCOFFDumper>(XObj, Writer);
  1079. }
  1080. } // namespace llvm