From: Pierre Muller Date: Wed, 24 Dec 2014 10:06:57 +0000 (+0000) Subject: This patch adds support for printing out the pdata section of PE objects. X-Git-Tag: gdb-7.9.0-release~232 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=854399ea9d0d5d5c14b4035bbc0adfe891f26a3d;p=external%2Fbinutils.git This patch adds support for printing out the pdata section of PE objects. * pe-x86_64.c (pex64_bfd_print_pdata): Add external declaration. (bfd_pe_print_data): Set macro to pex64_bfd_print_data. * pei-x86_64.c (pex64_bfd_print_pdata): Changed to global function. Now handles multiple .pdata sections. (pex_bfd_print_pdata_section): New static helper function, using most of old pex_bfd_print_pdata function code, but adding support for coff pe objects, which might have some fields starting at zero offset. (pex64_print_all_pdata_sections) : New static helper function, used in call to bfd_map_over_sections inside new pex66_bfd_print_pdata function. (bfd_boolean pdata_count): New static variable, used to return bfd_boolean value for pex64_bfd_print_pdata function. --- diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 7b0ad1d..af3fe44 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,21 @@ +2014-12-24 Pierre Muller + + Add support for pdata output for pe coff objects. + * pe-x86_64.c (pex64_bfd_print_pdata): Add external + declaration. + (bfd_pe_print_data): Set macro to pex64_bfd_print_data. + * pei-x86_64.c (pex64_bfd_print_pdata): Changed to + global function. Now handles multiple .pdata sections. + (pex_bfd_print_pdata_section): New static helper function, + using most of old pex_bfd_print_pdata function code, but adding + support for coff pe objects, which might have some fields + starting at zero offset. + (pex64_print_all_pdata_sections) : New static helper function, + used in call to bfd_map_over_sections inside new + pex66_bfd_print_pdata function. + (bfd_boolean pdata_count): New static variable, used to return + bfd_boolean value for pex64_bfd_print_pdata function. + 2014-12-24 Alan Modra * linker.c (_bfd_generic_link_output_symbols): Remove BSF_WEAK diff --git a/bfd/pe-x86_64.c b/bfd/pe-x86_64.c index 673a544..adaefb7 100644 --- a/bfd/pe-x86_64.c +++ b/bfd/pe-x86_64.c @@ -58,6 +58,12 @@ { COFF_SECTION_NAME_PARTIAL_MATCH (".gnu.linkonce.wi."), \ COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 0 } +/* The function pex64_bfd_print_pdata is implemented in pei-x86_64.c + source, but has be extended to also handle pe objects. */ +extern bfd_boolean pex64_bfd_print_pdata (bfd *, void *); + +#define bfd_pe_print_pdata pex64_bfd_print_pdata + #include "coff-x86_64.c" /* Entry for big object files. */ diff --git a/bfd/pei-x86_64.c b/bfd/pei-x86_64.c index ccb5774..16d8899 100644 --- a/bfd/pei-x86_64.c +++ b/bfd/pei-x86_64.c @@ -115,6 +115,7 @@ pex64_get_unwind_info (bfd *abfd, struct pex64_unwind_info *ui, void *data) ui->sizeofUnwindCodes = PEX64_UWI_SIZEOF_UWCODE_ARRAY (ui->CountOfCodes); ui->SizeOfBlock = ui->sizeofUnwindCodes + 4; ui->rawUnwindCodes = &ex_dta[4]; + ex_dta += ui->SizeOfBlock; switch (ui->Flags) { @@ -396,7 +397,7 @@ pex64_dump_xdata (FILE *file, bfd *abfd, : pex_regs[(unsigned int) ui.FrameRegister]); /* PR 17512: file: 2245-7442-0.004. */ - if (ui.CountOfCodes * 2 + ui.rawUnwindCodes + addr >= xdata + xdata_section->size) + if (ui.CountOfCodes * 2 + ui.rawUnwindCodes > xdata + xdata_section->size) fprintf (file, _("Too many unwind codes (%ld)\n"), (long) ui.CountOfCodes); else pex64_xdata_print_uwd_codes (file, abfd, &ui, rf); @@ -458,23 +459,24 @@ sort_xdata_arr (const void *l, const void *r) /* Display unwind tables for x86-64. */ static bfd_boolean -pex64_bfd_print_pdata (bfd *abfd, void *vfile) +pex64_bfd_print_pdata_section (bfd *abfd, void *vfile, asection *pdata_section) { FILE *file = (FILE *) vfile; bfd_byte *pdata = NULL; bfd_byte *xdata = NULL; - asection *pdata_section = bfd_get_section_by_name (abfd, ".pdata"); - asection *xdata_section; + asection *xdata_section = NULL; bfd_vma xdata_base; bfd_size_type i; + bfd_size_type datasize; bfd_size_type stop; - bfd_vma prev_beginaddress = 0; - bfd_vma prev_unwinddata_rva = 0; + bfd_vma prev_beginaddress = (bfd_vma) -1; + bfd_vma prev_unwinddata_rva = (bfd_vma) -1; bfd_vma imagebase; int onaline = PDATA_ROW_SIZE; int seen_error = 0; bfd_vma *xdata_arr = NULL; int xdata_arr_cnt; + bfd_boolean virt_size_is_zero = FALSE; /* Sanity checks. */ if (pdata_section == NULL @@ -483,20 +485,39 @@ pex64_bfd_print_pdata (bfd *abfd, void *vfile) return TRUE; stop = pei_section_data (abfd, pdata_section)->virt_size; - /* PR 17512: file: 005-181405-0.004. */ - if (stop == 0 || pdata_section->size == 0) + if ((stop % onaline) != 0) + fprintf (file, + _("Warning: %s section size (%ld) is not a multiple of %d\n"), + pdata_section->name, (long) stop, onaline); + + datasize = pdata_section->size; + if (datasize == 0) { - fprintf (file, _("No unwind data in .pdata section\n")); + if (stop) + fprintf (file, _("Warning: %s section size is zero\n"), + pdata_section->name); return TRUE; } - if ((stop % onaline) != 0) - fprintf (file, - _("warning: .pdata section size (%ld) is not a multiple of %d\n"), - (long) stop, onaline); + + /* virt_size might be zero for objects. */ + if (stop == 0 && strcmp (abfd->xvec->name, "pe-x86-64") == 0) + { + stop = (datasize / onaline) * onaline; + virt_size_is_zero = TRUE; + } + else if (datasize < stop) + { + fprintf (file, + _("Warning: %s section size (%ld) is smaller than virtual size (%ld)\n"), + pdata_section->name, datasize, stop); + /* Be sure not to read passed datasize. */ + stop = datasize / onaline; + } /* Display functions table. */ fprintf (file, - _("\nThe Function Table (interpreted .pdata section contents)\n")); + _("\nThe Function Table (interpreted %s section contents)\n"), + pdata_section->name); fprintf (file, _("vma:\t\t\tBeginAddress\t EndAddress\t UnwindData\n")); @@ -507,7 +528,10 @@ pex64_bfd_print_pdata (bfd *abfd, void *vfile) xdata_arr = (bfd_vma *) xmalloc (sizeof (bfd_vma) * ((stop / onaline) + 1)); xdata_arr_cnt = 0; - imagebase = pe_data (abfd)->pe_opthdr.ImageBase; + if (strcmp (abfd->xvec->name, "pei-x86-64") == 0) + imagebase = pe_data (abfd)->pe_opthdr.ImageBase; + else + imagebase = 0; for (i = 0; i < stop; i += onaline) { @@ -554,8 +578,9 @@ pex64_bfd_print_pdata (bfd *abfd, void *vfile) seen_error = 1; fprintf (file, " has negative unwind address\n"); } - if (rf.rva_UnwindData && !PEX64_IS_RUNTIME_FUNCTION_CHAINED (&rf)) - xdata_arr[xdata_arr_cnt++] = rf.rva_UnwindData; + else if ((rf.rva_UnwindData && !PEX64_IS_RUNTIME_FUNCTION_CHAINED (&rf)) + || virt_size_is_zero) + xdata_arr[xdata_arr_cnt++] = rf.rva_UnwindData; } if (seen_error) @@ -571,20 +596,41 @@ pex64_bfd_print_pdata (bfd *abfd, void *vfile) /* Find the section containing the unwind data (.xdata). */ xdata_base = xdata_arr[0]; - xdata_section = pex64_get_section_by_rva (abfd, xdata_base, ".rdata"); - - if (!xdata_section) - xdata_section = pex64_get_section_by_rva (abfd, xdata_base, ".data"); + /* For sections with long names, first look for the same + section name, replacing .pdata by .xdata prefix. */ + if (strcmp (pdata_section->name, ".pdata") != 0) + { + char *xdata_name = alloca (strlen (pdata_section->name + 1)); + + xdata_name = strcpy (xdata_name, pdata_section->name); + /* Transform .pdata prefix into .xdata prefix. */ + if (strlen (xdata_name) > 1) + xdata_name [1] = 'x'; + xdata_section = pex64_get_section_by_rva (abfd, xdata_base, + xdata_name); + } + /* Second, try the .xdata section itself. */ if (!xdata_section) xdata_section = pex64_get_section_by_rva (abfd, xdata_base, ".xdata"); - if (!xdata_section) + /* Otherwise, if xdata_base is non zero, search also inside + other standard sections. */ + if (!xdata_section && xdata_base) + xdata_section = pex64_get_section_by_rva (abfd, xdata_base, ".rdata"); + if (!xdata_section && xdata_base) + xdata_section = pex64_get_section_by_rva (abfd, xdata_base, ".data"); + if (!xdata_section && xdata_base) xdata_section = pex64_get_section_by_rva (abfd, xdata_base, ".pdata"); - if (!xdata_section) + if (!xdata_section && xdata_base) xdata_section = pex64_get_section_by_rva (abfd, xdata_base, ".text"); + /* Transfer xdata section into xdata array. */ if (!xdata_section || !bfd_malloc_and_get_section (abfd, xdata_section, &xdata)) goto done; + /* Avoid "also used "... ouput for single unwind info + in object file. */ + prev_unwinddata_rva = (bfd_vma) -1; + /* Do dump of pdata related xdata. */ for (i = 0; i < stop; i += onaline) { @@ -600,7 +646,7 @@ pex64_bfd_print_pdata (bfd *abfd, void *vfile) /* We are probably into the padding of the section now. */ break; if (i == 0) - fprintf (file, "\nDump of .xdata\n"); + fprintf (file, _("\nDump of %s\n"), xdata_section->name); fputc (' ', file); fprintf_vma (file, rf.rva_UnwindData + imagebase); @@ -623,7 +669,7 @@ pex64_bfd_print_pdata (bfd *abfd, void *vfile) fprintf_vma (file, rf.rva_EndAddress + imagebase); fputc ('\n', file); - if (rf.rva_UnwindData != 0) + if (rf.rva_UnwindData != 0 || virt_size_is_zero) { if (PEX64_IS_RUNTIME_FUNCTION_CHAINED (&rf)) { @@ -679,6 +725,37 @@ pex64_bfd_print_pdata (bfd *abfd, void *vfile) return TRUE; } +/* Static counter of number of found pdata sections. */ +static bfd_boolean pdata_count; + +/* Functionn prototype. */ +bfd_boolean pex64_bfd_print_pdata (bfd *, void *); + +/* Helper function for bfd_map_over_section. */ +static void +pex64_print_all_pdata_sections (bfd *abfd, asection *pdata, void *obj) +{ + if (CONST_STRNEQ (pdata->name, ".pdata")) + { + if (pex64_bfd_print_pdata_section (abfd, obj, pdata)) + pdata_count++; + } +} + +bfd_boolean +pex64_bfd_print_pdata (bfd *abfd, void *vfile) +{ + asection *pdata_section = bfd_get_section_by_name (abfd, ".pdata"); + + if (pdata_section) + return pex64_bfd_print_pdata_section (abfd, vfile, pdata_section); + + pdata_count = 0; + bfd_map_over_sections (abfd, pex64_print_all_pdata_sections, vfile); + return (pdata_count > 0); +} + #define bfd_pe_print_pdata pex64_bfd_print_pdata +#define bfd_coff_std_swap_table bfd_coff_pei_swap_table #include "coff-x86_64.c"