COFFDumper.cpp 44 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192
  1. //===-- COFFDumper.cpp - COFF-specific dumper -------------------*- C++ -*-===//
  2. //
  3. // The LLVM Compiler Infrastructure
  4. //
  5. // This file is distributed under the University of Illinois Open Source
  6. // License. See LICENSE.TXT for details.
  7. //
  8. //===----------------------------------------------------------------------===//
  9. ///
  10. /// \file
  11. /// \brief This file implements the COFF-specific dumper for llvm-readobj.
  12. ///
  13. //===----------------------------------------------------------------------===//
  14. #include "llvm-readobj.h"
  15. #include "ARMWinEHPrinter.h"
  16. #include "Error.h"
  17. #include "ObjDumper.h"
  18. #include "StackMapPrinter.h"
  19. #include "StreamWriter.h"
  20. #include "Win64EHDumper.h"
  21. #include "llvm/ADT/DenseMap.h"
  22. #include "llvm/ADT/SmallString.h"
  23. #include "llvm/ADT/StringExtras.h"
  24. #include "llvm/Object/COFF.h"
  25. #include "llvm/Object/ObjectFile.h"
  26. #include "llvm/Support/COFF.h"
  27. #include "llvm/Support/Casting.h"
  28. #include "llvm/Support/Compiler.h"
  29. #include "llvm/Support/DataExtractor.h"
  30. #include "llvm/Support/Format.h"
  31. #include "llvm/Support/SourceMgr.h"
  32. #include "llvm/Support/Win64EH.h"
  33. #include "llvm/Support/raw_ostream.h"
  34. #include <algorithm>
  35. #include <cstring>
  36. #include <system_error>
  37. #include <time.h>
  38. using namespace llvm;
  39. using namespace llvm::object;
  40. using namespace llvm::Win64EH;
  41. namespace {
  42. class COFFDumper : public ObjDumper {
  43. public:
  44. COFFDumper(const llvm::object::COFFObjectFile *Obj, StreamWriter& Writer)
  45. : ObjDumper(Writer)
  46. , Obj(Obj) {
  47. }
  48. void printFileHeaders() override;
  49. void printSections() override;
  50. void printRelocations() override;
  51. void printSymbols() override;
  52. void printDynamicSymbols() override;
  53. void printUnwindInfo() override;
  54. void printCOFFImports() override;
  55. void printCOFFExports() override;
  56. void printCOFFDirectives() override;
  57. void printCOFFBaseReloc() override;
  58. void printStackMap() const override;
  59. private:
  60. void printSymbol(const SymbolRef &Sym);
  61. void printRelocation(const SectionRef &Section, const RelocationRef &Reloc);
  62. void printDataDirectory(uint32_t Index, const std::string &FieldName);
  63. void printDOSHeader(const dos_header *DH);
  64. template <class PEHeader> void printPEHeader(const PEHeader *Hdr);
  65. void printBaseOfDataField(const pe32_header *Hdr);
  66. void printBaseOfDataField(const pe32plus_header *Hdr);
  67. void printCodeViewDebugInfo(const SectionRef &Section);
  68. void printCodeViewSymbolsSubsection(StringRef Subsection,
  69. const SectionRef &Section,
  70. uint32_t Offset);
  71. void cacheRelocations();
  72. std::error_code resolveSymbol(const coff_section *Section, uint64_t Offset,
  73. SymbolRef &Sym);
  74. std::error_code resolveSymbolName(const coff_section *Section,
  75. uint64_t Offset, StringRef &Name);
  76. void printImportedSymbols(iterator_range<imported_symbol_iterator> Range);
  77. void printDelayImportedSymbols(
  78. const DelayImportDirectoryEntryRef &I,
  79. iterator_range<imported_symbol_iterator> Range);
  80. typedef DenseMap<const coff_section*, std::vector<RelocationRef> > RelocMapTy;
  81. const llvm::object::COFFObjectFile *Obj;
  82. bool RelocCached = false;
  83. RelocMapTy RelocMap;
  84. StringRef CVFileIndexToStringOffsetTable;
  85. StringRef CVStringTable;
  86. };
  87. } // namespace
  88. namespace llvm {
  89. std::error_code createCOFFDumper(const object::ObjectFile *Obj,
  90. StreamWriter &Writer,
  91. std::unique_ptr<ObjDumper> &Result) {
  92. const COFFObjectFile *COFFObj = dyn_cast<COFFObjectFile>(Obj);
  93. if (!COFFObj)
  94. return readobj_error::unsupported_obj_file_format;
  95. Result.reset(new COFFDumper(COFFObj, Writer));
  96. return readobj_error::success;
  97. }
  98. } // namespace llvm
  99. // Given a a section and an offset into this section the function returns the
  100. // symbol used for the relocation at the offset.
  101. std::error_code COFFDumper::resolveSymbol(const coff_section *Section,
  102. uint64_t Offset, SymbolRef &Sym) {
  103. cacheRelocations();
  104. const auto &Relocations = RelocMap[Section];
  105. for (const auto &Relocation : Relocations) {
  106. uint64_t RelocationOffset = Relocation.getOffset();
  107. if (RelocationOffset == Offset) {
  108. Sym = *Relocation.getSymbol();
  109. return readobj_error::success;
  110. }
  111. }
  112. return readobj_error::unknown_symbol;
  113. }
  114. // Given a section and an offset into this section the function returns the name
  115. // of the symbol used for the relocation at the offset.
  116. std::error_code COFFDumper::resolveSymbolName(const coff_section *Section,
  117. uint64_t Offset,
  118. StringRef &Name) {
  119. SymbolRef Symbol;
  120. if (std::error_code EC = resolveSymbol(Section, Offset, Symbol))
  121. return EC;
  122. ErrorOr<StringRef> NameOrErr = Symbol.getName();
  123. if (std::error_code EC = NameOrErr.getError())
  124. return EC;
  125. Name = *NameOrErr;
  126. return std::error_code();
  127. }
  128. static const EnumEntry<COFF::MachineTypes> ImageFileMachineType[] = {
  129. LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_UNKNOWN ),
  130. LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_AM33 ),
  131. LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_AMD64 ),
  132. LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_ARM ),
  133. LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_ARMNT ),
  134. LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_EBC ),
  135. LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_I386 ),
  136. LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_IA64 ),
  137. LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_M32R ),
  138. LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_MIPS16 ),
  139. LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_MIPSFPU ),
  140. LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_MIPSFPU16),
  141. LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_POWERPC ),
  142. LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_POWERPCFP),
  143. LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_R4000 ),
  144. LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_SH3 ),
  145. LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_SH3DSP ),
  146. LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_SH4 ),
  147. LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_SH5 ),
  148. LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_THUMB ),
  149. LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_WCEMIPSV2)
  150. };
  151. static const EnumEntry<COFF::Characteristics> ImageFileCharacteristics[] = {
  152. LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_RELOCS_STRIPPED ),
  153. LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_EXECUTABLE_IMAGE ),
  154. LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_LINE_NUMS_STRIPPED ),
  155. LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_LOCAL_SYMS_STRIPPED ),
  156. LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_AGGRESSIVE_WS_TRIM ),
  157. LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_LARGE_ADDRESS_AWARE ),
  158. LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_BYTES_REVERSED_LO ),
  159. LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_32BIT_MACHINE ),
  160. LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_DEBUG_STRIPPED ),
  161. LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP),
  162. LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_NET_RUN_FROM_SWAP ),
  163. LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_SYSTEM ),
  164. LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_DLL ),
  165. LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_UP_SYSTEM_ONLY ),
  166. LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_BYTES_REVERSED_HI )
  167. };
  168. static const EnumEntry<COFF::WindowsSubsystem> PEWindowsSubsystem[] = {
  169. LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SUBSYSTEM_UNKNOWN ),
  170. LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SUBSYSTEM_NATIVE ),
  171. LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SUBSYSTEM_WINDOWS_GUI ),
  172. LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SUBSYSTEM_WINDOWS_CUI ),
  173. LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SUBSYSTEM_POSIX_CUI ),
  174. LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SUBSYSTEM_WINDOWS_CE_GUI ),
  175. LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SUBSYSTEM_EFI_APPLICATION ),
  176. LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER),
  177. LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER ),
  178. LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SUBSYSTEM_EFI_ROM ),
  179. LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SUBSYSTEM_XBOX ),
  180. };
  181. static const EnumEntry<COFF::DLLCharacteristics> PEDLLCharacteristics[] = {
  182. LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_HIGH_ENTROPY_VA ),
  183. LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE ),
  184. LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_FORCE_INTEGRITY ),
  185. LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_NX_COMPAT ),
  186. LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_NO_ISOLATION ),
  187. LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_NO_SEH ),
  188. LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_NO_BIND ),
  189. LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_APPCONTAINER ),
  190. LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_WDM_DRIVER ),
  191. LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_GUARD_CF ),
  192. LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_DLL_CHARACTERISTICS_TERMINAL_SERVER_AWARE),
  193. };
  194. static const EnumEntry<COFF::SectionCharacteristics>
  195. ImageSectionCharacteristics[] = {
  196. LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_TYPE_NO_PAD ),
  197. LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_CNT_CODE ),
  198. LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_CNT_INITIALIZED_DATA ),
  199. LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_CNT_UNINITIALIZED_DATA),
  200. LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_LNK_OTHER ),
  201. LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_LNK_INFO ),
  202. LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_LNK_REMOVE ),
  203. LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_LNK_COMDAT ),
  204. LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_GPREL ),
  205. LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_MEM_PURGEABLE ),
  206. LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_MEM_16BIT ),
  207. LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_MEM_LOCKED ),
  208. LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_MEM_PRELOAD ),
  209. LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_1BYTES ),
  210. LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_2BYTES ),
  211. LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_4BYTES ),
  212. LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_8BYTES ),
  213. LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_16BYTES ),
  214. LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_32BYTES ),
  215. LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_64BYTES ),
  216. LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_128BYTES ),
  217. LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_256BYTES ),
  218. LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_512BYTES ),
  219. LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_1024BYTES ),
  220. LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_2048BYTES ),
  221. LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_4096BYTES ),
  222. LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_ALIGN_8192BYTES ),
  223. LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_LNK_NRELOC_OVFL ),
  224. LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_MEM_DISCARDABLE ),
  225. LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_MEM_NOT_CACHED ),
  226. LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_MEM_NOT_PAGED ),
  227. LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_MEM_SHARED ),
  228. LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_MEM_EXECUTE ),
  229. LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_MEM_READ ),
  230. LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_SCN_MEM_WRITE )
  231. };
  232. static const EnumEntry<COFF::SymbolBaseType> ImageSymType[] = {
  233. { "Null" , COFF::IMAGE_SYM_TYPE_NULL },
  234. { "Void" , COFF::IMAGE_SYM_TYPE_VOID },
  235. { "Char" , COFF::IMAGE_SYM_TYPE_CHAR },
  236. { "Short" , COFF::IMAGE_SYM_TYPE_SHORT },
  237. { "Int" , COFF::IMAGE_SYM_TYPE_INT },
  238. { "Long" , COFF::IMAGE_SYM_TYPE_LONG },
  239. { "Float" , COFF::IMAGE_SYM_TYPE_FLOAT },
  240. { "Double", COFF::IMAGE_SYM_TYPE_DOUBLE },
  241. { "Struct", COFF::IMAGE_SYM_TYPE_STRUCT },
  242. { "Union" , COFF::IMAGE_SYM_TYPE_UNION },
  243. { "Enum" , COFF::IMAGE_SYM_TYPE_ENUM },
  244. { "MOE" , COFF::IMAGE_SYM_TYPE_MOE },
  245. { "Byte" , COFF::IMAGE_SYM_TYPE_BYTE },
  246. { "Word" , COFF::IMAGE_SYM_TYPE_WORD },
  247. { "UInt" , COFF::IMAGE_SYM_TYPE_UINT },
  248. { "DWord" , COFF::IMAGE_SYM_TYPE_DWORD }
  249. };
  250. static const EnumEntry<COFF::SymbolComplexType> ImageSymDType[] = {
  251. { "Null" , COFF::IMAGE_SYM_DTYPE_NULL },
  252. { "Pointer" , COFF::IMAGE_SYM_DTYPE_POINTER },
  253. { "Function", COFF::IMAGE_SYM_DTYPE_FUNCTION },
  254. { "Array" , COFF::IMAGE_SYM_DTYPE_ARRAY }
  255. };
  256. static const EnumEntry<COFF::SymbolStorageClass> ImageSymClass[] = {
  257. { "EndOfFunction" , COFF::IMAGE_SYM_CLASS_END_OF_FUNCTION },
  258. { "Null" , COFF::IMAGE_SYM_CLASS_NULL },
  259. { "Automatic" , COFF::IMAGE_SYM_CLASS_AUTOMATIC },
  260. { "External" , COFF::IMAGE_SYM_CLASS_EXTERNAL },
  261. { "Static" , COFF::IMAGE_SYM_CLASS_STATIC },
  262. { "Register" , COFF::IMAGE_SYM_CLASS_REGISTER },
  263. { "ExternalDef" , COFF::IMAGE_SYM_CLASS_EXTERNAL_DEF },
  264. { "Label" , COFF::IMAGE_SYM_CLASS_LABEL },
  265. { "UndefinedLabel" , COFF::IMAGE_SYM_CLASS_UNDEFINED_LABEL },
  266. { "MemberOfStruct" , COFF::IMAGE_SYM_CLASS_MEMBER_OF_STRUCT },
  267. { "Argument" , COFF::IMAGE_SYM_CLASS_ARGUMENT },
  268. { "StructTag" , COFF::IMAGE_SYM_CLASS_STRUCT_TAG },
  269. { "MemberOfUnion" , COFF::IMAGE_SYM_CLASS_MEMBER_OF_UNION },
  270. { "UnionTag" , COFF::IMAGE_SYM_CLASS_UNION_TAG },
  271. { "TypeDefinition" , COFF::IMAGE_SYM_CLASS_TYPE_DEFINITION },
  272. { "UndefinedStatic", COFF::IMAGE_SYM_CLASS_UNDEFINED_STATIC },
  273. { "EnumTag" , COFF::IMAGE_SYM_CLASS_ENUM_TAG },
  274. { "MemberOfEnum" , COFF::IMAGE_SYM_CLASS_MEMBER_OF_ENUM },
  275. { "RegisterParam" , COFF::IMAGE_SYM_CLASS_REGISTER_PARAM },
  276. { "BitField" , COFF::IMAGE_SYM_CLASS_BIT_FIELD },
  277. { "Block" , COFF::IMAGE_SYM_CLASS_BLOCK },
  278. { "Function" , COFF::IMAGE_SYM_CLASS_FUNCTION },
  279. { "EndOfStruct" , COFF::IMAGE_SYM_CLASS_END_OF_STRUCT },
  280. { "File" , COFF::IMAGE_SYM_CLASS_FILE },
  281. { "Section" , COFF::IMAGE_SYM_CLASS_SECTION },
  282. { "WeakExternal" , COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL },
  283. { "CLRToken" , COFF::IMAGE_SYM_CLASS_CLR_TOKEN }
  284. };
  285. static const EnumEntry<COFF::COMDATType> ImageCOMDATSelect[] = {
  286. { "NoDuplicates", COFF::IMAGE_COMDAT_SELECT_NODUPLICATES },
  287. { "Any" , COFF::IMAGE_COMDAT_SELECT_ANY },
  288. { "SameSize" , COFF::IMAGE_COMDAT_SELECT_SAME_SIZE },
  289. { "ExactMatch" , COFF::IMAGE_COMDAT_SELECT_EXACT_MATCH },
  290. { "Associative" , COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE },
  291. { "Largest" , COFF::IMAGE_COMDAT_SELECT_LARGEST },
  292. { "Newest" , COFF::IMAGE_COMDAT_SELECT_NEWEST }
  293. };
  294. static const EnumEntry<COFF::WeakExternalCharacteristics>
  295. WeakExternalCharacteristics[] = {
  296. { "NoLibrary", COFF::IMAGE_WEAK_EXTERN_SEARCH_NOLIBRARY },
  297. { "Library" , COFF::IMAGE_WEAK_EXTERN_SEARCH_LIBRARY },
  298. { "Alias" , COFF::IMAGE_WEAK_EXTERN_SEARCH_ALIAS }
  299. };
  300. template <typename T>
  301. static std::error_code getSymbolAuxData(const COFFObjectFile *Obj,
  302. COFFSymbolRef Symbol,
  303. uint8_t AuxSymbolIdx, const T *&Aux) {
  304. ArrayRef<uint8_t> AuxData = Obj->getSymbolAuxData(Symbol);
  305. AuxData = AuxData.slice(AuxSymbolIdx * Obj->getSymbolTableEntrySize());
  306. Aux = reinterpret_cast<const T*>(AuxData.data());
  307. return readobj_error::success;
  308. }
  309. void COFFDumper::cacheRelocations() {
  310. if (RelocCached)
  311. return;
  312. RelocCached = true;
  313. for (const SectionRef &S : Obj->sections()) {
  314. const coff_section *Section = Obj->getCOFFSection(S);
  315. for (const RelocationRef &Reloc : S.relocations())
  316. RelocMap[Section].push_back(Reloc);
  317. // Sort relocations by address.
  318. std::sort(RelocMap[Section].begin(), RelocMap[Section].end(),
  319. relocAddressLess);
  320. }
  321. }
  322. void COFFDumper::printDataDirectory(uint32_t Index, const std::string &FieldName) {
  323. const data_directory *Data;
  324. if (Obj->getDataDirectory(Index, Data))
  325. return;
  326. W.printHex(FieldName + "RVA", Data->RelativeVirtualAddress);
  327. W.printHex(FieldName + "Size", Data->Size);
  328. }
  329. void COFFDumper::printFileHeaders() {
  330. time_t TDS = Obj->getTimeDateStamp();
  331. char FormattedTime[20] = { };
  332. strftime(FormattedTime, 20, "%Y-%m-%d %H:%M:%S", gmtime(&TDS));
  333. {
  334. DictScope D(W, "ImageFileHeader");
  335. W.printEnum ("Machine", Obj->getMachine(),
  336. makeArrayRef(ImageFileMachineType));
  337. W.printNumber("SectionCount", Obj->getNumberOfSections());
  338. W.printHex ("TimeDateStamp", FormattedTime, Obj->getTimeDateStamp());
  339. W.printHex ("PointerToSymbolTable", Obj->getPointerToSymbolTable());
  340. W.printNumber("SymbolCount", Obj->getNumberOfSymbols());
  341. W.printNumber("OptionalHeaderSize", Obj->getSizeOfOptionalHeader());
  342. W.printFlags ("Characteristics", Obj->getCharacteristics(),
  343. makeArrayRef(ImageFileCharacteristics));
  344. }
  345. // Print PE header. This header does not exist if this is an object file and
  346. // not an executable.
  347. const pe32_header *PEHeader = nullptr;
  348. if (error(Obj->getPE32Header(PEHeader)))
  349. return;
  350. if (PEHeader)
  351. printPEHeader<pe32_header>(PEHeader);
  352. const pe32plus_header *PEPlusHeader = nullptr;
  353. if (error(Obj->getPE32PlusHeader(PEPlusHeader)))
  354. return;
  355. if (PEPlusHeader)
  356. printPEHeader<pe32plus_header>(PEPlusHeader);
  357. if (const dos_header *DH = Obj->getDOSHeader())
  358. printDOSHeader(DH);
  359. }
  360. void COFFDumper::printDOSHeader(const dos_header *DH) {
  361. DictScope D(W, "DOSHeader");
  362. W.printString("Magic", StringRef(DH->Magic, sizeof(DH->Magic)));
  363. W.printNumber("UsedBytesInTheLastPage", DH->UsedBytesInTheLastPage);
  364. W.printNumber("FileSizeInPages", DH->FileSizeInPages);
  365. W.printNumber("NumberOfRelocationItems", DH->NumberOfRelocationItems);
  366. W.printNumber("HeaderSizeInParagraphs", DH->HeaderSizeInParagraphs);
  367. W.printNumber("MinimumExtraParagraphs", DH->MinimumExtraParagraphs);
  368. W.printNumber("MaximumExtraParagraphs", DH->MaximumExtraParagraphs);
  369. W.printNumber("InitialRelativeSS", DH->InitialRelativeSS);
  370. W.printNumber("InitialSP", DH->InitialSP);
  371. W.printNumber("Checksum", DH->Checksum);
  372. W.printNumber("InitialIP", DH->InitialIP);
  373. W.printNumber("InitialRelativeCS", DH->InitialRelativeCS);
  374. W.printNumber("AddressOfRelocationTable", DH->AddressOfRelocationTable);
  375. W.printNumber("OverlayNumber", DH->OverlayNumber);
  376. W.printNumber("OEMid", DH->OEMid);
  377. W.printNumber("OEMinfo", DH->OEMinfo);
  378. W.printNumber("AddressOfNewExeHeader", DH->AddressOfNewExeHeader);
  379. }
  380. template <class PEHeader>
  381. void COFFDumper::printPEHeader(const PEHeader *Hdr) {
  382. DictScope D(W, "ImageOptionalHeader");
  383. W.printNumber("MajorLinkerVersion", Hdr->MajorLinkerVersion);
  384. W.printNumber("MinorLinkerVersion", Hdr->MinorLinkerVersion);
  385. W.printNumber("SizeOfCode", Hdr->SizeOfCode);
  386. W.printNumber("SizeOfInitializedData", Hdr->SizeOfInitializedData);
  387. W.printNumber("SizeOfUninitializedData", Hdr->SizeOfUninitializedData);
  388. W.printHex ("AddressOfEntryPoint", Hdr->AddressOfEntryPoint);
  389. W.printHex ("BaseOfCode", Hdr->BaseOfCode);
  390. printBaseOfDataField(Hdr);
  391. W.printHex ("ImageBase", Hdr->ImageBase);
  392. W.printNumber("SectionAlignment", Hdr->SectionAlignment);
  393. W.printNumber("FileAlignment", Hdr->FileAlignment);
  394. W.printNumber("MajorOperatingSystemVersion",
  395. Hdr->MajorOperatingSystemVersion);
  396. W.printNumber("MinorOperatingSystemVersion",
  397. Hdr->MinorOperatingSystemVersion);
  398. W.printNumber("MajorImageVersion", Hdr->MajorImageVersion);
  399. W.printNumber("MinorImageVersion", Hdr->MinorImageVersion);
  400. W.printNumber("MajorSubsystemVersion", Hdr->MajorSubsystemVersion);
  401. W.printNumber("MinorSubsystemVersion", Hdr->MinorSubsystemVersion);
  402. W.printNumber("SizeOfImage", Hdr->SizeOfImage);
  403. W.printNumber("SizeOfHeaders", Hdr->SizeOfHeaders);
  404. W.printEnum ("Subsystem", Hdr->Subsystem, makeArrayRef(PEWindowsSubsystem));
  405. W.printFlags ("Characteristics", Hdr->DLLCharacteristics,
  406. makeArrayRef(PEDLLCharacteristics));
  407. W.printNumber("SizeOfStackReserve", Hdr->SizeOfStackReserve);
  408. W.printNumber("SizeOfStackCommit", Hdr->SizeOfStackCommit);
  409. W.printNumber("SizeOfHeapReserve", Hdr->SizeOfHeapReserve);
  410. W.printNumber("SizeOfHeapCommit", Hdr->SizeOfHeapCommit);
  411. W.printNumber("NumberOfRvaAndSize", Hdr->NumberOfRvaAndSize);
  412. if (Hdr->NumberOfRvaAndSize > 0) {
  413. DictScope D(W, "DataDirectory");
  414. static const char * const directory[] = {
  415. "ExportTable", "ImportTable", "ResourceTable", "ExceptionTable",
  416. "CertificateTable", "BaseRelocationTable", "Debug", "Architecture",
  417. "GlobalPtr", "TLSTable", "LoadConfigTable", "BoundImport", "IAT",
  418. "DelayImportDescriptor", "CLRRuntimeHeader", "Reserved"
  419. };
  420. for (uint32_t i = 0; i < Hdr->NumberOfRvaAndSize; ++i) {
  421. printDataDirectory(i, directory[i]);
  422. }
  423. }
  424. }
  425. void COFFDumper::printBaseOfDataField(const pe32_header *Hdr) {
  426. W.printHex("BaseOfData", Hdr->BaseOfData);
  427. }
  428. void COFFDumper::printBaseOfDataField(const pe32plus_header *) {}
  429. void COFFDumper::printCodeViewDebugInfo(const SectionRef &Section) {
  430. StringRef Data;
  431. if (error(Section.getContents(Data)))
  432. return;
  433. SmallVector<StringRef, 10> FunctionNames;
  434. StringMap<StringRef> FunctionLineTables;
  435. ListScope D(W, "CodeViewDebugInfo");
  436. {
  437. // FIXME: Add more offset correctness checks.
  438. DataExtractor DE(Data, true, 4);
  439. uint32_t Offset = 0,
  440. Magic = DE.getU32(&Offset);
  441. W.printHex("Magic", Magic);
  442. if (Magic != COFF::DEBUG_SECTION_MAGIC) {
  443. error(object_error::parse_failed);
  444. return;
  445. }
  446. bool Finished = false;
  447. while (DE.isValidOffset(Offset) && !Finished) {
  448. // The section consists of a number of subsection in the following format:
  449. // |Type|PayloadSize|Payload...|
  450. uint32_t SubSectionType = DE.getU32(&Offset),
  451. PayloadSize = DE.getU32(&Offset);
  452. ListScope S(W, "Subsection");
  453. W.printHex("Type", SubSectionType);
  454. W.printHex("PayloadSize", PayloadSize);
  455. if (PayloadSize > Data.size() - Offset) {
  456. error(object_error::parse_failed);
  457. return;
  458. }
  459. StringRef Contents = Data.substr(Offset, PayloadSize);
  460. if (opts::CodeViewSubsectionBytes) {
  461. // Print the raw contents to simplify debugging if anything goes wrong
  462. // afterwards.
  463. W.printBinaryBlock("Contents", Contents);
  464. }
  465. switch (SubSectionType) {
  466. case COFF::DEBUG_SYMBOL_SUBSECTION:
  467. if (opts::SectionSymbols)
  468. printCodeViewSymbolsSubsection(Contents, Section, Offset);
  469. break;
  470. case COFF::DEBUG_LINE_TABLE_SUBSECTION: {
  471. // Holds a PC to file:line table. Some data to parse this subsection is
  472. // stored in the other subsections, so just check sanity and store the
  473. // pointers for deferred processing.
  474. if (PayloadSize < 12) {
  475. // There should be at least three words to store two function
  476. // relocations and size of the code.
  477. error(object_error::parse_failed);
  478. return;
  479. }
  480. StringRef FunctionName;
  481. if (error(resolveSymbolName(Obj->getCOFFSection(Section), Offset,
  482. FunctionName)))
  483. return;
  484. W.printString("FunctionName", FunctionName);
  485. if (FunctionLineTables.count(FunctionName) != 0) {
  486. // Saw debug info for this function already?
  487. error(object_error::parse_failed);
  488. return;
  489. }
  490. FunctionLineTables[FunctionName] = Contents;
  491. FunctionNames.push_back(FunctionName);
  492. break;
  493. }
  494. case COFF::DEBUG_STRING_TABLE_SUBSECTION:
  495. if (PayloadSize == 0 || CVStringTable.data() != nullptr ||
  496. Contents.back() != '\0') {
  497. // Empty or duplicate or non-null-terminated subsection.
  498. error(object_error::parse_failed);
  499. return;
  500. }
  501. CVStringTable = Contents;
  502. break;
  503. case COFF::DEBUG_INDEX_SUBSECTION:
  504. // Holds the translation table from file indices
  505. // to offsets in the string table.
  506. if (PayloadSize == 0 ||
  507. CVFileIndexToStringOffsetTable.data() != nullptr) {
  508. // Empty or duplicate subsection.
  509. error(object_error::parse_failed);
  510. return;
  511. }
  512. CVFileIndexToStringOffsetTable = Contents;
  513. break;
  514. }
  515. Offset += PayloadSize;
  516. // Align the reading pointer by 4.
  517. Offset += (-Offset) % 4;
  518. }
  519. }
  520. // Dump the line tables now that we've read all the subsections and know all
  521. // the required information.
  522. for (unsigned I = 0, E = FunctionNames.size(); I != E; ++I) {
  523. StringRef Name = FunctionNames[I];
  524. ListScope S(W, "FunctionLineTable");
  525. W.printString("FunctionName", Name);
  526. DataExtractor DE(FunctionLineTables[Name], true, 4);
  527. uint32_t Offset = 6; // Skip relocations.
  528. uint16_t Flags = DE.getU16(&Offset);
  529. W.printHex("Flags", Flags);
  530. bool HasColumnInformation =
  531. Flags & COFF::DEBUG_LINE_TABLES_HAVE_COLUMN_RECORDS;
  532. uint32_t FunctionSize = DE.getU32(&Offset);
  533. W.printHex("CodeSize", FunctionSize);
  534. while (DE.isValidOffset(Offset)) {
  535. // For each range of lines with the same filename, we have a segment
  536. // in the line table. The filename string is accessed using double
  537. // indirection to the string table subsection using the index subsection.
  538. uint32_t OffsetInIndex = DE.getU32(&Offset),
  539. SegmentLength = DE.getU32(&Offset),
  540. FullSegmentSize = DE.getU32(&Offset);
  541. if (FullSegmentSize !=
  542. 12 + 8 * SegmentLength +
  543. (HasColumnInformation ? 4 * SegmentLength : 0)) {
  544. error(object_error::parse_failed);
  545. return;
  546. }
  547. uint32_t FilenameOffset;
  548. {
  549. DataExtractor SDE(CVFileIndexToStringOffsetTable, true, 4);
  550. uint32_t OffsetInSDE = OffsetInIndex;
  551. if (!SDE.isValidOffset(OffsetInSDE)) {
  552. error(object_error::parse_failed);
  553. return;
  554. }
  555. FilenameOffset = SDE.getU32(&OffsetInSDE);
  556. }
  557. if (FilenameOffset == 0 || FilenameOffset + 1 >= CVStringTable.size() ||
  558. CVStringTable.data()[FilenameOffset - 1] != '\0') {
  559. // Each string in an F3 subsection should be preceded by a null
  560. // character.
  561. error(object_error::parse_failed);
  562. return;
  563. }
  564. StringRef Filename(CVStringTable.data() + FilenameOffset);
  565. ListScope S(W, "FilenameSegment");
  566. W.printString("Filename", Filename);
  567. for (unsigned J = 0; J != SegmentLength && DE.isValidOffset(Offset);
  568. ++J) {
  569. // Then go the (PC, LineNumber) pairs. The line number is stored in the
  570. // least significant 31 bits of the respective word in the table.
  571. uint32_t PC = DE.getU32(&Offset),
  572. LineNumber = DE.getU32(&Offset) & 0x7fffffff;
  573. if (PC >= FunctionSize) {
  574. error(object_error::parse_failed);
  575. return;
  576. }
  577. char Buffer[32];
  578. format("+0x%X", PC).snprint(Buffer, 32);
  579. W.printNumber(Buffer, LineNumber);
  580. }
  581. if (HasColumnInformation) {
  582. for (unsigned J = 0; J != SegmentLength && DE.isValidOffset(Offset);
  583. ++J) {
  584. uint16_t ColStart = DE.getU16(&Offset);
  585. W.printNumber("ColStart", ColStart);
  586. uint16_t ColEnd = DE.getU16(&Offset);
  587. W.printNumber("ColEnd", ColEnd);
  588. }
  589. }
  590. }
  591. }
  592. }
  593. void COFFDumper::printCodeViewSymbolsSubsection(StringRef Subsection,
  594. const SectionRef &Section,
  595. uint32_t OffsetInSection) {
  596. if (Subsection.size() == 0) {
  597. error(object_error::parse_failed);
  598. return;
  599. }
  600. DataExtractor DE(Subsection, true, 4);
  601. uint32_t Offset = 0;
  602. // Function-level subsections have "procedure start" and "procedure end"
  603. // commands that should come in pairs and surround relevant info.
  604. bool InFunctionScope = false;
  605. while (DE.isValidOffset(Offset)) {
  606. // Read subsection segments one by one.
  607. uint16_t Size = DE.getU16(&Offset);
  608. // The section size includes the size of the type identifier.
  609. if (Size < 2 || !DE.isValidOffsetForDataOfSize(Offset, Size)) {
  610. error(object_error::parse_failed);
  611. return;
  612. }
  613. Size -= 2;
  614. uint16_t Type = DE.getU16(&Offset);
  615. switch (Type) {
  616. case COFF::DEBUG_SYMBOL_TYPE_PROC_START: {
  617. DictScope S(W, "ProcStart");
  618. if (InFunctionScope || Size < 36) {
  619. error(object_error::parse_failed);
  620. return;
  621. }
  622. InFunctionScope = true;
  623. // We're currently interested in a limited subset of fields in this
  624. // segment, just ignore the rest of the fields for now.
  625. uint8_t Unused[12];
  626. DE.getU8(&Offset, Unused, 12);
  627. uint32_t CodeSize = DE.getU32(&Offset);
  628. DE.getU8(&Offset, Unused, 12);
  629. StringRef SectionName;
  630. if (error(resolveSymbolName(Obj->getCOFFSection(Section),
  631. OffsetInSection + Offset, SectionName)))
  632. return;
  633. Offset += 4;
  634. DE.getU8(&Offset, Unused, 3);
  635. StringRef DisplayName = DE.getCStr(&Offset);
  636. if (!DE.isValidOffset(Offset)) {
  637. error(object_error::parse_failed);
  638. return;
  639. }
  640. W.printString("DisplayName", DisplayName);
  641. W.printString("Section", SectionName);
  642. W.printHex("CodeSize", CodeSize);
  643. break;
  644. }
  645. case COFF::DEBUG_SYMBOL_TYPE_PROC_END: {
  646. W.startLine() << "ProcEnd\n";
  647. if (!InFunctionScope || Size > 0) {
  648. error(object_error::parse_failed);
  649. return;
  650. }
  651. InFunctionScope = false;
  652. break;
  653. }
  654. default: {
  655. if (opts::CodeViewSubsectionBytes) {
  656. ListScope S(W, "Record");
  657. W.printHex("Size", Size);
  658. W.printHex("Type", Type);
  659. StringRef Contents = DE.getData().substr(Offset, Size);
  660. W.printBinaryBlock("Contents", Contents);
  661. }
  662. Offset += Size;
  663. break;
  664. }
  665. }
  666. }
  667. if (InFunctionScope)
  668. error(object_error::parse_failed);
  669. }
  670. void COFFDumper::printSections() {
  671. ListScope SectionsD(W, "Sections");
  672. int SectionNumber = 0;
  673. for (const SectionRef &Sec : Obj->sections()) {
  674. ++SectionNumber;
  675. const coff_section *Section = Obj->getCOFFSection(Sec);
  676. StringRef Name;
  677. if (error(Sec.getName(Name)))
  678. Name = "";
  679. DictScope D(W, "Section");
  680. W.printNumber("Number", SectionNumber);
  681. W.printBinary("Name", Name, Section->Name);
  682. W.printHex ("VirtualSize", Section->VirtualSize);
  683. W.printHex ("VirtualAddress", Section->VirtualAddress);
  684. W.printNumber("RawDataSize", Section->SizeOfRawData);
  685. W.printHex ("PointerToRawData", Section->PointerToRawData);
  686. W.printHex ("PointerToRelocations", Section->PointerToRelocations);
  687. W.printHex ("PointerToLineNumbers", Section->PointerToLinenumbers);
  688. W.printNumber("RelocationCount", Section->NumberOfRelocations);
  689. W.printNumber("LineNumberCount", Section->NumberOfLinenumbers);
  690. W.printFlags ("Characteristics", Section->Characteristics,
  691. makeArrayRef(ImageSectionCharacteristics),
  692. COFF::SectionCharacteristics(0x00F00000));
  693. if (opts::SectionRelocations) {
  694. ListScope D(W, "Relocations");
  695. for (const RelocationRef &Reloc : Sec.relocations())
  696. printRelocation(Sec, Reloc);
  697. }
  698. if (opts::SectionSymbols) {
  699. ListScope D(W, "Symbols");
  700. for (const SymbolRef &Symbol : Obj->symbols()) {
  701. if (!Sec.containsSymbol(Symbol))
  702. continue;
  703. printSymbol(Symbol);
  704. }
  705. }
  706. if (Name == ".debug$S" && opts::CodeView)
  707. printCodeViewDebugInfo(Sec);
  708. if (opts::SectionData &&
  709. !(Section->Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA)) {
  710. StringRef Data;
  711. if (error(Sec.getContents(Data)))
  712. break;
  713. W.printBinaryBlock("SectionData", Data);
  714. }
  715. }
  716. }
  717. void COFFDumper::printRelocations() {
  718. ListScope D(W, "Relocations");
  719. int SectionNumber = 0;
  720. for (const SectionRef &Section : Obj->sections()) {
  721. ++SectionNumber;
  722. StringRef Name;
  723. if (error(Section.getName(Name)))
  724. continue;
  725. bool PrintedGroup = false;
  726. for (const RelocationRef &Reloc : Section.relocations()) {
  727. if (!PrintedGroup) {
  728. W.startLine() << "Section (" << SectionNumber << ") " << Name << " {\n";
  729. W.indent();
  730. PrintedGroup = true;
  731. }
  732. printRelocation(Section, Reloc);
  733. }
  734. if (PrintedGroup) {
  735. W.unindent();
  736. W.startLine() << "}\n";
  737. }
  738. }
  739. }
  740. void COFFDumper::printRelocation(const SectionRef &Section,
  741. const RelocationRef &Reloc) {
  742. uint64_t Offset = Reloc.getOffset();
  743. uint64_t RelocType = Reloc.getType();
  744. SmallString<32> RelocName;
  745. StringRef SymbolName;
  746. Reloc.getTypeName(RelocName);
  747. symbol_iterator Symbol = Reloc.getSymbol();
  748. if (Symbol != Obj->symbol_end()) {
  749. ErrorOr<StringRef> SymbolNameOrErr = Symbol->getName();
  750. if (error(SymbolNameOrErr.getError()))
  751. return;
  752. SymbolName = *SymbolNameOrErr;
  753. }
  754. if (opts::ExpandRelocs) {
  755. DictScope Group(W, "Relocation");
  756. W.printHex("Offset", Offset);
  757. W.printNumber("Type", RelocName, RelocType);
  758. W.printString("Symbol", SymbolName.empty() ? "-" : SymbolName);
  759. } else {
  760. raw_ostream& OS = W.startLine();
  761. OS << W.hex(Offset)
  762. << " " << RelocName
  763. << " " << (SymbolName.empty() ? "-" : SymbolName)
  764. << "\n";
  765. }
  766. }
  767. void COFFDumper::printSymbols() {
  768. ListScope Group(W, "Symbols");
  769. for (const SymbolRef &Symbol : Obj->symbols())
  770. printSymbol(Symbol);
  771. }
  772. void COFFDumper::printDynamicSymbols() { ListScope Group(W, "DynamicSymbols"); }
  773. static ErrorOr<StringRef>
  774. getSectionName(const llvm::object::COFFObjectFile *Obj, int32_t SectionNumber,
  775. const coff_section *Section) {
  776. if (Section) {
  777. StringRef SectionName;
  778. if (std::error_code EC = Obj->getSectionName(Section, SectionName))
  779. return EC;
  780. return SectionName;
  781. }
  782. if (SectionNumber == llvm::COFF::IMAGE_SYM_DEBUG)
  783. return StringRef("IMAGE_SYM_DEBUG");
  784. if (SectionNumber == llvm::COFF::IMAGE_SYM_ABSOLUTE)
  785. return StringRef("IMAGE_SYM_ABSOLUTE");
  786. if (SectionNumber == llvm::COFF::IMAGE_SYM_UNDEFINED)
  787. return StringRef("IMAGE_SYM_UNDEFINED");
  788. return StringRef("");
  789. }
  790. void COFFDumper::printSymbol(const SymbolRef &Sym) {
  791. DictScope D(W, "Symbol");
  792. COFFSymbolRef Symbol = Obj->getCOFFSymbol(Sym);
  793. const coff_section *Section;
  794. if (std::error_code EC = Obj->getSection(Symbol.getSectionNumber(), Section)) {
  795. W.startLine() << "Invalid section number: " << EC.message() << "\n";
  796. W.flush();
  797. return;
  798. }
  799. StringRef SymbolName;
  800. if (Obj->getSymbolName(Symbol, SymbolName))
  801. SymbolName = "";
  802. StringRef SectionName = "";
  803. ErrorOr<StringRef> Res =
  804. getSectionName(Obj, Symbol.getSectionNumber(), Section);
  805. if (Res)
  806. SectionName = *Res;
  807. W.printString("Name", SymbolName);
  808. W.printNumber("Value", Symbol.getValue());
  809. W.printNumber("Section", SectionName, Symbol.getSectionNumber());
  810. W.printEnum ("BaseType", Symbol.getBaseType(), makeArrayRef(ImageSymType));
  811. W.printEnum ("ComplexType", Symbol.getComplexType(),
  812. makeArrayRef(ImageSymDType));
  813. W.printEnum ("StorageClass", Symbol.getStorageClass(),
  814. makeArrayRef(ImageSymClass));
  815. W.printNumber("AuxSymbolCount", Symbol.getNumberOfAuxSymbols());
  816. for (uint8_t I = 0; I < Symbol.getNumberOfAuxSymbols(); ++I) {
  817. if (Symbol.isFunctionDefinition()) {
  818. const coff_aux_function_definition *Aux;
  819. if (error(getSymbolAuxData(Obj, Symbol, I, Aux)))
  820. break;
  821. DictScope AS(W, "AuxFunctionDef");
  822. W.printNumber("TagIndex", Aux->TagIndex);
  823. W.printNumber("TotalSize", Aux->TotalSize);
  824. W.printHex("PointerToLineNumber", Aux->PointerToLinenumber);
  825. W.printHex("PointerToNextFunction", Aux->PointerToNextFunction);
  826. } else if (Symbol.isAnyUndefined()) {
  827. const coff_aux_weak_external *Aux;
  828. if (error(getSymbolAuxData(Obj, Symbol, I, Aux)))
  829. break;
  830. ErrorOr<COFFSymbolRef> Linked = Obj->getSymbol(Aux->TagIndex);
  831. StringRef LinkedName;
  832. std::error_code EC = Linked.getError();
  833. if (EC || (EC = Obj->getSymbolName(*Linked, LinkedName))) {
  834. LinkedName = "";
  835. error(EC);
  836. }
  837. DictScope AS(W, "AuxWeakExternal");
  838. W.printNumber("Linked", LinkedName, Aux->TagIndex);
  839. W.printEnum ("Search", Aux->Characteristics,
  840. makeArrayRef(WeakExternalCharacteristics));
  841. } else if (Symbol.isFileRecord()) {
  842. const char *FileName;
  843. if (error(getSymbolAuxData(Obj, Symbol, I, FileName)))
  844. break;
  845. DictScope AS(W, "AuxFileRecord");
  846. StringRef Name(FileName, Symbol.getNumberOfAuxSymbols() *
  847. Obj->getSymbolTableEntrySize());
  848. W.printString("FileName", Name.rtrim(StringRef("\0", 1)));
  849. break;
  850. } else if (Symbol.isSectionDefinition()) {
  851. const coff_aux_section_definition *Aux;
  852. if (error(getSymbolAuxData(Obj, Symbol, I, Aux)))
  853. break;
  854. int32_t AuxNumber = Aux->getNumber(Symbol.isBigObj());
  855. DictScope AS(W, "AuxSectionDef");
  856. W.printNumber("Length", Aux->Length);
  857. W.printNumber("RelocationCount", Aux->NumberOfRelocations);
  858. W.printNumber("LineNumberCount", Aux->NumberOfLinenumbers);
  859. W.printHex("Checksum", Aux->CheckSum);
  860. W.printNumber("Number", AuxNumber);
  861. W.printEnum("Selection", Aux->Selection, makeArrayRef(ImageCOMDATSelect));
  862. if (Section && Section->Characteristics & COFF::IMAGE_SCN_LNK_COMDAT
  863. && Aux->Selection == COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) {
  864. const coff_section *Assoc;
  865. StringRef AssocName = "";
  866. std::error_code EC = Obj->getSection(AuxNumber, Assoc);
  867. ErrorOr<StringRef> Res = getSectionName(Obj, AuxNumber, Assoc);
  868. if (Res)
  869. AssocName = *Res;
  870. if (!EC)
  871. EC = Res.getError();
  872. if (EC) {
  873. AssocName = "";
  874. error(EC);
  875. }
  876. W.printNumber("AssocSection", AssocName, AuxNumber);
  877. }
  878. } else if (Symbol.isCLRToken()) {
  879. const coff_aux_clr_token *Aux;
  880. if (error(getSymbolAuxData(Obj, Symbol, I, Aux)))
  881. break;
  882. ErrorOr<COFFSymbolRef> ReferredSym =
  883. Obj->getSymbol(Aux->SymbolTableIndex);
  884. StringRef ReferredName;
  885. std::error_code EC = ReferredSym.getError();
  886. if (EC || (EC = Obj->getSymbolName(*ReferredSym, ReferredName))) {
  887. ReferredName = "";
  888. error(EC);
  889. }
  890. DictScope AS(W, "AuxCLRToken");
  891. W.printNumber("AuxType", Aux->AuxType);
  892. W.printNumber("Reserved", Aux->Reserved);
  893. W.printNumber("SymbolTableIndex", ReferredName, Aux->SymbolTableIndex);
  894. } else {
  895. W.startLine() << "<unhandled auxiliary record>\n";
  896. }
  897. }
  898. }
  899. void COFFDumper::printUnwindInfo() {
  900. ListScope D(W, "UnwindInformation");
  901. switch (Obj->getMachine()) {
  902. case COFF::IMAGE_FILE_MACHINE_AMD64: {
  903. Win64EH::Dumper Dumper(W);
  904. Win64EH::Dumper::SymbolResolver
  905. Resolver = [](const object::coff_section *Section, uint64_t Offset,
  906. SymbolRef &Symbol, void *user_data) -> std::error_code {
  907. COFFDumper *Dumper = reinterpret_cast<COFFDumper *>(user_data);
  908. return Dumper->resolveSymbol(Section, Offset, Symbol);
  909. };
  910. Win64EH::Dumper::Context Ctx(*Obj, Resolver, this);
  911. Dumper.printData(Ctx);
  912. break;
  913. }
  914. case COFF::IMAGE_FILE_MACHINE_ARMNT: {
  915. ARM::WinEH::Decoder Decoder(W);
  916. Decoder.dumpProcedureData(*Obj);
  917. break;
  918. }
  919. default:
  920. W.printEnum("unsupported Image Machine", Obj->getMachine(),
  921. makeArrayRef(ImageFileMachineType));
  922. break;
  923. }
  924. }
  925. void COFFDumper::printImportedSymbols(
  926. iterator_range<imported_symbol_iterator> Range) {
  927. for (const ImportedSymbolRef &I : Range) {
  928. StringRef Sym;
  929. if (error(I.getSymbolName(Sym))) return;
  930. uint16_t Ordinal;
  931. if (error(I.getOrdinal(Ordinal))) return;
  932. W.printNumber("Symbol", Sym, Ordinal);
  933. }
  934. }
  935. void COFFDumper::printDelayImportedSymbols(
  936. const DelayImportDirectoryEntryRef &I,
  937. iterator_range<imported_symbol_iterator> Range) {
  938. int Index = 0;
  939. for (const ImportedSymbolRef &S : Range) {
  940. DictScope Import(W, "Import");
  941. StringRef Sym;
  942. if (error(S.getSymbolName(Sym))) return;
  943. uint16_t Ordinal;
  944. if (error(S.getOrdinal(Ordinal))) return;
  945. W.printNumber("Symbol", Sym, Ordinal);
  946. uint64_t Addr;
  947. if (error(I.getImportAddress(Index++, Addr))) return;
  948. W.printHex("Address", Addr);
  949. }
  950. }
  951. void COFFDumper::printCOFFImports() {
  952. // Regular imports
  953. for (const ImportDirectoryEntryRef &I : Obj->import_directories()) {
  954. DictScope Import(W, "Import");
  955. StringRef Name;
  956. if (error(I.getName(Name))) return;
  957. W.printString("Name", Name);
  958. uint32_t Addr;
  959. if (error(I.getImportLookupTableRVA(Addr))) return;
  960. W.printHex("ImportLookupTableRVA", Addr);
  961. if (error(I.getImportAddressTableRVA(Addr))) return;
  962. W.printHex("ImportAddressTableRVA", Addr);
  963. printImportedSymbols(I.imported_symbols());
  964. }
  965. // Delay imports
  966. for (const DelayImportDirectoryEntryRef &I : Obj->delay_import_directories()) {
  967. DictScope Import(W, "DelayImport");
  968. StringRef Name;
  969. if (error(I.getName(Name))) return;
  970. W.printString("Name", Name);
  971. const delay_import_directory_table_entry *Table;
  972. if (error(I.getDelayImportTable(Table))) return;
  973. W.printHex("Attributes", Table->Attributes);
  974. W.printHex("ModuleHandle", Table->ModuleHandle);
  975. W.printHex("ImportAddressTable", Table->DelayImportAddressTable);
  976. W.printHex("ImportNameTable", Table->DelayImportNameTable);
  977. W.printHex("BoundDelayImportTable", Table->BoundDelayImportTable);
  978. W.printHex("UnloadDelayImportTable", Table->UnloadDelayImportTable);
  979. printDelayImportedSymbols(I, I.imported_symbols());
  980. }
  981. }
  982. void COFFDumper::printCOFFExports() {
  983. for (const ExportDirectoryEntryRef &E : Obj->export_directories()) {
  984. DictScope Export(W, "Export");
  985. StringRef Name;
  986. uint32_t Ordinal, RVA;
  987. if (error(E.getSymbolName(Name)))
  988. continue;
  989. if (error(E.getOrdinal(Ordinal)))
  990. continue;
  991. if (error(E.getExportRVA(RVA)))
  992. continue;
  993. W.printNumber("Ordinal", Ordinal);
  994. W.printString("Name", Name);
  995. W.printHex("RVA", RVA);
  996. }
  997. }
  998. void COFFDumper::printCOFFDirectives() {
  999. for (const SectionRef &Section : Obj->sections()) {
  1000. StringRef Contents;
  1001. StringRef Name;
  1002. if (error(Section.getName(Name)))
  1003. continue;
  1004. if (Name != ".drectve")
  1005. continue;
  1006. if (error(Section.getContents(Contents)))
  1007. return;
  1008. W.printString("Directive(s)", Contents);
  1009. }
  1010. }
  1011. static StringRef getBaseRelocTypeName(uint8_t Type) {
  1012. switch (Type) {
  1013. case COFF::IMAGE_REL_BASED_ABSOLUTE: return "ABSOLUTE";
  1014. case COFF::IMAGE_REL_BASED_HIGH: return "HIGH";
  1015. case COFF::IMAGE_REL_BASED_LOW: return "LOW";
  1016. case COFF::IMAGE_REL_BASED_HIGHLOW: return "HIGHLOW";
  1017. case COFF::IMAGE_REL_BASED_HIGHADJ: return "HIGHADJ";
  1018. case COFF::IMAGE_REL_BASED_ARM_MOV32T: return "ARM_MOV32(T)";
  1019. case COFF::IMAGE_REL_BASED_DIR64: return "DIR64";
  1020. default: return "unknown (" + llvm::utostr(Type) + ")";
  1021. }
  1022. }
  1023. void COFFDumper::printCOFFBaseReloc() {
  1024. ListScope D(W, "BaseReloc");
  1025. for (const BaseRelocRef &I : Obj->base_relocs()) {
  1026. uint8_t Type;
  1027. uint32_t RVA;
  1028. if (error(I.getRVA(RVA)))
  1029. continue;
  1030. if (error(I.getType(Type)))
  1031. continue;
  1032. DictScope Import(W, "Entry");
  1033. W.printString("Type", getBaseRelocTypeName(Type));
  1034. W.printHex("Address", RVA);
  1035. }
  1036. }
  1037. void COFFDumper::printStackMap() const {
  1038. object::SectionRef StackMapSection;
  1039. for (auto Sec : Obj->sections()) {
  1040. StringRef Name;
  1041. Sec.getName(Name);
  1042. if (Name == ".llvm_stackmaps") {
  1043. StackMapSection = Sec;
  1044. break;
  1045. }
  1046. }
  1047. if (StackMapSection == object::SectionRef())
  1048. return;
  1049. StringRef StackMapContents;
  1050. StackMapSection.getContents(StackMapContents);
  1051. ArrayRef<uint8_t> StackMapContentsArray(
  1052. reinterpret_cast<const uint8_t*>(StackMapContents.data()),
  1053. StackMapContents.size());
  1054. if (Obj->isLittleEndian())
  1055. prettyPrintStackMap(
  1056. llvm::outs(),
  1057. StackMapV1Parser<support::little>(StackMapContentsArray));
  1058. else
  1059. prettyPrintStackMap(llvm::outs(),
  1060. StackMapV1Parser<support::big>(StackMapContentsArray));
  1061. }