Update year range in copyright notice of binutils files
[deliverable/binutils-gdb.git] / bfd / pei-x86_64.c
index 11ee73a2de52496be3994f7647e83f53816ee92c..db307266c83b99cb777a010e72d7c1ddd5d3016a 100644 (file)
@@ -1,5 +1,5 @@
 /* BFD back-end for Intel 386 PE IMAGE COFF files.
-   Copyright (C) 2006-2014 Free Software Foundation, Inc.
+   Copyright (C) 2006-2018 Free Software Foundation, Inc.
 
    This file is part of BFD, the Binary File Descriptor library.
 
 #include "sysdep.h"
 #include "bfd.h"
 
-#define TARGET_SYM             x86_64_pei_vec
-#define TARGET_NAME            "pei-x86-64"
+#define TARGET_SYM             x86_64_pei_vec
+#define TARGET_NAME            "pei-x86-64"
 #define COFF_IMAGE_WITH_PE
 #define COFF_WITH_PE
 #define COFF_WITH_pex64
-#define PCRELOFFSET            TRUE
+#define PCRELOFFSET            TRUE
 #if defined (USE_MINGW64_LEADING_UNDERSCORES)
-#define TARGET_UNDERSCORE      '_'
+#define TARGET_UNDERSCORE      '_'
 #else
-#define TARGET_UNDERSCORE      0
+#define TARGET_UNDERSCORE      0
 #endif
 /* Long section names not allowed in executable images, only object files.  */
 #define COFF_LONG_SECTION_NAMES 0
@@ -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)
     {
@@ -161,7 +162,7 @@ pex64_xdata_print_uwd_codes (FILE *file, bfd *abfd,
       && PEX64_UNWCODE_CODE (ui->rawUnwindCodes[1]) == UWOP_EPILOG)
     {
       /* Display epilog opcode (whose docoding is not fully documented).
-         Looks to be designed to speed-up unwinding, as there is no need
+        Looks to be designed to speed-up unwinding, as there is no need
         to decode instruction flow if outside an epilog.  */
       unsigned int func_size = rf->rva_EndAddress - rf->rva_BeginAddress;
 
@@ -276,8 +277,9 @@ pex64_xdata_print_uwd_codes (FILE *file, bfd *abfd,
            fprintf (file, ", unknown(%u))", info);
          break;
        default:
-         /* Already caught by the previous scan.  */
-         abort ();
+         /* PR 17512: file: 2245-7442-0.004.  */
+         fprintf (file, _("Unknown: %x"), PEX64_UNWCODE_CODE (dta[1]));
+         break;
       }
       if (unexpected)
        fprintf (file, " [Unexpected!]");
@@ -317,17 +319,31 @@ pex64_dump_xdata (FILE *file, bfd *abfd,
   bfd_vma vaddr;
   bfd_vma end_addr;
   bfd_vma addr = rf->rva_UnwindData;
+  bfd_size_type sec_size = xdata_section->rawsize > 0 ? xdata_section->rawsize : xdata_section->size;
   struct pex64_unwind_info ui;
 
   vaddr = xdata_section->vma - pe_data (abfd)->pe_opthdr.ImageBase;
   addr -= vaddr;
 
+  /* PR 17512: file: 2245-7442-0.004.  */
+  if (addr >= sec_size)
+    {
+      fprintf (file, _("warning: xdata section corrupt\n"));
+      return;
+    }
+
   if (endx)
-    end_addr = endx[0] - vaddr;
+    {
+      end_addr = endx[0] - vaddr;
+      /* PR 17512: file: 2245-7442-0.004.  */
+      if (end_addr > sec_size)
+       {
+         fprintf (file, _("warning: xdata section corrupt"));
+         end_addr = sec_size;
+       }
+    }
   else
-    end_addr = (xdata_section->rawsize != 0 ?
-               xdata_section->rawsize : xdata_section->size);
-
+    end_addr = sec_size;
 
   pex64_get_unwind_info (abfd, &ui, &xdata[addr]);
 
@@ -380,7 +396,11 @@ pex64_dump_xdata (FILE *file, bfd *abfd,
           ui.FrameRegister == 0 ? "none"
           : pex_regs[(unsigned int) ui.FrameRegister]);
 
-  pex64_xdata_print_uwd_codes (file, abfd, &ui, rf);
+  /* PR 17512: file: 2245-7442-0.004.  */
+  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);
 
   switch (ui.Flags)
     {
@@ -439,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
@@ -464,20 +485,42 @@ 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,
+            /* xgettext:c-format */
+            _("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,
+                /* xgettext:c-format */
+                _("Warning: %s section size (%ld) is smaller than virtual size (%ld)\n"),
+                pdata_section->name, (unsigned long) datasize,
+                (unsigned long) 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"));
 
@@ -488,7 +531,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)
     {
@@ -517,7 +563,7 @@ pex64_bfd_print_pdata (bfd *abfd, void *vfile)
          seen_error = 1;
          fprintf (file, "  has %s begin address as predecessor\n",
            (rf.rva_BeginAddress < prev_beginaddress ? "smaller" : "same"));
-        }
+       }
       prev_beginaddress = rf.rva_BeginAddress;
       /* Now we check for negative addresses.  */
       if ((prev_beginaddress & 0x80000000) != 0)
@@ -535,8 +581,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)
@@ -552,20 +599,43 @@ 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)
+    {
+      size_t len = strlen (pdata_section->name);
+      char *xdata_name = xmalloc (len + 1);
+
+      xdata_name = memcpy (xdata_name, pdata_section->name, len + 1);
+      /* Transform .pdata prefix into .xdata prefix.  */
+      if (len > 1)
+       xdata_name [1] = 'x';
+      xdata_section = pex64_get_section_by_rva (abfd, xdata_base,
+                                               xdata_name);
+      free (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)
     {
@@ -573,6 +643,7 @@ pex64_bfd_print_pdata (bfd *abfd, void *vfile)
 
       if (i + PDATA_ROW_SIZE > stop)
        break;
+
       pex64_get_runtime_function (abfd, &rf, &pdata[i]);
 
       if (rf.rva_BeginAddress == 0 && rf.rva_EndAddress == 0
@@ -580,7 +651,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);
@@ -603,7 +674,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))
            {
@@ -633,7 +704,7 @@ pex64_bfd_print_pdata (bfd *abfd, void *vfile)
 
              /* Search for the current entry in the sorted array.  */
              p = (bfd_vma *)
-                 bsearch (&rf.rva_UnwindData, xdata_arr,
+                 bsearch (&rf.rva_UnwindData, xdata_arr,
                           (size_t) xdata_arr_cnt, sizeof (bfd_vma),
                           sort_xdata_arr);
 
@@ -642,6 +713,7 @@ pex64_bfd_print_pdata (bfd *abfd, void *vfile)
                 identical pointers in the array; advance past all of them.  */
              while (p[0] <= rf.rva_UnwindData)
                ++p;
+
              if (p[0] == ~((bfd_vma) 0))
                p = NULL;
 
@@ -658,6 +730,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"
This page took 0.027748 seconds and 4 git commands to generate.