@@ -31,6 +31,159 @@ using namespace llvm::objdump;
31
31
using namespace llvm ::object;
32
32
using namespace llvm ::Win64EH;
33
33
34
+ namespace {
35
+ template <typename T> struct EnumEntry {
36
+ T Value;
37
+ StringRef Name;
38
+ };
39
+
40
+ class COFFDumper {
41
+ public:
42
+ explicit COFFDumper (const llvm::object::COFFObjectFile &Obj) : Obj(Obj) {
43
+ Is64 = !Obj.getPE32Header ();
44
+ }
45
+
46
+ template <class PEHeader > void printPEHeader (const PEHeader &Hdr) const ;
47
+
48
+ private:
49
+ template <typename T> FormattedNumber formatAddr (T V) const {
50
+ return format_hex_no_prefix (V, Is64 ? 16 : 8 );
51
+ };
52
+
53
+ uint32_t getBaseOfData (const void *Hdr) const {
54
+ return Is64 ? 0 : static_cast <const pe32_header *>(Hdr)->BaseOfData ;
55
+ }
56
+
57
+ const llvm::object::COFFObjectFile &Obj;
58
+ bool Is64;
59
+ };
60
+ } // namespace
61
+
62
+ constexpr EnumEntry<uint16_t > PEHeaderMagic[] = {
63
+ {uint16_t (COFF::PE32Header::PE32), " PE32" },
64
+ {uint16_t (COFF::PE32Header::PE32_PLUS), " PE32+" },
65
+ };
66
+
67
+ constexpr EnumEntry<COFF::WindowsSubsystem> PEWindowsSubsystem[] = {
68
+ {COFF::IMAGE_SUBSYSTEM_UNKNOWN, " unspecified" },
69
+ {COFF::IMAGE_SUBSYSTEM_NATIVE, " NT native" },
70
+ {COFF::IMAGE_SUBSYSTEM_WINDOWS_GUI, " Windows GUI" },
71
+ {COFF::IMAGE_SUBSYSTEM_WINDOWS_CUI, " Windows CUI" },
72
+ {COFF::IMAGE_SUBSYSTEM_POSIX_CUI, " POSIX CUI" },
73
+ {COFF::IMAGE_SUBSYSTEM_WINDOWS_CE_GUI, " Wince CUI" },
74
+ {COFF::IMAGE_SUBSYSTEM_EFI_APPLICATION, " EFI application" },
75
+ {COFF::IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER, " EFI boot service driver" },
76
+ {COFF::IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER, " EFI runtime driver" },
77
+ {COFF::IMAGE_SUBSYSTEM_EFI_ROM, " SAL runtime driver" },
78
+ {COFF::IMAGE_SUBSYSTEM_XBOX, " XBOX" },
79
+ };
80
+
81
+ template <typename T, typename TEnum>
82
+ static void printOptionalEnumName (T Value,
83
+ ArrayRef<EnumEntry<TEnum>> EnumValues) {
84
+ for (const EnumEntry<TEnum> &I : EnumValues)
85
+ if (I.Value == Value) {
86
+ outs () << " \t (" << I.Name << ' )' ;
87
+ return ;
88
+ }
89
+ }
90
+
91
+ template <class PEHeader >
92
+ void COFFDumper::printPEHeader (const PEHeader &Hdr) const {
93
+ auto print = [](const char *K, auto V, const char *Fmt = " %d\n " ) {
94
+ outs () << format (" %-23s " , K) << format (Fmt, V);
95
+ };
96
+ auto printU16 = [&](const char *K, support::ulittle16_t V,
97
+ const char *Fmt = " %d\n " ) { print (K, uint16_t (V), Fmt); };
98
+ auto printU32 = [&](const char *K, support::ulittle32_t V,
99
+ const char *Fmt = " %d\n " ) { print (K, uint32_t (V), Fmt); };
100
+ auto printAddr = [=](const char *K, uint64_t V) {
101
+ outs () << format (" %-23s " , K) << formatAddr (V) << ' \n ' ;
102
+ };
103
+
104
+ printU16 (" Magic" , Hdr.Magic , " %04x" );
105
+ printOptionalEnumName (Hdr.Magic , makeArrayRef (PEHeaderMagic));
106
+ outs () << ' \n ' ;
107
+ print (" MajorLinkerVersion" , Hdr.MajorLinkerVersion );
108
+ print (" MinorLinkerVersion" , Hdr.MinorLinkerVersion );
109
+ printAddr (" SizeOfCode" , Hdr.SizeOfCode );
110
+ printAddr (" SizeOfInitializedData" , Hdr.SizeOfInitializedData );
111
+ printAddr (" SizeOfUninitializedData" , Hdr.SizeOfUninitializedData );
112
+ printAddr (" AddressOfEntryPoint" , Hdr.AddressOfEntryPoint );
113
+ printAddr (" BaseOfCode" , Hdr.BaseOfCode );
114
+ if (!Is64)
115
+ printAddr (" BaseOfData" , getBaseOfData (&Hdr));
116
+ printAddr (" ImageBase" , Hdr.ImageBase );
117
+ printU32 (" SectionAlignment" , Hdr.SectionAlignment , " %08x\n " );
118
+ printU32 (" FileAlignment" , Hdr.FileAlignment , " %08x\n " );
119
+ printU16 (" MajorOSystemVersion" , Hdr.MajorOperatingSystemVersion );
120
+ printU16 (" MinorOSystemVersion" , Hdr.MinorOperatingSystemVersion );
121
+ printU16 (" MajorImageVersion" , Hdr.MajorImageVersion );
122
+ printU16 (" MinorImageVersion" , Hdr.MinorImageVersion );
123
+ printU16 (" MajorSubsystemVersion" , Hdr.MajorSubsystemVersion );
124
+ printU16 (" MinorSubsystemVersion" , Hdr.MinorSubsystemVersion );
125
+ printU32 (" Win32Version" , Hdr.Win32VersionValue , " %08x\n " );
126
+ printU32 (" SizeOfImage" , Hdr.SizeOfImage , " %08x\n " );
127
+ printU32 (" SizeOfHeaders" , Hdr.SizeOfHeaders , " %08x\n " );
128
+ printU32 (" CheckSum" , Hdr.CheckSum , " %08x\n " );
129
+ printU16 (" Subsystem" , Hdr.Subsystem , " %08x" );
130
+ printOptionalEnumName (Hdr.Subsystem , makeArrayRef (PEWindowsSubsystem));
131
+ outs () << ' \n ' ;
132
+
133
+ printU16 (" DllCharacteristics" , Hdr.DLLCharacteristics , " %08x\n " );
134
+ #define FLAG (Name ) \
135
+ if (Hdr.DLLCharacteristics & COFF::IMAGE_DLL_CHARACTERISTICS_##Name) \
136
+ outs () << " \t\t\t\t\t " << #Name << ' \n ' ;
137
+ FLAG (HIGH_ENTROPY_VA);
138
+ FLAG (DYNAMIC_BASE);
139
+ FLAG (FORCE_INTEGRITY);
140
+ FLAG (NX_COMPAT);
141
+ FLAG (NO_ISOLATION);
142
+ FLAG (NO_SEH);
143
+ FLAG (NO_BIND);
144
+ FLAG (APPCONTAINER);
145
+ FLAG (WDM_DRIVER);
146
+ FLAG (GUARD_CF);
147
+ FLAG (TERMINAL_SERVER_AWARE);
148
+ #undef FLAG
149
+
150
+ printAddr (" SizeOfStackReserve" , Hdr.SizeOfStackReserve );
151
+ printAddr (" SizeOfStackCommit" , Hdr.SizeOfStackCommit );
152
+ printAddr (" SizeOfHeapReserve" , Hdr.SizeOfHeapReserve );
153
+ printAddr (" SizeOfHeapCommit" , Hdr.SizeOfHeapCommit );
154
+ printU32 (" LoaderFlags" , Hdr.LoaderFlags , " %08x\n " );
155
+ printU32 (" NumberOfRvaAndSizes" , Hdr.NumberOfRvaAndSize , " %08x\n " );
156
+
157
+ static const char *DirName[COFF::NUM_DATA_DIRECTORIES + 1 ] = {
158
+ " Export Directory [.edata (or where ever we found it)]" ,
159
+ " Import Directory [parts of .idata]" ,
160
+ " Resource Directory [.rsrc]" ,
161
+ " Exception Directory [.pdata]" ,
162
+ " Security Directory" ,
163
+ " Base Relocation Directory [.reloc]" ,
164
+ " Debug Directory" ,
165
+ " Description Directory" ,
166
+ " Special Directory" ,
167
+ " Thread Storage Directory [.tls]" ,
168
+ " Load Configuration Directory" ,
169
+ " Bound Import Directory" ,
170
+ " Import Address Table Directory" ,
171
+ " Delay Import Directory" ,
172
+ " CLR Runtime Header" ,
173
+ " Reserved" ,
174
+ };
175
+ outs () << " \n The Data Directory\n " ;
176
+ for (uint32_t I = 0 ; I != array_lengthof (DirName); ++I) {
177
+ uint32_t Addr = 0 , Size = 0 ;
178
+ if (const data_directory *Data = Obj.getDataDirectory (I)) {
179
+ Addr = Data->RelativeVirtualAddress ;
180
+ Size = Data->Size ;
181
+ }
182
+ outs () << format (" Entry %x " , I) << formatAddr (Addr)
183
+ << format (" %08x %s\n " , uint32_t (Size), DirName[I]);
184
+ }
185
+ }
186
+
34
187
// Returns the name of the unwind code.
35
188
static StringRef getUnwindCodeTypeName (uint8_t Code) {
36
189
switch (Code) {
@@ -622,12 +775,47 @@ void objdump::printCOFFUnwindInfo(const COFFObjectFile *Obj) {
622
775
}
623
776
}
624
777
625
- void objdump::printCOFFFileHeader (const object::ObjectFile *Obj) {
626
- const COFFObjectFile *file = dyn_cast<const COFFObjectFile>(Obj);
627
- printTLSDirectory (file);
628
- printLoadConfiguration (file);
629
- printImportTables (file);
630
- printExportTable (file);
778
+ void objdump::printCOFFFileHeader (const COFFObjectFile &Obj) {
779
+ COFFDumper CD (Obj);
780
+ const uint16_t Cha = Obj.getCharacteristics ();
781
+ outs () << " Characteristics 0x" << Twine::utohexstr (Cha) << ' \n ' ;
782
+ #define FLAG (F, Name ) \
783
+ if (Cha & F) \
784
+ outs () << ' \t ' << Name << ' \n ' ;
785
+ FLAG (COFF::IMAGE_FILE_RELOCS_STRIPPED, " relocations stripped" );
786
+ FLAG (COFF::IMAGE_FILE_EXECUTABLE_IMAGE, " executable" );
787
+ FLAG (COFF::IMAGE_FILE_LINE_NUMS_STRIPPED, " line numbers stripped" );
788
+ FLAG (COFF::IMAGE_FILE_LOCAL_SYMS_STRIPPED, " symbols stripped" );
789
+ FLAG (COFF::IMAGE_FILE_LARGE_ADDRESS_AWARE, " large address aware" );
790
+ FLAG (COFF::IMAGE_FILE_BYTES_REVERSED_LO, " little endian" );
791
+ FLAG (COFF::IMAGE_FILE_32BIT_MACHINE, " 32 bit words" );
792
+ FLAG (COFF::IMAGE_FILE_DEBUG_STRIPPED, " debugging information removed" );
793
+ FLAG (COFF::IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP,
794
+ " copy to swap file if on removable media" );
795
+ FLAG (COFF::IMAGE_FILE_NET_RUN_FROM_SWAP,
796
+ " copy to swap file if on network media" );
797
+ FLAG (COFF::IMAGE_FILE_SYSTEM, " system file" );
798
+ FLAG (COFF::IMAGE_FILE_DLL, " DLL" );
799
+ FLAG (COFF::IMAGE_FILE_UP_SYSTEM_ONLY, " run only on uniprocessor machine" );
800
+ FLAG (COFF::IMAGE_FILE_BYTES_REVERSED_HI, " big endian" );
801
+ #undef FLAG
802
+
803
+ // TODO Support PE_IMAGE_DEBUG_TYPE_REPRO.
804
+ // Since ctime(3) returns a 26 character string of the form:
805
+ // "Sun Sep 16 01:03:52 1973\n\0"
806
+ // just print 24 characters.
807
+ const time_t Timestamp = Obj.getTimeDateStamp ();
808
+ outs () << format (" \n Time/Date %.24s\n " , ctime (&Timestamp));
809
+
810
+ if (const pe32_header *Hdr = Obj.getPE32Header ())
811
+ CD.printPEHeader <pe32_header>(*Hdr);
812
+ else if (const pe32plus_header *Hdr = Obj.getPE32PlusHeader ())
813
+ CD.printPEHeader <pe32plus_header>(*Hdr);
814
+
815
+ printTLSDirectory (&Obj);
816
+ printLoadConfiguration (&Obj);
817
+ printImportTables (&Obj);
818
+ printExportTable (&Obj);
631
819
}
632
820
633
821
void objdump::printCOFFSymbolTable (const object::COFFImportFile *i) {
0 commit comments