XCOFFDumper.cpp 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955
  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. #include <stddef.h>
  19. using namespace llvm;
  20. using namespace object;
  21. namespace {
  22. class XCOFFDumper : public ObjDumper {
  23. public:
  24. XCOFFDumper(const XCOFFObjectFile &Obj, ScopedPrinter &Writer)
  25. : ObjDumper(Writer, Obj.getFileName()), Obj(Obj) {}
  26. void printFileHeaders() override;
  27. void printAuxiliaryHeader() override;
  28. void printSectionHeaders() override;
  29. void printRelocations() override;
  30. void printSymbols() override;
  31. void printDynamicSymbols() override;
  32. void printUnwindInfo() override;
  33. void printStackMap() const override;
  34. void printNeededLibraries() override;
  35. void printStringTable() override;
  36. private:
  37. template <typename T> void printSectionHeaders(ArrayRef<T> Sections);
  38. template <typename T> void printGenericSectionHeader(T &Sec) const;
  39. template <typename T> void printOverflowSectionHeader(T &Sec) const;
  40. template <typename T> const T *getAuxEntPtr(uintptr_t AuxAddress);
  41. void printFileAuxEnt(const XCOFFFileAuxEnt *AuxEntPtr);
  42. void printCsectAuxEnt(XCOFFCsectAuxRef AuxEntRef);
  43. void printSectAuxEntForStat(const XCOFFSectAuxEntForStat *AuxEntPtr);
  44. void printExceptionAuxEnt(const XCOFFExceptionAuxEnt *AuxEntPtr);
  45. void printFunctionAuxEnt(const XCOFFFunctionAuxEnt32 *AuxEntPtr);
  46. void printFunctionAuxEnt(const XCOFFFunctionAuxEnt64 *AuxEntPtr);
  47. void printBlockAuxEnt(const XCOFFBlockAuxEnt32 *AuxEntPtr);
  48. void printBlockAuxEnt(const XCOFFBlockAuxEnt64 *AuxEntPtr);
  49. template <typename T> void printSectAuxEntForDWARF(const T *AuxEntPtr);
  50. void printSymbol(const SymbolRef &);
  51. template <typename RelTy> void printRelocation(RelTy Reloc);
  52. template <typename Shdr, typename RelTy>
  53. void printRelocations(ArrayRef<Shdr> Sections);
  54. void printAuxiliaryHeader(const XCOFFAuxiliaryHeader32 *AuxHeader);
  55. void printAuxiliaryHeader(const XCOFFAuxiliaryHeader64 *AuxHeader);
  56. const XCOFFObjectFile &Obj;
  57. };
  58. } // anonymous namespace
  59. void XCOFFDumper::printFileHeaders() {
  60. DictScope DS(W, "FileHeader");
  61. W.printHex("Magic", Obj.getMagic());
  62. W.printNumber("NumberOfSections", Obj.getNumberOfSections());
  63. // Negative timestamp values are reserved for future use.
  64. int32_t TimeStamp = Obj.getTimeStamp();
  65. if (TimeStamp > 0) {
  66. // This handling of the time stamp assumes that the host system's time_t is
  67. // compatible with AIX time_t. If a platform is not compatible, the lit
  68. // tests will let us know.
  69. time_t TimeDate = TimeStamp;
  70. char FormattedTime[21] = {};
  71. size_t BytesWritten =
  72. strftime(FormattedTime, 21, "%Y-%m-%dT%H:%M:%SZ", gmtime(&TimeDate));
  73. if (BytesWritten)
  74. W.printHex("TimeStamp", FormattedTime, TimeStamp);
  75. else
  76. W.printHex("Timestamp", TimeStamp);
  77. } else {
  78. W.printHex("TimeStamp", TimeStamp == 0 ? "None" : "Reserved Value",
  79. TimeStamp);
  80. }
  81. // The number of symbol table entries is an unsigned value in 64-bit objects
  82. // and a signed value (with negative values being 'reserved') in 32-bit
  83. // objects.
  84. if (Obj.is64Bit()) {
  85. W.printHex("SymbolTableOffset", Obj.getSymbolTableOffset64());
  86. W.printNumber("SymbolTableEntries", Obj.getNumberOfSymbolTableEntries64());
  87. } else {
  88. W.printHex("SymbolTableOffset", Obj.getSymbolTableOffset32());
  89. int32_t SymTabEntries = Obj.getRawNumberOfSymbolTableEntries32();
  90. if (SymTabEntries >= 0)
  91. W.printNumber("SymbolTableEntries", SymTabEntries);
  92. else
  93. W.printHex("SymbolTableEntries", "Reserved Value", SymTabEntries);
  94. }
  95. W.printHex("OptionalHeaderSize", Obj.getOptionalHeaderSize());
  96. W.printHex("Flags", Obj.getFlags());
  97. // TODO FIXME Add support for the auxiliary header (if any) once
  98. // XCOFFObjectFile has the necessary support.
  99. }
  100. void XCOFFDumper::printAuxiliaryHeader() {
  101. if (Obj.is64Bit())
  102. printAuxiliaryHeader(Obj.auxiliaryHeader64());
  103. else
  104. printAuxiliaryHeader(Obj.auxiliaryHeader32());
  105. }
  106. void XCOFFDumper::printSectionHeaders() {
  107. if (Obj.is64Bit())
  108. printSectionHeaders(Obj.sections64());
  109. else
  110. printSectionHeaders(Obj.sections32());
  111. }
  112. void XCOFFDumper::printRelocations() {
  113. if (Obj.is64Bit())
  114. printRelocations<XCOFFSectionHeader64, XCOFFRelocation64>(Obj.sections64());
  115. else
  116. printRelocations<XCOFFSectionHeader32, XCOFFRelocation32>(Obj.sections32());
  117. }
  118. const EnumEntry<XCOFF::RelocationType> RelocationTypeNameclass[] = {
  119. #define ECase(X) \
  120. { #X, XCOFF::X }
  121. ECase(R_POS), ECase(R_RL), ECase(R_RLA), ECase(R_NEG),
  122. ECase(R_REL), ECase(R_TOC), ECase(R_TRL), ECase(R_TRLA),
  123. ECase(R_GL), ECase(R_TCL), ECase(R_REF), ECase(R_BA),
  124. ECase(R_BR), ECase(R_RBA), ECase(R_RBR), ECase(R_TLS),
  125. ECase(R_TLS_IE), ECase(R_TLS_LD), ECase(R_TLS_LE), ECase(R_TLSM),
  126. ECase(R_TLSML), ECase(R_TOCU), ECase(R_TOCL)
  127. #undef ECase
  128. };
  129. template <typename RelTy> void XCOFFDumper::printRelocation(RelTy Reloc) {
  130. Expected<StringRef> ErrOrSymbolName =
  131. Obj.getSymbolNameByIndex(Reloc.SymbolIndex);
  132. if (Error E = ErrOrSymbolName.takeError()) {
  133. reportUniqueWarning(std::move(E));
  134. return;
  135. }
  136. StringRef SymbolName = *ErrOrSymbolName;
  137. StringRef RelocName = XCOFF::getRelocationTypeString(Reloc.Type);
  138. if (opts::ExpandRelocs) {
  139. DictScope Group(W, "Relocation");
  140. W.printHex("Virtual Address", Reloc.VirtualAddress);
  141. W.printNumber("Symbol", SymbolName, Reloc.SymbolIndex);
  142. W.printString("IsSigned", Reloc.isRelocationSigned() ? "Yes" : "No");
  143. W.printNumber("FixupBitValue", Reloc.isFixupIndicated() ? 1 : 0);
  144. W.printNumber("Length", Reloc.getRelocatedLength());
  145. W.printEnum("Type", (uint8_t)Reloc.Type,
  146. makeArrayRef(RelocationTypeNameclass));
  147. } else {
  148. raw_ostream &OS = W.startLine();
  149. OS << W.hex(Reloc.VirtualAddress) << " " << RelocName << " " << SymbolName
  150. << "(" << Reloc.SymbolIndex << ") " << W.hex(Reloc.Info) << "\n";
  151. }
  152. }
  153. template <typename Shdr, typename RelTy>
  154. void XCOFFDumper::printRelocations(ArrayRef<Shdr> Sections) {
  155. ListScope LS(W, "Relocations");
  156. uint16_t Index = 0;
  157. for (const Shdr &Sec : Sections) {
  158. ++Index;
  159. // Only the .text, .data, .tdata, and STYP_DWARF sections have relocation.
  160. if (Sec.Flags != XCOFF::STYP_TEXT && Sec.Flags != XCOFF::STYP_DATA &&
  161. Sec.Flags != XCOFF::STYP_TDATA && Sec.Flags != XCOFF::STYP_DWARF)
  162. continue;
  163. Expected<ArrayRef<RelTy>> ErrOrRelocations = Obj.relocations<Shdr, RelTy>(Sec);
  164. if (Error E = ErrOrRelocations.takeError()) {
  165. reportUniqueWarning(std::move(E));
  166. continue;
  167. }
  168. const ArrayRef<RelTy> Relocations = *ErrOrRelocations;
  169. if (Relocations.empty())
  170. continue;
  171. W.startLine() << "Section (index: " << Index << ") " << Sec.getName()
  172. << " {\n";
  173. W.indent();
  174. for (const RelTy Reloc : Relocations)
  175. printRelocation(Reloc);
  176. W.unindent();
  177. W.startLine() << "}\n";
  178. }
  179. }
  180. const EnumEntry<XCOFF::CFileStringType> FileStringType[] = {
  181. #define ECase(X) \
  182. { #X, XCOFF::X }
  183. ECase(XFT_FN), ECase(XFT_CT), ECase(XFT_CV), ECase(XFT_CD)
  184. #undef ECase
  185. };
  186. const EnumEntry<XCOFF::SymbolAuxType> SymAuxType[] = {
  187. #define ECase(X) \
  188. { #X, XCOFF::X }
  189. ECase(AUX_EXCEPT), ECase(AUX_FCN), ECase(AUX_SYM), ECase(AUX_FILE),
  190. ECase(AUX_CSECT), ECase(AUX_SECT)
  191. #undef ECase
  192. };
  193. void XCOFFDumper::printFileAuxEnt(const XCOFFFileAuxEnt *AuxEntPtr) {
  194. assert((!Obj.is64Bit() || AuxEntPtr->AuxType == XCOFF::AUX_FILE) &&
  195. "Mismatched auxiliary type!");
  196. StringRef FileName =
  197. unwrapOrError(Obj.getFileName(), Obj.getCFileName(AuxEntPtr));
  198. DictScope SymDs(W, "File Auxiliary Entry");
  199. W.printNumber("Index",
  200. Obj.getSymbolIndex(reinterpret_cast<uintptr_t>(AuxEntPtr)));
  201. W.printString("Name", FileName);
  202. W.printEnum("Type", static_cast<uint8_t>(AuxEntPtr->Type),
  203. makeArrayRef(FileStringType));
  204. if (Obj.is64Bit()) {
  205. W.printEnum("Auxiliary Type", static_cast<uint8_t>(AuxEntPtr->AuxType),
  206. makeArrayRef(SymAuxType));
  207. }
  208. }
  209. static const EnumEntry<XCOFF::StorageMappingClass> CsectStorageMappingClass[] =
  210. {
  211. #define ECase(X) \
  212. { #X, XCOFF::X }
  213. ECase(XMC_PR), ECase(XMC_RO), ECase(XMC_DB), ECase(XMC_GL),
  214. ECase(XMC_XO), ECase(XMC_SV), ECase(XMC_SV64), ECase(XMC_SV3264),
  215. ECase(XMC_TI), ECase(XMC_TB), ECase(XMC_RW), ECase(XMC_TC0),
  216. ECase(XMC_TC), ECase(XMC_TD), ECase(XMC_DS), ECase(XMC_UA),
  217. ECase(XMC_BS), ECase(XMC_UC), ECase(XMC_TL), ECase(XMC_UL),
  218. ECase(XMC_TE)
  219. #undef ECase
  220. };
  221. const EnumEntry<XCOFF::SymbolType> CsectSymbolTypeClass[] = {
  222. #define ECase(X) \
  223. { #X, XCOFF::X }
  224. ECase(XTY_ER), ECase(XTY_SD), ECase(XTY_LD), ECase(XTY_CM)
  225. #undef ECase
  226. };
  227. void XCOFFDumper::printCsectAuxEnt(XCOFFCsectAuxRef AuxEntRef) {
  228. assert((!Obj.is64Bit() || AuxEntRef.getAuxType64() == XCOFF::AUX_CSECT) &&
  229. "Mismatched auxiliary type!");
  230. DictScope SymDs(W, "CSECT Auxiliary Entry");
  231. W.printNumber("Index", Obj.getSymbolIndex(AuxEntRef.getEntryAddress()));
  232. W.printNumber(AuxEntRef.isLabel() ? "ContainingCsectSymbolIndex"
  233. : "SectionLen",
  234. AuxEntRef.getSectionOrLength());
  235. W.printHex("ParameterHashIndex", AuxEntRef.getParameterHashIndex());
  236. W.printHex("TypeChkSectNum", AuxEntRef.getTypeChkSectNum());
  237. // Print out symbol alignment and type.
  238. W.printNumber("SymbolAlignmentLog2", AuxEntRef.getAlignmentLog2());
  239. W.printEnum("SymbolType", AuxEntRef.getSymbolType(),
  240. makeArrayRef(CsectSymbolTypeClass));
  241. W.printEnum("StorageMappingClass",
  242. static_cast<uint8_t>(AuxEntRef.getStorageMappingClass()),
  243. makeArrayRef(CsectStorageMappingClass));
  244. if (Obj.is64Bit()) {
  245. W.printEnum("Auxiliary Type", static_cast<uint8_t>(XCOFF::AUX_CSECT),
  246. makeArrayRef(SymAuxType));
  247. } else {
  248. W.printHex("StabInfoIndex", AuxEntRef.getStabInfoIndex32());
  249. W.printHex("StabSectNum", AuxEntRef.getStabSectNum32());
  250. }
  251. }
  252. void XCOFFDumper::printSectAuxEntForStat(
  253. const XCOFFSectAuxEntForStat *AuxEntPtr) {
  254. assert(!Obj.is64Bit() && "32-bit interface called on 64-bit object file.");
  255. DictScope SymDs(W, "Sect Auxiliary Entry For Stat");
  256. W.printNumber("Index",
  257. Obj.getSymbolIndex(reinterpret_cast<uintptr_t>(AuxEntPtr)));
  258. W.printNumber("SectionLength", AuxEntPtr->SectionLength);
  259. // Unlike the corresponding fields in the section header, NumberOfRelocEnt
  260. // and NumberOfLineNum do not handle values greater than 65535.
  261. W.printNumber("NumberOfRelocEnt", AuxEntPtr->NumberOfRelocEnt);
  262. W.printNumber("NumberOfLineNum", AuxEntPtr->NumberOfLineNum);
  263. }
  264. void XCOFFDumper::printExceptionAuxEnt(const XCOFFExceptionAuxEnt *AuxEntPtr) {
  265. assert(Obj.is64Bit() && "64-bit interface called on 32-bit object file.");
  266. DictScope SymDs(W, "Exception Auxiliary Entry");
  267. W.printNumber("Index",
  268. Obj.getSymbolIndex(reinterpret_cast<uintptr_t>(AuxEntPtr)));
  269. W.printHex("OffsetToExceptionTable", AuxEntPtr->OffsetToExceptionTbl);
  270. W.printHex("SizeOfFunction", AuxEntPtr->SizeOfFunction);
  271. W.printNumber("SymbolIndexOfNextBeyond", AuxEntPtr->SymIdxOfNextBeyond);
  272. W.printEnum("Auxiliary Type", static_cast<uint8_t>(AuxEntPtr->AuxType),
  273. makeArrayRef(SymAuxType));
  274. }
  275. void XCOFFDumper::printFunctionAuxEnt(const XCOFFFunctionAuxEnt32 *AuxEntPtr) {
  276. assert(!Obj.is64Bit() && "32-bit interface called on 64-bit object file.");
  277. DictScope SymDs(W, "Function Auxiliary Entry");
  278. W.printNumber("Index",
  279. Obj.getSymbolIndex(reinterpret_cast<uintptr_t>(AuxEntPtr)));
  280. W.printHex("OffsetToExceptionTable", AuxEntPtr->OffsetToExceptionTbl);
  281. W.printHex("SizeOfFunction", AuxEntPtr->SizeOfFunction);
  282. W.printHex("PointerToLineNum", AuxEntPtr->PtrToLineNum);
  283. W.printNumber("SymbolIndexOfNextBeyond", AuxEntPtr->SymIdxOfNextBeyond);
  284. }
  285. void XCOFFDumper::printFunctionAuxEnt(const XCOFFFunctionAuxEnt64 *AuxEntPtr) {
  286. assert(Obj.is64Bit() && "64-bit interface called on 32-bit object file.");
  287. DictScope SymDs(W, "Function Auxiliary Entry");
  288. W.printNumber("Index",
  289. Obj.getSymbolIndex(reinterpret_cast<uintptr_t>(AuxEntPtr)));
  290. W.printHex("SizeOfFunction", AuxEntPtr->SizeOfFunction);
  291. W.printHex("PointerToLineNum", AuxEntPtr->PtrToLineNum);
  292. W.printNumber("SymbolIndexOfNextBeyond", AuxEntPtr->SymIdxOfNextBeyond);
  293. W.printEnum("Auxiliary Type", static_cast<uint8_t>(AuxEntPtr->AuxType),
  294. makeArrayRef(SymAuxType));
  295. }
  296. void XCOFFDumper::printBlockAuxEnt(const XCOFFBlockAuxEnt32 *AuxEntPtr) {
  297. assert(!Obj.is64Bit() && "32-bit interface called on 64-bit object file.");
  298. DictScope SymDs(W, "Block Auxiliary Entry");
  299. W.printNumber("Index",
  300. Obj.getSymbolIndex(reinterpret_cast<uintptr_t>(AuxEntPtr)));
  301. W.printHex("LineNumber (High 2 Bytes)", AuxEntPtr->LineNumHi);
  302. W.printHex("LineNumber (Low 2 Bytes)", AuxEntPtr->LineNumLo);
  303. }
  304. void XCOFFDumper::printBlockAuxEnt(const XCOFFBlockAuxEnt64 *AuxEntPtr) {
  305. assert(Obj.is64Bit() && "64-bit interface called on 32-bit object file.");
  306. DictScope SymDs(W, "Block Auxiliary Entry");
  307. W.printNumber("Index",
  308. Obj.getSymbolIndex(reinterpret_cast<uintptr_t>(AuxEntPtr)));
  309. W.printHex("LineNumber", AuxEntPtr->LineNum);
  310. W.printEnum("Auxiliary Type", static_cast<uint8_t>(AuxEntPtr->AuxType),
  311. makeArrayRef(SymAuxType));
  312. }
  313. template <typename T>
  314. void XCOFFDumper::printSectAuxEntForDWARF(const T *AuxEntPtr) {
  315. DictScope SymDs(W, "Sect Auxiliary Entry For DWARF");
  316. W.printNumber("Index",
  317. Obj.getSymbolIndex(reinterpret_cast<uintptr_t>(AuxEntPtr)));
  318. W.printHex("LengthOfSectionPortion", AuxEntPtr->LengthOfSectionPortion);
  319. W.printNumber("NumberOfRelocEntries", AuxEntPtr->NumberOfRelocEnt);
  320. if (Obj.is64Bit())
  321. W.printEnum("Auxiliary Type", static_cast<uint8_t>(XCOFF::AUX_SECT),
  322. makeArrayRef(SymAuxType));
  323. }
  324. const EnumEntry<XCOFF::StorageClass> SymStorageClass[] = {
  325. #define ECase(X) \
  326. { #X, XCOFF::X }
  327. ECase(C_NULL), ECase(C_AUTO), ECase(C_EXT), ECase(C_STAT),
  328. ECase(C_REG), ECase(C_EXTDEF), ECase(C_LABEL), ECase(C_ULABEL),
  329. ECase(C_MOS), ECase(C_ARG), ECase(C_STRTAG), ECase(C_MOU),
  330. ECase(C_UNTAG), ECase(C_TPDEF), ECase(C_USTATIC), ECase(C_ENTAG),
  331. ECase(C_MOE), ECase(C_REGPARM), ECase(C_FIELD), ECase(C_BLOCK),
  332. ECase(C_FCN), ECase(C_EOS), ECase(C_FILE), ECase(C_LINE),
  333. ECase(C_ALIAS), ECase(C_HIDDEN), ECase(C_HIDEXT), ECase(C_BINCL),
  334. ECase(C_EINCL), ECase(C_INFO), ECase(C_WEAKEXT), ECase(C_DWARF),
  335. ECase(C_GSYM), ECase(C_LSYM), ECase(C_PSYM), ECase(C_RSYM),
  336. ECase(C_RPSYM), ECase(C_STSYM), ECase(C_TCSYM), ECase(C_BCOMM),
  337. ECase(C_ECOML), ECase(C_ECOMM), ECase(C_DECL), ECase(C_ENTRY),
  338. ECase(C_FUN), ECase(C_BSTAT), ECase(C_ESTAT), ECase(C_GTLS),
  339. ECase(C_STTLS), ECase(C_EFCN)
  340. #undef ECase
  341. };
  342. static StringRef GetSymbolValueName(XCOFF::StorageClass SC) {
  343. switch (SC) {
  344. case XCOFF::C_EXT:
  345. case XCOFF::C_WEAKEXT:
  346. case XCOFF::C_HIDEXT:
  347. case XCOFF::C_STAT:
  348. case XCOFF::C_FCN:
  349. case XCOFF::C_BLOCK:
  350. return "Value (RelocatableAddress)";
  351. case XCOFF::C_FILE:
  352. return "Value (SymbolTableIndex)";
  353. case XCOFF::C_DWARF:
  354. return "Value (OffsetInDWARF)";
  355. case XCOFF::C_FUN:
  356. case XCOFF::C_STSYM:
  357. case XCOFF::C_BINCL:
  358. case XCOFF::C_EINCL:
  359. case XCOFF::C_INFO:
  360. case XCOFF::C_BSTAT:
  361. case XCOFF::C_LSYM:
  362. case XCOFF::C_PSYM:
  363. case XCOFF::C_RPSYM:
  364. case XCOFF::C_RSYM:
  365. case XCOFF::C_ECOML:
  366. assert(false && "This StorageClass for the symbol is not yet implemented.");
  367. return "";
  368. default:
  369. return "Value";
  370. }
  371. }
  372. const EnumEntry<XCOFF::CFileLangId> CFileLangIdClass[] = {
  373. #define ECase(X) \
  374. { #X, XCOFF::X }
  375. ECase(TB_C), ECase(TB_CPLUSPLUS)
  376. #undef ECase
  377. };
  378. const EnumEntry<XCOFF::CFileCpuId> CFileCpuIdClass[] = {
  379. #define ECase(X) \
  380. { #X, XCOFF::X }
  381. ECase(TCPU_PPC64), ECase(TCPU_COM), ECase(TCPU_970)
  382. #undef ECase
  383. };
  384. template <typename T> const T *XCOFFDumper::getAuxEntPtr(uintptr_t AuxAddress) {
  385. const T *AuxEntPtr = reinterpret_cast<const T *>(AuxAddress);
  386. Obj.checkSymbolEntryPointer(reinterpret_cast<uintptr_t>(AuxEntPtr));
  387. return AuxEntPtr;
  388. }
  389. static void printUnexpectedRawAuxEnt(ScopedPrinter &W, uintptr_t AuxAddress) {
  390. W.startLine() << "!Unexpected raw auxiliary entry data:\n";
  391. W.startLine() << format_bytes(
  392. ArrayRef<uint8_t>(
  393. reinterpret_cast<const uint8_t *>(AuxAddress),
  394. XCOFF::SymbolTableEntrySize),
  395. None, XCOFF::SymbolTableEntrySize)
  396. << "\n";
  397. }
  398. void XCOFFDumper::printSymbol(const SymbolRef &S) {
  399. DataRefImpl SymbolDRI = S.getRawDataRefImpl();
  400. XCOFFSymbolRef SymbolEntRef = Obj.toSymbolRef(SymbolDRI);
  401. uint8_t NumberOfAuxEntries = SymbolEntRef.getNumberOfAuxEntries();
  402. DictScope SymDs(W, "Symbol");
  403. StringRef SymbolName =
  404. unwrapOrError(Obj.getFileName(), SymbolEntRef.getName());
  405. uint32_t SymbolIdx = Obj.getSymbolIndex(SymbolEntRef.getEntryAddress());
  406. XCOFF::StorageClass SymbolClass = SymbolEntRef.getStorageClass();
  407. W.printNumber("Index", SymbolIdx);
  408. W.printString("Name", SymbolName);
  409. W.printHex(GetSymbolValueName(SymbolClass), SymbolEntRef.getValue());
  410. StringRef SectionName =
  411. unwrapOrError(Obj.getFileName(), Obj.getSymbolSectionName(SymbolEntRef));
  412. W.printString("Section", SectionName);
  413. if (SymbolClass == XCOFF::C_FILE) {
  414. W.printEnum("Source Language ID", SymbolEntRef.getLanguageIdForCFile(),
  415. makeArrayRef(CFileLangIdClass));
  416. W.printEnum("CPU Version ID", SymbolEntRef.getCPUTypeIddForCFile(),
  417. makeArrayRef(CFileCpuIdClass));
  418. } else
  419. W.printHex("Type", SymbolEntRef.getSymbolType());
  420. W.printEnum("StorageClass", static_cast<uint8_t>(SymbolClass),
  421. makeArrayRef(SymStorageClass));
  422. W.printNumber("NumberOfAuxEntries", NumberOfAuxEntries);
  423. if (NumberOfAuxEntries == 0)
  424. return;
  425. auto checkNumOfAux = [=] {
  426. if (NumberOfAuxEntries > 1)
  427. reportUniqueWarning("the " +
  428. enumToString(static_cast<uint8_t>(SymbolClass),
  429. makeArrayRef(SymStorageClass)) +
  430. " symbol at index " + Twine(SymbolIdx) +
  431. " should not have more than 1 "
  432. "auxiliary entry");
  433. };
  434. switch (SymbolClass) {
  435. case XCOFF::C_FILE:
  436. // If the symbol is C_FILE and has auxiliary entries...
  437. for (int I = 1; I <= NumberOfAuxEntries; I++) {
  438. uintptr_t AuxAddress = XCOFFObjectFile::getAdvancedSymbolEntryAddress(
  439. SymbolEntRef.getEntryAddress(), I);
  440. if (Obj.is64Bit() &&
  441. *Obj.getSymbolAuxType(AuxAddress) != XCOFF::SymbolAuxType::AUX_FILE) {
  442. printUnexpectedRawAuxEnt(W, AuxAddress);
  443. continue;
  444. }
  445. const XCOFFFileAuxEnt *FileAuxEntPtr =
  446. getAuxEntPtr<XCOFFFileAuxEnt>(AuxAddress);
  447. printFileAuxEnt(FileAuxEntPtr);
  448. }
  449. break;
  450. case XCOFF::C_EXT:
  451. case XCOFF::C_WEAKEXT:
  452. case XCOFF::C_HIDEXT: {
  453. if (!SymbolEntRef.isFunction() && NumberOfAuxEntries > 1)
  454. reportUniqueWarning("the non-function " +
  455. enumToString(static_cast<uint8_t>(SymbolClass),
  456. makeArrayRef(SymStorageClass)) +
  457. " symbol at index " + Twine(SymbolIdx) +
  458. " should have only 1 auxiliary entry, i.e. the CSECT "
  459. "auxiliary entry");
  460. // For 32-bit objects, print the function auxiliary symbol table entry. The
  461. // last one must be a CSECT auxiliary entry.
  462. // For 64-bit objects, both a function auxiliary entry and an exception
  463. // auxiliary entry may appear, print them in the loop and skip printing the
  464. // CSECT auxiliary entry, which will be printed outside the loop.
  465. for (int I = 1; I <= NumberOfAuxEntries; I++) {
  466. if ((I == NumberOfAuxEntries && !Obj.is64Bit()) ||
  467. !SymbolEntRef.isFunction())
  468. break;
  469. uintptr_t AuxAddress = XCOFFObjectFile::getAdvancedSymbolEntryAddress(
  470. SymbolEntRef.getEntryAddress(), I);
  471. if (Obj.is64Bit()) {
  472. XCOFF::SymbolAuxType Type = *Obj.getSymbolAuxType(AuxAddress);
  473. if (Type == XCOFF::SymbolAuxType::AUX_CSECT)
  474. continue;
  475. if (Type == XCOFF::SymbolAuxType::AUX_FCN) {
  476. const XCOFFFunctionAuxEnt64 *AuxEntPtr =
  477. getAuxEntPtr<XCOFFFunctionAuxEnt64>(AuxAddress);
  478. printFunctionAuxEnt(AuxEntPtr);
  479. } else if (Type == XCOFF::SymbolAuxType::AUX_EXCEPT) {
  480. const XCOFFExceptionAuxEnt *AuxEntPtr =
  481. getAuxEntPtr<XCOFFExceptionAuxEnt>(AuxAddress);
  482. printExceptionAuxEnt(AuxEntPtr);
  483. } else {
  484. printUnexpectedRawAuxEnt(W, AuxAddress);
  485. }
  486. } else {
  487. const XCOFFFunctionAuxEnt32 *AuxEntPtr =
  488. getAuxEntPtr<XCOFFFunctionAuxEnt32>(AuxAddress);
  489. printFunctionAuxEnt(AuxEntPtr);
  490. }
  491. }
  492. // Print the CSECT auxiliary entry.
  493. auto ErrOrCsectAuxRef = SymbolEntRef.getXCOFFCsectAuxRef();
  494. if (!ErrOrCsectAuxRef)
  495. reportUniqueWarning(ErrOrCsectAuxRef.takeError());
  496. else
  497. printCsectAuxEnt(*ErrOrCsectAuxRef);
  498. break;
  499. }
  500. case XCOFF::C_STAT: {
  501. checkNumOfAux();
  502. const XCOFFSectAuxEntForStat *StatAuxEntPtr =
  503. getAuxEntPtr<XCOFFSectAuxEntForStat>(
  504. XCOFFObjectFile::getAdvancedSymbolEntryAddress(
  505. SymbolEntRef.getEntryAddress(), 1));
  506. printSectAuxEntForStat(StatAuxEntPtr);
  507. break;
  508. }
  509. case XCOFF::C_DWARF: {
  510. checkNumOfAux();
  511. uintptr_t AuxAddress = XCOFFObjectFile::getAdvancedSymbolEntryAddress(
  512. SymbolEntRef.getEntryAddress(), 1);
  513. if (Obj.is64Bit()) {
  514. const XCOFFSectAuxEntForDWARF64 *AuxEntPtr =
  515. getAuxEntPtr<XCOFFSectAuxEntForDWARF64>(AuxAddress);
  516. printSectAuxEntForDWARF<XCOFFSectAuxEntForDWARF64>(AuxEntPtr);
  517. } else {
  518. const XCOFFSectAuxEntForDWARF32 *AuxEntPtr =
  519. getAuxEntPtr<XCOFFSectAuxEntForDWARF32>(AuxAddress);
  520. printSectAuxEntForDWARF<XCOFFSectAuxEntForDWARF32>(AuxEntPtr);
  521. }
  522. break;
  523. }
  524. case XCOFF::C_BLOCK:
  525. case XCOFF::C_FCN: {
  526. checkNumOfAux();
  527. uintptr_t AuxAddress = XCOFFObjectFile::getAdvancedSymbolEntryAddress(
  528. SymbolEntRef.getEntryAddress(), 1);
  529. if (Obj.is64Bit()) {
  530. const XCOFFBlockAuxEnt64 *AuxEntPtr =
  531. getAuxEntPtr<XCOFFBlockAuxEnt64>(AuxAddress);
  532. printBlockAuxEnt(AuxEntPtr);
  533. } else {
  534. const XCOFFBlockAuxEnt32 *AuxEntPtr =
  535. getAuxEntPtr<XCOFFBlockAuxEnt32>(AuxAddress);
  536. printBlockAuxEnt(AuxEntPtr);
  537. }
  538. break;
  539. }
  540. default:
  541. for (int i = 1; i <= NumberOfAuxEntries; i++) {
  542. printUnexpectedRawAuxEnt(W,
  543. XCOFFObjectFile::getAdvancedSymbolEntryAddress(
  544. SymbolEntRef.getEntryAddress(), i));
  545. }
  546. break;
  547. }
  548. }
  549. void XCOFFDumper::printSymbols() {
  550. ListScope Group(W, "Symbols");
  551. for (const SymbolRef &S : Obj.symbols())
  552. printSymbol(S);
  553. }
  554. void XCOFFDumper::printStringTable() {
  555. DictScope DS(W, "StringTable");
  556. StringRef StrTable = Obj.getStringTable();
  557. uint32_t StrTabSize = StrTable.size();
  558. W.printNumber("Length", StrTabSize);
  559. // Print strings from the fifth byte, since the first four bytes contain the
  560. // length (in bytes) of the string table (including the length field).
  561. if (StrTabSize > 4)
  562. printAsStringList(StrTable, 4);
  563. }
  564. void XCOFFDumper::printDynamicSymbols() {
  565. llvm_unreachable("Unimplemented functionality for XCOFFDumper");
  566. }
  567. void XCOFFDumper::printUnwindInfo() {
  568. llvm_unreachable("Unimplemented functionality for XCOFFDumper");
  569. }
  570. void XCOFFDumper::printStackMap() const {
  571. llvm_unreachable("Unimplemented functionality for XCOFFDumper");
  572. }
  573. void XCOFFDumper::printNeededLibraries() {
  574. ListScope D(W, "NeededLibraries");
  575. auto ImportFilesOrError = Obj.getImportFileTable();
  576. if (!ImportFilesOrError) {
  577. reportUniqueWarning(ImportFilesOrError.takeError());
  578. return;
  579. }
  580. StringRef ImportFileTable = ImportFilesOrError.get();
  581. const char *CurrentStr = ImportFileTable.data();
  582. const char *TableEnd = ImportFileTable.end();
  583. // Default column width for names is 13 even if no names are that long.
  584. size_t BaseWidth = 13;
  585. // Get the max width of BASE columns.
  586. for (size_t StrIndex = 0; CurrentStr < TableEnd; ++StrIndex) {
  587. size_t CurrentLen = strlen(CurrentStr);
  588. CurrentStr += strlen(CurrentStr) + 1;
  589. if (StrIndex % 3 == 1)
  590. BaseWidth = std::max(BaseWidth, CurrentLen);
  591. }
  592. auto &OS = static_cast<formatted_raw_ostream &>(W.startLine());
  593. // Each entry consists of 3 strings: the path_name, base_name and
  594. // archive_member_name. The first entry is a default LIBPATH value and other
  595. // entries have no path_name. We just dump the base_name and
  596. // archive_member_name here.
  597. OS << left_justify("BASE", BaseWidth) << " MEMBER\n";
  598. CurrentStr = ImportFileTable.data();
  599. for (size_t StrIndex = 0; CurrentStr < TableEnd;
  600. ++StrIndex, CurrentStr += strlen(CurrentStr) + 1) {
  601. if (StrIndex >= 3 && StrIndex % 3 != 0) {
  602. if (StrIndex % 3 == 1)
  603. OS << " " << left_justify(CurrentStr, BaseWidth) << " ";
  604. else
  605. OS << CurrentStr << "\n";
  606. }
  607. }
  608. }
  609. const EnumEntry<XCOFF::SectionTypeFlags> SectionTypeFlagsNames[] = {
  610. #define ECase(X) \
  611. { #X, XCOFF::X }
  612. ECase(STYP_PAD), ECase(STYP_DWARF), ECase(STYP_TEXT),
  613. ECase(STYP_DATA), ECase(STYP_BSS), ECase(STYP_EXCEPT),
  614. ECase(STYP_INFO), ECase(STYP_TDATA), ECase(STYP_TBSS),
  615. ECase(STYP_LOADER), ECase(STYP_DEBUG), ECase(STYP_TYPCHK),
  616. ECase(STYP_OVRFLO)
  617. #undef ECase
  618. };
  619. template <typename T>
  620. void XCOFFDumper::printOverflowSectionHeader(T &Sec) const {
  621. if (Obj.is64Bit()) {
  622. reportWarning(make_error<StringError>("An 64-bit XCOFF object file may not "
  623. "contain an overflow section header.",
  624. object_error::parse_failed),
  625. Obj.getFileName());
  626. }
  627. W.printString("Name", Sec.getName());
  628. W.printNumber("NumberOfRelocations", Sec.PhysicalAddress);
  629. W.printNumber("NumberOfLineNumbers", Sec.VirtualAddress);
  630. W.printHex("Size", Sec.SectionSize);
  631. W.printHex("RawDataOffset", Sec.FileOffsetToRawData);
  632. W.printHex("RelocationPointer", Sec.FileOffsetToRelocationInfo);
  633. W.printHex("LineNumberPointer", Sec.FileOffsetToLineNumberInfo);
  634. W.printNumber("IndexOfSectionOverflowed", Sec.NumberOfRelocations);
  635. W.printNumber("IndexOfSectionOverflowed", Sec.NumberOfLineNumbers);
  636. }
  637. template <typename T>
  638. void XCOFFDumper::printGenericSectionHeader(T &Sec) const {
  639. W.printString("Name", Sec.getName());
  640. W.printHex("PhysicalAddress", Sec.PhysicalAddress);
  641. W.printHex("VirtualAddress", Sec.VirtualAddress);
  642. W.printHex("Size", Sec.SectionSize);
  643. W.printHex("RawDataOffset", Sec.FileOffsetToRawData);
  644. W.printHex("RelocationPointer", Sec.FileOffsetToRelocationInfo);
  645. W.printHex("LineNumberPointer", Sec.FileOffsetToLineNumberInfo);
  646. W.printNumber("NumberOfRelocations", Sec.NumberOfRelocations);
  647. W.printNumber("NumberOfLineNumbers", Sec.NumberOfLineNumbers);
  648. }
  649. void XCOFFDumper::printAuxiliaryHeader(
  650. const XCOFFAuxiliaryHeader32 *AuxHeader) {
  651. if (AuxHeader == nullptr)
  652. return;
  653. uint16_t AuxSize = Obj.getOptionalHeaderSize();
  654. uint16_t PartialFieldOffset = AuxSize;
  655. const char *PartialFieldName = nullptr;
  656. DictScope DS(W, "AuxiliaryHeader");
  657. #define PrintAuxMember32(H, S, T) \
  658. if (offsetof(XCOFFAuxiliaryHeader32, T) + \
  659. sizeof(XCOFFAuxiliaryHeader32::T) <= \
  660. AuxSize) \
  661. W.print##H(S, AuxHeader->T); \
  662. else if (offsetof(XCOFFAuxiliaryHeader32, T) < AuxSize) { \
  663. PartialFieldOffset = offsetof(XCOFFAuxiliaryHeader32, T); \
  664. PartialFieldName = S; \
  665. }
  666. PrintAuxMember32(Hex, "Magic", AuxMagic);
  667. PrintAuxMember32(Hex, "Version", Version);
  668. PrintAuxMember32(Hex, "Size of .text section", TextSize);
  669. PrintAuxMember32(Hex, "Size of .data section", InitDataSize);
  670. PrintAuxMember32(Hex, "Size of .bss section", BssDataSize);
  671. PrintAuxMember32(Hex, "Entry point address", EntryPointAddr);
  672. PrintAuxMember32(Hex, ".text section start address", TextStartAddr);
  673. PrintAuxMember32(Hex, ".data section start address", DataStartAddr);
  674. PrintAuxMember32(Hex, "TOC anchor address", TOCAnchorAddr);
  675. PrintAuxMember32(Number, "Section number of entryPoint", SecNumOfEntryPoint);
  676. PrintAuxMember32(Number, "Section number of .text", SecNumOfText);
  677. PrintAuxMember32(Number, "Section number of .data", SecNumOfData);
  678. PrintAuxMember32(Number, "Section number of TOC", SecNumOfTOC);
  679. PrintAuxMember32(Number, "Section number of loader data", SecNumOfLoader);
  680. PrintAuxMember32(Number, "Section number of .bss", SecNumOfBSS);
  681. PrintAuxMember32(Hex, "Maxium alignment of .text", MaxAlignOfText);
  682. PrintAuxMember32(Hex, "Maxium alignment of .data", MaxAlignOfData);
  683. PrintAuxMember32(Hex, "Module type", ModuleType);
  684. PrintAuxMember32(Hex, "CPU type of objects", CpuFlag);
  685. PrintAuxMember32(Hex, "(Reserved)", CpuType);
  686. PrintAuxMember32(Hex, "Maximum stack size", MaxStackSize);
  687. PrintAuxMember32(Hex, "Maximum data size", MaxDataSize);
  688. PrintAuxMember32(Hex, "Reserved for debugger", ReservedForDebugger);
  689. PrintAuxMember32(Hex, "Text page size", TextPageSize);
  690. PrintAuxMember32(Hex, "Data page size", DataPageSize);
  691. PrintAuxMember32(Hex, "Stack page size", StackPageSize);
  692. if (offsetof(XCOFFAuxiliaryHeader32, FlagAndTDataAlignment) +
  693. sizeof(XCOFFAuxiliaryHeader32::FlagAndTDataAlignment) <=
  694. AuxSize) {
  695. W.printHex("Flag", AuxHeader->getFlag());
  696. W.printHex("Alignment of thread-local storage",
  697. AuxHeader->getTDataAlignment());
  698. }
  699. PrintAuxMember32(Number, "Section number for .tdata", SecNumOfTData);
  700. PrintAuxMember32(Number, "Section number for .tbss", SecNumOfTBSS);
  701. // Deal with error.
  702. if (PartialFieldOffset < AuxSize) {
  703. std::string ErrInfo;
  704. llvm::raw_string_ostream StringOS(ErrInfo);
  705. StringOS << "Only partial field for " << PartialFieldName << " at offset ("
  706. << PartialFieldOffset << ").";
  707. StringOS.flush();
  708. reportWarning(
  709. make_error<GenericBinaryError>(ErrInfo, object_error::parse_failed),
  710. "-");
  711. W.printBinary(
  712. "Raw data", "",
  713. ArrayRef<uint8_t>((const uint8_t *)(AuxHeader) + PartialFieldOffset,
  714. AuxSize - PartialFieldOffset));
  715. } else if (sizeof(XCOFFAuxiliaryHeader32) < AuxSize) {
  716. reportWarning(make_error<GenericBinaryError>(
  717. "There are extra data beyond auxiliary header",
  718. object_error::parse_failed),
  719. "-");
  720. W.printBinary("Extra raw data", "",
  721. ArrayRef<uint8_t>((const uint8_t *)(AuxHeader) +
  722. sizeof(XCOFFAuxiliaryHeader32),
  723. AuxSize - sizeof(XCOFFAuxiliaryHeader32)));
  724. }
  725. #undef PrintAuxMember32
  726. }
  727. void XCOFFDumper::printAuxiliaryHeader(
  728. const XCOFFAuxiliaryHeader64 *AuxHeader) {
  729. if (AuxHeader == nullptr)
  730. return;
  731. uint16_t AuxSize = Obj.getOptionalHeaderSize();
  732. uint16_t PartialFieldOffset = AuxSize;
  733. const char *PartialFieldName = nullptr;
  734. DictScope DS(W, "AuxiliaryHeader");
  735. #define PrintAuxMember64(H, S, T) \
  736. if (offsetof(XCOFFAuxiliaryHeader64, T) + \
  737. sizeof(XCOFFAuxiliaryHeader64::T) <= \
  738. AuxSize) \
  739. W.print##H(S, AuxHeader->T); \
  740. else if (offsetof(XCOFFAuxiliaryHeader64, T) < AuxSize) { \
  741. PartialFieldOffset = offsetof(XCOFFAuxiliaryHeader64, T); \
  742. PartialFieldName = S; \
  743. }
  744. PrintAuxMember64(Hex, "Magic", AuxMagic);
  745. PrintAuxMember64(Hex, "Version", Version);
  746. PrintAuxMember64(Hex, "Reserved for debugger", ReservedForDebugger);
  747. PrintAuxMember64(Hex, ".text section start address", TextStartAddr);
  748. PrintAuxMember64(Hex, ".data section start address", DataStartAddr);
  749. PrintAuxMember64(Hex, "TOC anchor address", TOCAnchorAddr);
  750. PrintAuxMember64(Number, "Section number of entryPoint", SecNumOfEntryPoint);
  751. PrintAuxMember64(Number, "Section number of .text", SecNumOfText);
  752. PrintAuxMember64(Number, "Section number of .data", SecNumOfData);
  753. PrintAuxMember64(Number, "Section number of TOC", SecNumOfTOC);
  754. PrintAuxMember64(Number, "Section number of loader data", SecNumOfLoader);
  755. PrintAuxMember64(Number, "Section number of .bss", SecNumOfBSS);
  756. PrintAuxMember64(Hex, "Maxium alignment of .text", MaxAlignOfText);
  757. PrintAuxMember64(Hex, "Maxium alignment of .data", MaxAlignOfData);
  758. PrintAuxMember64(Hex, "Module type", ModuleType);
  759. PrintAuxMember64(Hex, "CPU type of objects", CpuFlag);
  760. PrintAuxMember64(Hex, "(Reserved)", CpuType);
  761. PrintAuxMember64(Hex, "Text page size", TextPageSize);
  762. PrintAuxMember64(Hex, "Data page size", DataPageSize);
  763. PrintAuxMember64(Hex, "Stack page size", StackPageSize);
  764. if (offsetof(XCOFFAuxiliaryHeader64, FlagAndTDataAlignment) +
  765. sizeof(XCOFFAuxiliaryHeader64::FlagAndTDataAlignment) <=
  766. AuxSize) {
  767. W.printHex("Flag", AuxHeader->getFlag());
  768. W.printHex("Alignment of thread-local storage",
  769. AuxHeader->getTDataAlignment());
  770. }
  771. PrintAuxMember64(Hex, "Size of .text section", TextSize);
  772. PrintAuxMember64(Hex, "Size of .data section", InitDataSize);
  773. PrintAuxMember64(Hex, "Size of .bss section", BssDataSize);
  774. PrintAuxMember64(Hex, "Entry point address", EntryPointAddr);
  775. PrintAuxMember64(Hex, "Maximum stack size", MaxStackSize);
  776. PrintAuxMember64(Hex, "Maximum data size", MaxDataSize);
  777. PrintAuxMember64(Number, "Section number for .tdata", SecNumOfTData);
  778. PrintAuxMember64(Number, "Section number for .tbss", SecNumOfTBSS);
  779. PrintAuxMember64(Hex, "Additional flags 64-bit XCOFF", XCOFF64Flag);
  780. if (PartialFieldOffset < AuxSize) {
  781. std::string ErrInfo;
  782. llvm::raw_string_ostream StringOS(ErrInfo);
  783. StringOS << "Only partial field for " << PartialFieldName << " at offset ("
  784. << PartialFieldOffset << ").";
  785. StringOS.flush();
  786. reportWarning(
  787. make_error<GenericBinaryError>(ErrInfo, object_error::parse_failed),
  788. "-");
  789. ;
  790. W.printBinary(
  791. "Raw data", "",
  792. ArrayRef<uint8_t>((const uint8_t *)(AuxHeader) + PartialFieldOffset,
  793. AuxSize - PartialFieldOffset));
  794. } else if (sizeof(XCOFFAuxiliaryHeader64) < AuxSize) {
  795. reportWarning(make_error<GenericBinaryError>(
  796. "There are extra data beyond auxiliary header",
  797. object_error::parse_failed),
  798. "-");
  799. W.printBinary("Extra raw data", "",
  800. ArrayRef<uint8_t>((const uint8_t *)(AuxHeader) +
  801. sizeof(XCOFFAuxiliaryHeader64),
  802. AuxSize - sizeof(XCOFFAuxiliaryHeader64)));
  803. }
  804. #undef PrintAuxMember64
  805. }
  806. template <typename T>
  807. void XCOFFDumper::printSectionHeaders(ArrayRef<T> Sections) {
  808. ListScope Group(W, "Sections");
  809. uint16_t Index = 1;
  810. for (const T &Sec : Sections) {
  811. DictScope SecDS(W, "Section");
  812. W.printNumber("Index", Index++);
  813. uint16_t SectionType = Sec.getSectionType();
  814. switch (SectionType) {
  815. case XCOFF::STYP_OVRFLO:
  816. printOverflowSectionHeader(Sec);
  817. break;
  818. case XCOFF::STYP_LOADER:
  819. case XCOFF::STYP_EXCEPT:
  820. case XCOFF::STYP_TYPCHK:
  821. // TODO The interpretation of loader, exception and type check section
  822. // headers are different from that of generic section headers. We will
  823. // implement them later. We interpret them as generic section headers for
  824. // now.
  825. default:
  826. printGenericSectionHeader(Sec);
  827. break;
  828. }
  829. if (Sec.isReservedSectionType())
  830. W.printHex("Flags", "Reserved", SectionType);
  831. else
  832. W.printEnum("Type", SectionType, makeArrayRef(SectionTypeFlagsNames));
  833. }
  834. if (opts::SectionRelocations)
  835. report_fatal_error("Dumping section relocations is unimplemented");
  836. if (opts::SectionSymbols)
  837. report_fatal_error("Dumping symbols is unimplemented");
  838. if (opts::SectionData)
  839. report_fatal_error("Dumping section data is unimplemented");
  840. }
  841. namespace llvm {
  842. std::unique_ptr<ObjDumper>
  843. createXCOFFDumper(const object::XCOFFObjectFile &XObj, ScopedPrinter &Writer) {
  844. return std::make_unique<XCOFFDumper>(XObj, Writer);
  845. }
  846. } // namespace llvm