1 /* od-pe.c -- dump information about a PE object file.
2 Copyright (C) 2011-2025 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)
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. */
25 #include "safe-ctype.h"
30 #include "coff/internal.h"
31 #define L_LNNO_SIZE 4 /* FIXME: which value should we use ? */
32 #include "coff/external.h"
36 #include "libiberty.h"
38 /* Index of the options in the options[] array. */
39 #define OPT_FILE_HEADER 0
41 #define OPT_SECTIONS 2
48 #define OPT_TRACEBACK 9
52 /* List of actions. */
53 static struct objdump_private_option options
[] =
70 /* Simplified section header. */
73 /* NUL terminated name. */
79 /* Offsets in file. */
84 /* Number of relocs and line numbers. */
89 /* Translation entry type. The last entry must be {0, NULL}. */
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"},
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" },
145 typedef struct target_specific_info
147 unsigned int machine_number
;
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
)
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
;
213 pe_help (FILE *stream
)
215 fprintf (stream
, _("\
217 header Display the file header\n\
218 sections Display the section headers\n\
222 /* Return true if ABFD is handled. */
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. */
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. */
245 dump_flags (const struct xlat_table
* table
, unsigned int flags
)
247 unsigned int r
= flags
;
249 const struct xlat_table
*t
;
251 for (t
= table
; t
->name
; t
++)
252 if ((flags
& t
->val
) != 0)
260 fputs (t
->name
, stdout
);
263 /* Undecoded flags. */
268 printf (_("unknown: 0x%x"), r
);
272 /* Dump the file header. */
275 dump_pe_file_header (bfd
* abfd
,
276 struct external_PEI_filehdr
* fhdr
,
277 struct external_PEI_IMAGE_hdr
* ihdr
)
281 unsigned long ihdr_off
= 0;
284 printf (_("\n File header not present\n"));
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
345 const unsigned char * message
= (const unsigned char *) fhdr
->dos_message
;
346 unsigned int len
= sizeof (fhdr
->dos_message
);
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)
363 seen_count
= string_start
= 0;
369 printf (_("Stub message:\t\t\t"));
370 while (string_start
< len
)
372 char c
= message
[string_start
++];
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
);
399 printf (_("not set\n"));
402 /* Not correct on all platforms, but works on unix. */
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
);
420 if (opt_header_size
== PEPAOUTSZ
)
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"));
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"));
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
)
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"),
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"));
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"));
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"));
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"));
636 printf (_("\n Optional header not present\n"));
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 "));
673 printf (_("Align: *unknown* "));
676 /* Dump the section's header. */
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
);
687 /* The section header starts after the file, image and optional headers. */
689 off
= sizeof (struct external_filehdr
) + opthdr
;
691 off
= (int) bfd_h_get_16 (abfd
, fhdr
->e_lfanew
) + sizeof (* ihdr
) + opthdr
;
693 printf (_("\nSection headers (at offset 0x%08x):\n"), off
);
697 printf (_(" No section headers\n"));
700 if (bfd_seek (abfd
, off
, SEEK_SET
) != 0)
702 non_fatal (_("cannot seek to section headers start\n"));
706 /* We don't translate this string as it consists of field names. */
708 printf (" # Name paddr vaddr size scnptr relptr lnnoptr nrel nlnno Flags\n");
710 printf (" # Name paddr vaddr size scnptr relptr lnnoptr nrel nlnno\n");
713 for (i
= 0; i
< n_scns
; i
++)
715 struct external_scnhdr scn
;
718 if (bfd_read (&scn
, sizeof (scn
), abfd
) != sizeof (scn
))
720 non_fatal (_("cannot read section header"));
724 printf ("%2d %-8.8s %08x %08x %08x %08x %08x %08x %5d %5d",
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
);
737 printf (_(" %08x "), flags
);
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
;
748 dump_flags (section_flag_xlat
, flags
);
754 /* Handle a PE format file. */
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). */
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"));
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"),
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",
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"));
826 struct external_PEI_IMAGE_hdr ihdr
;
827 memcpy (&ihdr
.f_magic
, &ehdr
, sizeof (ehdr
));
828 dump_pe (abfd
, NULL
, &ihdr
);
832 non_fatal ("unknown PE format binary - unsupported magic number: %#x",
838 /* Dump a PE file. */
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
))
848 // FIXME: Handle PE format core files ?
858 const struct objdump_private_desc objdump_private_desc_pe
=