1 /* od-pe.c -- dump information about a PE object file.
2 Copyright (C) 2011-2023 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 /* Display the list of name (from TABLE) for FLAGS, using comma to
231 separate them. A name is displayed if FLAGS & VAL is not 0. */
234 dump_flags (const struct xlat_table
* table
, unsigned int flags
)
236 unsigned int r
= flags
;
238 const struct xlat_table
*t
;
240 for (t
= table
; t
->name
; t
++)
241 if ((flags
& t
->val
) != 0)
249 fputs (t
->name
, stdout
);
252 /* Undecoded flags. */
257 printf (_("unknown: 0x%x"), r
);
261 /* Dump the file header. */
264 dump_pe_file_header (bfd
* abfd
,
265 struct external_PEI_filehdr
* fhdr
,
266 struct external_PEI_IMAGE_hdr
* ihdr
)
270 unsigned long ihdr_off
= 0;
273 printf (_("\n File header not present\n"));
276 printf (_("\n File Header (at offset 0):\n"));
278 // The values of the following fields are normally fixed.
279 // But we display them anyway, in case there are discrepancies.
281 data
= bfd_h_get_16 (abfd
, fhdr
->e_cblp
);
282 printf (_("Bytes on Last Page:\t\t%d\n"), data
);
284 data
= bfd_h_get_16 (abfd
, fhdr
->e_cp
);
285 printf (_("Pages In File:\t\t\t%d\n"), data
);
287 data
= bfd_h_get_16 (abfd
, fhdr
->e_crlc
);
288 printf (_("Relocations:\t\t\t%d\n"), data
);
290 data
= bfd_h_get_16 (abfd
, fhdr
->e_cparhdr
);
291 printf (_("Size of header in paragraphs:\t%d\n"), data
);
293 data
= bfd_h_get_16 (abfd
, fhdr
->e_minalloc
);
294 printf (_("Min extra paragraphs needed:\t%d\n"), data
);
296 data
= bfd_h_get_16 (abfd
, fhdr
->e_maxalloc
);
297 printf (_("Max extra paragraphs needed:\t%d\n"), data
);
299 data
= bfd_h_get_16 (abfd
, fhdr
->e_ss
);
300 printf (_("Initial (relative) SS value:\t%d\n"), data
);
302 data
= bfd_h_get_16 (abfd
, fhdr
->e_sp
);
303 printf (_("Initial SP value:\t\t%d\n"), data
);
305 data
= bfd_h_get_16 (abfd
, fhdr
->e_csum
);
306 printf (_("Checksum:\t\t\t%#x\n"), data
);
308 data
= bfd_h_get_16 (abfd
, fhdr
->e_ip
);
309 printf (_("Initial IP value:\t\t%d\n"), data
);
311 data
= bfd_h_get_16 (abfd
, fhdr
->e_cs
);
312 printf (_("Initial (relative) CS value:\t%d\n"), data
);
314 data
= bfd_h_get_16 (abfd
, fhdr
->e_lfarlc
);
315 printf (_("File address of reloc table:\t%d\n"), data
);
317 data
= bfd_h_get_16 (abfd
, fhdr
->e_ovno
);
318 printf (_("Overlay number:\t\t\t%d\n"), data
);
320 data
= bfd_h_get_16 (abfd
, fhdr
->e_oemid
);
321 printf (_("OEM identifier:\t\t\t%d\n"), data
);
323 data
= bfd_h_get_16 (abfd
, fhdr
->e_oeminfo
);
324 printf (_("OEM information:\t\t%#x\n"), data
);
326 ldata
= bfd_h_get_32 (abfd
, fhdr
->e_lfanew
);
327 printf (_("File address of new exe header:\t%#lx\n"), ldata
);
329 /* Display the first string found in the stub.
330 FIXME: Look for more than one string ?
331 FIXME: Strictly speaking we may not have read the full stub, since
332 it can be longer than the dos_message array in the PEI_fileheader
334 const unsigned char * message
= (const unsigned char *) fhdr
->dos_message
;
335 unsigned int len
= sizeof (fhdr
->dos_message
);
337 unsigned int seen_count
= 0;
338 unsigned int string_start
= 0;
340 for (i
= 0; i
< len
; i
++)
342 if (ISPRINT (message
[i
]))
344 if (string_start
== 0)
352 seen_count
= string_start
= 0;
358 printf (_("Stub message:\t\t\t"));
359 while (string_start
< len
)
361 char c
= message
[string_start
++];
369 ihdr_off
= (long) bfd_h_get_32 (abfd
, fhdr
->e_lfanew
);
372 printf (_("\n Image Header (at offset %#lx):\n"), ihdr_off
);
374 /* Note - we try to make this output use the same format as the output from -p.
375 But since there are multiple headers to display and the order of the fields
376 in the headers do not match the order of information displayed by -p, there
377 are some discrepancies. */
379 unsigned int machine
= (int) bfd_h_get_16 (abfd
, ihdr
->f_magic
);
380 printf (_("Machine Number:\t\t\t%#x\t\t- %s\n"), machine
,
381 get_target_specific_info (machine
)->name
);
383 printf (_("Number of sections:\t\t\%d\n"), (int) bfd_h_get_16 (abfd
, ihdr
->f_nscns
));
385 long timedat
= bfd_h_get_32 (abfd
, ihdr
->f_timdat
);
386 printf (_("Time/Date:\t\t\t%#08lx\t- "), timedat
);
388 printf (_("not set\n"));
391 /* Not correct on all platforms, but works on unix. */
393 fputs (ctime (&t
), stdout
);
396 printf (_("Symbol table offset:\t\t%#08lx\n"),
397 (long) bfd_h_get_32 (abfd
, ihdr
->f_symptr
));
398 printf (_("Number of symbols:\t\t\%ld\n"),
399 (long) bfd_h_get_32 (abfd
, ihdr
->f_nsyms
));
401 unsigned int opt_header_size
= (int) bfd_h_get_16 (abfd
, ihdr
->f_opthdr
);
402 printf (_("Optional header size:\t\t%#x\n"), opt_header_size
);
404 unsigned int flags
= (int) bfd_h_get_16 (abfd
, ihdr
->f_flags
);
405 printf (_("Flags:\t\t\t\t0x%04x\t\t- "), flags
);
406 dump_flags (file_flag_xlat
, flags
);
409 if (opt_header_size
== PEPAOUTSZ
)
413 printf (_("\n Optional 64-bit AOUT Header (at offset %#lx):\n"),
414 ihdr_off
+ sizeof (* ihdr
));
416 // Fortunately, it appears that the size and layout of the
417 // PEPAOUTHDR header is consistent across all architectures.
418 if (bfd_seek (abfd
, ihdr_off
+ sizeof (* ihdr
), SEEK_SET
) != 0
419 || bfd_read (&xhdr
, sizeof (xhdr
), abfd
) != sizeof (xhdr
))
420 printf (_("error: unable to read AOUT and PE+ headers\n"));
423 data
= (int) bfd_h_get_16 (abfd
, xhdr
.standard
.magic
);
424 printf (_("Magic:\t\t\t\t%x\t\t- %s\n"), data
,
425 data
== 0x020b ? "PE32+" : _("Unknown"));
427 printf (_("Version:\t\t\t%x\n"),
428 (int) bfd_h_get_16 (abfd
, xhdr
.standard
.vstamp
));
430 printf (_("Text Size:\t\t\t%#lx\n"),
431 (long) bfd_h_get_32 (abfd
, xhdr
.standard
.tsize
));
432 printf (_("Data Size:\t\t\t%#lx\n"),
433 (long) bfd_h_get_32 (abfd
, xhdr
.standard
.dsize
));
434 printf (_("BSS Size:\t\t\t%#lx\n"),
435 (long) bfd_h_get_32 (abfd
, xhdr
.standard
.bsize
));
436 printf (_("Entry Point:\t\t\t%#lx\n"),
437 (long) bfd_h_get_32 (abfd
, xhdr
.standard
.entry
));
438 printf (_("Text Start:\t\t\t%#lx\n"),
439 (long) bfd_h_get_32 (abfd
, xhdr
.standard
.text_start
));
440 /* There is no data_start field in the PE+ standard header. */
442 printf (_("\n Optional PE+ Header (at offset %#lx):\n"),
443 ihdr_off
+ sizeof (* ihdr
) + sizeof (xhdr
.standard
));
445 printf (_("Image Base:\t\t\t%#lx\n"),
446 (long) bfd_h_get_32 (abfd
, xhdr
.ImageBase
));
447 printf (_("Section Alignment:\t\t%#lx\n"),
448 (long) bfd_h_get_32 (abfd
, xhdr
.SectionAlignment
));
449 printf (_("File Alignment:\t\t\t%#lx\n"),
450 (long) bfd_h_get_32 (abfd
, xhdr
.FileAlignment
));
451 printf (_("Major OS Version:\t\t%d\n"),
452 (int) bfd_h_get_16 (abfd
, xhdr
.MajorOperatingSystemVersion
));
453 printf (_("Minor OS ersion:\t\t%d\n"),
454 (int) bfd_h_get_16 (abfd
, xhdr
.MinorOperatingSystemVersion
));
455 printf (_("Major Image Version:\t\t%d\n"),
456 (int) bfd_h_get_16 (abfd
, xhdr
.MajorImageVersion
));
457 printf (_("Minor Image Version:\t\t%d\n"),
458 (int) bfd_h_get_16 (abfd
, xhdr
.MinorImageVersion
));
459 printf (_("Major Subsystem Version:\t%d\n"),
460 (int) bfd_h_get_16 (abfd
, xhdr
.MajorSubsystemVersion
));
461 printf (_("Minor Subsystem Version:\t%d\n"),
462 (int) bfd_h_get_16 (abfd
, xhdr
.MinorSubsystemVersion
));
463 printf (_("Size Of Image:\t\t\t%#lx\n"),
464 (long) bfd_h_get_32 (abfd
, xhdr
.SizeOfImage
));
465 printf (_("Size Of Headers:\t\t%#lx\n"),
466 (long) bfd_h_get_32 (abfd
, xhdr
.SizeOfHeaders
));
467 printf (_("CheckSum:\t\t\t%#lx\n"),
468 (long) bfd_h_get_32 (abfd
, xhdr
.CheckSum
));
469 printf (_("Subsystem:\t\t\t%d\n"),
470 (int) bfd_h_get_16 (abfd
, xhdr
.Subsystem
));
471 // FIXME: Decode the characteristics.
472 printf (_("DllCharacteristics:\t\t%#x\n"),
473 (int) bfd_h_get_16 (abfd
, xhdr
.DllCharacteristics
));
474 printf (_("Size Of Stack Reserve:\t\t%#lx\n"),
475 (long) bfd_h_get_32 (abfd
, xhdr
.SizeOfStackReserve
));
476 printf (_("Size Of Stack Commit:\t\t%#lx\n"),
477 (long) bfd_h_get_32 (abfd
, xhdr
.SizeOfStackCommit
));
478 printf (_("Size Of Heap Reserve:\t\t%#lx\n"),
479 (long) bfd_h_get_32 (abfd
, xhdr
.SizeOfHeapReserve
));
480 printf (_("Size Of Heap Commit:\t\t%#lx\n"),
481 (long) bfd_h_get_32 (abfd
, xhdr
.SizeOfHeapCommit
));
482 printf (_("Loader Flags:\t\t\t%#lx\n"),
483 (long) bfd_h_get_32 (abfd
, xhdr
.LoaderFlags
));
484 printf (_("Number Of Rva and Sizes:\t%#lx\n"),
485 (long) bfd_h_get_32 (abfd
, xhdr
.NumberOfRvaAndSizes
));
487 // FIXME: Decode the Data Directory.
490 else if (opt_header_size
== AOUTSZ
)
494 /* Different architectures have different sizes of AOUT header. */
495 unsigned int aout_hdr_size
= get_target_specific_info (machine
)->aout_hdr_size
;
497 unsigned long off
= ihdr_off
+ sizeof (* ihdr
);
498 unsigned long size
= sizeof (xhdr
.standard
);
500 printf (_("\n Optional 32-bit AOUT Header (at offset %#lx, size %d):\n"),
503 if (bfd_seek (abfd
, off
, SEEK_SET
) != 0
504 || bfd_read (&xhdr
.standard
, size
, abfd
) != size
)
505 printf (_("error: unable to seek to/read AOUT header\n"));
508 data
= (int) bfd_h_get_16 (abfd
, xhdr
.standard
.magic
);
509 printf (_("Magic:\t\t\t\t%x\t\t- %s\n"), data
,
510 data
== 0x010b ? "PE32" : _("Unknown"));
512 printf (_("Version:\t\t\t%x\n"),
513 (int) bfd_h_get_16 (abfd
, xhdr
.standard
.vstamp
));
515 printf (_("Text Size:\t\t\t%#lx\n"),
516 (long) bfd_h_get_32 (abfd
, xhdr
.standard
.tsize
));
517 printf (_("Data Size:\t\t\t%#lx\n"),
518 (long) bfd_h_get_32 (abfd
, xhdr
.standard
.dsize
));
519 printf (_("BSS Size:\t\t\t%#lx\n"),
520 (long) bfd_h_get_32 (abfd
, xhdr
.standard
.bsize
));
521 printf (_("Entry Point:\t\t\t%#lx\n"),
522 (long) bfd_h_get_32 (abfd
, xhdr
.standard
.entry
));
523 printf (_("Text Start:\t\t\t%#lx\n"),
524 (long) bfd_h_get_32 (abfd
, xhdr
.standard
.text_start
));
525 printf (_("Data Start:\t\t\t%#lx\n"),
526 (long) bfd_h_get_32 (abfd
, xhdr
.standard
.data_start
));
529 off
= ihdr_off
+ sizeof (* ihdr
) + aout_hdr_size
;
530 size
= sizeof (xhdr
) - sizeof (xhdr
.standard
);
532 printf (_("\n Optional PE Header (at offset %#lx):\n"), off
);
534 /* FIXME: Sanitizers might complain about reading more bytes than
535 fit into the ImageBase field. Find a way to solve this. */
536 if (bfd_seek (abfd
, off
, SEEK_SET
) != 0
537 || bfd_read (&xhdr
.ImageBase
, size
, abfd
) != size
)
538 printf (_("error: unable to seek to/read PE header\n"));
541 printf (_("Image Base:\t\t\t%#lx\n"),
542 (long) bfd_h_get_32 (abfd
, xhdr
.ImageBase
));
543 printf (_("Section Alignment:\t\t%#lx\n"),
544 (long) bfd_h_get_32 (abfd
, xhdr
.SectionAlignment
));
545 printf (_("File Alignment:\t\t\t%#lx\n"),
546 (long) bfd_h_get_32 (abfd
, xhdr
.FileAlignment
));
547 printf (_("Major OS Version:\t\t%d\n"),
548 (int) bfd_h_get_16 (abfd
, xhdr
.MajorOperatingSystemVersion
));
549 printf (_("Minor OS ersion:\t\t%d\n"),
550 (int) bfd_h_get_16 (abfd
, xhdr
.MinorOperatingSystemVersion
));
551 printf (_("Major Image Version:\t\t%d\n"),
552 (int) bfd_h_get_16 (abfd
, xhdr
.MajorImageVersion
));
553 printf (_("Minor Image Version:\t\t%d\n"),
554 (int) bfd_h_get_16 (abfd
, xhdr
.MinorImageVersion
));
555 printf (_("Major Subsystem Version:\t%d\n"),
556 (int) bfd_h_get_16 (abfd
, xhdr
.MajorSubsystemVersion
));
557 printf (_("Minor Subsystem Version:\t%d\n"),
558 (int) bfd_h_get_16 (abfd
, xhdr
.MinorSubsystemVersion
));
559 printf (_("Size Of Image:\t\t\t%#lx\n"),
560 (long) bfd_h_get_32 (abfd
, xhdr
.SizeOfImage
));
561 printf (_("Size Of Headers:\t\t%#lx\n"),
562 (long) bfd_h_get_32 (abfd
, xhdr
.SizeOfHeaders
));
563 printf (_("CheckSum:\t\t\t%#lx\n"),
564 (long) bfd_h_get_32 (abfd
, xhdr
.CheckSum
));
565 printf (_("Subsystem:\t\t\t%d\n"),
566 (int) bfd_h_get_16 (abfd
, xhdr
.Subsystem
));
567 // FIXME: Decode the characteristics.
568 printf (_("DllCharacteristics:\t\t%#x\n"),
569 (int) bfd_h_get_16 (abfd
, xhdr
.DllCharacteristics
));
570 printf (_("Size Of Stack Reserve:\t\t%#lx\n"),
571 (long) bfd_h_get_32 (abfd
, xhdr
.SizeOfStackReserve
));
572 printf (_("Size Of Stack Commit:\t\t%#lx\n"),
573 (long) bfd_h_get_32 (abfd
, xhdr
.SizeOfStackCommit
));
574 printf (_("Size Of Heap Reserve:\t\t%#lx\n"),
575 (long) bfd_h_get_32 (abfd
, xhdr
.SizeOfHeapReserve
));
576 printf (_("Size Of Heap Commit:\t\t%#lx\n"),
577 (long) bfd_h_get_32 (abfd
, xhdr
.SizeOfHeapCommit
));
578 printf (_("Loader Flags:\t\t\t%#lx\n"),
579 (long) bfd_h_get_32 (abfd
, xhdr
.LoaderFlags
));
580 printf (_("Number Of Rva and Sizes:\t%#lx\n"),
581 (long) bfd_h_get_32 (abfd
, xhdr
.NumberOfRvaAndSizes
));
583 // FIXME: Decode the Data Directory.
586 else if (opt_header_size
!= 0)
588 printf (_("\nUnsupported size of Optional Header\n"));
591 printf (_("\n Optional header not present\n"));
594 /* Dump the sections header. */
597 dump_pe_sections_header (bfd
* abfd
,
598 struct external_PEI_filehdr
* fhdr
,
599 struct external_PEI_IMAGE_hdr
* ihdr
)
601 unsigned int opthdr
= (int) bfd_h_get_16 (abfd
, ihdr
->f_opthdr
);
602 unsigned int n_scns
= (int) bfd_h_get_16 (abfd
, ihdr
->f_nscns
);
605 /* The section header starts after the file, image and optional headers. */
607 off
= sizeof (struct external_filehdr
) + opthdr
;
609 off
= (int) bfd_h_get_16 (abfd
, fhdr
->e_lfanew
) + sizeof (* ihdr
) + opthdr
;
611 printf (_("\nSection headers (at offset 0x%08x):\n"), off
);
615 printf (_(" No section headers\n"));
618 if (bfd_seek (abfd
, off
, SEEK_SET
) != 0)
620 non_fatal (_("cannot seek to section headers start\n"));
624 /* We don't translate this string as it consists of field names. */
626 printf (" # Name paddr vaddr size scnptr relptr lnnoptr nrel nlnno Flags\n");
628 printf (" # Name paddr vaddr size scnptr relptr lnnoptr nrel nlnno\n");
631 for (i
= 0; i
< n_scns
; i
++)
633 struct external_scnhdr scn
;
636 if (bfd_read (&scn
, sizeof (scn
), abfd
) != sizeof (scn
))
638 non_fatal (_("cannot read section header"));
642 printf ("%2d %-8.8s %08x %08x %08x %08x %08x %08x %5d %5d",
644 (unsigned int) bfd_h_get_32 (abfd
, scn
.s_paddr
),
645 (unsigned int) bfd_h_get_32 (abfd
, scn
.s_vaddr
),
646 (unsigned int) bfd_h_get_32 (abfd
, scn
.s_size
),
647 (unsigned int) bfd_h_get_32 (abfd
, scn
.s_scnptr
),
648 (unsigned int) bfd_h_get_32 (abfd
, scn
.s_relptr
),
649 (unsigned int) bfd_h_get_32 (abfd
, scn
.s_lnnoptr
),
650 (unsigned int) bfd_h_get_16 (abfd
, scn
.s_nreloc
),
651 (unsigned int) bfd_h_get_16 (abfd
, scn
.s_nlnno
));
653 flags
= bfd_h_get_32 (abfd
, scn
.s_flags
);
655 printf (_(" %08x "), flags
);
657 printf (_("\n Flags: %08x: "), flags
);
661 /* Skip the alignment bits. */
662 flags
&= ~ IMAGE_SCN_ALIGN_POWER_BIT_MASK
;
663 dump_flags (section_flag_xlat
, flags
);
670 /* Handle a PE format file. */
674 struct external_PEI_filehdr
* fhdr
,
675 struct external_PEI_IMAGE_hdr
* ihdr
)
677 if (options
[OPT_FILE_HEADER
].selected
)
678 dump_pe_file_header (abfd
, fhdr
, ihdr
);
680 if (options
[OPT_SECTIONS
].selected
)
681 dump_pe_sections_header (abfd
, fhdr
, ihdr
);
684 /* Dump ABFD (according to the options[] array). */
687 pe_dump_obj (bfd
*abfd
)
689 struct external_PEI_filehdr fhdr
;
691 /* Read file header. */
692 if (bfd_seek (abfd
, 0, SEEK_SET
) != 0
693 || bfd_read (&fhdr
, sizeof (fhdr
), abfd
) != sizeof (fhdr
))
695 non_fatal (_("cannot seek to/read file header"));
699 unsigned short magic
= bfd_h_get_16 (abfd
, fhdr
.e_magic
);
701 /* PE format executable files have a full external_PEI_filehdr structure
702 at the start. PE format object files just have an external_filehdr
703 structure at the start. */
704 if (magic
== IMAGE_DOS_SIGNATURE
)
706 unsigned int ihdr_offset
= (int) bfd_h_get_16 (abfd
, fhdr
.e_lfanew
);
708 /* FIXME: We could reuse the fields in fhdr, but that might
709 confuse various sanitization and memory checker tools. */
710 struct external_PEI_IMAGE_hdr ihdr
;
712 if (bfd_seek (abfd
, ihdr_offset
, SEEK_SET
) != 0
713 || bfd_read (&ihdr
, sizeof (ihdr
), abfd
) != sizeof (ihdr
))
715 non_fatal (_("cannot seek to/read image header at offset %#x"),
720 unsigned int signature
= (int) bfd_h_get_16 (abfd
, ihdr
.nt_signature
);
721 if (signature
!= IMAGE_NT_SIGNATURE
)
723 non_fatal ("file does not have an NT format signature: %#x",
728 dump_pe (abfd
, &fhdr
, &ihdr
);
730 /* See if we recognise this particular PE object file. */
731 else if (get_target_specific_info (magic
)->machine_number
)
733 struct external_filehdr ehdr
;
735 if (bfd_seek (abfd
, 0, SEEK_SET
) != 0
736 || bfd_read (&ehdr
, sizeof (ehdr
), abfd
) != sizeof (ehdr
))
738 non_fatal (_("cannot seek to/read image header"));
742 struct external_PEI_IMAGE_hdr ihdr
;
743 memcpy (&ihdr
.f_magic
, &ehdr
, sizeof (ehdr
));
744 dump_pe (abfd
, NULL
, &ihdr
);
748 non_fatal ("unknown PE format binary - unsupported magic number: %#x",
754 /* Dump a PE file. */
759 /* We rely on BFD to decide if the file is a core file. Note that core
760 files are only supported on native environment by BFD. */
761 switch (bfd_get_format (abfd
))
764 // FIXME: Handle PE format core files ?
774 const struct objdump_private_desc objdump_private_desc_pe
=