1 /* BFD back-end for Intel 386 PE IMAGE COFF files.
2 Copyright 2006, 2007, 2009 Free Software Foundation, Inc.
4 This file is part of BFD, the Binary File Descriptor library.
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
21 Written by Kai Tietz, OneVision Software GmbH&CoKg. */
26 #define TARGET_SYM x86_64pei_vec
27 #define TARGET_NAME "pei-x86-64"
28 #define COFF_IMAGE_WITH_PE
30 #define COFF_WITH_pex64
31 #define PCRELOFFSET TRUE
32 #define TARGET_UNDERSCORE '_'
33 /* Long section names not allowed in executable images, only object files. */
34 #define COFF_LONG_SECTION_NAMES 0
35 #define COFF_SUPPORT_GNU_LINKONCE
36 #define COFF_LONG_FILENAMES
37 #define PDATA_ROW_SIZE (3 * 4)
39 #define COFF_SECTION_ALIGNMENT_ENTRIES \
40 { COFF_SECTION_NAME_EXACT_MATCH (".bss"), \
41 COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 4 }, \
42 { COFF_SECTION_NAME_EXACT_MATCH (".data"), \
43 COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 4 }, \
44 { COFF_SECTION_NAME_EXACT_MATCH (".rdata"), \
45 COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 4 }, \
46 { COFF_SECTION_NAME_EXACT_MATCH (".text"), \
47 COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 4 }, \
48 { COFF_SECTION_NAME_PARTIAL_MATCH (".idata"), \
49 COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 2 }, \
50 { COFF_SECTION_NAME_EXACT_MATCH (".pdata"), \
51 COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 2 }, \
52 { COFF_SECTION_NAME_PARTIAL_MATCH (".debug"), \
53 COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 0 }, \
54 { COFF_SECTION_NAME_PARTIAL_MATCH (".gnu.linkonce.wi."), \
55 COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 0 }
57 /* Note we have to make sure not to include headers twice.
58 Not all headers are wrapped in #ifdef guards, so we define
59 PEI_HEADERS to prevent double including in coff-x86_64.c */
64 #include "coff/x86_64.h"
65 #include "coff/internal.h"
69 #include "libiberty.h"
72 #define AOUTSZ PEPAOUTSZ
73 #define PEAOUTHDR PEPAOUTHDR
75 static const char *pex_regs
[16] = {
76 "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi",
77 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"
81 pex64_get_runtime_function (bfd
*abfd
, struct pex64_runtime_function
*rf
,
84 const struct external_pex64_runtime_function
*ex_rf
=
85 (const struct external_pex64_runtime_function
*) data
;
86 rf
->rva_BeginAddress
= bfd_get_32 (abfd
, ex_rf
->rva_BeginAddress
);
87 rf
->rva_EndAddress
= bfd_get_32 (abfd
, ex_rf
->rva_EndAddress
);
88 rf
->rva_UnwindData
= bfd_get_32 (abfd
, ex_rf
->rva_UnwindData
);
89 rf
->isChained
= PEX64_IS_RUNTIME_FUNCTION_CHAINED (rf
);
90 rf
->rva_UnwindData
= PEX64_GET_UNWINDDATA_UNIFIED_RVA (rf
);
94 pex64_get_unwind_info (bfd
*abfd
, struct pex64_unwind_info
*ui
, void *data
)
96 struct external_pex64_unwind_info
*ex_ui
=
97 (struct external_pex64_unwind_info
*) data
;
98 bfd_byte
*ex_dta
= (bfd_byte
*) data
;
100 memset (ui
, 0, sizeof (struct pex64_unwind_info
));
101 ui
->Version
= PEX64_UWI_VERSION (ex_ui
->Version_Flags
);
102 ui
->Flags
= PEX64_UWI_FLAGS (ex_ui
->Version_Flags
);
103 ui
->SizeOfPrologue
= (bfd_vma
) ex_ui
->SizeOfPrologue
;
104 ui
->CountOfCodes
= (bfd_vma
) ex_ui
->CountOfCodes
;
105 ui
->FrameRegister
= PEX64_UWI_FRAMEREG (ex_ui
->FrameRegisterOffset
);
106 ui
->FrameOffset
= PEX64_UWI_FRAMEOFF (ex_ui
->FrameRegisterOffset
);
107 ui
->sizeofUnwindCodes
= PEX64_UWI_SIZEOF_UWCODE_ARRAY (ui
->CountOfCodes
);
108 ui
->SizeOfBlock
= ui
->sizeofUnwindCodes
+ 4;
109 ui
->rawUnwindCodes
= &ex_dta
[4];
110 ex_dta
+= ui
->SizeOfBlock
;
113 case UNW_FLAG_EHANDLER
:
114 ui
->rva_ExceptionHandler
= bfd_get_32 (abfd
, ex_dta
);
116 case UNW_FLAG_UHANDLER
:
117 ui
->rva_TerminationHandler
= bfd_get_32 (abfd
, ex_dta
);
119 case UNW_FLAG_FHANDLER
:
120 ui
->rva_FrameHandler
= bfd_get_32 (abfd
, ex_dta
);
121 ui
->FrameHandlerArgument
= bfd_get_32 (abfd
, ex_dta
+ 4);
122 ui
->SizeOfBlock
+= 8;
124 case UNW_FLAG_CHAININFO
:
125 ui
->rva_FunctionEntry
= bfd_get_32 (abfd
, ex_dta
);
126 ui
->SizeOfBlock
+= 4;
132 ui
->SizeOfBlock
+= 8;
133 ui
->CountOfScopes
= bfd_get_32 (abfd
, ex_dta
);
135 ui
->rawScopeEntries
= ex_dta
;
136 ui
->SizeOfBlock
+= (ui
->CountOfScopes
* PEX64_SCOPE_ENTRY_SIZE
);
140 pex64_get_scope_entry (bfd
*abfd
, struct pex64_scope_entry
*se
,
141 bfd_vma idx
, const bfd_byte
*x
)
143 const struct external_pex64_scope_entry
*ex_se
;
144 x
+= (idx
* PEX64_SCOPE_ENTRY_SIZE
);
145 ex_se
= (const struct external_pex64_scope_entry
*) x
;
146 memset (se
, 0, sizeof (struct pex64_scope_entry
));
147 se
->rva_BeginAddress
= bfd_get_32 (abfd
, ex_se
->rva_BeginAddress
);
148 se
->rva_EndAddress
= bfd_get_32 (abfd
, ex_se
->rva_EndAddress
);
149 se
->rva_HandlerAddress
= bfd_get_32 (abfd
, ex_se
->rva_HandlerAddress
);
150 se
->rva_JumpAddress
= bfd_get_32 (abfd
, ex_se
->rva_JumpAddress
);
154 pex64_xdata_print_uwd_codes (FILE *file
, struct pex64_unwind_info
*ui
,
159 const bfd_byte
*insns
[256];
160 bfd_vma insns_count
= 0;
161 const bfd_byte
*dta
= ui
->rawUnwindCodes
;
163 if (ui
->CountOfCodes
== 0 || !dta
)
166 /* Sort array ascending. Note: it is stored in reversed order. */
167 for (i
= 0; i
< ui
->CountOfCodes
; i
++)
171 t
= insns
[insns_count
++] = &dta
[i
* 2];
172 switch (PEX64_UNWCODE_CODE (t
[1]))
174 case UWOP_PUSH_NONVOL
:
175 case UWOP_ALLOC_SMALL
:
177 case UWOP_PUSH_MACHFRAME
:
179 case UWOP_ALLOC_LARGE
:
180 if (PEX64_UNWCODE_INFO (t
[1]) == 0)
185 else if (PEX64_UNWCODE_INFO (t
[1]) == 1)
192 fprintf (file
, "\t contains unknown code (%u).\n",
193 (unsigned int) PEX64_UNWCODE_CODE (t
[1]));
195 case UWOP_SAVE_NONVOL
:
197 case UWOP_SAVE_XMM128
:
200 case UWOP_SAVE_NONVOL_FAR
:
201 case UWOP_SAVE_XMM_FAR
:
202 case UWOP_SAVE_XMM128_FAR
:
207 fprintf (file
, "\t At pc 0x");
208 fprintf_vma (file
, pc_addr
);
209 fprintf (file
, " there are the following saves (in logical order).\n");
210 for (i
= insns_count
; i
> 0;)
214 fprintf (file
, "\t insn ends at pc+0x%02x: ", (unsigned int) dta
[0]);
215 switch (PEX64_UNWCODE_CODE (dta
[1]))
217 case UWOP_PUSH_NONVOL
:
218 fprintf (file
, "push %s.\n", pex_regs
[PEX64_UNWCODE_INFO (dta
[1])]);
220 case UWOP_ALLOC_LARGE
:
221 if (PEX64_UNWCODE_INFO (dta
[1]) == 0)
223 tmp
= (bfd_vma
) (*((unsigned short *) &dta
[2]));
227 tmp
= (bfd_vma
) (*((unsigned int *)&dta
[2]));
228 fprintf (file
, "save stack region of size 0x");
229 fprintf_vma (file
, tmp
);
230 fprintf (file
,".\n");
232 case UWOP_ALLOC_SMALL
:
233 tmp
= (bfd_vma
) PEX64_UNWCODE_INFO (dta
[1]);
236 fprintf (file
, "save stack region of size 0x");
237 fprintf_vma (file
, tmp
);
238 fprintf (file
,".\n");
241 tmp
= (bfd_vma
) PEX64_UNWCODE_INFO (dta
[1]);
243 fprintf (file
, "FPReg = (FrameReg) + 0x");
244 fprintf_vma (file
, tmp
);
245 fprintf (file
, ".\n");
247 case UWOP_SAVE_NONVOL
:
248 fprintf (file
, "mov %s at 0x",
249 pex_regs
[PEX64_UNWCODE_INFO (dta
[1])]);
250 tmp
= (bfd_vma
) (*((unsigned short *) &dta
[2]));
252 fprintf_vma (file
, tmp
);
253 fprintf (file
, ".\n");
255 case UWOP_SAVE_NONVOL_FAR
:
256 fprintf (file
, "mov %s at 0x",
257 pex_regs
[PEX64_UNWCODE_INFO (dta
[1])]);
258 tmp
= (bfd_vma
) (*((unsigned int *) &dta
[2]));
259 fprintf_vma (file
, tmp
);
260 fprintf (file
, ".\n");
263 tmp
= (bfd_vma
) (*((unsigned short *) &dta
[2]));
265 fprintf (file
, "mov mm%u at 0x",
266 (unsigned int) PEX64_UNWCODE_INFO (dta
[1]));
267 fprintf_vma (file
, tmp
);
268 fprintf (file
, ".\n");
270 case UWOP_SAVE_XMM_FAR
:
271 tmp
= (bfd_vma
) (*((unsigned int *) &dta
[2]));
272 fprintf (file
, "mov mm%u at 0x",
273 (unsigned int) PEX64_UNWCODE_INFO (dta
[1]));
274 fprintf_vma (file
, tmp
);
275 fprintf (file
, ".\n");
277 case UWOP_SAVE_XMM128
:
278 tmp
= (bfd_vma
) (*((unsigned short *) &dta
[2]));
280 fprintf (file
, "mov xmm%u at 0x",
281 (unsigned int) PEX64_UNWCODE_INFO ( dta
[1]));
282 fprintf_vma (file
, tmp
);
283 fprintf (file
, ".\n");
285 case UWOP_SAVE_XMM128_FAR
:
286 tmp
= (bfd_vma
) (*((unsigned int *) &dta
[2]));
287 fprintf (file
, "mov xmm%u at 0x",
288 (unsigned int) PEX64_UNWCODE_INFO (dta
[1]));
289 fprintf_vma (file
, tmp
);
290 fprintf (file
, ".\n");
292 case UWOP_PUSH_MACHFRAME
:
293 fprintf (file
, "interrupt entry (SS, old RSP, EFLAGS, CS, RIP");
294 if (PEX64_UNWCODE_INFO (dta
[1]) == 0)
298 else if (PEX64_UNWCODE_INFO (dta
[1]) == 1)
300 fprintf (file
, ",ErrorCode)");
303 fprintf (file
, ", unknown(%u))",
304 (unsigned int) PEX64_UNWCODE_INFO (dta
[1]));
305 fprintf (file
,".\n");
308 fprintf (file
, "unknown code %u.\n",
309 (unsigned int) PEX64_UNWCODE_INFO (dta
[1]));
316 pex64_get_section_by_rva (bfd
*abfd
, bfd_vma addr
, const char *sec_name
)
318 asection
*section
= bfd_get_section_by_name (abfd
, sec_name
);
320 bfd_size_type datasize
= 0;
323 || coff_section_data (abfd
, section
) == NULL
324 || pei_section_data (abfd
, section
) == NULL
)
326 vsize
= section
->vma
- pe_data (abfd
)->pe_opthdr
.ImageBase
;
327 datasize
= section
->size
;
328 if (!datasize
|| vsize
> addr
|| (vsize
+ datasize
) < addr
)
334 pex64_dump_xdata (FILE *file
, bfd
*abfd
, bfd_vma addr
, bfd_vma pc_addr
)
336 asection
*section
= pex64_get_section_by_rva (abfd
, addr
, ".rdata");
338 bfd_byte
*data
= NULL
;
342 section
= pex64_get_section_by_rva (abfd
, addr
, ".data");
344 section
= pex64_get_section_by_rva (abfd
, addr
, ".xdata");
347 section
= pex64_get_section_by_rva (abfd
, addr
, ".pdata");
350 fprintf (file
, "\t Shares information with pdata element at 0x");
351 fprintf_vma (file
, addr
+ pe_data (abfd
)->pe_opthdr
.ImageBase
);
352 fprintf (file
, ".\n");
357 vsize
= section
->vma
- pe_data (abfd
)->pe_opthdr
.ImageBase
;
359 if (bfd_malloc_and_get_section (abfd
, section
, &data
))
361 struct pex64_unwind_info ui
;
366 pex64_get_unwind_info (abfd
, &ui
, &data
[addr
]);
370 fprintf (file
, "\tVersion %u (unknown).\n", (unsigned int) ui
.Version
);
374 fprintf (file
, "\tFlags: ");
377 case UNW_FLAG_NHANDLER
:
378 fprintf (file
, "UNW_FLAG_NHANDLER");
380 case UNW_FLAG_EHANDLER
:
381 fprintf (file
, "UNW_FLAG_EHANDLER");
383 case UNW_FLAG_UHANDLER
:
384 fprintf (file
, "UNW_FLAG_UHANDLER");
386 case UNW_FLAG_FHANDLER
:
387 fprintf (file
, "UNW_FLAG_FHANDLER = (UNW_FLAG_EHANDLER | UNW_FLAG_UHANDLER)");
389 case UNW_FLAG_CHAININFO
:
390 fprintf (file
, "UNW_FLAG_CHAININFO");
393 fprintf (file
, "unknown flags value 0x%x", (unsigned int) ui
.Flags
);
396 fprintf (file
, ".\n");
397 if (ui
.CountOfCodes
!= 0)
398 fprintf (file
, "\tEntry has %u codes.", (unsigned int) ui
.CountOfCodes
);
399 fprintf (file
, "\tPrologue size: %u, Frame offset = 0x%x.\n",
400 (unsigned int) ui
.SizeOfPrologue
, (unsigned int) ui
.FrameOffset
);
401 fprintf (file
, "\tFrame register is %s.\n",
402 ui
.FrameRegister
== 0 ? "CFA"
403 : pex_regs
[(unsigned int) ui
.FrameRegister
]);
405 pex64_xdata_print_uwd_codes (file
, &ui
, pc_addr
);
409 case UNW_FLAG_NHANDLER
:
411 case UNW_FLAG_EHANDLER
:
412 fprintf (file
, "\texception_handler at 0x%x.\n", (unsigned int) ui
.rva_ExceptionHandler
);
414 case UNW_FLAG_UHANDLER
:
415 fprintf (file
, "\ttermination_handler at 0x%x.\n", (unsigned int) ui
.rva_TerminationHandler
);
416 case UNW_FLAG_FHANDLER
:
417 fprintf (file
, "\tframe_handler at 0x%x.\n", (unsigned int) ui
.rva_FrameHandler
);
418 fprintf (file
, "\t Argument for FrameHandler: 0x%x.\n",
419 (unsigned int) ui
.FrameHandlerArgument
);
421 case UNW_FLAG_CHAININFO
:
422 fprintf (file
, "\t Function Entry: 0x%x\n", (unsigned int) ui
.rva_FunctionEntry
);
425 fprintf (file
, "\t Unknown flag value of 0x%x\n", (unsigned int) ui
.Flags
);
428 fprintf (file
, "\t 0x%x # of scope(s)\n", (unsigned int) ui
.CountOfScopes
);
429 for (i
= 0; i
< ui
.CountOfScopes
; i
++)
431 struct pex64_scope_entry se
;
432 pex64_get_scope_entry (abfd
, &se
, i
, ui
.rawScopeEntries
);
433 fprintf (file
, "\t scope #%u: BeginAddress: 0x%x, EndAddress: 0x%x,"
434 "\n\t\tHandlerAddress:0x%x, JumpTarget:0x%x\n",
435 (unsigned int) (i
+ 1),
436 (unsigned int) se
.rva_BeginAddress
,
437 (unsigned int) se
.rva_EndAddress
,
438 (unsigned int) se
.rva_HandlerAddress
,
439 (unsigned int) se
.rva_JumpAddress
);
447 pex64_bfd_print_pdata (bfd
*abfd
, void *vfile
)
449 FILE *file
= (FILE *) vfile
;
450 bfd_byte
*data
= NULL
;
451 asection
*section
= bfd_get_section_by_name (abfd
, ".pdata");
452 bfd_size_type datasize
= 0;
454 bfd_size_type start
, stop
;
455 int onaline
= PDATA_ROW_SIZE
;
458 || coff_section_data (abfd
, section
) == NULL
459 || pei_section_data (abfd
, section
) == NULL
)
462 stop
= pei_section_data (abfd
, section
)->virt_size
;
463 if ((stop
% onaline
) != 0)
465 _("warning: .pdata section size (%ld) is not a multiple of %d\n"),
466 (long) stop
, onaline
);
469 _("\nThe Function Table (interpreted .pdata section contents)\n"));
471 fprintf (file
, _("vma:\t\t\tBeginAddress\t EndAddress\t UnwindData\n"));
473 datasize
= section
->size
;
477 if (!bfd_malloc_and_get_section (abfd
, section
, &data
))
486 for (i
= start
; i
< stop
; i
+= onaline
)
488 struct pex64_runtime_function rf
;
490 if (i
+ PDATA_ROW_SIZE
> stop
)
492 pex64_get_runtime_function (abfd
, &rf
, &data
[i
]);
494 if (rf
.rva_BeginAddress
== 0 && rf
.rva_EndAddress
== 0
495 && rf
.rva_UnwindData
== 0)
496 /* We are probably into the padding of the section now. */
500 fprintf_vma (file
, i
+ section
->vma
);
501 fprintf (file
, ":\t");
502 rf
.rva_BeginAddress
+= pe_data (abfd
)->pe_opthdr
.ImageBase
;
503 fprintf_vma (file
, rf
.rva_BeginAddress
);
505 rf
.rva_EndAddress
+= pe_data (abfd
)->pe_opthdr
.ImageBase
;
506 fprintf_vma (file
, rf
.rva_EndAddress
);
508 fprintf_vma (file
, rf
.rva_UnwindData
);
509 fprintf (file
, "\n");
511 if (rf
.rva_UnwindData
!= 0)
515 fprintf (file
, "\t shares information with pdata element at 0x");
516 fprintf_vma (file
, rf
.rva_UnwindData
+ pe_data (abfd
)->pe_opthdr
.ImageBase
);
517 fprintf (file
, ".\n");
520 pex64_dump_xdata (file
, abfd
, rf
.rva_UnwindData
, rf
.rva_BeginAddress
);
529 #define bfd_pe_print_pdata pex64_bfd_print_pdata
531 #include "coff-x86_64.c"