This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
Re: RFC: Dumping of .pdata/.xdata for x64 PE+
2009/4/16 H.J. Lu <hjl.tools@gmail.com>:
> On Thu, Apr 16, 2009 at 10:04 AM, Kai Tietz <ktietz70@googlemail.com> wrote:
>> 2009/4/16 H.J. Lu <hjl.tools@gmail.com>:
>>> On Thu, Apr 16, 2009 at 9:41 AM, Kai Tietz <ktietz70@googlemail.com> wrote:
>>>> 2009/4/16 Dave Korn <dave.korn.cygwin@googlemail.com>:
>>>>> Kai Tietz wrote:
>>>>>> 2009/4/16 Dave Korn <dave.korn.cygwin@googlemail.com>:
>>>>>
>>>>>>> ?Although it's not used a lot, there is at least precedent (bfd/pe-mips.c)
>>>>>>> for putting such format-and-arch specific functions into the master back-end
>>>>>>> file. ?How would you feel about putting this function into bfd/pei-x86_64.c?
>>>>>>
>>>>>> Well, in general the implementation could be in pei-x86_64.c file. I
>>>>>> am just not sure if the EFI versions possible want to use this, too.
>>>>>> If so, it has to be at in common file.
>>>>>
>>>>> ?Hey, you should talk to HJ; he's planning to refactor EFI to use PEI
>>>>> vectors[*]. ?Yes, if this function can be used directly (or more-or-less)
>>>>> directly for EFI formats too, then it should have an XX in the name and go
>>>>> into peXXigen.c, that would be fine.
>>>>>
>>>>>>> Index: src/bfd/pei-x86_64.c
>>>>>>> ===================================================================
>>>>>>> --- src.orig/bfd/pei-x86_64.c
>>>>>>> +++ src/bfd/pei-x86_64.c
>>>>>>> @@ -25,9 +25,9 @@
>>>>>>>
>>>>>>> ?#define TARGET_SYM ? ? ? ? ? ? x86_64pei_vec
>>>>>>> ?#define TARGET_NAME ? ? ? ? ? ?"pei-x86-64"
>>>>>>> -#define COFF_IMAGE_WITH_PE
>>>>>>> ?#define COFF_WITH_PE
>>>>>>> ?#define COFF_WITH_pex64
>>>>>>> +#define COFF_IMAGE_WITH_PE
>>>>>>> ?#define PCRELOFFSET ? ? ? ? ? ?TRUE
>>>>>>>
>>>>>>> ?That change is not really necessary :)
>>>>>> Ups, I missed to update the patch. Of course it is not necessary ;)
>>>>>> Instead the macro #define bfd_pe_print_pdata ? _bfd_pex64_print_pdata
>>>>>> has to be added.
>>>>>
>>>>> ?Sorry, I trimmed that bit; it was present in your patch but I had no comment
>>>>> to make about it since it is obviously correct!
>>>>>
>>>>>> I meant the flag value in UNWIND_INFO. It appears to exists value 3
>>>>>> for it (UNW_FLAG_EHANDLER|UNW_FLAG_UHANDLER). And the corresponding
>>>>>> data (after the array of unwind codes) is different. It contains a
>>>>>> frame pointer (relative to frame offset+frameRegister) AFAIU. I was
>>>>>> asking if somebody has an idea what the pointer points to on stack. I
>>>>>> assume it is an object pointer, or the establisher frame itself.
>>>>>
>>>>> ?Ah, so in terms of the description at
>>>>> http://msdn.microsoft.com/en-us/library/ddssxxy8(VS.80).aspx:
>>>>>
>>>>> ---------------------------------<snip>---------------------------------
>>>>> (1) Exception Handler
>>>>>
>>>>> ULONG ? ? ? ? ? Address of exception handler
>>>>> variable ? ? ? ?Language-specific handler data (optional)
>>>>>
>>>>> ?Address of exception handler
>>>>>
>>>>> ? ?This is an image-relative pointer to either the function's
>>>>> language-specific exception/termination handler (if flag UNW_FLAG_CHAININFO is
>>>>> clear and one of the flags UNW_FLAG_EHANDLER or UNW_FLAG_UHANDLER is set).
>>>>>
>>>>> Language-specific handler data
>>>>>
>>>>> ? ?This is the function's language-specific exception handler data. The
>>>>> format of this data is unspecified and completely determined by the specific
>>>>> exception handler in use.
>>>>> ---------------------------------<snip>---------------------------------
>>>>>
>>>>> ... you've got the function pointer OK, and you want to know about the
>>>>> language-specific data? ?I would imagine that the establisher frame is
>>>>> computed by the unwinder using the prolog unwind codes, and so does not need
>>>>> to be present in the language-specific data; the most obvious thing I can
>>>>> think of is that this language-specific data ought to in some fashion point to
>>>>> some information that tells what kind of exceptions to catch, e.g. in C++,
>>>>> where the runtime is using SEH to catch C++ exception types, I would suppose
>>>>> the exception handler pointer points to a function in MSVC that's the
>>>>> modern-day equivalent of except_handler3, and the language-specific data would
>>>>> point in some fashion to a list of the exception types for which catch(){...}
>>>>> blocks exist. ?I imagine we'll have to do some fancy reverse engineering to
>>>>> figure it all out.
>>>>>
>>>>> ? ?cheers,
>>>>> ? ? ?DaveK
>>>>> --
>>>>> [*] - http://sourceware.org/ml/binutils/2009-04/msg00230.html
>>>>>
>>>>
>>>> Hello HJ,
>>>>
>>>> as I read that you want to refactor EFI to use PEI. What is your
>>>> opinion about the place for the xdata dumping for x64?
>>>>
>>>
>>> Can you put it in pei-x86_64.c?
>>>
>>> --
>>> H.J.
>>>
>>
>> Ok, put the complete code from peXXigen.c into pei-x86_64.c and make it static.
>>
>> Is this ok for you and the refactoring?
>>
>
> That is fine with me.
>
> Thanks.
>
>
> --
> H.J.
>
Ok, here is the patch
ChangeLog
2009-04-16 Kai Tietz <kai.tietz@onevision.com>
* coff-x86_64.c (PEI_HEADERS): Protect includes.
(PE): Remove macro name checks.
* pei-x86_64.c (PEI_HEADERS): Define to prevent double
include in coff-x86_64.c of headers.
(pex_regs): New static variable.
(pep_xdata_print_uwd_codes): New static function.
(pep_get_section_by_rva): Likewise.
(pep_dump_xdata):
(_xx_bfd_print_pdata): Likewise.
(bfd_pe_print_pdata): Define as _xx_bfd_print_pdata.
* peXXigen.c (_bfd_pex64_print_pdata): Removed implementation.
* libpei.h (_bfd_pex64_print_pdata): : Removed declaration.
Tested for x86_64-pc-mingw32 target. Is this patch ok to apply?
Cheers,
Kai
--
| (\_/) This is Bunny. Copy and paste
| (='.'=) Bunny into your signature to help
| (")_(") him gain world domination
Index: src/bfd/coff-x86_64.c
===================================================================
--- src.orig/bfd/coff-x86_64.c
+++ src/bfd/coff-x86_64.c
@@ -24,6 +24,10 @@
#define COFF_WITH_pex64
#endif
+/* Note we have to make sure not all headers are protected
+ by closurs, so we check define PEI_HEADERS to prevent
+ double including in pei-x86_64.c. */
+#ifndef PEI_HEADERS
#include "sysdep.h"
#include "bfd.h"
#include "libbfd.h"
@@ -32,6 +36,7 @@
#include "coff/pe.h"
#include "libcoff.h"
#include "libiberty.h"
+#endif
#define BADMAG(x) AMD64BADMAG(x)
@@ -711,14 +716,9 @@ coff_amd64_is_local_label_name (bfd *abf
#endif /* TARGET_UNDERSCORE */
-#ifdef PE
-#undef bfd_pe_print_pdata
-#define bfd_pe_print_pdata _bfd_pex64_print_pdata
-#else /* PE */
#ifndef bfd_pe_print_pdata
#define bfd_pe_print_pdata NULL
#endif
-#endif /* PE */
#include "coffcode.h"
Index: src/bfd/peXXigen.c
===================================================================
--- src.orig/bfd/peXXigen.c
+++ src/bfd/peXXigen.c
@@ -1895,87 +1895,6 @@ _bfd_XX_print_ce_compressed_pdata (bfd *
#undef PDATA_ROW_SIZE
}
-#ifdef COFF_WITH_pex64
-/* The PE+ x64 variant. */
-bfd_boolean
-_bfd_pex64_print_pdata (bfd *abfd, void *vfile)
-{
-# define PDATA_ROW_SIZE (3 * 4)
- FILE *file = (FILE *) vfile;
- bfd_byte *data = NULL;
- asection *section = bfd_get_section_by_name (abfd, ".pdata");
- bfd_size_type datasize = 0;
- bfd_size_type i;
- bfd_size_type start, stop;
- int onaline = PDATA_ROW_SIZE;
- struct sym_cache sym_cache = {0, 0};
-
- if (section == NULL
- || coff_section_data (abfd, section) == NULL
- || pei_section_data (abfd, section) == NULL)
- return TRUE;
-
- stop = pei_section_data (abfd, section)->virt_size;
- if ((stop % onaline) != 0)
- fprintf (file,
- _("warning: .pdata section size (%ld) is not a multiple of %d\n"),
- (long) stop, onaline);
-
- fprintf (file,
- _("\nThe Function Table (interpreted .pdata section contents)\n"));
-
- fprintf (file, _("vma:\t\t\tBeginAddress\t EndAddress\t UnwindData\n"));
-
- datasize = section->size;
- if (datasize == 0)
- return TRUE;
-
- if (!bfd_malloc_and_get_section (abfd, section, &data))
- {
- if (data != NULL)
- free (data);
- return FALSE;
- }
-
- start = 0;
-
- for (i = start; i < stop; i += onaline)
- {
- bfd_vma begin_addr;
- bfd_vma end_addr;
- bfd_vma unwind_data_addr;
-
- if (i + PDATA_ROW_SIZE > stop)
- break;
-
- begin_addr = bfd_get_32 (abfd, data + i);
- end_addr = bfd_get_32 (abfd, data + i + 4);
- unwind_data_addr = bfd_get_32 (abfd, data + i + 8);
-
- if (begin_addr == 0 && end_addr == 0 && unwind_data_addr == 0)
- /* We are probably into the padding of the section now. */
- break;
-
- fputc (' ', file);
- fprintf_vma (file, i + section->vma);
- fprintf (file, ":\t");
- fprintf_vma (file, begin_addr);
- fputc (' ', file);
- fprintf_vma (file, end_addr);
- fputc (' ', file);
- fprintf_vma (file, unwind_data_addr);
-
- fprintf (file, "\n");
- }
-
- free (data);
-
- cleanup_syms (&sym_cache);
-
- return TRUE;
-#undef PDATA_ROW_SIZE
-}
-#endif
#define IMAGE_REL_BASED_HIGHADJ 4
static const char * const tbl[] =
Index: src/bfd/pei-x86_64.c
===================================================================
--- src.orig/bfd/pei-x86_64.c
+++ src/bfd/pei-x86_64.c
@@ -25,9 +25,9 @@
#define TARGET_SYM x86_64pei_vec
#define TARGET_NAME "pei-x86-64"
-#define COFF_IMAGE_WITH_PE
#define COFF_WITH_PE
#define COFF_WITH_pex64
+#define COFF_IMAGE_WITH_PE
#define PCRELOFFSET TRUE
#define TARGET_UNDERSCORE '_'
/* Long section names not allowed in executable images, only object files. */
@@ -53,4 +53,434 @@
{ COFF_SECTION_NAME_PARTIAL_MATCH (".gnu.linkonce.wi."), \
COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 0 }
+/* Note we have to make sure not all headers are
+ protected by closurs, so define PEI_HEADERS to
+ prevent double including in coff-x86_64.c */
+#define PEI_HEADERS
+#include "sysdep.h"
+#include "bfd.h"
+#include "libbfd.h"
+#include "coff/x86_64.h"
+#include "coff/internal.h"
+#include "coff/pe.h"
+#include "libcoff.h"
+#include "libpei.h"
+#include "libiberty.h"
+
+#undef AOUTSZ
+#define AOUTSZ PEPAOUTSZ
+#define PEAOUTHDR PEPAOUTHDR
+
+static const char *pex_regs[16] = {
+ "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi",
+ "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"
+};
+
+static void
+pep_xdata_print_uwd_codes(bfd_byte *dta, bfd_vma count, FILE *file, bfd_vma pc_addr)
+{
+ bfd_vma i;
+ bfd_vma tmp = 0;
+ bfd_byte *insns[256];
+ bfd_vma insns_count = 0;
+
+ if (!count || !dta)
+ return;
+ /* Sort array ascending. Note: it is stored in reveresed order. */
+ for (i = 0; i < count; i++)
+ {
+ bfd_byte *t;
+
+ t = insns[insns_count++] = &dta[i * 2];
+ switch (t[1] & 0xf)
+ {
+ case 0: case 2:
+ case 3: case 10:
+ break;
+ case 1:
+ if (((t[1]>>4)&0xf)==0)
+ {
+ i += 1;
+ break;
+ }
+ else if (((t[1]>>4)&0xf)==1)
+ {
+ i += 2;
+ break;
+ }
+ /* fall through. */
+ default:
+ fprintf (file, "\t contains unknown code (%u).\n", (unsigned int) (t[1]&0xf));
+ return;
+ case 4: case 6: case 8:
+ i++;
+ break;
+ case 5: case 7: case 9:
+ i += 2;
+ break;
+ }
+ }
+ fprintf (file, "\t At pc 0x");
+ fprintf_vma (file, pc_addr);
+ fprintf (file, " there are the following saves (in logical order).\n");
+ for (i = insns_count; i > 0;)
+ {
+ --i;
+ dta = insns[i];
+ fprintf (file, "\t insn ends at pc+0x%02x: ", (unsigned int) dta[0]);
+ switch (dta[1]&0xf) {
+ case 0: /* UWOP_PUSH_NONVOL. */
+ fprintf (file, "push %s.\n", pex_regs[((dta[1]>>4)&0xf)]);
+ break;
+ case 1: /* UWOP_ALLOC_LARGE. */
+ if (((dta[1]>>4)&0xf) == 0)
+ tmp = (bfd_vma) (*((unsigned short *)&dta[2]));
+ else
+ tmp = (bfd_vma) (*((unsigned int *)&dta[2]));
+ tmp *= 8;
+ fprintf (file, "save stack region of size 0x");
+ fprintf_vma (file, tmp);
+ fprintf (file,".\n");
+ break;
+ case 2: /* UWOP_ALLOC_SMALL. */
+ tmp = (bfd_vma) ((dta[1]>>4)&0xf);
+ tmp += 1;
+ tmp *= 8;
+ fprintf (file, "save stack region of size 0x");
+ fprintf_vma (file, tmp);
+ fprintf (file,".\n");
+ break;
+ case 3: /* UWOP_SET_FPREG. */
+ tmp = (bfd_vma) ((dta[1]>>4)&0xf);
+ tmp *= 16;
+ fprintf (file, "FPReg = (FrameReg) + 0x");
+ fprintf_vma (file, tmp);
+ fprintf (file, ".\n");
+ break;
+ case 4: /* UWOP_SAVE_NONVOL. */
+ fprintf (file, "mov %s at 0x", pex_regs[((dta[1]>>4)&0xf)]);
+ tmp = (bfd_vma) (*((unsigned short *) &dta[2]));
+ tmp *= 8;
+ fprintf_vma (file, tmp);
+ fprintf (file, ".\n");
+ break;
+ case 5: /* UWOP_SAVE_NONVOL_FAR. */
+ fprintf (file, "mov %s at 0x", pex_regs[((dta[1]>>4)&0xf)]);
+ tmp = (bfd_vma) (*((unsigned int *) &dta[2]));
+ fprintf_vma (file, tmp);
+ fprintf (file, ".\n");
+ break;
+ case 6: /* UWOP_SAVE_XMM. */
+ tmp = (bfd_vma) (*((unsigned short *) &dta[2]));
+ tmp *= 8;
+ fprintf (file, "mov mm%u at 0x", (unsigned int)((dta[1]>>4)&0xf));
+ fprintf_vma (file, tmp);
+ fprintf (file, ".\n");
+ break;
+ case 7: /* UWOP_SAVE_XMM_FAR. */
+ tmp = (bfd_vma) (*((unsigned int *) &dta[2]));
+ fprintf (file, "mov mm%u at 0x", (unsigned int)((dta[1]>>4)&0xf));
+ fprintf_vma (file, tmp);
+ fprintf (file, ".\n");
+ break;
+ case 8: /* UWOP_SAVE_XMM128. */
+ tmp = (bfd_vma) (*((unsigned short *) &dta[2]));
+ tmp *= 16;
+ fprintf (file, "mov xmm%u at 0x", (unsigned int)((dta[1]>>4)&0xf));
+ fprintf_vma (file, tmp);
+ fprintf (file, ".\n");
+ break;
+ case 9: /* UWOP_SAVE_XMM128_FAR. */
+ tmp = (bfd_vma) (*((unsigned int *) &dta[2]));
+ fprintf (file, "mov xmm%u at 0x", (unsigned int)((dta[1]>>4)&0xf));
+ fprintf_vma (file, tmp);
+ fprintf (file, ".\n");
+ break;
+ case 10: /* UWOP_PUSH_MACHFRAME. */
+ fprintf (file, "interrupt entry (SS, old RSP, EFLAGS, CS, RIP");
+ if (((dta[1]>>4)&0xf) == 0)
+ {
+ fprintf (file, ")");
+ }
+ else if (((dta[1]>>4)&0xf) == 1)
+ {
+ fprintf (file, ",ErrorCode)");
+ }
+ else
+ {
+ fprintf (file, ", unknown(%u))", ((dta[1]>>4)&0xf));
+ }
+ fprintf (file,".\n");
+ break;
+ default:
+ fprintf (file, "unknown code %u.\n", (unsigned int) (dta[1]&0xf));
+ break;
+ }
+ }
+}
+
+static asection *
+pep_get_section_by_rva (bfd *abfd, bfd_vma addr, const char *sec_name)
+{
+ asection *section = bfd_get_section_by_name (abfd, sec_name);
+ bfd_vma vsize;
+ bfd_size_type datasize = 0;
+
+ if (section == NULL
+ || coff_section_data (abfd, section) == NULL
+ || pei_section_data (abfd, section) == NULL)
+ return NULL;
+ vsize = section->vma - pe_data (abfd)->pe_opthdr.ImageBase;
+ datasize = section->size;
+ if (!datasize || vsize > addr || (vsize + datasize) < addr)
+ return NULL;
+ return section;
+}
+
+static void
+pep_dump_xdata (FILE *file, bfd *abfd, bfd_vma addr, bfd_vma pc_addr)
+{
+ asection *section = pep_get_section_by_rva (abfd, addr, ".rdata");
+ bfd_vma vsize;
+ bfd_byte *data = NULL;
+
+ if (!section)
+ section = pep_get_section_by_rva (abfd, addr, ".data");
+ if (!section)
+ section = pep_get_section_by_rva (abfd, addr, ".xdata");
+ if (!section)
+ {
+ section = pep_get_section_by_rva (abfd, addr, ".pdata");
+ if (section)
+ {
+ addr &= ~1;
+ fprintf (file, "\t Shares information with pdata element at 0x");
+ fprintf_vma (file, addr + pe_data (abfd)->pe_opthdr.ImageBase);
+ fprintf (file, ".\n");
+ }
+ return;
+ }
+ vsize = section->vma - pe_data (abfd)->pe_opthdr.ImageBase;
+ addr -= vsize;
+ if (bfd_malloc_and_get_section (abfd, section, &data))
+ {
+ bfd_vma version;
+ bfd_vma flags;
+ bfd_vma sizeof_prologue;
+ bfd_vma count_of_codes;
+ bfd_vma frame_register;
+ bfd_vma frame_offset;
+
+ /* Array of UNWIND_CODE with count_of_codes elements. This
+ this structure has byte size and the following definition:
+ UBYTE CodeOffset;
+ UBYTE UnwindOperationCode : 4;
+ UBYTE OperationInfo : 4;
+ */
+ bfd_byte *unwind_code;
+ /* if flag has bit 0 set, there is an exception hander. */
+ bfd_vma exception_handler = 0;
+ /* if flag has bit 2 set, there is a function entry present. */
+ bfd_vma function_entry = 0;
+ /* if flag has bit 0 set, there is an additionally exception data present. */
+
+ if (!data) return;
+ version = (bfd_vma) data[addr];
+ flags = (version >> 3) & 0x1f;
+ version &= 3;
+ sizeof_prologue = (bfd_vma) data[addr + 1];
+ count_of_codes = (bfd_vma) data[addr + 2];
+ frame_register = (bfd_vma) data[addr + 3];
+ frame_offset = (frame_register >> 4) & 0xf;
+ frame_register &= 0xf;
+ addr += 4;
+ unwind_code = &data[addr];
+ addr += ((count_of_codes + 1) & ~1) * 2;
+
+ if (version != 1)
+ fprintf (file, "\tVersion %u (unknown).\n", (unsigned int) version);
+ fprintf (file, "\tFlags: ");
+ switch ((flags & 0x1f))
+ {
+ case 0:
+ fprintf (file, "none");
+ break;
+ case 1:
+ fprintf (file, "UNW_FLAG_EHANDLER");
+ break;
+ case 2:
+ fprintf (file, "UNW_FLAG_UHANDLER");
+ break;
+ case 3:
+ fprintf (file, "UNW_FLAG_EHANDLER | UNW_FLAG_UHANDLER");
+ break;
+ case 4:
+ fprintf (file, "UNW_FLAG_CHAININFO");
+ break;
+ default:
+ fprintf (file, "unknown flags 0x%x", (unsigned int) flags);
+ break;
+ }
+ fprintf (file, ".\n");
+ if (count_of_codes != 0)
+ fprintf (file, "\tEntry has %u codes.", (unsigned int) count_of_codes);
+ fprintf (file, "\tPrologue size: %u, Frame offset = 0x%x.\n",
+ (unsigned int) sizeof_prologue, (unsigned int) frame_offset);
+ fprintf (file, "\tFrame register is %s.\n",
+ frame_register == 0 ? "CFA" : pex_regs[(unsigned int) frame_register]);
+
+ pep_xdata_print_uwd_codes (unwind_code, count_of_codes, file, pc_addr);
+
+ if ((flags & 1) != 0)
+ {
+ exception_handler = bfd_get_32 (abfd, data + addr);
+ addr += 4;
+ }
+ else if ((flags & 2) != 0)
+ {
+ exception_handler = bfd_get_32 (abfd, data + addr);
+ addr += 4;
+ }
+ else if ((flags & 4) != 0)
+ {
+ function_entry = bfd_get_32 (abfd, data + addr);
+ addr += 4; /* RUNTIME_FUNCTION * */
+ }
+ if ((flags & 3) == 3)
+ {
+ fprintf (file, "\t Argument at Framebase + 0x%x",
+ (unsigned int) bfd_get_32 (abfd, data + addr));
+ if (bfd_get_32 (abfd, data + addr + 4) != 0
+ || bfd_get_32 (abfd, data + addr + 8) != 0)
+ fprintf (file, " and unknown data 0x%x, 0x%x",
+ (unsigned int) bfd_get_32 (abfd, data + addr + 4),
+ (unsigned int) bfd_get_32 (abfd, data + addr + 8));
+ fprintf (file, ".\n");
+ addr += 12; /* RUNTIME_FUNCTION */
+ }
+
+ if ((flags & 3) == 1)
+ fprintf (file, "\texception_handler at 0x%x.\n", (unsigned int) exception_handler);
+ else if ((flags & 4) != 0)
+ fprintf (file, "\tFunction Entry: 0x%x\n", (unsigned int) function_entry);
+ if ((flags & 2) != 0)
+ {
+ fprintf (file, "\texception_handler/terminate at 0x%x.\n", (unsigned int) exception_handler);
+ }
+ if ((flags & 3) == 1 || (flags & 3) == 2)
+ {
+ bfd_vma i;
+ bfd_vma count = bfd_get_32 (abfd, data + addr);
+ addr += 4;
+ fprintf (file, "\t 0x%x # of scope(s)\n", (unsigned int) count);
+ for (i = 0; i < count && i < 255; i++)
+ {
+ fprintf (file, "\t scope #%u: BeginAddress: 0x%x, EndAddress: 0x%x,\n"
+ "\t\tHandlerAddress:0x%x, JumpTarget:0x%x\n",(unsigned int) (i+1),
+ (unsigned int) bfd_get_32 (abfd, data + addr),
+ (unsigned int) bfd_get_32 (abfd, data + addr + 4),
+ (unsigned int) bfd_get_32 (abfd, data + addr + 8),
+ (unsigned int) bfd_get_32 (abfd, data + addr + 12));
+ addr += 16;
+ }
+ if (i < count)
+ fprintf (file, "\t ...\n");
+ }
+ }
+ if (data != NULL)
+ free (data);
+}
+
+static bfd_boolean
+_xx_bfd_print_pdata (bfd *abfd, void *vfile)
+{
+# define PDATA_ROW_SIZE (3 * 4)
+ FILE *file = (FILE *) vfile;
+ bfd_byte *data = NULL;
+ asection *section = bfd_get_section_by_name (abfd, ".pdata");
+ bfd_size_type datasize = 0;
+ bfd_size_type i;
+ bfd_size_type start, stop;
+ int onaline = PDATA_ROW_SIZE;
+
+ if (section == NULL
+ || coff_section_data (abfd, section) == NULL
+ || pei_section_data (abfd, section) == NULL)
+ return TRUE;
+
+ stop = pei_section_data (abfd, section)->virt_size;
+ if ((stop % onaline) != 0)
+ fprintf (file,
+ _("warning: .pdata section size (%ld) is not a multiple of %d\n"),
+ (long) stop, onaline);
+
+ fprintf (file,
+ _("\nThe Function Table (interpreted .pdata section contents)\n"));
+
+ fprintf (file, _("vma:\t\t\tBeginAddress\t EndAddress\t UnwindData\n"));
+
+ datasize = section->size;
+ if (datasize == 0)
+ return TRUE;
+
+ if (!bfd_malloc_and_get_section (abfd, section, &data))
+ {
+ if (data != NULL)
+ free (data);
+ return FALSE;
+ }
+
+ start = 0;
+
+ for (i = start; i < stop; i += onaline)
+ {
+ bfd_vma begin_addr;
+ bfd_vma end_addr;
+ bfd_vma unwind_data_addr;
+
+ if (i + PDATA_ROW_SIZE > stop)
+ break;
+
+ begin_addr = bfd_get_32 (abfd, data + i);
+ end_addr = bfd_get_32 (abfd, data + i + 4);
+ unwind_data_addr = bfd_get_32 (abfd, data + i + 8);
+
+ if (begin_addr == 0 && end_addr == 0 && unwind_data_addr == 0)
+ /* We are probably into the padding of the section now. */
+ break;
+
+ fputc (' ', file);
+ fprintf_vma (file, i + section->vma);
+ fprintf (file, ":\t");
+ begin_addr += pe_data (abfd)->pe_opthdr.ImageBase;
+ fprintf_vma (file, begin_addr);
+ fputc (' ', file);
+ end_addr += pe_data (abfd)->pe_opthdr.ImageBase;
+ fprintf_vma (file, end_addr);
+ fputc (' ', file);
+ fprintf_vma (file, unwind_data_addr);
+ fprintf (file, "\n");
+
+ if (unwind_data_addr != 0)
+ {
+ if ((unwind_data_addr & 1) != 0)
+ {
+ unwind_data_addr &= ~1;
+ fprintf (file, "\t shares information with pdata element at 0x");
+ fprintf_vma (file, unwind_data_addr + pe_data (abfd)->pe_opthdr.ImageBase);
+ fprintf (file, ".\n");
+ }
+ else
+ pep_dump_xdata (file, abfd, unwind_data_addr, begin_addr);
+ }
+ }
+
+ free (data);
+
+ return TRUE;
+#undef PDATA_ROW_SIZE
+}
+
+#define bfd_pe_print_pdata _xx_bfd_print_pdata
+
#include "coff-x86_64.c"
Index: src/bfd/libpei.h
===================================================================
--- src.orig/bfd/libpei.h
+++ src/bfd/libpei.h
@@ -394,4 +394,3 @@ bfd_boolean _bfd_pe64_print_ce_compresse
bfd_boolean _bfd_pex64_print_ce_compressed_pdata (bfd *, void *);
bfd_boolean _bfd_pep_print_ce_compressed_pdata (bfd *, void *);
-bfd_boolean _bfd_pex64_print_pdata (bfd *, void *);