XCOFFDumper.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521
  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/ScopedPrinter.h"
  16. using namespace llvm;
  17. using namespace object;
  18. namespace {
  19. class XCOFFDumper : public ObjDumper {
  20. public:
  21. XCOFFDumper(const XCOFFObjectFile &Obj, ScopedPrinter &Writer)
  22. : ObjDumper(Writer, Obj.getFileName()), Obj(Obj) {}
  23. void printFileHeaders() override;
  24. void printSectionHeaders() override;
  25. void printRelocations() override;
  26. void printSymbols() override;
  27. void printDynamicSymbols() override;
  28. void printUnwindInfo() override;
  29. void printStackMap() const override;
  30. void printNeededLibraries() override;
  31. private:
  32. template <typename T> void printSectionHeaders(ArrayRef<T> Sections);
  33. template <typename T> void printGenericSectionHeader(T &Sec) const;
  34. template <typename T> void printOverflowSectionHeader(T &Sec) const;
  35. void printFileAuxEnt(const XCOFFFileAuxEnt *AuxEntPtr);
  36. void printCsectAuxEnt32(const XCOFFCsectAuxEnt32 *AuxEntPtr);
  37. void printSectAuxEntForStat(const XCOFFSectAuxEntForStat *AuxEntPtr);
  38. void printSymbol(const SymbolRef &);
  39. void printRelocations(ArrayRef<XCOFFSectionHeader32> Sections);
  40. const XCOFFObjectFile &Obj;
  41. };
  42. } // anonymous namespace
  43. void XCOFFDumper::printFileHeaders() {
  44. DictScope DS(W, "FileHeader");
  45. W.printHex("Magic", Obj.getMagic());
  46. W.printNumber("NumberOfSections", Obj.getNumberOfSections());
  47. // Negative timestamp values are reserved for future use.
  48. int32_t TimeStamp = Obj.getTimeStamp();
  49. if (TimeStamp > 0) {
  50. // This handling of the time stamp assumes that the host system's time_t is
  51. // compatible with AIX time_t. If a platform is not compatible, the lit
  52. // tests will let us know.
  53. time_t TimeDate = TimeStamp;
  54. char FormattedTime[21] = {};
  55. size_t BytesWritten =
  56. strftime(FormattedTime, 21, "%Y-%m-%dT%H:%M:%SZ", gmtime(&TimeDate));
  57. if (BytesWritten)
  58. W.printHex("TimeStamp", FormattedTime, TimeStamp);
  59. else
  60. W.printHex("Timestamp", TimeStamp);
  61. } else {
  62. W.printHex("TimeStamp", TimeStamp == 0 ? "None" : "Reserved Value",
  63. TimeStamp);
  64. }
  65. // The number of symbol table entries is an unsigned value in 64-bit objects
  66. // and a signed value (with negative values being 'reserved') in 32-bit
  67. // objects.
  68. if (Obj.is64Bit()) {
  69. W.printHex("SymbolTableOffset", Obj.getSymbolTableOffset64());
  70. W.printNumber("SymbolTableEntries", Obj.getNumberOfSymbolTableEntries64());
  71. } else {
  72. W.printHex("SymbolTableOffset", Obj.getSymbolTableOffset32());
  73. int32_t SymTabEntries = Obj.getRawNumberOfSymbolTableEntries32();
  74. if (SymTabEntries >= 0)
  75. W.printNumber("SymbolTableEntries", SymTabEntries);
  76. else
  77. W.printHex("SymbolTableEntries", "Reserved Value", SymTabEntries);
  78. }
  79. W.printHex("OptionalHeaderSize", Obj.getOptionalHeaderSize());
  80. W.printHex("Flags", Obj.getFlags());
  81. // TODO FIXME Add support for the auxiliary header (if any) once
  82. // XCOFFObjectFile has the necessary support.
  83. }
  84. void XCOFFDumper::printSectionHeaders() {
  85. if (Obj.is64Bit())
  86. printSectionHeaders(Obj.sections64());
  87. else
  88. printSectionHeaders(Obj.sections32());
  89. }
  90. void XCOFFDumper::printRelocations() {
  91. if (Obj.is64Bit())
  92. llvm_unreachable("64-bit relocation output not implemented!");
  93. else
  94. printRelocations(Obj.sections32());
  95. }
  96. static const EnumEntry<XCOFF::RelocationType> RelocationTypeNameclass[] = {
  97. #define ECase(X) \
  98. { #X, XCOFF::X }
  99. ECase(R_POS), ECase(R_RL), ECase(R_RLA), ECase(R_NEG),
  100. ECase(R_REL), ECase(R_TOC), ECase(R_TRL), ECase(R_TRLA),
  101. ECase(R_GL), ECase(R_TCL), ECase(R_REF), ECase(R_BA),
  102. ECase(R_BR), ECase(R_RBA), ECase(R_RBR), ECase(R_TLS),
  103. ECase(R_TLS_IE), ECase(R_TLS_LD), ECase(R_TLS_LE), ECase(R_TLSM),
  104. ECase(R_TLSML), ECase(R_TOCU), ECase(R_TOCL)
  105. #undef ECase
  106. };
  107. void XCOFFDumper::printRelocations(ArrayRef<XCOFFSectionHeader32> Sections) {
  108. if (!opts::ExpandRelocs)
  109. report_fatal_error("Unexpanded relocation output not implemented.");
  110. ListScope LS(W, "Relocations");
  111. uint16_t Index = 0;
  112. for (const auto &Sec : Sections) {
  113. ++Index;
  114. // Only the .text, .data, .tdata, and STYP_DWARF sections have relocation.
  115. if (Sec.Flags != XCOFF::STYP_TEXT && Sec.Flags != XCOFF::STYP_DATA &&
  116. Sec.Flags != XCOFF::STYP_TDATA && Sec.Flags != XCOFF::STYP_DWARF)
  117. continue;
  118. auto Relocations = unwrapOrError(Obj.getFileName(), Obj.relocations(Sec));
  119. if (Relocations.empty())
  120. continue;
  121. W.startLine() << "Section (index: " << Index << ") " << Sec.getName()
  122. << " {\n";
  123. for (auto Reloc : Relocations) {
  124. StringRef SymbolName = unwrapOrError(
  125. Obj.getFileName(), Obj.getSymbolNameByIndex(Reloc.SymbolIndex));
  126. DictScope RelocScope(W, "Relocation");
  127. W.printHex("Virtual Address", Reloc.VirtualAddress);
  128. W.printNumber("Symbol", SymbolName, Reloc.SymbolIndex);
  129. W.printString("IsSigned", Reloc.isRelocationSigned() ? "Yes" : "No");
  130. W.printNumber("FixupBitValue", Reloc.isFixupIndicated() ? 1 : 0);
  131. W.printNumber("Length", Reloc.getRelocatedLength());
  132. W.printEnum("Type", (uint8_t)Reloc.Type,
  133. makeArrayRef(RelocationTypeNameclass));
  134. }
  135. W.unindent();
  136. W.startLine() << "}\n";
  137. }
  138. }
  139. static const EnumEntry<XCOFF::CFileStringType> FileStringType[] = {
  140. #define ECase(X) \
  141. { #X, XCOFF::X }
  142. ECase(XFT_FN), ECase(XFT_CT), ECase(XFT_CV), ECase(XFT_CD)
  143. #undef ECase
  144. };
  145. void XCOFFDumper::printFileAuxEnt(const XCOFFFileAuxEnt *AuxEntPtr) {
  146. if (Obj.is64Bit())
  147. report_fatal_error(
  148. "Printing for File Auxiliary Entry in 64-bit is unimplemented.");
  149. StringRef FileName =
  150. unwrapOrError(Obj.getFileName(), Obj.getCFileName(AuxEntPtr));
  151. DictScope SymDs(W, "File Auxiliary Entry");
  152. W.printNumber("Index",
  153. Obj.getSymbolIndex(reinterpret_cast<uintptr_t>(AuxEntPtr)));
  154. W.printString("Name", FileName);
  155. W.printEnum("Type", static_cast<uint8_t>(AuxEntPtr->Type),
  156. makeArrayRef(FileStringType));
  157. }
  158. static const EnumEntry<XCOFF::StorageMappingClass> CsectStorageMappingClass[] =
  159. {
  160. #define ECase(X) \
  161. { #X, XCOFF::X }
  162. ECase(XMC_PR), ECase(XMC_RO), ECase(XMC_DB),
  163. ECase(XMC_GL), ECase(XMC_XO), ECase(XMC_SV),
  164. ECase(XMC_SV64), ECase(XMC_SV3264), ECase(XMC_TI),
  165. ECase(XMC_TB), ECase(XMC_RW), ECase(XMC_TC0),
  166. ECase(XMC_TC), ECase(XMC_TD), ECase(XMC_DS),
  167. ECase(XMC_UA), ECase(XMC_BS), ECase(XMC_UC),
  168. ECase(XMC_TL), ECase(XMC_TE)
  169. #undef ECase
  170. };
  171. static const EnumEntry<XCOFF::SymbolType> CsectSymbolTypeClass[] = {
  172. #define ECase(X) \
  173. { #X, XCOFF::X }
  174. ECase(XTY_ER), ECase(XTY_SD), ECase(XTY_LD), ECase(XTY_CM)
  175. #undef ECase
  176. };
  177. void XCOFFDumper::printCsectAuxEnt32(const XCOFFCsectAuxEnt32 *AuxEntPtr) {
  178. assert(!Obj.is64Bit() && "32-bit interface called on 64-bit object file.");
  179. DictScope SymDs(W, "CSECT Auxiliary Entry");
  180. W.printNumber("Index",
  181. Obj.getSymbolIndex(reinterpret_cast<uintptr_t>(AuxEntPtr)));
  182. if (AuxEntPtr->isLabel())
  183. W.printNumber("ContainingCsectSymbolIndex", AuxEntPtr->SectionOrLength);
  184. else
  185. W.printNumber("SectionLen", AuxEntPtr->SectionOrLength);
  186. W.printHex("ParameterHashIndex", AuxEntPtr->ParameterHashIndex);
  187. W.printHex("TypeChkSectNum", AuxEntPtr->TypeChkSectNum);
  188. // Print out symbol alignment and type.
  189. W.printNumber("SymbolAlignmentLog2", AuxEntPtr->getAlignmentLog2());
  190. W.printEnum("SymbolType", AuxEntPtr->getSymbolType(),
  191. makeArrayRef(CsectSymbolTypeClass));
  192. W.printEnum("StorageMappingClass",
  193. static_cast<uint8_t>(AuxEntPtr->StorageMappingClass),
  194. makeArrayRef(CsectStorageMappingClass));
  195. W.printHex("StabInfoIndex", AuxEntPtr->StabInfoIndex);
  196. W.printHex("StabSectNum", AuxEntPtr->StabSectNum);
  197. }
  198. void XCOFFDumper::printSectAuxEntForStat(
  199. const XCOFFSectAuxEntForStat *AuxEntPtr) {
  200. assert(!Obj.is64Bit() && "32-bit interface called on 64-bit object file.");
  201. DictScope SymDs(W, "Sect Auxiliary Entry For Stat");
  202. W.printNumber("Index",
  203. Obj.getSymbolIndex(reinterpret_cast<uintptr_t>(AuxEntPtr)));
  204. W.printNumber("SectionLength", AuxEntPtr->SectionLength);
  205. // Unlike the corresponding fields in the section header, NumberOfRelocEnt
  206. // and NumberOfLineNum do not handle values greater than 65535.
  207. W.printNumber("NumberOfRelocEnt", AuxEntPtr->NumberOfRelocEnt);
  208. W.printNumber("NumberOfLineNum", AuxEntPtr->NumberOfLineNum);
  209. }
  210. static const EnumEntry<XCOFF::StorageClass> SymStorageClass[] = {
  211. #define ECase(X) \
  212. { #X, XCOFF::X }
  213. ECase(C_NULL), ECase(C_AUTO), ECase(C_EXT), ECase(C_STAT),
  214. ECase(C_REG), ECase(C_EXTDEF), ECase(C_LABEL), ECase(C_ULABEL),
  215. ECase(C_MOS), ECase(C_ARG), ECase(C_STRTAG), ECase(C_MOU),
  216. ECase(C_UNTAG), ECase(C_TPDEF), ECase(C_USTATIC), ECase(C_ENTAG),
  217. ECase(C_MOE), ECase(C_REGPARM), ECase(C_FIELD), ECase(C_BLOCK),
  218. ECase(C_FCN), ECase(C_EOS), ECase(C_FILE), ECase(C_LINE),
  219. ECase(C_ALIAS), ECase(C_HIDDEN), ECase(C_HIDEXT), ECase(C_BINCL),
  220. ECase(C_EINCL), ECase(C_INFO), ECase(C_WEAKEXT), ECase(C_DWARF),
  221. ECase(C_GSYM), ECase(C_LSYM), ECase(C_PSYM), ECase(C_RSYM),
  222. ECase(C_RPSYM), ECase(C_STSYM), ECase(C_TCSYM), ECase(C_BCOMM),
  223. ECase(C_ECOML), ECase(C_ECOMM), ECase(C_DECL), ECase(C_ENTRY),
  224. ECase(C_FUN), ECase(C_BSTAT), ECase(C_ESTAT), ECase(C_GTLS),
  225. ECase(C_STTLS), ECase(C_EFCN)
  226. #undef ECase
  227. };
  228. static StringRef GetSymbolValueName(XCOFF::StorageClass SC) {
  229. switch (SC) {
  230. case XCOFF::C_EXT:
  231. case XCOFF::C_WEAKEXT:
  232. case XCOFF::C_HIDEXT:
  233. case XCOFF::C_STAT:
  234. return "Value (RelocatableAddress)";
  235. case XCOFF::C_FILE:
  236. return "Value (SymbolTableIndex)";
  237. case XCOFF::C_FCN:
  238. case XCOFF::C_BLOCK:
  239. case XCOFF::C_FUN:
  240. case XCOFF::C_STSYM:
  241. case XCOFF::C_BINCL:
  242. case XCOFF::C_EINCL:
  243. case XCOFF::C_INFO:
  244. case XCOFF::C_BSTAT:
  245. case XCOFF::C_LSYM:
  246. case XCOFF::C_PSYM:
  247. case XCOFF::C_RPSYM:
  248. case XCOFF::C_RSYM:
  249. case XCOFF::C_ECOML:
  250. case XCOFF::C_DWARF:
  251. assert(false && "This StorageClass for the symbol is not yet implemented.");
  252. return "";
  253. default:
  254. return "Value";
  255. }
  256. }
  257. static const EnumEntry<XCOFF::CFileLangId> CFileLangIdClass[] = {
  258. #define ECase(X) \
  259. { #X, XCOFF::X }
  260. ECase(TB_C), ECase(TB_CPLUSPLUS)
  261. #undef ECase
  262. };
  263. static const EnumEntry<XCOFF::CFileCpuId> CFileCpuIdClass[] = {
  264. #define ECase(X) \
  265. { #X, XCOFF::X }
  266. ECase(TCPU_PPC64), ECase(TCPU_COM), ECase(TCPU_970)
  267. #undef ECase
  268. };
  269. void XCOFFDumper::printSymbol(const SymbolRef &S) {
  270. if (Obj.is64Bit())
  271. report_fatal_error("64-bit support is unimplemented.");
  272. DataRefImpl SymbolDRI = S.getRawDataRefImpl();
  273. const XCOFFSymbolEntry *SymbolEntPtr = Obj.toSymbolEntry(SymbolDRI);
  274. XCOFFSymbolRef XCOFFSymRef(SymbolDRI, &Obj);
  275. uint8_t NumberOfAuxEntries = XCOFFSymRef.getNumberOfAuxEntries();
  276. DictScope SymDs(W, "Symbol");
  277. StringRef SymbolName =
  278. unwrapOrError(Obj.getFileName(), Obj.getSymbolName(SymbolDRI));
  279. W.printNumber("Index",
  280. Obj.getSymbolIndex(reinterpret_cast<uintptr_t>(SymbolEntPtr)));
  281. W.printString("Name", SymbolName);
  282. W.printHex(GetSymbolValueName(SymbolEntPtr->StorageClass),
  283. SymbolEntPtr->Value);
  284. StringRef SectionName =
  285. unwrapOrError(Obj.getFileName(), Obj.getSymbolSectionName(SymbolEntPtr));
  286. W.printString("Section", SectionName);
  287. if (XCOFFSymRef.getStorageClass() == XCOFF::C_FILE) {
  288. W.printEnum("Source Language ID",
  289. SymbolEntPtr->CFileLanguageIdAndTypeId.LanguageId,
  290. makeArrayRef(CFileLangIdClass));
  291. W.printEnum("CPU Version ID",
  292. SymbolEntPtr->CFileLanguageIdAndTypeId.CpuTypeId,
  293. makeArrayRef(CFileCpuIdClass));
  294. } else
  295. W.printHex("Type", SymbolEntPtr->SymbolType);
  296. W.printEnum("StorageClass", static_cast<uint8_t>(SymbolEntPtr->StorageClass),
  297. makeArrayRef(SymStorageClass));
  298. W.printNumber("NumberOfAuxEntries", SymbolEntPtr->NumberOfAuxEntries);
  299. if (NumberOfAuxEntries == 0)
  300. return;
  301. switch (XCOFFSymRef.getStorageClass()) {
  302. case XCOFF::C_FILE:
  303. // If the symbol is C_FILE and has auxiliary entries...
  304. for (int i = 1; i <= NumberOfAuxEntries; i++) {
  305. const XCOFFFileAuxEnt *FileAuxEntPtr =
  306. reinterpret_cast<const XCOFFFileAuxEnt *>(SymbolEntPtr + i);
  307. #ifndef NDEBUG
  308. Obj.checkSymbolEntryPointer(reinterpret_cast<uintptr_t>(FileAuxEntPtr));
  309. #endif
  310. printFileAuxEnt(FileAuxEntPtr);
  311. }
  312. break;
  313. case XCOFF::C_EXT:
  314. case XCOFF::C_WEAKEXT:
  315. case XCOFF::C_HIDEXT:
  316. // If the symbol is for a function, and it has more than 1 auxiliary entry,
  317. // then one of them must be function auxiliary entry which we do not
  318. // support yet.
  319. if (XCOFFSymRef.isFunction() && NumberOfAuxEntries >= 2)
  320. report_fatal_error("Function auxiliary entry printing is unimplemented.");
  321. // If there is more than 1 auxiliary entry, instead of printing out
  322. // error information, print out the raw Auxiliary entry from 1st till
  323. // the last - 1. The last one must be a CSECT Auxiliary Entry.
  324. for (int i = 1; i < NumberOfAuxEntries; i++) {
  325. W.startLine() << "!Unexpected raw auxiliary entry data:\n";
  326. W.startLine() << format_bytes(
  327. ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(SymbolEntPtr + i),
  328. XCOFF::SymbolTableEntrySize));
  329. }
  330. // The symbol's last auxiliary entry is a CSECT Auxiliary Entry.
  331. printCsectAuxEnt32(XCOFFSymRef.getXCOFFCsectAuxEnt32());
  332. break;
  333. case XCOFF::C_STAT:
  334. if (NumberOfAuxEntries > 1)
  335. report_fatal_error(
  336. "C_STAT symbol should not have more than 1 auxiliary entry.");
  337. const XCOFFSectAuxEntForStat *StatAuxEntPtr;
  338. StatAuxEntPtr =
  339. reinterpret_cast<const XCOFFSectAuxEntForStat *>(SymbolEntPtr + 1);
  340. #ifndef NDEBUG
  341. Obj.checkSymbolEntryPointer(reinterpret_cast<uintptr_t>(StatAuxEntPtr));
  342. #endif
  343. printSectAuxEntForStat(StatAuxEntPtr);
  344. break;
  345. case XCOFF::C_DWARF:
  346. case XCOFF::C_BLOCK:
  347. case XCOFF::C_FCN:
  348. report_fatal_error("Symbol table entry printing for this storage class "
  349. "type is unimplemented.");
  350. break;
  351. default:
  352. for (int i = 1; i <= NumberOfAuxEntries; i++) {
  353. W.startLine() << "!Unexpected raw auxiliary entry data:\n";
  354. W.startLine() << format_bytes(
  355. ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(SymbolEntPtr + i),
  356. XCOFF::SymbolTableEntrySize));
  357. }
  358. break;
  359. }
  360. }
  361. void XCOFFDumper::printSymbols() {
  362. ListScope Group(W, "Symbols");
  363. for (const SymbolRef &S : Obj.symbols())
  364. printSymbol(S);
  365. }
  366. void XCOFFDumper::printDynamicSymbols() {
  367. llvm_unreachable("Unimplemented functionality for XCOFFDumper");
  368. }
  369. void XCOFFDumper::printUnwindInfo() {
  370. llvm_unreachable("Unimplemented functionality for XCOFFDumper");
  371. }
  372. void XCOFFDumper::printStackMap() const {
  373. llvm_unreachable("Unimplemented functionality for XCOFFDumper");
  374. }
  375. void XCOFFDumper::printNeededLibraries() {
  376. llvm_unreachable("Unimplemented functionality for XCOFFDumper");
  377. }
  378. static const EnumEntry<XCOFF::SectionTypeFlags> SectionTypeFlagsNames[] = {
  379. #define ECase(X) \
  380. { #X, XCOFF::X }
  381. ECase(STYP_PAD), ECase(STYP_DWARF), ECase(STYP_TEXT),
  382. ECase(STYP_DATA), ECase(STYP_BSS), ECase(STYP_EXCEPT),
  383. ECase(STYP_INFO), ECase(STYP_TDATA), ECase(STYP_TBSS),
  384. ECase(STYP_LOADER), ECase(STYP_DEBUG), ECase(STYP_TYPCHK),
  385. ECase(STYP_OVRFLO)
  386. #undef ECase
  387. };
  388. template <typename T>
  389. void XCOFFDumper::printOverflowSectionHeader(T &Sec) const {
  390. if (Obj.is64Bit()) {
  391. reportWarning(make_error<StringError>("An 64-bit XCOFF object file may not "
  392. "contain an overflow section header.",
  393. object_error::parse_failed),
  394. Obj.getFileName());
  395. }
  396. W.printString("Name", Sec.getName());
  397. W.printNumber("NumberOfRelocations", Sec.PhysicalAddress);
  398. W.printNumber("NumberOfLineNumbers", Sec.VirtualAddress);
  399. W.printHex("Size", Sec.SectionSize);
  400. W.printHex("RawDataOffset", Sec.FileOffsetToRawData);
  401. W.printHex("RelocationPointer", Sec.FileOffsetToRelocationInfo);
  402. W.printHex("LineNumberPointer", Sec.FileOffsetToLineNumberInfo);
  403. W.printNumber("IndexOfSectionOverflowed", Sec.NumberOfRelocations);
  404. W.printNumber("IndexOfSectionOverflowed", Sec.NumberOfLineNumbers);
  405. }
  406. template <typename T>
  407. void XCOFFDumper::printGenericSectionHeader(T &Sec) const {
  408. W.printString("Name", Sec.getName());
  409. W.printHex("PhysicalAddress", Sec.PhysicalAddress);
  410. W.printHex("VirtualAddress", Sec.VirtualAddress);
  411. W.printHex("Size", Sec.SectionSize);
  412. W.printHex("RawDataOffset", Sec.FileOffsetToRawData);
  413. W.printHex("RelocationPointer", Sec.FileOffsetToRelocationInfo);
  414. W.printHex("LineNumberPointer", Sec.FileOffsetToLineNumberInfo);
  415. W.printNumber("NumberOfRelocations", Sec.NumberOfRelocations);
  416. W.printNumber("NumberOfLineNumbers", Sec.NumberOfLineNumbers);
  417. }
  418. template <typename T>
  419. void XCOFFDumper::printSectionHeaders(ArrayRef<T> Sections) {
  420. ListScope Group(W, "Sections");
  421. uint16_t Index = 1;
  422. for (const T &Sec : Sections) {
  423. DictScope SecDS(W, "Section");
  424. W.printNumber("Index", Index++);
  425. uint16_t SectionType = Sec.getSectionType();
  426. switch (SectionType) {
  427. case XCOFF::STYP_OVRFLO:
  428. printOverflowSectionHeader(Sec);
  429. break;
  430. case XCOFF::STYP_LOADER:
  431. case XCOFF::STYP_EXCEPT:
  432. case XCOFF::STYP_TYPCHK:
  433. // TODO The interpretation of loader, exception and type check section
  434. // headers are different from that of generic section headers. We will
  435. // implement them later. We interpret them as generic section headers for
  436. // now.
  437. default:
  438. printGenericSectionHeader(Sec);
  439. break;
  440. }
  441. if (Sec.isReservedSectionType())
  442. W.printHex("Flags", "Reserved", SectionType);
  443. else
  444. W.printEnum("Type", SectionType, makeArrayRef(SectionTypeFlagsNames));
  445. }
  446. if (opts::SectionRelocations)
  447. report_fatal_error("Dumping section relocations is unimplemented");
  448. if (opts::SectionSymbols)
  449. report_fatal_error("Dumping symbols is unimplemented");
  450. if (opts::SectionData)
  451. report_fatal_error("Dumping section data is unimplemented");
  452. }
  453. namespace llvm {
  454. std::unique_ptr<ObjDumper>
  455. createXCOFFDumper(const object::XCOFFObjectFile &XObj, ScopedPrinter &Writer) {
  456. return std::make_unique<XCOFFDumper>(XObj, Writer);
  457. }
  458. } // namespace llvm