1 /* BFD back-end for Intel 386 PE IMAGE COFF files.
2 Copyright (C) 2006-2024 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_64_pei_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 }
64 #include "coff/x86_64.h"
65 #include "coff/internal.h"
69 #include "libiberty.h"
72 #define AOUTSZ PEPAOUTSZ
73 #define PEAOUTHDR PEPAOUTHDR
75 /* Name of registers according to SEH conventions. */
77 static const char * const pex_regs
[16] = {
78 "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi",
79 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"
82 /* Swap in a runtime function. */
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
);
95 /* Swap in unwind info header. */
98 pex64_get_unwind_info (bfd
*abfd
, struct pex64_unwind_info
*ui
,
99 void *data
, void *data_end
)
101 struct external_pex64_unwind_info
*ex_ui
=
102 (struct external_pex64_unwind_info
*) data
;
103 bfd_byte
*ex_dta
= (bfd_byte
*) data
;
104 bfd_byte
*ex_dta_end
= (bfd_byte
*) data_end
;
106 memset (ui
, 0, sizeof (struct pex64_unwind_info
));
108 if (ex_dta_end
- ex_dta
< 4)
111 ui
->Version
= PEX64_UWI_VERSION (ex_ui
->Version_Flags
);
112 ui
->Flags
= PEX64_UWI_FLAGS (ex_ui
->Version_Flags
);
113 ui
->SizeOfPrologue
= (bfd_vma
) ex_ui
->SizeOfPrologue
;
114 ui
->CountOfCodes
= (bfd_vma
) ex_ui
->CountOfCodes
;
115 ui
->FrameRegister
= PEX64_UWI_FRAMEREG (ex_ui
->FrameRegisterOffset
);
116 ui
->FrameOffset
= PEX64_UWI_FRAMEOFF (ex_ui
->FrameRegisterOffset
);
117 ui
->sizeofUnwindCodes
= PEX64_UWI_SIZEOF_UWCODE_ARRAY (ui
->CountOfCodes
);
118 ui
->SizeOfBlock
= ui
->sizeofUnwindCodes
+ 4;
119 ui
->rawUnwindCodes
= ex_dta
+ 4;
120 ui
->rawUnwindCodesEnd
= ex_dta_end
;
122 if ((size_t) (ex_dta_end
- ex_dta
) < ui
->SizeOfBlock
)
124 ex_dta
+= ui
->SizeOfBlock
;
128 case UNW_FLAG_CHAININFO
:
129 if (ex_dta_end
- ex_dta
< 12)
131 ui
->rva_BeginAddress
= bfd_get_32 (abfd
, ex_dta
+ 0);
132 ui
->rva_EndAddress
= bfd_get_32 (abfd
, ex_dta
+ 4);
133 ui
->rva_UnwindData
= bfd_get_32 (abfd
, ex_dta
+ 8);
134 ui
->SizeOfBlock
+= 12;
136 case UNW_FLAG_EHANDLER
:
137 case UNW_FLAG_UHANDLER
:
138 case UNW_FLAG_FHANDLER
:
139 if (ex_dta_end
- ex_dta
< 4)
141 ui
->rva_ExceptionHandler
= bfd_get_32 (abfd
, ex_dta
);
142 ui
->SizeOfBlock
+= 4;
149 /* Display unwind codes. */
152 pex64_xdata_print_uwd_codes (FILE *file
, bfd
*abfd
,
153 struct pex64_unwind_info
*ui
,
154 struct pex64_runtime_function
*rf
)
157 unsigned int tmp
; /* At least 32 bits. */
160 if (ui
->CountOfCodes
== 0 || ui
->rawUnwindCodes
== NULL
)
163 /* According to UNWIND_CODE documentation:
164 If an FP reg is used, the any unwind code taking an offset must only be
165 used after the FP reg is established in the prolog.
166 But there are counter examples of that in system dlls... */
171 if ((size_t) (ui
->rawUnwindCodesEnd
- ui
->rawUnwindCodes
)
172 < ui
->CountOfCodes
* 2)
174 fprintf (file
, _("warning: corrupt unwind data\n"));
179 && PEX64_UNWCODE_CODE (ui
->rawUnwindCodes
[1]) == UWOP_EPILOG
)
181 /* Display epilog opcode (whose docoding is not fully documented).
182 Looks to be designed to speed-up unwinding, as there is no need
183 to decode instruction flow if outside an epilog. */
184 unsigned int func_size
= rf
->rva_EndAddress
- rf
->rva_BeginAddress
;
186 fprintf (file
, "\tv2 epilog (length: %02x) at pc+:",
187 ui
->rawUnwindCodes
[0]);
189 if (PEX64_UNWCODE_INFO (ui
->rawUnwindCodes
[1]))
190 fprintf (file
, " 0x%x", func_size
- ui
->rawUnwindCodes
[0]);
193 for (; i
< ui
->CountOfCodes
; i
++)
195 const bfd_byte
*dta
= ui
->rawUnwindCodes
+ 2 * i
;
198 if (PEX64_UNWCODE_CODE (dta
[1]) != UWOP_EPILOG
)
200 off
= dta
[0] | (PEX64_UNWCODE_INFO (dta
[1]) << 8);
202 fprintf (file
, " [pad]");
204 fprintf (file
, " 0x%x", func_size
- off
);
209 for (; i
< ui
->CountOfCodes
; i
++)
211 const bfd_byte
*dta
= ui
->rawUnwindCodes
+ 2 * i
;
212 unsigned int info
= PEX64_UNWCODE_INFO (dta
[1]);
213 int unexpected
= false;
215 fprintf (file
, "\t pc+0x%02x: ", (unsigned int) dta
[0]);
217 switch (PEX64_UNWCODE_CODE (dta
[1]))
219 case UWOP_PUSH_NONVOL
:
220 fprintf (file
, "push %s", pex_regs
[info
]);
223 case UWOP_ALLOC_LARGE
:
226 if (ui
->rawUnwindCodesEnd
- dta
< 4)
228 fprintf (file
, _("warning: corrupt unwind data\n"));
231 tmp
= bfd_get_16 (abfd
, dta
+ 2) * 8;
236 if (ui
->rawUnwindCodesEnd
- dta
< 6)
238 fprintf (file
, _("warning: corrupt unwind data\n"));
241 tmp
= bfd_get_32 (abfd
, dta
+ 2);
244 fprintf (file
, "alloc large area: rsp = rsp - 0x%x", tmp
);
247 case UWOP_ALLOC_SMALL
:
248 fprintf (file
, "alloc small area: rsp = rsp - 0x%x", (info
+ 1) * 8);
252 /* According to the documentation, info field is unused. */
253 fprintf (file
, "FPReg: %s = rsp + 0x%x (info = 0x%x)",
254 pex_regs
[ui
->FrameRegister
],
255 (unsigned int) ui
->FrameOffset
* 16, info
);
256 unexpected
= ui
->FrameRegister
== 0;
257 save_allowed
= false;
260 case UWOP_SAVE_NONVOL
:
261 if (ui
->rawUnwindCodesEnd
- dta
< 4)
263 fprintf (file
, _("warning: corrupt unwind data\n"));
266 tmp
= bfd_get_16 (abfd
, dta
+ 2) * 8;
268 fprintf (file
, "save %s at rsp + 0x%x", pex_regs
[info
], tmp
);
269 unexpected
= !save_allowed
;
272 case UWOP_SAVE_NONVOL_FAR
:
273 if (ui
->rawUnwindCodesEnd
- dta
< 6)
275 fprintf (file
, _("warning: corrupt unwind data\n"));
278 tmp
= bfd_get_32 (abfd
, dta
+ 2);
280 fprintf (file
, "save %s at rsp + 0x%x", pex_regs
[info
], tmp
);
281 unexpected
= !save_allowed
;
285 if (ui
->Version
== 1)
287 if (ui
->rawUnwindCodesEnd
- dta
< 4)
289 fprintf (file
, _("warning: corrupt unwind data\n"));
292 tmp
= bfd_get_16 (abfd
, dta
+ 2) * 8;
294 fprintf (file
, "save mm%u at rsp + 0x%x", info
, tmp
);
295 unexpected
= !save_allowed
;
297 else if (ui
->Version
== 2)
299 fprintf (file
, "epilog %02x %01x", dta
[0], info
);
304 case UWOP_SAVE_XMM_FAR
:
305 if (ui
->rawUnwindCodesEnd
- dta
< 6)
307 fprintf (file
, _("warning: corrupt unwind data\n"));
310 tmp
= bfd_get_32 (abfd
, dta
+ 2) * 8;
312 fprintf (file
, "save mm%u at rsp + 0x%x", info
, tmp
);
313 unexpected
= !save_allowed
;
316 case UWOP_SAVE_XMM128
:
317 if (ui
->rawUnwindCodesEnd
- dta
< 4)
319 fprintf (file
, _("warning: corrupt unwind data\n"));
322 tmp
= bfd_get_16 (abfd
, dta
+ 2) * 16;
324 fprintf (file
, "save xmm%u at rsp + 0x%x", info
, tmp
);
325 unexpected
= !save_allowed
;
328 case UWOP_SAVE_XMM128_FAR
:
329 if (ui
->rawUnwindCodesEnd
- dta
< 6)
331 fprintf (file
, _("warning: corrupt unwind data\n"));
334 tmp
= bfd_get_32 (abfd
, dta
+ 2) * 16;
336 fprintf (file
, "save xmm%u at rsp + 0x%x", info
, tmp
);
337 unexpected
= !save_allowed
;
340 case UWOP_PUSH_MACHFRAME
:
341 fprintf (file
, "interrupt entry (SS, old RSP, EFLAGS, CS, RIP");
345 fprintf (file
, ",ErrorCode)");
347 fprintf (file
, ", unknown(%u))", info
);
351 /* PR 17512: file: 2245-7442-0.004. */
352 fprintf (file
, _("Unknown: %x"), PEX64_UNWCODE_CODE (dta
[1]));
357 fprintf (file
, " [Unexpected!]");
362 /* Check wether section SEC_NAME contains the xdata at address ADDR. */
365 pex64_get_section_by_rva (bfd
*abfd
, bfd_vma addr
, const char *sec_name
)
367 asection
*section
= bfd_get_section_by_name (abfd
, sec_name
);
369 bfd_size_type datasize
= 0;
372 || coff_section_data (abfd
, section
) == NULL
373 || pei_section_data (abfd
, section
) == NULL
)
375 vsize
= section
->vma
- pe_data (abfd
)->pe_opthdr
.ImageBase
;
376 datasize
= section
->size
;
377 if (!datasize
|| vsize
> addr
|| (vsize
+ datasize
) < addr
)
382 /* Dump xdata at for function RF to FILE. The argument XDATA_SECTION
383 designate the bfd section containing the xdata, XDATA is its content,
384 and ENDX the size if known (or NULL). */
387 pex64_dump_xdata (FILE *file
, bfd
*abfd
,
388 asection
*xdata_section
, bfd_byte
*xdata
, bfd_vma
*endx
,
389 struct pex64_runtime_function
*rf
)
393 bfd_vma addr
= rf
->rva_UnwindData
;
394 bfd_size_type sec_size
= xdata_section
->rawsize
> 0 ? xdata_section
->rawsize
: xdata_section
->size
;
395 struct pex64_unwind_info ui
;
397 vaddr
= xdata_section
->vma
- pe_data (abfd
)->pe_opthdr
.ImageBase
;
400 /* PR 17512: file: 2245-7442-0.004. */
401 if (addr
>= sec_size
)
403 fprintf (file
, _("warning: xdata section corrupt\n"));
409 end_addr
= endx
[0] - vaddr
;
410 /* PR 17512: file: 2245-7442-0.004. */
411 if (end_addr
> sec_size
)
413 fprintf (file
, _("warning: xdata section corrupt\n"));
420 if (! pex64_get_unwind_info (abfd
, &ui
, xdata
+ addr
, xdata
+ end_addr
))
422 fprintf (file
, _("warning: xdata section corrupt\n"));
426 if (ui
.Version
!= 1 && ui
.Version
!= 2)
429 fprintf (file
, "\tVersion %u (unknown).\n",
430 (unsigned int) ui
.Version
);
431 for (i
= 0; addr
< end_addr
; addr
+= 1, i
++)
434 fprintf (file
, "\t %03x:", i
);
435 fprintf (file
, " %02x", xdata
[addr
]);
437 fprintf (file
, "\n");
440 fprintf (file
, "\n");
444 fprintf (file
, "\tVersion: %d, Flags: ", ui
.Version
);
447 case UNW_FLAG_NHANDLER
:
448 fprintf (file
, "none");
450 case UNW_FLAG_EHANDLER
:
451 fprintf (file
, "UNW_FLAG_EHANDLER");
453 case UNW_FLAG_UHANDLER
:
454 fprintf (file
, "UNW_FLAG_UHANDLER");
456 case UNW_FLAG_FHANDLER
:
458 (file
, "UNW_FLAG_EHANDLER | UNW_FLAG_UHANDLER");
460 case UNW_FLAG_CHAININFO
:
461 fprintf (file
, "UNW_FLAG_CHAININFO");
464 fprintf (file
, "unknown flags value 0x%x", (unsigned int) ui
.Flags
);
468 fprintf (file
, "\tNbr codes: %u, ", (unsigned int) ui
.CountOfCodes
);
469 fprintf (file
, "Prologue size: 0x%02x, Frame offset: 0x%x, ",
470 (unsigned int) ui
.SizeOfPrologue
, (unsigned int) ui
.FrameOffset
);
471 fprintf (file
, "Frame reg: %s\n",
472 ui
.FrameRegister
== 0 ? "none"
473 : pex_regs
[(unsigned int) ui
.FrameRegister
]);
475 /* PR 17512: file: 2245-7442-0.004. */
476 if (ui
.CountOfCodes
* 2 + ui
.rawUnwindCodes
> xdata
+ xdata_section
->size
)
477 fprintf (file
, _("Too many unwind codes (%ld)\n"), (long) ui
.CountOfCodes
);
479 pex64_xdata_print_uwd_codes (file
, abfd
, &ui
, rf
);
483 case UNW_FLAG_EHANDLER
:
484 case UNW_FLAG_UHANDLER
:
485 case UNW_FLAG_FHANDLER
:
486 fprintf (file
, "\tHandler: %016" PRIx64
".\n",
487 ui
.rva_ExceptionHandler
+ pe_data (abfd
)->pe_opthdr
.ImageBase
);
489 case UNW_FLAG_CHAININFO
:
490 fprintf (file
, "\tChain: start: %016" PRIx64
", end: %016" PRIx64
,
491 ui
.rva_BeginAddress
, ui
.rva_EndAddress
);
492 fprintf (file
, "\n\t unwind data: %016" PRIx64
".\n",
497 /* Now we need end of this xdata block. */
498 addr
+= ui
.SizeOfBlock
;
502 fprintf (file
,"\tUser data:\n");
503 for (i
= 0; addr
< end_addr
; addr
+= 1, i
++)
506 fprintf (file
, "\t %03x:", i
);
507 fprintf (file
, " %02x", xdata
[addr
]);
509 fprintf (file
, "\n");
512 fprintf (file
, "\n");
516 /* Helper function to sort xdata. The entries of xdata are sorted to know
517 the size of each entry. */
520 sort_xdata_arr (const void *l
, const void *r
)
522 const bfd_vma
*lp
= (const bfd_vma
*) l
;
523 const bfd_vma
*rp
= (const bfd_vma
*) r
;
527 return (*lp
< *rp
? -1 : 1);
530 /* Display unwind tables for x86-64. */
533 pex64_bfd_print_pdata_section (bfd
*abfd
, void *vfile
, asection
*pdata_section
)
535 FILE *file
= (FILE *) vfile
;
536 bfd_byte
*pdata
= NULL
;
537 bfd_byte
*xdata
= NULL
;
538 asection
*xdata_section
= NULL
;
541 bfd_size_type datasize
;
543 bfd_vma prev_beginaddress
= (bfd_vma
) -1;
544 bfd_vma prev_unwinddata_rva
= (bfd_vma
) -1;
546 int onaline
= PDATA_ROW_SIZE
;
548 bfd_vma
*xdata_arr
= NULL
;
550 bool virt_size_is_zero
= false;
553 if (pdata_section
== NULL
554 || (pdata_section
->flags
& SEC_HAS_CONTENTS
) == 0
555 || coff_section_data (abfd
, pdata_section
) == NULL
556 || pei_section_data (abfd
, pdata_section
) == NULL
)
559 stop
= pei_section_data (abfd
, pdata_section
)->virt_size
;
560 if ((stop
% onaline
) != 0)
562 /* xgettext:c-format */
563 _("Warning: %s section size (%ld) is not a multiple of %d\n"),
564 pdata_section
->name
, (long) stop
, onaline
);
566 datasize
= pdata_section
->size
;
570 fprintf (file
, _("Warning: %s section size is zero\n"),
571 pdata_section
->name
);
575 /* virt_size might be zero for objects. */
576 if (stop
== 0 && strcmp (abfd
->xvec
->name
, "pe-x86-64") == 0)
579 virt_size_is_zero
= true;
581 else if (datasize
< stop
)
584 /* xgettext:c-format */
585 _("Warning: %s section size (%ld) is smaller than virtual size (%ld)\n"),
586 pdata_section
->name
, (unsigned long) datasize
,
587 (unsigned long) stop
);
588 /* Be sure not to read past datasize. */
592 /* Display functions table. */
594 _("\nThe Function Table (interpreted %s section contents)\n"),
595 pdata_section
->name
);
597 fprintf (file
, _("vma:\t\t\tBeginAddress\t EndAddress\t UnwindData\n"));
599 if (!bfd_malloc_and_get_section (abfd
, pdata_section
, &pdata
))
602 /* Table of xdata entries. */
603 xdata_arr
= (bfd_vma
*) xmalloc (sizeof (bfd_vma
) * ((stop
/ onaline
) + 1));
606 if (strcmp (abfd
->xvec
->name
, "pei-x86-64") == 0)
607 imagebase
= pe_data (abfd
)->pe_opthdr
.ImageBase
;
611 for (i
= 0; i
< stop
; i
+= onaline
)
613 struct pex64_runtime_function rf
;
615 if (i
+ PDATA_ROW_SIZE
> stop
)
618 pex64_get_runtime_function (abfd
, &rf
, &pdata
[i
]);
620 if (rf
.rva_BeginAddress
== 0 && rf
.rva_EndAddress
== 0
621 && rf
.rva_UnwindData
== 0)
622 /* We are probably into the padding of the section now. */
624 fprintf (file
, " %016" PRIx64
, i
+ pdata_section
->vma
);
625 fprintf (file
, ":\t%016" PRIx64
, imagebase
+ rf
.rva_BeginAddress
);
626 fprintf (file
, " %016" PRIx64
, imagebase
+ rf
.rva_EndAddress
);
627 fprintf (file
, " %016" PRIx64
"\n", imagebase
+ rf
.rva_UnwindData
);
628 if (i
!= 0 && rf
.rva_BeginAddress
<= prev_beginaddress
)
631 fprintf (file
, " has %s begin address as predecessor\n",
632 (rf
.rva_BeginAddress
< prev_beginaddress
? "smaller" : "same"));
634 prev_beginaddress
= rf
.rva_BeginAddress
;
635 /* Now we check for negative addresses. */
636 if ((prev_beginaddress
& 0x80000000) != 0)
639 fprintf (file
, " has negative begin address\n");
641 if ((rf
.rva_EndAddress
& 0x80000000) != 0)
644 fprintf (file
, " has negative end address\n");
646 if ((rf
.rva_UnwindData
& 0x80000000) != 0)
649 fprintf (file
, " has negative unwind address\n");
651 else if ((rf
.rva_UnwindData
&& !PEX64_IS_RUNTIME_FUNCTION_CHAINED (&rf
))
652 || virt_size_is_zero
)
653 xdata_arr
[xdata_arr_cnt
++] = rf
.rva_UnwindData
;
659 /* Add end of list marker. */
660 xdata_arr
[xdata_arr_cnt
++] = ~((bfd_vma
) 0);
662 /* Sort start RVAs of xdata. */
663 if (xdata_arr_cnt
> 1)
664 qsort (xdata_arr
, (size_t) xdata_arr_cnt
, sizeof (bfd_vma
),
667 /* Find the section containing the unwind data (.xdata). */
668 xdata_base
= xdata_arr
[0];
669 /* For sections with long names, first look for the same
670 section name, replacing .pdata by .xdata prefix. */
671 if (strcmp (pdata_section
->name
, ".pdata") != 0)
673 size_t len
= strlen (pdata_section
->name
);
674 char *xdata_name
= xmalloc (len
+ 1);
676 xdata_name
= memcpy (xdata_name
, pdata_section
->name
, len
+ 1);
677 /* Transform .pdata prefix into .xdata prefix. */
679 xdata_name
[1] = 'x';
680 xdata_section
= pex64_get_section_by_rva (abfd
, xdata_base
,
684 /* Second, try the .xdata section itself. */
686 xdata_section
= pex64_get_section_by_rva (abfd
, xdata_base
, ".xdata");
687 /* Otherwise, if xdata_base is non zero, search also inside
688 other standard sections. */
689 if (!xdata_section
&& xdata_base
)
690 xdata_section
= pex64_get_section_by_rva (abfd
, xdata_base
, ".rdata");
691 if (!xdata_section
&& xdata_base
)
692 xdata_section
= pex64_get_section_by_rva (abfd
, xdata_base
, ".data");
693 if (!xdata_section
&& xdata_base
)
694 xdata_section
= pex64_get_section_by_rva (abfd
, xdata_base
, ".pdata");
695 if (!xdata_section
&& xdata_base
)
696 xdata_section
= pex64_get_section_by_rva (abfd
, xdata_base
, ".text");
697 /* Transfer xdata section into xdata array. */
699 || (xdata_section
->flags
& SEC_HAS_CONTENTS
) == 0
700 || !bfd_malloc_and_get_section (abfd
, xdata_section
, &xdata
))
703 /* Avoid "also used "... ouput for single unwind info
705 prev_unwinddata_rva
= (bfd_vma
) -1;
707 /* Do dump of pdata related xdata. */
708 for (i
= 0; i
< stop
; i
+= onaline
)
710 struct pex64_runtime_function rf
;
712 if (i
+ PDATA_ROW_SIZE
> stop
)
715 pex64_get_runtime_function (abfd
, &rf
, &pdata
[i
]);
717 if (rf
.rva_BeginAddress
== 0 && rf
.rva_EndAddress
== 0
718 && rf
.rva_UnwindData
== 0)
719 /* We are probably into the padding of the section now. */
722 fprintf (file
, _("\nDump of %s\n"), xdata_section
->name
);
724 fprintf (file
, " %016" PRIx64
, rf
.rva_UnwindData
+ imagebase
);
726 if (prev_unwinddata_rva
== rf
.rva_UnwindData
)
728 /* Do not dump again the xdata for the same entry. */
729 fprintf (file
, " also used for function at %016" PRIx64
"\n",
730 rf
.rva_BeginAddress
+ imagebase
);
734 prev_unwinddata_rva
= rf
.rva_UnwindData
;
736 fprintf (file
, " (rva: %08x): %016" PRIx64
" - %016" PRIx64
"\n",
737 (unsigned int) rf
.rva_UnwindData
,
738 rf
.rva_BeginAddress
+ imagebase
,
739 rf
.rva_EndAddress
+ imagebase
);
741 if (rf
.rva_UnwindData
!= 0 || virt_size_is_zero
)
743 if (PEX64_IS_RUNTIME_FUNCTION_CHAINED (&rf
))
745 bfd_vma altent
= PEX64_GET_UNWINDDATA_UNIFIED_RVA (&rf
);
746 bfd_vma pdata_vma
= bfd_section_vma (pdata_section
);
747 struct pex64_runtime_function arf
;
749 fprintf (file
, "\t shares information with ");
752 if (altent
>= pdata_vma
753 && altent
- pdata_vma
+ PDATA_ROW_SIZE
<= stop
)
755 pex64_get_runtime_function
756 (abfd
, &arf
, &pdata
[altent
- pdata_vma
]);
757 fprintf (file
, "pdata element at 0x%016" PRIx64
,
761 fprintf (file
, "unknown pdata element");
762 fprintf (file
, ".\n");
768 /* Search for the current entry in the sorted array. */
770 bsearch (&rf
.rva_UnwindData
, xdata_arr
,
771 (size_t) xdata_arr_cnt
, sizeof (bfd_vma
),
774 /* Advance to the next pointer into the xdata section. We may
775 have shared xdata entries, which will result in a string of
776 identical pointers in the array; advance past all of them. */
777 while (p
[0] <= rf
.rva_UnwindData
)
780 if (p
[0] == ~((bfd_vma
) 0))
783 pex64_dump_xdata (file
, abfd
, xdata_section
, xdata
, p
, &rf
);
799 /* Number of found pdata sections. */
800 unsigned int pdata_count
;
803 /* Functionn prototype. */
804 bool pex64_bfd_print_pdata (bfd
*, void *);
806 /* Helper function for bfd_map_over_section. */
808 pex64_print_all_pdata_sections (bfd
*abfd
, asection
*pdata
, void *arg
)
810 struct pex64_paps
*paps
= arg
;
811 if (startswith (pdata
->name
, ".pdata"))
813 if (pex64_bfd_print_pdata_section (abfd
, paps
->obj
, pdata
))
819 pex64_bfd_print_pdata (bfd
*abfd
, void *vfile
)
821 asection
*pdata_section
= bfd_get_section_by_name (abfd
, ".pdata");
822 struct pex64_paps paps
;
825 return pex64_bfd_print_pdata_section (abfd
, vfile
, pdata_section
);
828 paps
.pdata_count
= 0;
829 bfd_map_over_sections (abfd
, pex64_print_all_pdata_sections
, &paps
);
830 return paps
.pdata_count
!= 0;
833 #define bfd_pe_print_pdata pex64_bfd_print_pdata
834 #define bfd_coff_std_swap_table bfd_coff_pei_swap_table
836 #include "coff-x86_64.c"