Add a test for the gcore script
[binutils-gdb.git] / binutils / od-pe.c
bloba0b8a1a45cd39c94248cca8a07f891681ad06f46
1 /* od-pe.c -- dump information about a PE object file.
2 Copyright (C) 2011-2024 Free Software Foundation, Inc.
3 Written by Tristan Gingold, Adacore and Nick Clifton, Red Hat.
5 This file is part of GNU Binutils.
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
10 any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, 51 Franklin Street - Fifth Floor, Boston,
20 MA 02110-1301, USA. */
22 #include "sysdep.h"
23 #include <stddef.h>
24 #include <time.h>
25 #include "safe-ctype.h"
26 #include "bfd.h"
27 #include "objdump.h"
28 #include "bucomm.h"
29 #include "bfdlink.h"
30 #include "coff/internal.h"
31 #define L_LNNO_SIZE 4 /* FIXME: which value should we use ? */
32 #include "coff/external.h"
33 #include "coff/pe.h"
34 #include "libcoff.h"
35 #include "libpei.h"
36 #include "libiberty.h"
38 /* Index of the options in the options[] array. */
39 #define OPT_FILE_HEADER 0
40 #define OPT_AOUT 1
41 #define OPT_SECTIONS 2
42 #define OPT_SYMS 3
43 #define OPT_RELOCS 4
44 #define OPT_LINENO 5
45 #define OPT_LOADER 6
46 #define OPT_EXCEPT 7
47 #define OPT_TYPCHK 8
48 #define OPT_TRACEBACK 9
49 #define OPT_TOC 10
50 #define OPT_LDINFO 11
52 /* List of actions. */
53 static struct objdump_private_option options[] =
55 { "header", 0 },
56 { "aout", 0 },
57 { "sections", 0 },
58 { "syms", 0 },
59 { "relocs", 0 },
60 { "lineno", 0 },
61 { "loader", 0 },
62 { "except", 0 },
63 { "typchk", 0 },
64 { "traceback", 0 },
65 { "toc", 0 },
66 { "ldinfo", 0 },
67 { NULL, 0 }
70 /* Simplified section header. */
71 struct pe_section
73 /* NUL terminated name. */
74 char name[9];
76 /* Section flags. */
77 unsigned int flags;
79 /* Offsets in file. */
80 ufile_ptr scnptr;
81 ufile_ptr relptr;
82 ufile_ptr lnnoptr;
84 /* Number of relocs and line numbers. */
85 unsigned int nreloc;
86 unsigned int nlnno;
89 /* Translation entry type. The last entry must be {0, NULL}. */
91 struct xlat_table
93 unsigned int val;
94 const char * name;
97 /* PE file flags. */
98 static const struct xlat_table file_flag_xlat[] =
100 { IMAGE_FILE_RELOCS_STRIPPED, "RELOCS STRIPPED"},
101 { IMAGE_FILE_EXECUTABLE_IMAGE, "EXECUTABLE"},
102 { IMAGE_FILE_LINE_NUMS_STRIPPED, "LINE NUMS STRIPPED"},
103 { IMAGE_FILE_LOCAL_SYMS_STRIPPED, "LOCAL SYMS STRIPPED"},
104 { IMAGE_FILE_AGGRESSIVE_WS_TRIM, "AGGRESSIVE WS TRIM"},
105 { IMAGE_FILE_LARGE_ADDRESS_AWARE, "LARGE ADDRESS AWARE"},
106 { IMAGE_FILE_16BIT_MACHINE, "16BIT MACHINE"},
107 { IMAGE_FILE_BYTES_REVERSED_LO, "BYTES REVERSED LO"},
108 { IMAGE_FILE_32BIT_MACHINE, "32BIT MACHINE"},
109 { IMAGE_FILE_DEBUG_STRIPPED, "DEBUG STRIPPED"},
110 { IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP, "REMOVABLE RUN FROM SWAP"},
111 { IMAGE_FILE_NET_RUN_FROM_SWAP, "NET RUN FROM SWAP"},
112 { IMAGE_FILE_SYSTEM, "SYSTEM"},
113 { IMAGE_FILE_DLL, "DLL"},
114 { IMAGE_FILE_UP_SYSTEM_ONLY, "UP SYSTEM ONLY"},
115 { IMAGE_FILE_BYTES_REVERSED_HI, "BYTES REVERSED HI"},
116 { 0, NULL }
119 /* PE section flags. */
120 static const struct xlat_table section_flag_xlat[] =
122 { IMAGE_SCN_MEM_DISCARDABLE, "DISCARDABLE" },
123 { IMAGE_SCN_MEM_EXECUTE, "EXECUTE" },
124 { IMAGE_SCN_MEM_READ, "READ" },
125 { IMAGE_SCN_MEM_WRITE, "WRITE" },
126 { IMAGE_SCN_TYPE_NO_PAD, "NO PAD" },
127 { IMAGE_SCN_CNT_CODE, "CODE" },
128 { IMAGE_SCN_CNT_INITIALIZED_DATA, "INITIALIZED DATA" },
129 { IMAGE_SCN_CNT_UNINITIALIZED_DATA, "UNINITIALIZED DATA" },
130 { IMAGE_SCN_LNK_OTHER, "OTHER" },
131 { IMAGE_SCN_LNK_INFO, "INFO" },
132 { IMAGE_SCN_LNK_REMOVE, "REMOVE" },
133 { IMAGE_SCN_LNK_COMDAT, "COMDAT" },
134 { IMAGE_SCN_MEM_FARDATA, "FARDATA" },
135 { IMAGE_SCN_MEM_PURGEABLE, "PURGEABLE" },
136 { IMAGE_SCN_MEM_LOCKED, "LOCKED" },
137 { IMAGE_SCN_MEM_PRELOAD, "PRELOAD" },
138 { IMAGE_SCN_LNK_NRELOC_OVFL, "NRELOC OVFL" },
139 { IMAGE_SCN_MEM_NOT_CACHED, "NOT CACHED" },
140 { IMAGE_SCN_MEM_NOT_PAGED, "NOT PAGED" },
141 { IMAGE_SCN_MEM_SHARED, "SHARED" },
142 { 0, NULL }
145 typedef struct target_specific_info
147 unsigned int machine_number;
148 const char * name;
149 unsigned int aout_hdr_size;
150 } target_specific_info;
152 const struct target_specific_info targ_info[] =
154 { IMAGE_FILE_MACHINE_ALPHA, "ALPHA", 80 },
155 { IMAGE_FILE_MACHINE_ALPHA64, "ALPHA64", 80 },
156 { IMAGE_FILE_MACHINE_AM33, "AM33", AOUTHDRSZ },
157 { IMAGE_FILE_MACHINE_AMD64, "AMD64", AOUTHDRSZ },
158 { IMAGE_FILE_MACHINE_ARM, "ARM", AOUTHDRSZ },
159 { IMAGE_FILE_MACHINE_ARM64, "ARM64", AOUTHDRSZ },
160 { IMAGE_FILE_MACHINE_ARMNT, "ARM NT", AOUTHDRSZ },
161 { IMAGE_FILE_MACHINE_CEE, "CEE", AOUTHDRSZ },
162 { IMAGE_FILE_MACHINE_CEF, "CEF", AOUTHDRSZ },
163 { IMAGE_FILE_MACHINE_EBC, "EBC", AOUTHDRSZ },
164 { IMAGE_FILE_MACHINE_I386, "I386", AOUTHDRSZ },
165 { IMAGE_FILE_MACHINE_IA64, "IA64", 108 },
166 { IMAGE_FILE_MACHINE_LOONGARCH64, "LOONGARCH64", AOUTHDRSZ },
167 { IMAGE_FILE_MACHINE_M32R, "M32R", AOUTHDRSZ },
168 { IMAGE_FILE_MACHINE_M68K, "M68K", AOUTHDRSZ },
169 { IMAGE_FILE_MACHINE_MIPS16, "MIPS16", 56 },
170 { IMAGE_FILE_MACHINE_MIPSFPU, "MIPSFPU", 56 },
171 { IMAGE_FILE_MACHINE_MIPSFPU16, "MIPSFPU16", 56 },
172 { IMAGE_FILE_MACHINE_POWERPC, "POWERPC", 72 },
173 { IMAGE_FILE_MACHINE_POWERPCFP, "POWERPCFP", 72 },
174 { IMAGE_FILE_MACHINE_R10000, "R10000", AOUTHDRSZ },
175 { IMAGE_FILE_MACHINE_R3000, "R3000", AOUTHDRSZ },
176 { IMAGE_FILE_MACHINE_R4000, "R4000", AOUTHDRSZ },
177 { IMAGE_FILE_MACHINE_SH3, "SH3", AOUTHDRSZ },
178 { IMAGE_FILE_MACHINE_SH3DSP, "SH3DSP", AOUTHDRSZ },
179 { IMAGE_FILE_MACHINE_SH3E, "SH3E", AOUTHDRSZ },
180 { IMAGE_FILE_MACHINE_SH4, "SH4", AOUTHDRSZ },
181 { IMAGE_FILE_MACHINE_SH5, "SH5", AOUTHDRSZ },
182 { IMAGE_FILE_MACHINE_THUMB, "THUMB", AOUTHDRSZ },
183 { IMAGE_FILE_MACHINE_TRICORE, "TRICORE", AOUTHDRSZ },
184 { IMAGE_FILE_MACHINE_WCEMIPSV2, "WCEMIPSV2", AOUTHDRSZ },
186 { 0x0093, "TI C4X", 28 },
187 { 0x00C1, "TI C4X", 28 },
188 { 0x00C2, "TI C4X", 28 },
189 { 0x0500, "SH (big endian)", AOUTHDRSZ },
190 { 0x0550, "SH (little endian)", AOUTHDRSZ },
191 { 0x0a00, "ARM", AOUTHDRSZ },
192 { 0x0b00, "MCore", AOUTHDRSZ }
195 static const struct target_specific_info unknown_info =
196 { 0, "unknown", AOUTHDRSZ };
198 static const struct target_specific_info *
199 get_target_specific_info (unsigned int machine)
201 unsigned int i;
203 for (i = ARRAY_SIZE (targ_info); i--;)
204 if (targ_info[i].machine_number == machine)
205 return targ_info + i;
207 return &unknown_info;
210 /* Display help. */
212 static void
213 pe_help (FILE *stream)
215 fprintf (stream, _("\
216 For PE files:\n\
217 header Display the file header\n\
218 sections Display the section headers\n\
219 "));
222 /* Return true if ABFD is handled. */
224 static int
225 pe_filter (bfd *abfd)
227 return bfd_get_flavour (abfd) == bfd_target_coff_flavour;
230 /* Return string representation of the platform id
231 stored in upper 2 bits of Win32Version field. */
233 static const char *
234 pe_platform_id_str (unsigned int platform_id)
236 static const char *const platform_id_str_table[4] =
237 { "WinNT", "WinCE", "Win32s", "Win9x" };
238 return platform_id_str_table[platform_id & 0x3];
241 /* Display the list of name (from TABLE) for FLAGS, using comma to
242 separate them. A name is displayed if FLAGS & VAL is not 0. */
244 static void
245 dump_flags (const struct xlat_table * table, unsigned int flags)
247 unsigned int r = flags;
248 bool first = true;
249 const struct xlat_table *t;
251 for (t = table; t->name; t++)
252 if ((flags & t->val) != 0)
254 r &= ~t->val;
256 if (first)
257 first = false;
258 else
259 putchar (',');
260 fputs (t->name, stdout);
263 /* Undecoded flags. */
264 if (r != 0)
266 if (!first)
267 putchar (',');
268 printf (_("unknown: 0x%x"), r);
272 /* Dump the file header. */
274 static void
275 dump_pe_file_header (bfd * abfd,
276 struct external_PEI_filehdr * fhdr,
277 struct external_PEI_IMAGE_hdr * ihdr)
279 unsigned int data;
280 unsigned long ldata;
281 unsigned long ihdr_off = 0;
283 if (fhdr == NULL)
284 printf (_("\n File header not present\n"));
285 else
287 printf (_("\n File Header (at offset 0):\n"));
289 // The values of the following fields are normally fixed.
290 // But we display them anyway, in case there are discrepancies.
292 data = bfd_h_get_16 (abfd, fhdr->e_cblp);
293 printf (_("Bytes on Last Page:\t\t%d\n"), data);
295 data = bfd_h_get_16 (abfd, fhdr->e_cp);
296 printf (_("Pages In File:\t\t\t%d\n"), data);
298 data = bfd_h_get_16 (abfd, fhdr->e_crlc);
299 printf (_("Relocations:\t\t\t%d\n"), data);
301 data = bfd_h_get_16 (abfd, fhdr->e_cparhdr);
302 printf (_("Size of header in paragraphs:\t%d\n"), data);
304 data = bfd_h_get_16 (abfd, fhdr->e_minalloc);
305 printf (_("Min extra paragraphs needed:\t%d\n"), data);
307 data = bfd_h_get_16 (abfd, fhdr->e_maxalloc);
308 printf (_("Max extra paragraphs needed:\t%d\n"), data);
310 data = bfd_h_get_16 (abfd, fhdr->e_ss);
311 printf (_("Initial (relative) SS value:\t%d\n"), data);
313 data = bfd_h_get_16 (abfd, fhdr->e_sp);
314 printf (_("Initial SP value:\t\t%d\n"), data);
316 data = bfd_h_get_16 (abfd, fhdr->e_csum);
317 printf (_("Checksum:\t\t\t%#x\n"), data);
319 data = bfd_h_get_16 (abfd, fhdr->e_ip);
320 printf (_("Initial IP value:\t\t%d\n"), data);
322 data = bfd_h_get_16 (abfd, fhdr->e_cs);
323 printf (_("Initial (relative) CS value:\t%d\n"), data);
325 data = bfd_h_get_16 (abfd, fhdr->e_lfarlc);
326 printf (_("File address of reloc table:\t%d\n"), data);
328 data = bfd_h_get_16 (abfd, fhdr->e_ovno);
329 printf (_("Overlay number:\t\t\t%d\n"), data);
331 data = bfd_h_get_16 (abfd, fhdr->e_oemid);
332 printf (_("OEM identifier:\t\t\t%d\n"), data);
334 data = bfd_h_get_16 (abfd, fhdr->e_oeminfo);
335 printf (_("OEM information:\t\t%#x\n"), data);
337 ldata = bfd_h_get_32 (abfd, fhdr->e_lfanew);
338 printf (_("File address of new exe header:\t%#lx\n"), ldata);
340 /* Display the first string found in the stub.
341 FIXME: Look for more than one string ?
342 FIXME: Strictly speaking we may not have read the full stub, since
343 it can be longer than the dos_message array in the PEI_fileheader
344 structure. */
345 const unsigned char * message = (const unsigned char *) fhdr->dos_message;
346 unsigned int len = sizeof (fhdr->dos_message);
347 unsigned int i;
348 unsigned int seen_count = 0;
349 unsigned int string_start = 0;
351 for (i = 0; i < len; i++)
353 if (ISPRINT (message[i]))
355 if (string_start == 0)
356 string_start = i;
357 ++ seen_count;
358 if (seen_count > 4)
359 break;
361 else
363 seen_count = string_start = 0;
367 if (seen_count > 4)
369 printf (_("Stub message:\t\t\t"));
370 while (string_start < len)
372 char c = message[string_start ++];
373 if (! ISPRINT (c))
374 break;
375 putchar (c);
377 putchar ('\n');
380 ihdr_off = (long) bfd_h_get_32 (abfd, fhdr->e_lfanew);
383 printf (_("\n Image Header (at offset %#lx):\n"), ihdr_off);
385 /* Note - we try to make this output use the same format as the output from -p.
386 But since there are multiple headers to display and the order of the fields
387 in the headers do not match the order of information displayed by -p, there
388 are some discrepancies. */
390 unsigned int machine = (int) bfd_h_get_16 (abfd, ihdr->f_magic);
391 printf (_("Machine Number:\t\t\t%#x\t\t- %s\n"), machine,
392 get_target_specific_info (machine)->name);
394 printf (_("Number of sections:\t\t\%d\n"), (int) bfd_h_get_16 (abfd, ihdr->f_nscns));
396 long timedat = bfd_h_get_32 (abfd, ihdr->f_timdat);
397 printf (_("Time/Date:\t\t\t%#08lx\t- "), timedat);
398 if (timedat == 0)
399 printf (_("not set\n"));
400 else
402 /* Not correct on all platforms, but works on unix. */
403 time_t t = timedat;
404 fputs (ctime (&t), stdout);
407 printf (_("Symbol table offset:\t\t%#08lx\n"),
408 (long) bfd_h_get_32 (abfd, ihdr->f_symptr));
409 printf (_("Number of symbols:\t\t\%ld\n"),
410 (long) bfd_h_get_32 (abfd, ihdr->f_nsyms));
412 unsigned int opt_header_size = (int) bfd_h_get_16 (abfd, ihdr->f_opthdr);
413 printf (_("Optional header size:\t\t%#x\n"), opt_header_size);
415 unsigned int flags = (int) bfd_h_get_16 (abfd, ihdr->f_flags);
416 printf (_("Flags:\t\t\t\t0x%04x\t\t- "), flags);
417 dump_flags (file_flag_xlat, flags);
418 putchar ('\n');
420 if (opt_header_size == PEPAOUTSZ)
422 PEPAOUTHDR xhdr;
424 printf (_("\n Optional 64-bit AOUT Header (at offset %#lx):\n"),
425 ihdr_off + sizeof (* ihdr));
427 // Fortunately, it appears that the size and layout of the
428 // PEPAOUTHDR header is consistent across all architectures.
429 if (bfd_seek (abfd, ihdr_off + sizeof (* ihdr), SEEK_SET) != 0
430 || bfd_read (&xhdr, sizeof (xhdr), abfd) != sizeof (xhdr))
431 printf (_("error: unable to read AOUT and PE+ headers\n"));
432 else
434 data = (int) bfd_h_get_16 (abfd, xhdr.standard.magic);
435 printf (_("Magic:\t\t\t\t%x\t\t- %s\n"), data,
436 data == 0x020b ? "PE32+" : _("Unknown"));
438 printf (_("Linker Version:\t\t\t%x\t\t- %u.%02u\n"),
439 (int) bfd_h_get_16 (abfd, xhdr.standard.vstamp),
440 (int) (bfd_h_get_16 (abfd, xhdr.standard.vstamp) & 0xff),
441 (int) (bfd_h_get_16 (abfd, xhdr.standard.vstamp) >> 8));
443 printf (_("Text Size:\t\t\t%#lx\n"),
444 (long) bfd_h_get_32 (abfd, xhdr.standard.tsize));
445 printf (_("Data Size:\t\t\t%#lx\n"),
446 (long) bfd_h_get_32 (abfd, xhdr.standard.dsize));
447 printf (_("BSS Size:\t\t\t%#lx\n"),
448 (long) bfd_h_get_32 (abfd, xhdr.standard.bsize));
449 printf (_("Entry Point:\t\t\t%#lx\n"),
450 (long) bfd_h_get_32 (abfd, xhdr.standard.entry));
451 printf (_("Text Start:\t\t\t%#lx\n"),
452 (long) bfd_h_get_32 (abfd, xhdr.standard.text_start));
453 /* There is no data_start field in the PE+ standard header. */
455 printf (_("\n Optional PE+ Header (at offset %#lx):\n"),
456 ihdr_off + sizeof (* ihdr) + sizeof (xhdr.standard));
458 printf (_("Image Base:\t\t\t%#lx\n"),
459 (long) bfd_h_get_32 (abfd, xhdr.ImageBase));
460 printf (_("Section Alignment:\t\t%#lx\n"),
461 (long) bfd_h_get_32 (abfd, xhdr.SectionAlignment));
462 printf (_("File Alignment:\t\t\t%#lx\n"),
463 (long) bfd_h_get_32 (abfd, xhdr.FileAlignment));
465 printf (_("Image Version:\t\t\t%lx\t\t- %u.%02u\n"),
466 (long) bfd_h_get_32 (abfd, xhdr.MajorImageVersion),
467 (int) bfd_h_get_16 (abfd, xhdr.MajorImageVersion),
468 (int) bfd_h_get_16 (abfd, xhdr.MinorImageVersion));
470 printf (_("Minimal Subsystem Version:\t%lx\t\t- %u.%02u\n"),
471 (long) bfd_h_get_32 (abfd, xhdr.MajorSubsystemVersion),
472 (int) bfd_h_get_16 (abfd, xhdr.MajorSubsystemVersion),
473 (int) bfd_h_get_16 (abfd, xhdr.MinorSubsystemVersion));
475 printf (_("Minimal OS Version:\t\t%lx\t\t- %u.%02u\n"),
476 (long) bfd_h_get_32 (abfd, xhdr.MajorOperatingSystemVersion),
477 (int) bfd_h_get_16 (abfd, xhdr.MajorOperatingSystemVersion),
478 (int) bfd_h_get_16 (abfd, xhdr.MinorOperatingSystemVersion));
480 printf (_("Overwrite OS Version:\t\t%lx\t\t- "),
481 (long) bfd_h_get_32 (abfd, xhdr.Win32Version));
482 if (bfd_h_get_32 (abfd, xhdr.Win32Version) == 0)
483 printf (_("(default)\n"));
484 else
485 printf (_("%u.%02u (build %u, platform %s)\n"),
486 ((int) (bfd_h_get_32 (abfd, xhdr.Win32Version) & 0xff)),
487 ((int) ((bfd_h_get_32 (abfd, xhdr.Win32Version) >> 8) & 0xff)),
488 ((int) ((bfd_h_get_32 (abfd, xhdr.Win32Version) >> 16) & 0x3fff)),
489 pe_platform_id_str ((bfd_h_get_32 (abfd, xhdr.Win32Version) >> 30) & 0x3));
491 printf (_("Size Of Image:\t\t\t%#lx\n"),
492 (long) bfd_h_get_32 (abfd, xhdr.SizeOfImage));
493 printf (_("Size Of Headers:\t\t%#lx\n"),
494 (long) bfd_h_get_32 (abfd, xhdr.SizeOfHeaders));
495 printf (_("CheckSum:\t\t\t%#lx\n"),
496 (long) bfd_h_get_32 (abfd, xhdr.CheckSum));
497 printf (_("Subsystem:\t\t\t%d\n"),
498 (int) bfd_h_get_16 (abfd, xhdr.Subsystem));
499 // FIXME: Decode the characteristics.
500 printf (_("DllCharacteristics:\t\t%#x\n"),
501 (int) bfd_h_get_16 (abfd, xhdr.DllCharacteristics));
502 printf (_("Size Of Stack Reserve:\t\t%#lx\n"),
503 (long) bfd_h_get_32 (abfd, xhdr.SizeOfStackReserve));
504 printf (_("Size Of Stack Commit:\t\t%#lx\n"),
505 (long) bfd_h_get_32 (abfd, xhdr.SizeOfStackCommit));
506 printf (_("Size Of Heap Reserve:\t\t%#lx\n"),
507 (long) bfd_h_get_32 (abfd, xhdr.SizeOfHeapReserve));
508 printf (_("Size Of Heap Commit:\t\t%#lx\n"),
509 (long) bfd_h_get_32 (abfd, xhdr.SizeOfHeapCommit));
510 printf (_("Loader Flags:\t\t\t%#lx\n"),
511 (long) bfd_h_get_32 (abfd, xhdr.LoaderFlags));
512 printf (_("Number Of Rva and Sizes:\t%#lx\n"),
513 (long) bfd_h_get_32 (abfd, xhdr.NumberOfRvaAndSizes));
515 // FIXME: Decode the Data Directory.
518 else if (opt_header_size == AOUTSZ)
520 PEAOUTHDR xhdr;
522 /* Different architectures have different sizes of AOUT header. */
523 unsigned int aout_hdr_size = get_target_specific_info (machine)->aout_hdr_size;
525 unsigned long off = ihdr_off + sizeof (* ihdr);
526 unsigned long size = sizeof (xhdr.standard);
528 printf (_("\n Optional 32-bit AOUT Header (at offset %#lx, size %d):\n"),
529 off, aout_hdr_size);
531 if (bfd_seek (abfd, off, SEEK_SET) != 0
532 || bfd_read (&xhdr.standard, size, abfd) != size)
533 printf (_("error: unable to seek to/read AOUT header\n"));
534 else
536 data = (int) bfd_h_get_16 (abfd, xhdr.standard.magic);
537 printf (_("Magic:\t\t\t\t%x\t\t- %s\n"), data,
538 data == 0x010b ? "PE32" : _("Unknown"));
540 printf (_("Linker Version:\t\t\t%x\t\t- %u.%02u\n"),
541 (int) bfd_h_get_16 (abfd, xhdr.standard.vstamp),
542 (int) (bfd_h_get_16 (abfd, xhdr.standard.vstamp) & 0xff),
543 (int) (bfd_h_get_16 (abfd, xhdr.standard.vstamp) >> 8));
545 printf (_("Text Size:\t\t\t%#lx\n"),
546 (long) bfd_h_get_32 (abfd, xhdr.standard.tsize));
547 printf (_("Data Size:\t\t\t%#lx\n"),
548 (long) bfd_h_get_32 (abfd, xhdr.standard.dsize));
549 printf (_("BSS Size:\t\t\t%#lx\n"),
550 (long) bfd_h_get_32 (abfd, xhdr.standard.bsize));
551 printf (_("Entry Point:\t\t\t%#lx\n"),
552 (long) bfd_h_get_32 (abfd, xhdr.standard.entry));
553 printf (_("Text Start:\t\t\t%#lx\n"),
554 (long) bfd_h_get_32 (abfd, xhdr.standard.text_start));
555 printf (_("Data Start:\t\t\t%#lx\n"),
556 (long) bfd_h_get_32 (abfd, xhdr.standard.data_start));
559 off = ihdr_off + sizeof (* ihdr) + aout_hdr_size;
560 size = sizeof (xhdr) - sizeof (xhdr.standard);
562 printf (_("\n Optional PE Header (at offset %#lx):\n"), off);
564 /* FIXME: Sanitizers might complain about reading more bytes than
565 fit into the ImageBase field. Find a way to solve this. */
566 if (bfd_seek (abfd, off, SEEK_SET) != 0
567 || bfd_read (&xhdr.ImageBase, size, abfd) != size)
568 printf (_("error: unable to seek to/read PE header\n"));
569 else
571 printf (_("Image Base:\t\t\t%#lx\n"),
572 (long) bfd_h_get_32 (abfd, xhdr.ImageBase));
573 printf (_("Section Alignment:\t\t%#lx\n"),
574 (long) bfd_h_get_32 (abfd, xhdr.SectionAlignment));
575 printf (_("File Alignment:\t\t\t%#lx\n"),
576 (long) bfd_h_get_32 (abfd, xhdr.FileAlignment));
578 printf (_("Image Version:\t\t\t%lx\t\t- %u.%02u\n"),
579 (long) bfd_h_get_32 (abfd, xhdr.MajorImageVersion),
580 (int) bfd_h_get_16 (abfd, xhdr.MajorImageVersion),
581 (int) bfd_h_get_16 (abfd, xhdr.MinorImageVersion));
583 printf (_("Minimal Subsystem Version:\t%lx\t\t- %u.%02u\n"),
584 (long) bfd_h_get_32 (abfd, xhdr.MajorSubsystemVersion),
585 (int) bfd_h_get_16 (abfd, xhdr.MajorSubsystemVersion),
586 (int) bfd_h_get_16 (abfd, xhdr.MinorSubsystemVersion));
588 printf (_("Minimal OS Version:\t\t%lx\t\t- %u.%02u\n"),
589 (long) bfd_h_get_32 (abfd, xhdr.MajorOperatingSystemVersion),
590 (int) bfd_h_get_16 (abfd, xhdr.MajorOperatingSystemVersion),
591 (int) bfd_h_get_16 (abfd, xhdr.MinorOperatingSystemVersion));
593 printf (_("Overwrite OS Version:\t\t%lx\t\t- "),
594 (long) bfd_h_get_32 (abfd, xhdr.Win32Version));
595 if (bfd_h_get_32 (abfd, xhdr.Win32Version) == 0)
596 printf (_("(default)\n"));
597 else
598 printf (_("%u.%02u (build %u, platform %s)\n"),
599 ((int) (bfd_h_get_32 (abfd, xhdr.Win32Version) & 0xff)),
600 ((int) ((bfd_h_get_32 (abfd, xhdr.Win32Version) >> 8) & 0xff)),
601 ((int) ((bfd_h_get_32 (abfd, xhdr.Win32Version) >> 16) & 0x3fff)),
602 pe_platform_id_str ((bfd_h_get_32 (abfd, xhdr.Win32Version) >> 30) & 0x3));
604 printf (_("Size Of Image:\t\t\t%#lx\n"),
605 (long) bfd_h_get_32 (abfd, xhdr.SizeOfImage));
606 printf (_("Size Of Headers:\t\t%#lx\n"),
607 (long) bfd_h_get_32 (abfd, xhdr.SizeOfHeaders));
608 printf (_("CheckSum:\t\t\t%#lx\n"),
609 (long) bfd_h_get_32 (abfd, xhdr.CheckSum));
610 printf (_("Subsystem:\t\t\t%d\n"),
611 (int) bfd_h_get_16 (abfd, xhdr.Subsystem));
612 // FIXME: Decode the characteristics.
613 printf (_("DllCharacteristics:\t\t%#x\n"),
614 (int) bfd_h_get_16 (abfd, xhdr.DllCharacteristics));
615 printf (_("Size Of Stack Reserve:\t\t%#lx\n"),
616 (long) bfd_h_get_32 (abfd, xhdr.SizeOfStackReserve));
617 printf (_("Size Of Stack Commit:\t\t%#lx\n"),
618 (long) bfd_h_get_32 (abfd, xhdr.SizeOfStackCommit));
619 printf (_("Size Of Heap Reserve:\t\t%#lx\n"),
620 (long) bfd_h_get_32 (abfd, xhdr.SizeOfHeapReserve));
621 printf (_("Size Of Heap Commit:\t\t%#lx\n"),
622 (long) bfd_h_get_32 (abfd, xhdr.SizeOfHeapCommit));
623 printf (_("Loader Flags:\t\t\t%#lx\n"),
624 (long) bfd_h_get_32 (abfd, xhdr.LoaderFlags));
625 printf (_("Number Of Rva and Sizes:\t%#lx\n"),
626 (long) bfd_h_get_32 (abfd, xhdr.NumberOfRvaAndSizes));
628 // FIXME: Decode the Data Directory.
631 else if (opt_header_size != 0)
633 printf (_("\nUnsupported size of Optional Header\n"));
635 else
636 printf (_("\n Optional header not present\n"));
639 static void
640 dump_alignment (unsigned int flags)
642 flags &= IMAGE_SCN_ALIGN_POWER_BIT_MASK;
644 if (flags == IMAGE_SCN_ALIGN_8192BYTES)
645 printf (_("Align: 8192 "));
646 else if (flags == IMAGE_SCN_ALIGN_4096BYTES)
647 printf (_("Align: 4096 "));
648 else if (flags == IMAGE_SCN_ALIGN_2048BYTES)
649 printf (_("Align: 2048 "));
650 else if (flags == IMAGE_SCN_ALIGN_1024BYTES)
651 printf (_("Align: 1024 "));
652 else if (flags == IMAGE_SCN_ALIGN_512BYTES)
653 printf (_("Align: 512 "));
654 else if (flags == IMAGE_SCN_ALIGN_256BYTES)
655 printf (_("Align: 256 "));
656 else if (flags == IMAGE_SCN_ALIGN_128BYTES)
657 printf (_("Align: 128 "));
658 else if (flags == IMAGE_SCN_ALIGN_64BYTES)
659 printf (_("Align: 64 "));
660 else if (flags == IMAGE_SCN_ALIGN_32BYTES)
661 printf (_("Align: 32 "));
662 else if (flags == IMAGE_SCN_ALIGN_16BYTES)
663 printf (_("Align: 16 "));
664 else if (flags == IMAGE_SCN_ALIGN_8BYTES)
665 printf (_("Align: 8 "));
666 else if (flags == IMAGE_SCN_ALIGN_4BYTES)
667 printf (_("Align: 4 "));
668 else if (flags == IMAGE_SCN_ALIGN_2BYTES)
669 printf (_("Align: 2 "));
670 else if (flags == IMAGE_SCN_ALIGN_1BYTES)
671 printf (_("Align: 1 "));
672 else
673 printf (_("Align: *unknown* "));
676 /* Dump the section's header. */
678 static void
679 dump_pe_sections_header (bfd * abfd,
680 struct external_PEI_filehdr * fhdr,
681 struct external_PEI_IMAGE_hdr * ihdr)
683 unsigned int opthdr = (int) bfd_h_get_16 (abfd, ihdr->f_opthdr);
684 unsigned int n_scns = (int) bfd_h_get_16 (abfd, ihdr->f_nscns);
685 unsigned int off;
687 /* The section header starts after the file, image and optional headers. */
688 if (fhdr == NULL)
689 off = sizeof (struct external_filehdr) + opthdr;
690 else
691 off = (int) bfd_h_get_16 (abfd, fhdr->e_lfanew) + sizeof (* ihdr) + opthdr;
693 printf (_("\nSection headers (at offset 0x%08x):\n"), off);
695 if (n_scns == 0)
697 printf (_(" No section headers\n"));
698 return;
700 if (bfd_seek (abfd, off, SEEK_SET) != 0)
702 non_fatal (_("cannot seek to section headers start\n"));
703 return;
706 /* We don't translate this string as it consists of field names. */
707 if (wide_output)
708 printf (" # Name paddr vaddr size scnptr relptr lnnoptr nrel nlnno Flags\n");
709 else
710 printf (" # Name paddr vaddr size scnptr relptr lnnoptr nrel nlnno\n");
712 unsigned int i;
713 for (i = 0; i < n_scns; i++)
715 struct external_scnhdr scn;
716 unsigned int flags;
718 if (bfd_read (&scn, sizeof (scn), abfd) != sizeof (scn))
720 non_fatal (_("cannot read section header"));
721 return;
724 printf ("%2d %-8.8s %08x %08x %08x %08x %08x %08x %5d %5d",
725 i + 1, scn.s_name,
726 (unsigned int) bfd_h_get_32 (abfd, scn.s_paddr),
727 (unsigned int) bfd_h_get_32 (abfd, scn.s_vaddr),
728 (unsigned int) bfd_h_get_32 (abfd, scn.s_size),
729 (unsigned int) bfd_h_get_32 (abfd, scn.s_scnptr),
730 (unsigned int) bfd_h_get_32 (abfd, scn.s_relptr),
731 (unsigned int) bfd_h_get_32 (abfd, scn.s_lnnoptr),
732 (unsigned int) bfd_h_get_16 (abfd, scn.s_nreloc),
733 (unsigned int) bfd_h_get_16 (abfd, scn.s_nlnno));
735 flags = bfd_h_get_32 (abfd, scn.s_flags);
736 if (wide_output)
737 printf (_(" %08x "), flags);
738 else
739 printf (_("\n Flags: %08x: "), flags);
741 if (flags & IMAGE_SCN_ALIGN_POWER_BIT_MASK)
743 dump_alignment (flags);
744 flags &= ~ IMAGE_SCN_ALIGN_POWER_BIT_MASK;
747 if (flags != 0)
748 dump_flags (section_flag_xlat, flags);
750 putchar ('\n');
754 /* Handle a PE format file. */
756 static void
757 dump_pe (bfd * abfd,
758 struct external_PEI_filehdr * fhdr,
759 struct external_PEI_IMAGE_hdr * ihdr)
761 if (options[OPT_FILE_HEADER].selected)
762 dump_pe_file_header (abfd, fhdr, ihdr);
764 if (options[OPT_SECTIONS].selected)
765 dump_pe_sections_header (abfd, fhdr, ihdr);
768 /* Dump ABFD (according to the options[] array). */
770 static void
771 pe_dump_obj (bfd *abfd)
773 struct external_PEI_filehdr fhdr;
775 /* Read file header. */
776 if (bfd_seek (abfd, 0, SEEK_SET) != 0
777 || bfd_read (&fhdr, sizeof (fhdr), abfd) != sizeof (fhdr))
779 non_fatal (_("cannot seek to/read file header"));
780 return;
783 unsigned short magic = bfd_h_get_16 (abfd, fhdr.e_magic);
785 /* PE format executable files have a full external_PEI_filehdr structure
786 at the start. PE format object files just have an external_filehdr
787 structure at the start. */
788 if (magic == IMAGE_DOS_SIGNATURE)
790 unsigned int ihdr_offset = (int) bfd_h_get_16 (abfd, fhdr.e_lfanew);
792 /* FIXME: We could reuse the fields in fhdr, but that might
793 confuse various sanitization and memory checker tools. */
794 struct external_PEI_IMAGE_hdr ihdr;
796 if (bfd_seek (abfd, ihdr_offset, SEEK_SET) != 0
797 || bfd_read (&ihdr, sizeof (ihdr), abfd) != sizeof (ihdr))
799 non_fatal (_("cannot seek to/read image header at offset %#x"),
800 ihdr_offset);
801 return;
804 unsigned int signature = (int) bfd_h_get_16 (abfd, ihdr.nt_signature);
805 if (signature != IMAGE_NT_SIGNATURE)
807 non_fatal ("file does not have an NT format signature: %#x",
808 signature);
809 return;
812 dump_pe (abfd, &fhdr, &ihdr);
814 /* See if we recognise this particular PE object file. */
815 else if (get_target_specific_info (magic)->machine_number)
817 struct external_filehdr ehdr;
819 if (bfd_seek (abfd, 0, SEEK_SET) != 0
820 || bfd_read (&ehdr, sizeof (ehdr), abfd) != sizeof (ehdr))
822 non_fatal (_("cannot seek to/read image header"));
823 return;
826 struct external_PEI_IMAGE_hdr ihdr;
827 memcpy (&ihdr.f_magic, &ehdr, sizeof (ehdr));
828 dump_pe (abfd, NULL, &ihdr);
830 else
832 non_fatal ("unknown PE format binary - unsupported magic number: %#x",
833 magic);
834 return;
838 /* Dump a PE file. */
840 static void
841 pe_dump (bfd *abfd)
843 /* We rely on BFD to decide if the file is a core file. Note that core
844 files are only supported on native environment by BFD. */
845 switch (bfd_get_format (abfd))
847 case bfd_core:
848 // FIXME: Handle PE format core files ?
849 break;
850 default:
851 pe_dump_obj (abfd);
852 break;
856 /* Vector for pe. */
858 const struct objdump_private_desc objdump_private_desc_pe =
860 pe_help,
861 pe_filter,
862 pe_dump,
863 options