This patch adds support for printing out the pdata section of PE objects.
authorPierre Muller <muller@sourceware.org>
Wed, 24 Dec 2014 10:06:57 +0000 (10:06 +0000)
committerNick Clifton <nickc@redhat.com>
Wed, 24 Dec 2014 10:06:57 +0000 (10:06 +0000)
* 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.

bfd/ChangeLog
bfd/pe-x86_64.c
bfd/pei-x86_64.c

index 7b0ad1d..af3fe44 100644 (file)
@@ -1,3 +1,21 @@
+2014-12-24  Pierre Muller  <muller@sourceware.org>
+
+       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  <amodra@gmail.com>
 
        * linker.c (_bfd_generic_link_output_symbols): Remove BSF_WEAK
index 673a544..adaefb7 100644 (file)
 { 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.  */
index ccb5774..16d8899 100644 (file)
@@ -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"