Add epilog unwind for x86_64 pe/coff
authorTristan Gingold <gingold@adacore.com>
Wed, 4 Dec 2013 13:53:12 +0000 (14:53 +0100)
committerTristan Gingold <gingold@adacore.com>
Fri, 6 Dec 2013 10:54:31 +0000 (11:54 +0100)
include/coff/
2013-12-06  Tristan Gingold  <gingold@adacore.com>

* pe.h (UWOP_EPILOG, UWOP_PARE): Define.

bfd/
2013-12-06  Tristan Gingold  <gingold@adacore.com>

* pei-x86_64.c (pex64_xdata_print_uwd_codes): Add argument rf.
Display epilog opcode.
(pex64_dump_xdata): Add argument rf; make addr a local variable.
Adjust call to pex64_xdata_print_uwd_codes.
(pex64_bfd_print_pdata): Display code range, adjust call to
pex64_dump_xdata.

bfd/ChangeLog
bfd/pei-x86_64.c
include/coff/ChangeLog
include/coff/pe.h

index c42307fa787ddc469e70e35d596462708209889d..4a2bc286a31a173c4489648a290fd8c074ccab5d 100644 (file)
@@ -1,3 +1,11 @@
+2013-12-06  Tristan Gingold  <gingold@adacore.com>
+
+       * pei-x86_64.c (pex64_xdata_print_uwd_codes): Add argument rf.
+       Display epilog opcode.
+       (pex64_dump_xdata): Add argument rf; make addr a local variable.
+       Adjust call to pex64_xdata_print_uwd_codes.
+       (pex64_bfd_print_pdata): Display code range, adjust call to
+
 2013-12-05  Tristan Gingold  <gingold@adacore.com>
 
        * mach-o.c (bfd_mach_o_mkobject_init): Use bfd_zalloc.
index ecbef47c50328de48e54794f40d96f9c5b935939..40ca4a61d52bcfa3bea0b2e82cc743403fe847b2 100644 (file)
@@ -139,7 +139,8 @@ pex64_get_unwind_info (bfd *abfd, struct pex64_unwind_info *ui, void *data)
 
 static void
 pex64_xdata_print_uwd_codes (FILE *file, bfd *abfd,
-                            struct pex64_unwind_info *ui)
+                            struct pex64_unwind_info *ui,
+                            struct pex64_runtime_function *rf)
 {
   unsigned int i;
   unsigned int tmp; /* At least 32 bits.  */
@@ -156,17 +157,31 @@ pex64_xdata_print_uwd_codes (FILE *file, bfd *abfd,
 
   i = 0;
 
-  if (ui->Version == 2 && PEX64_UNWCODE_CODE (ui->rawUnwindCodes[1]) == 6)
+  if (ui->Version == 2
+      && PEX64_UNWCODE_CODE (ui->rawUnwindCodes[1]) == UWOP_EPILOG)
     {
-      /* Display opcodes 6 (whose meaning is not documented).  */
-      fprintf (file, "\tv2 opcode6:");
+      /* Display epilog opcode (whose docoding is not fully documented).
+         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;
+
+      fprintf (file, "\tv2 epilog (length: %02x) at pc+:",
+              ui->rawUnwindCodes[0]);
+      if (PEX64_UNWCODE_INFO (ui->rawUnwindCodes[1]))
+       fprintf (file, " 0x%x", func_size - ui->rawUnwindCodes[0]);
+      i++;
       for (; i < ui->CountOfCodes; i++)
        {
          const bfd_byte *dta = ui->rawUnwindCodes + 2 * i;
+         unsigned int off;
 
-         if (PEX64_UNWCODE_CODE (dta[1]) != 6)
+         if (PEX64_UNWCODE_CODE (dta[1]) != UWOP_EPILOG)
            break;
-         fprintf (file, " %02x %01x", dta[0], PEX64_UNWCODE_INFO (dta[1]));
+         off = dta[0] | (PEX64_UNWCODE_INFO (dta[1]) << 8);
+         if (off == 0)
+           fprintf (file, " [pad]");
+         else
+           fprintf (file, " 0x%x", func_size - off);
        }
       fputc ('\n', file);
     }
@@ -229,7 +244,7 @@ pex64_xdata_print_uwd_codes (FILE *file, bfd *abfd,
            }
          else if (ui->Version == 2)
            {
-             fprintf (file, "v2-opc6 %02x %01x", dta[0], info);
+             fprintf (file, "epilog %02x %01x", dta[0], info);
              unexpected = TRUE;
            }
          break;
@@ -290,15 +305,18 @@ pex64_get_section_by_rva (bfd *abfd, bfd_vma addr, const char *sec_name)
   return section;
 }
 
-/* Dump xdata at rva ADDR to FILE for ABFD.  */
+/* Dump xdata at for function RF to FILE.  The argument XDATA_SECTION
+   designate the bfd section containing the xdata, XDATA is its content,
+   and ENDX the size if known (or NULL).  */
 
 static void
 pex64_dump_xdata (FILE *file, bfd *abfd,
-                 asection *xdata_section, bfd_byte *xdata,
-                 bfd_vma addr, bfd_vma *endx)
+                 asection *xdata_section, bfd_byte *xdata, bfd_vma *endx,
+                 struct pex64_runtime_function *rf)
 {
   bfd_vma vaddr;
   bfd_vma end_addr;
+  bfd_vma addr = rf->rva_UnwindData;
   struct pex64_unwind_info ui;
 
   vaddr = xdata_section->vma - pe_data (abfd)->pe_opthdr.ImageBase;
@@ -362,7 +380,7 @@ 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);
+  pex64_xdata_print_uwd_codes (file, abfd, &ui, rf);
 
   switch (ui.Flags)
     {
@@ -571,9 +589,11 @@ pex64_bfd_print_pdata (bfd *abfd, void *vfile)
       else
        prev_unwinddata_rva = rf.rva_UnwindData;
 
-      fprintf (file, " (rva: %08x): for function at ",
+      fprintf (file, " (rva: %08x): ",
               (unsigned int) rf.rva_UnwindData);
       fprintf_vma (file, rf.rva_BeginAddress + imagebase);
+      fprintf (file, " - ");
+      fprintf_vma (file, rf.rva_EndAddress + imagebase);
       fputc ('\n', file);
 
       if (rf.rva_UnwindData != 0)
@@ -618,8 +638,7 @@ pex64_bfd_print_pdata (bfd *abfd, void *vfile)
              if (p[0] == ~((bfd_vma) 0))
                p = NULL;
 
-             pex64_dump_xdata (file, abfd, xdata_section, xdata,
-                               rf.rva_UnwindData, p);
+             pex64_dump_xdata (file, abfd, xdata_section, xdata, p, &rf);
            }
        }
     }
index 2a9c0aba181250a0e89b46a4f3ee1ac8ae706c57..639fb669d3604ea27e2a2e22b23b1746f1295235 100644 (file)
@@ -1,3 +1,7 @@
+2013-12-06  Tristan Gingold  <gingold@adacore.com>
+
+       * pe.h (UWOP_EPILOG, UWOP_PARE): Define.
+
 2013-07-10  Tristan Gingold  <gingold@adacore.com>
 
        * rs6000.h (external_core_dumpx): New structure.
index 3b372769a0e64ead660c823dab039cc91746e297..5e2b37e3412fab86e3c5ce239abf79794916c388 100644 (file)
@@ -392,8 +392,10 @@ struct external_pex64_runtime_function
 #define UWOP_SET_FPREG       3
 #define UWOP_SAVE_NONVOL      4
 #define UWOP_SAVE_NONVOL_FAR  5
-#define UWOP_SAVE_XMM        6 /* Deprecated, redefined in version 2.  */
-#define UWOP_SAVE_XMM_FAR     7        /* Deprecated.  */
+#define UWOP_SAVE_XMM         6 /* For version 1.  */
+#define UWOP_EPILOG           6 /* For version 2.  */
+#define UWOP_SAVE_XMM_FAR     7 /* For version 1 (deprecated).  */
+#define UWOP_SPARE            7 /* For version 2.  */
 #define UWOP_SAVE_XMM128      8
 #define UWOP_SAVE_XMM128_FAR  9
 #define UWOP_PUSH_MACHFRAME   10