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 #if defined (USE_MINGW64_LEADING_UNDERSCORES)
33 #define TARGET_UNDERSCORE '_'
35 #define TARGET_UNDERSCORE 0
37 /* Long section names not allowed in executable images, only object files. */
38 #define COFF_LONG_SECTION_NAMES 0
39 #define COFF_SUPPORT_GNU_LINKONCE
40 #define COFF_LONG_FILENAMES
41 #define PDATA_ROW_SIZE (3 * 4)
43 #define COFF_SECTION_ALIGNMENT_ENTRIES \
44 { COFF_SECTION_NAME_EXACT_MATCH (".bss"), \
45 COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 4 }, \
46 { COFF_SECTION_NAME_PARTIAL_MATCH (".data"), \
47 COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 4 }, \
48 { COFF_SECTION_NAME_PARTIAL_MATCH (".rdata"), \
49 COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 4 }, \
50 { COFF_SECTION_NAME_PARTIAL_MATCH (".text"), \
51 COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 4 }, \
52 { COFF_SECTION_NAME_PARTIAL_MATCH (".idata"), \
53 COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 2 }, \
54 { COFF_SECTION_NAME_EXACT_MATCH (".pdata"), \
55 COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 2 }, \
56 { COFF_SECTION_NAME_PARTIAL_MATCH (".debug"), \
57 COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 0 }, \
58 { COFF_SECTION_NAME_PARTIAL_MATCH (".gnu.linkonce.wi."), \
59 COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 0 }
61 /* Note we have to make sure not to include headers twice.
62 Not all headers are wrapped in #ifdef guards, so we define
63 PEI_HEADERS to prevent double including in coff-x86_64.c */
68 #include "coff/x86_64.h"
69 #include "coff/internal.h"
73 #include "libiberty.h"
76 #define AOUTSZ PEPAOUTSZ
77 #define PEAOUTHDR PEPAOUTHDR
79 static const char *pex_regs
[16] = {
80 "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi",
81 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"
85 pex64_get_runtime_function (bfd
*abfd
, struct pex64_runtime_function
*rf
,
88 const struct external_pex64_runtime_function
*ex_rf
=
89 (const struct external_pex64_runtime_function
*) data
;
90 rf
->rva_BeginAddress
= bfd_get_32 (abfd
, ex_rf
->rva_BeginAddress
);
91 rf
->rva_EndAddress
= bfd_get_32 (abfd
, ex_rf
->rva_EndAddress
);
92 rf
->rva_UnwindData
= bfd_get_32 (abfd
, ex_rf
->rva_UnwindData
);
93 rf
->isChained
= PEX64_IS_RUNTIME_FUNCTION_CHAINED (rf
);
94 rf
->rva_UnwindData
= PEX64_GET_UNWINDDATA_UNIFIED_RVA (rf
);
98 pex64_get_unwind_info (bfd
*abfd
, struct pex64_unwind_info
*ui
, void *data
)
100 struct external_pex64_unwind_info
*ex_ui
=
101 (struct external_pex64_unwind_info
*) data
;
102 bfd_byte
*ex_dta
= (bfd_byte
*) data
;
104 memset (ui
, 0, sizeof (struct pex64_unwind_info
));
105 ui
->Version
= PEX64_UWI_VERSION (ex_ui
->Version_Flags
);
106 ui
->Flags
= PEX64_UWI_FLAGS (ex_ui
->Version_Flags
);
107 ui
->SizeOfPrologue
= (bfd_vma
) ex_ui
->SizeOfPrologue
;
108 ui
->CountOfCodes
= (bfd_vma
) ex_ui
->CountOfCodes
;
109 ui
->FrameRegister
= PEX64_UWI_FRAMEREG (ex_ui
->FrameRegisterOffset
);
110 ui
->FrameOffset
= PEX64_UWI_FRAMEOFF (ex_ui
->FrameRegisterOffset
);
111 ui
->sizeofUnwindCodes
= PEX64_UWI_SIZEOF_UWCODE_ARRAY (ui
->CountOfCodes
);
112 ui
->SizeOfBlock
= ui
->sizeofUnwindCodes
+ 4;
113 ui
->rawUnwindCodes
= &ex_dta
[4];
114 ex_dta
+= ui
->SizeOfBlock
;
117 case UNW_FLAG_EHANDLER
:
118 ui
->rva_ExceptionHandler
= bfd_get_32 (abfd
, ex_dta
);
120 case UNW_FLAG_UHANDLER
:
121 ui
->rva_TerminationHandler
= bfd_get_32 (abfd
, ex_dta
);
123 case UNW_FLAG_FHANDLER
:
124 ui
->rva_FrameHandler
= bfd_get_32 (abfd
, ex_dta
);
125 ui
->FrameHandlerArgument
= bfd_get_32 (abfd
, ex_dta
+ 4);
126 ui
->SizeOfBlock
+= 8;
128 case UNW_FLAG_CHAININFO
:
129 ui
->rva_FunctionEntry
= bfd_get_32 (abfd
, ex_dta
);
130 ui
->SizeOfBlock
+= 4;
136 ui
->SizeOfBlock
+= 8;
137 ui
->CountOfScopes
= bfd_get_32 (abfd
, ex_dta
);
139 ui
->rawScopeEntries
= ex_dta
;
140 ui
->SizeOfBlock
+= (ui
->CountOfScopes
* PEX64_SCOPE_ENTRY_SIZE
);
144 pex64_get_scope_entry (bfd
*abfd
, struct pex64_scope_entry
*se
,
145 bfd_vma idx
, const bfd_byte
*x
)
147 const struct external_pex64_scope_entry
*ex_se
;
148 x
+= (idx
* PEX64_SCOPE_ENTRY_SIZE
);
149 ex_se
= (const struct external_pex64_scope_entry
*) x
;
150 memset (se
, 0, sizeof (struct pex64_scope_entry
));
151 se
->rva_BeginAddress
= bfd_get_32 (abfd
, ex_se
->rva_BeginAddress
);
152 se
->rva_EndAddress
= bfd_get_32 (abfd
, ex_se
->rva_EndAddress
);
153 se
->rva_HandlerAddress
= bfd_get_32 (abfd
, ex_se
->rva_HandlerAddress
);
154 se
->rva_JumpAddress
= bfd_get_32 (abfd
, ex_se
->rva_JumpAddress
);
158 pex64_xdata_print_uwd_codes (FILE *file
, struct pex64_unwind_info
*ui
,
163 const bfd_byte
*insns
[256];
164 bfd_vma insns_count
= 0;
165 const bfd_byte
*dta
= ui
->rawUnwindCodes
;
167 if (ui
->CountOfCodes
== 0 || !dta
)
170 /* Sort array ascending. Note: it is stored in reversed order. */
171 for (i
= 0; i
< ui
->CountOfCodes
; i
++)
175 t
= insns
[insns_count
++] = &dta
[i
* 2];
176 switch (PEX64_UNWCODE_CODE (t
[1]))
178 case UWOP_PUSH_NONVOL
:
179 case UWOP_ALLOC_SMALL
:
181 case UWOP_PUSH_MACHFRAME
:
183 case UWOP_ALLOC_LARGE
:
184 if (PEX64_UNWCODE_INFO (t
[1]) == 0)
189 else if (PEX64_UNWCODE_INFO (t
[1]) == 1)
196 fprintf (file
, "\t contains unknown code (%u).\n",
197 (unsigned int) PEX64_UNWCODE_CODE (t
[1]));
199 case UWOP_SAVE_NONVOL
:
201 case UWOP_SAVE_XMM128
:
204 case UWOP_SAVE_NONVOL_FAR
:
205 case UWOP_SAVE_XMM_FAR
:
206 case UWOP_SAVE_XMM128_FAR
:
211 fprintf (file
, "\t At pc 0x");
212 fprintf_vma (file
, pc_addr
);
213 fprintf (file
, " there are the following saves (in logical order).\n");
214 for (i
= insns_count
; i
> 0;)
218 fprintf (file
, "\t insn ends at pc+0x%02x: ", (unsigned int) dta
[0]);
219 switch (PEX64_UNWCODE_CODE (dta
[1]))
221 case UWOP_PUSH_NONVOL
:
222 fprintf (file
, "push %s.\n", pex_regs
[PEX64_UNWCODE_INFO (dta
[1])]);
224 case UWOP_ALLOC_LARGE
:
225 if (PEX64_UNWCODE_INFO (dta
[1]) == 0)
227 tmp
= (bfd_vma
) (*((unsigned short *) &dta
[2]));
231 tmp
= (bfd_vma
) (*((unsigned int *)&dta
[2]));
232 fprintf (file
, "save stack region of size 0x");
233 fprintf_vma (file
, tmp
);
234 fprintf (file
,".\n");
236 case UWOP_ALLOC_SMALL
:
237 tmp
= (bfd_vma
) PEX64_UNWCODE_INFO (dta
[1]);
240 fprintf (file
, "save stack region of size 0x");
241 fprintf_vma (file
, tmp
);
242 fprintf (file
,".\n");
245 tmp
= (bfd_vma
) PEX64_UNWCODE_INFO (dta
[1]);
247 fprintf (file
, "FPReg = (FrameReg) + 0x");
248 fprintf_vma (file
, tmp
);
249 fprintf (file
, ".\n");
251 case UWOP_SAVE_NONVOL
:
252 fprintf (file
, "mov %s at 0x",
253 pex_regs
[PEX64_UNWCODE_INFO (dta
[1])]);
254 tmp
= (bfd_vma
) (*((unsigned short *) &dta
[2]));
256 fprintf_vma (file
, tmp
);
257 fprintf (file
, ".\n");
259 case UWOP_SAVE_NONVOL_FAR
:
260 fprintf (file
, "mov %s at 0x",
261 pex_regs
[PEX64_UNWCODE_INFO (dta
[1])]);
262 tmp
= (bfd_vma
) (*((unsigned int *) &dta
[2]));
263 fprintf_vma (file
, tmp
);
264 fprintf (file
, ".\n");
267 tmp
= (bfd_vma
) (*((unsigned short *) &dta
[2]));
269 fprintf (file
, "mov mm%u at 0x",
270 (unsigned int) PEX64_UNWCODE_INFO (dta
[1]));
271 fprintf_vma (file
, tmp
);
272 fprintf (file
, ".\n");
274 case UWOP_SAVE_XMM_FAR
:
275 tmp
= (bfd_vma
) (*((unsigned int *) &dta
[2]));
276 fprintf (file
, "mov mm%u at 0x",
277 (unsigned int) PEX64_UNWCODE_INFO (dta
[1]));
278 fprintf_vma (file
, tmp
);
279 fprintf (file
, ".\n");
281 case UWOP_SAVE_XMM128
:
282 tmp
= (bfd_vma
) (*((unsigned short *) &dta
[2]));
284 fprintf (file
, "mov xmm%u at 0x",
285 (unsigned int) PEX64_UNWCODE_INFO ( dta
[1]));
286 fprintf_vma (file
, tmp
);
287 fprintf (file
, ".\n");
289 case UWOP_SAVE_XMM128_FAR
:
290 tmp
= (bfd_vma
) (*((unsigned int *) &dta
[2]));
291 fprintf (file
, "mov xmm%u at 0x",
292 (unsigned int) PEX64_UNWCODE_INFO (dta
[1]));
293 fprintf_vma (file
, tmp
);
294 fprintf (file
, ".\n");
296 case UWOP_PUSH_MACHFRAME
:
297 fprintf (file
, "interrupt entry (SS, old RSP, EFLAGS, CS, RIP");
298 if (PEX64_UNWCODE_INFO (dta
[1]) == 0)
302 else if (PEX64_UNWCODE_INFO (dta
[1]) == 1)
304 fprintf (file
, ",ErrorCode)");
307 fprintf (file
, ", unknown(%u))",
308 (unsigned int) PEX64_UNWCODE_INFO (dta
[1]));
309 fprintf (file
,".\n");
312 fprintf (file
, "unknown code %u.\n",
313 (unsigned int) PEX64_UNWCODE_INFO (dta
[1]));
320 pex64_get_section_by_rva (bfd
*abfd
, bfd_vma addr
, const char *sec_name
)
322 asection
*section
= bfd_get_section_by_name (abfd
, sec_name
);
324 bfd_size_type datasize
= 0;
327 || coff_section_data (abfd
, section
) == NULL
328 || pei_section_data (abfd
, section
) == NULL
)
330 vsize
= section
->vma
- pe_data (abfd
)->pe_opthdr
.ImageBase
;
331 datasize
= section
->size
;
332 if (!datasize
|| vsize
> addr
|| (vsize
+ datasize
) < addr
)
338 pex64_dump_xdata (FILE *file
, bfd
*abfd
, bfd_vma addr
, bfd_vma pc_addr
)
340 asection
*section
= pex64_get_section_by_rva (abfd
, addr
, ".rdata");
342 bfd_byte
*data
= NULL
;
346 section
= pex64_get_section_by_rva (abfd
, addr
, ".data");
348 section
= pex64_get_section_by_rva (abfd
, addr
, ".xdata");
351 section
= pex64_get_section_by_rva (abfd
, addr
, ".pdata");
354 fprintf (file
, "\t Shares information with pdata element at 0x");
355 fprintf_vma (file
, addr
+ pe_data (abfd
)->pe_opthdr
.ImageBase
);
356 fprintf (file
, ".\n");
361 vsize
= section
->vma
- pe_data (abfd
)->pe_opthdr
.ImageBase
;
363 if (bfd_malloc_and_get_section (abfd
, section
, &data
))
365 struct pex64_unwind_info ui
;
370 pex64_get_unwind_info (abfd
, &ui
, &data
[addr
]);
374 fprintf (file
, "\tVersion %u (unknown).\n", (unsigned int) ui
.Version
);
378 fprintf (file
, "\tFlags: ");
381 case UNW_FLAG_NHANDLER
:
382 fprintf (file
, "UNW_FLAG_NHANDLER");
384 case UNW_FLAG_EHANDLER
:
385 fprintf (file
, "UNW_FLAG_EHANDLER");
387 case UNW_FLAG_UHANDLER
:
388 fprintf (file
, "UNW_FLAG_UHANDLER");
390 case UNW_FLAG_FHANDLER
:
391 fprintf (file
, "UNW_FLAG_FHANDLER = (UNW_FLAG_EHANDLER | UNW_FLAG_UHANDLER)");
393 case UNW_FLAG_CHAININFO
:
394 fprintf (file
, "UNW_FLAG_CHAININFO");
397 fprintf (file
, "unknown flags value 0x%x", (unsigned int) ui
.Flags
);
400 fprintf (file
, ".\n");
401 if (ui
.CountOfCodes
!= 0)
402 fprintf (file
, "\tEntry has %u codes.", (unsigned int) ui
.CountOfCodes
);
403 fprintf (file
, "\tPrologue size: %u, Frame offset = 0x%x.\n",
404 (unsigned int) ui
.SizeOfPrologue
, (unsigned int) ui
.FrameOffset
);
405 fprintf (file
, "\tFrame register is %s.\n",
406 ui
.FrameRegister
== 0 ? "CFA"
407 : pex_regs
[(unsigned int) ui
.FrameRegister
]);
409 pex64_xdata_print_uwd_codes (file
, &ui
, pc_addr
);
413 case UNW_FLAG_NHANDLER
:
415 case UNW_FLAG_EHANDLER
:
416 fprintf (file
, "\texception_handler at 0x%x.\n", (unsigned int) ui
.rva_ExceptionHandler
);
418 case UNW_FLAG_UHANDLER
:
419 fprintf (file
, "\ttermination_handler at 0x%x.\n", (unsigned int) ui
.rva_TerminationHandler
);
420 case UNW_FLAG_FHANDLER
:
421 fprintf (file
, "\tframe_handler at 0x%x.\n", (unsigned int) ui
.rva_FrameHandler
);
422 fprintf (file
, "\t Argument for FrameHandler: 0x%x.\n",
423 (unsigned int) ui
.FrameHandlerArgument
);
425 case UNW_FLAG_CHAININFO
:
426 fprintf (file
, "\t Function Entry: 0x%x\n", (unsigned int) ui
.rva_FunctionEntry
);
429 fprintf (file
, "\t Unknown flag value of 0x%x\n", (unsigned int) ui
.Flags
);
432 fprintf (file
, "\t 0x%x # of scope(s)\n", (unsigned int) ui
.CountOfScopes
);
433 for (i
= 0; i
< ui
.CountOfScopes
; i
++)
435 struct pex64_scope_entry se
;
436 pex64_get_scope_entry (abfd
, &se
, i
, ui
.rawScopeEntries
);
437 fprintf (file
, "\t scope #%u: BeginAddress: 0x%x, EndAddress: 0x%x,"
438 "\n\t\tHandlerAddress:0x%x, JumpTarget:0x%x\n",
439 (unsigned int) (i
+ 1),
440 (unsigned int) se
.rva_BeginAddress
,
441 (unsigned int) se
.rva_EndAddress
,
442 (unsigned int) se
.rva_HandlerAddress
,
443 (unsigned int) se
.rva_JumpAddress
);
451 pex64_bfd_print_pdata (bfd
*abfd
, void *vfile
)
453 FILE *file
= (FILE *) vfile
;
454 bfd_byte
*data
= NULL
;
455 asection
*section
= bfd_get_section_by_name (abfd
, ".pdata");
456 bfd_size_type datasize
= 0;
458 bfd_size_type start
, stop
;
459 int onaline
= PDATA_ROW_SIZE
;
462 || coff_section_data (abfd
, section
) == NULL
463 || pei_section_data (abfd
, section
) == NULL
)
466 stop
= pei_section_data (abfd
, section
)->virt_size
;
467 if ((stop
% onaline
) != 0)
469 _("warning: .pdata section size (%ld) is not a multiple of %d\n"),
470 (long) stop
, onaline
);
473 _("\nThe Function Table (interpreted .pdata section contents)\n"));
475 fprintf (file
, _("vma:\t\t\tBeginAddress\t EndAddress\t UnwindData\n"));
477 datasize
= section
->size
;
481 if (!bfd_malloc_and_get_section (abfd
, section
, &data
))
490 for (i
= start
; i
< stop
; i
+= onaline
)
492 struct pex64_runtime_function rf
;
494 if (i
+ PDATA_ROW_SIZE
> stop
)
496 pex64_get_runtime_function (abfd
, &rf
, &data
[i
]);
498 if (rf
.rva_BeginAddress
== 0 && rf
.rva_EndAddress
== 0
499 && rf
.rva_UnwindData
== 0)
500 /* We are probably into the padding of the section now. */
504 fprintf_vma (file
, i
+ section
->vma
);
505 fprintf (file
, ":\t");
506 rf
.rva_BeginAddress
+= pe_data (abfd
)->pe_opthdr
.ImageBase
;
507 fprintf_vma (file
, rf
.rva_BeginAddress
);
509 rf
.rva_EndAddress
+= pe_data (abfd
)->pe_opthdr
.ImageBase
;
510 fprintf_vma (file
, rf
.rva_EndAddress
);
512 fprintf_vma (file
, rf
.rva_UnwindData
);
513 fprintf (file
, "\n");
515 if (rf
.rva_UnwindData
!= 0)
519 fprintf (file
, "\t shares information with pdata element at 0x");
520 fprintf_vma (file
, rf
.rva_UnwindData
+ pe_data (abfd
)->pe_opthdr
.ImageBase
);
521 fprintf (file
, ".\n");
524 pex64_dump_xdata (file
, abfd
, rf
.rva_UnwindData
, rf
.rva_BeginAddress
);
533 #define bfd_pe_print_pdata pex64_bfd_print_pdata
535 #include "coff-x86_64.c"