jit: make gdb_symtab::blocks an std::forward_list
[deliverable/binutils-gdb.git] / bfd / pei-x86_64.c
index fa9a267735925dd9363ed8b4dbcf3b00008d88f9..c0b97351defb044a4498fc70908ed89dfc83526e 100644 (file)
@@ -1,5 +1,5 @@
 /* BFD back-end for Intel 386 PE IMAGE COFF files.
 /* BFD back-end for Intel 386 PE IMAGE COFF files.
-   Copyright 2006, 2007, 2009 Free Software Foundation, Inc.
+   Copyright (C) 2006-2019 Free Software Foundation, Inc.
 
    This file is part of BFD, the Binary File Descriptor library.
 
 
    This file is part of BFD, the Binary File Descriptor library.
 
    along with this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
    MA 02110-1301, USA.
    along with this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
    MA 02110-1301, USA.
-   
+
    Written by Kai Tietz, OneVision Software GmbH&CoKg.  */
 
 #include "sysdep.h"
 #include "bfd.h"
 
    Written by Kai Tietz, OneVision Software GmbH&CoKg.  */
 
 #include "sysdep.h"
 #include "bfd.h"
 
-#define TARGET_SYM             x86_64pei_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 COFF_IMAGE_WITH_PE
 #define COFF_WITH_PE
 #define COFF_WITH_pex64
-#define PCRELOFFSET            TRUE
+#define PCRELOFFSET            TRUE
 #if defined (USE_MINGW64_LEADING_UNDERSCORES)
 #if defined (USE_MINGW64_LEADING_UNDERSCORES)
-#define TARGET_UNDERSCORE      '_'
+#define TARGET_UNDERSCORE      '_'
 #else
 #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
 #endif
 /* Long section names not allowed in executable images, only object files.  */
 #define COFF_LONG_SECTION_NAMES 0
 #define COFF_SECTION_ALIGNMENT_ENTRIES \
 { COFF_SECTION_NAME_EXACT_MATCH (".bss"), \
   COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 4 }, \
 #define COFF_SECTION_ALIGNMENT_ENTRIES \
 { COFF_SECTION_NAME_EXACT_MATCH (".bss"), \
   COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 4 }, \
-{ COFF_SECTION_NAME_EXACT_MATCH (".data"), \
+{ COFF_SECTION_NAME_PARTIAL_MATCH (".data"), \
   COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 4 }, \
   COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 4 }, \
-{ COFF_SECTION_NAME_EXACT_MATCH (".rdata"), \
+{ COFF_SECTION_NAME_PARTIAL_MATCH (".rdata"), \
   COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 4 }, \
   COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 4 }, \
-{ COFF_SECTION_NAME_EXACT_MATCH (".text"), \
+{ COFF_SECTION_NAME_PARTIAL_MATCH (".text"), \
   COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 4 }, \
 { COFF_SECTION_NAME_PARTIAL_MATCH (".idata"), \
   COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 2 }, \
   COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 4 }, \
 { COFF_SECTION_NAME_PARTIAL_MATCH (".idata"), \
   COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 2 }, \
 #define AOUTSZ         PEPAOUTSZ
 #define PEAOUTHDR      PEPAOUTHDR
 
 #define AOUTSZ         PEPAOUTSZ
 #define PEAOUTHDR      PEPAOUTHDR
 
-static const char *pex_regs[16] = {
+/* Name of registers according to SEH conventions.  */
+
+static const char * const pex_regs[16] = {
   "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi",
   "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"
 };
 
   "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi",
   "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"
 };
 
+/* Swap in a runtime function.  */
+
 static void
 pex64_get_runtime_function (bfd *abfd, struct pex64_runtime_function *rf,
                            const void *data)
 static void
 pex64_get_runtime_function (bfd *abfd, struct pex64_runtime_function *rf,
                            const void *data)
@@ -90,18 +94,24 @@ pex64_get_runtime_function (bfd *abfd, struct pex64_runtime_function *rf,
   rf->rva_BeginAddress = bfd_get_32 (abfd, ex_rf->rva_BeginAddress);
   rf->rva_EndAddress = bfd_get_32 (abfd, ex_rf->rva_EndAddress);
   rf->rva_UnwindData = bfd_get_32 (abfd, ex_rf->rva_UnwindData);
   rf->rva_BeginAddress = bfd_get_32 (abfd, ex_rf->rva_BeginAddress);
   rf->rva_EndAddress = bfd_get_32 (abfd, ex_rf->rva_EndAddress);
   rf->rva_UnwindData = bfd_get_32 (abfd, ex_rf->rva_UnwindData);
-  rf->isChained = PEX64_IS_RUNTIME_FUNCTION_CHAINED (rf);
-  rf->rva_UnwindData = PEX64_GET_UNWINDDATA_UNIFIED_RVA (rf);
 }
 
 }
 
-static void
-pex64_get_unwind_info (bfd *abfd, struct pex64_unwind_info *ui, void *data)
+/* Swap in unwind info header.  */
+
+static bfd_boolean
+pex64_get_unwind_info (bfd *abfd, struct pex64_unwind_info *ui,
+                      void *data, void *data_end)
 {
   struct external_pex64_unwind_info *ex_ui =
     (struct external_pex64_unwind_info *) data;
   bfd_byte *ex_dta = (bfd_byte *) data;
 {
   struct external_pex64_unwind_info *ex_ui =
     (struct external_pex64_unwind_info *) data;
   bfd_byte *ex_dta = (bfd_byte *) data;
+  bfd_byte *ex_dta_end = (bfd_byte *) data_end;
 
   memset (ui, 0, sizeof (struct pex64_unwind_info));
 
   memset (ui, 0, sizeof (struct pex64_unwind_info));
+
+  if (ex_dta >= ex_dta_end || ex_dta + 4 >= ex_dta_end)
+    return FALSE;
+
   ui->Version = PEX64_UWI_VERSION (ex_ui->Version_Flags);
   ui->Flags = PEX64_UWI_FLAGS (ex_ui->Version_Flags);
   ui->SizeOfPrologue = (bfd_vma) ex_ui->SizeOfPrologue;
   ui->Version = PEX64_UWI_VERSION (ex_ui->Version_Flags);
   ui->Flags = PEX64_UWI_FLAGS (ex_ui->Version_Flags);
   ui->SizeOfPrologue = (bfd_vma) ex_ui->SizeOfPrologue;
@@ -110,212 +120,262 @@ pex64_get_unwind_info (bfd *abfd, struct pex64_unwind_info *ui, void *data)
   ui->FrameOffset = PEX64_UWI_FRAMEOFF (ex_ui->FrameRegisterOffset);
   ui->sizeofUnwindCodes = PEX64_UWI_SIZEOF_UWCODE_ARRAY (ui->CountOfCodes);
   ui->SizeOfBlock = ui->sizeofUnwindCodes + 4;
   ui->FrameOffset = PEX64_UWI_FRAMEOFF (ex_ui->FrameRegisterOffset);
   ui->sizeofUnwindCodes = PEX64_UWI_SIZEOF_UWCODE_ARRAY (ui->CountOfCodes);
   ui->SizeOfBlock = ui->sizeofUnwindCodes + 4;
-  ui->rawUnwindCodes = &ex_dta[4];
+  ui->rawUnwindCodes = ex_dta + 4;
+  ui->rawUnwindCodesEnd = ex_dta_end;
+
   ex_dta += ui->SizeOfBlock;
   ex_dta += ui->SizeOfBlock;
+  if (ex_dta >= ex_dta_end)
+    return FALSE;
+
   switch (ui->Flags)
     {
   switch (ui->Flags)
     {
+    case UNW_FLAG_CHAININFO:
+      if (ex_dta + 12 >= ex_dta_end)
+       return FALSE;
+      ui->rva_BeginAddress = bfd_get_32 (abfd, ex_dta + 0);
+      ui->rva_EndAddress = bfd_get_32 (abfd, ex_dta + 4);
+      ui->rva_UnwindData = bfd_get_32 (abfd, ex_dta + 8);
+      ui->SizeOfBlock += 12;
+      return TRUE;
     case UNW_FLAG_EHANDLER:
     case UNW_FLAG_EHANDLER:
-      ui->rva_ExceptionHandler = bfd_get_32 (abfd, ex_dta);
-      break;
     case UNW_FLAG_UHANDLER:
     case UNW_FLAG_UHANDLER:
-      ui->rva_TerminationHandler = bfd_get_32 (abfd, ex_dta);
-      break;
     case UNW_FLAG_FHANDLER:
     case UNW_FLAG_FHANDLER:
-      ui->rva_FrameHandler = bfd_get_32 (abfd, ex_dta);
-      ui->FrameHandlerArgument = bfd_get_32 (abfd, ex_dta + 4);
-      ui->SizeOfBlock += 8;
-      return;
-    case UNW_FLAG_CHAININFO:
-      ui->rva_FunctionEntry = bfd_get_32 (abfd, ex_dta);
+      if (ex_dta + 4 >= ex_dta_end)
+       return FALSE;
+      ui->rva_ExceptionHandler = bfd_get_32 (abfd, ex_dta);
       ui->SizeOfBlock += 4;
       ui->SizeOfBlock += 4;
-      return;
+      return TRUE;
     default:
     default:
-      return;
+      return TRUE;
     }
     }
-  ex_dta += 4;
-  ui->SizeOfBlock += 8;
-  ui->CountOfScopes = bfd_get_32 (abfd, ex_dta);
-  ex_dta += 4;
-  ui->rawScopeEntries = ex_dta;
-  ui->SizeOfBlock += (ui->CountOfScopes * PEX64_SCOPE_ENTRY_SIZE);
 }
 
 }
 
-static void
-pex64_get_scope_entry (bfd *abfd, struct pex64_scope_entry *se,
-                      bfd_vma idx, const bfd_byte *x)
-{
-  const struct external_pex64_scope_entry *ex_se;
-  x += (idx * PEX64_SCOPE_ENTRY_SIZE);
-  ex_se = (const struct external_pex64_scope_entry *) x;
-  memset (se, 0, sizeof (struct pex64_scope_entry));
-  se->rva_BeginAddress = bfd_get_32 (abfd, ex_se->rva_BeginAddress);
-  se->rva_EndAddress = bfd_get_32 (abfd, ex_se->rva_EndAddress);
-  se->rva_HandlerAddress = bfd_get_32 (abfd, ex_se->rva_HandlerAddress);
-  se->rva_JumpAddress = bfd_get_32 (abfd, ex_se->rva_JumpAddress);
-}
+/* Display unwind codes.  */
 
 static void
 
 static void
-pex64_xdata_print_uwd_codes (FILE *file, struct pex64_unwind_info *ui,
-                            bfd_vma pc_addr)
+pex64_xdata_print_uwd_codes (FILE *file, bfd *abfd,
+                            struct pex64_unwind_info *ui,
+                            struct pex64_runtime_function *rf)
 {
 {
-  bfd_vma i;
-  bfd_vma tmp = 0;
-  const bfd_byte *insns[256];
-  bfd_vma insns_count = 0;
-  const bfd_byte *dta = ui->rawUnwindCodes;
+  unsigned int i;
+  unsigned int tmp; /* At least 32 bits.  */
+  int save_allowed;
 
 
-  if (ui->CountOfCodes == 0 || !dta)
+  if (ui->CountOfCodes == 0 || ui->rawUnwindCodes == NULL)
     return;
 
     return;
 
-  /* Sort array ascending. Note: it is stored in reversed order.  */
-  for (i = 0; i < ui->CountOfCodes; i++)
+  /* According to UNWIND_CODE documentation:
+      If an FP reg is used, the any unwind code taking an offset must only be
+      used after the FP reg is established in the prolog.
+     But there are counter examples of that in system dlls...  */
+  save_allowed = TRUE;
+
+  i = 0;
+
+  if (ui->rawUnwindCodes + 1 >= ui->rawUnwindCodesEnd)
     {
     {
-      const bfd_byte *t;
+      fprintf (file, _("warning: corrupt unwind data\n"));
+      return;
+    }
+
+  if (ui->Version == 2
+      && 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
+        to decode instruction flow if outside an epilog.  */
+      unsigned int func_size = rf->rva_EndAddress - rf->rva_BeginAddress;
 
 
-      t = insns[insns_count++] = &dta[i * 2];
-      switch (PEX64_UNWCODE_CODE (t[1]))
+      if (ui->rawUnwindCodes + 1 + (ui->CountOfCodes * 2) >= ui->rawUnwindCodesEnd)
        {
        {
-       case UWOP_PUSH_NONVOL:
-       case UWOP_ALLOC_SMALL:
-       case UWOP_SET_FPREG:
-       case UWOP_PUSH_MACHFRAME:
-         break;
-       case UWOP_ALLOC_LARGE:
-         if (PEX64_UNWCODE_INFO (t[1]) == 0)
-           {
-             i += 1;
-             break;
-           }
-         else if (PEX64_UNWCODE_INFO (t[1]) == 1)
-           {
-             i += 2;
-             break;
-           }
-         /* fall through.  */
-       default:
-         fprintf (file, "\t contains unknown code (%u).\n",
-                  (unsigned int) PEX64_UNWCODE_CODE (t[1]));
+         fprintf (file, _("warning: corrupt unwind data\n"));
          return;
          return;
-       case UWOP_SAVE_NONVOL:
-       case UWOP_SAVE_XMM:
-       case UWOP_SAVE_XMM128:
-         i++;
-         break;
-       case UWOP_SAVE_NONVOL_FAR:
-       case UWOP_SAVE_XMM_FAR:
-       case UWOP_SAVE_XMM128_FAR:
-         i += 2;
-         break;
        }
        }
+
+      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]) != UWOP_EPILOG)
+           break;
+         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);
     }
     }
-  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;)
+
+  if (ui->rawUnwindCodes + 2 + (ui->CountOfCodes * 2) >= ui->rawUnwindCodesEnd)
+    {
+      fprintf (file, _("warning: corrupt unwind data\n"));
+      return;
+    }
+
+  for (; i < ui->CountOfCodes; i++)
     {
     {
-      --i;
-      dta = insns[i];
-      fprintf (file, "\t  insn ends at pc+0x%02x: ", (unsigned int) dta[0]);
+      const bfd_byte *dta = ui->rawUnwindCodes + 2 * i;
+      unsigned int info = PEX64_UNWCODE_INFO (dta[1]);
+      int unexpected = FALSE;
+
+      fprintf (file, "\t  pc+0x%02x: ", (unsigned int) dta[0]);
+
       switch (PEX64_UNWCODE_CODE (dta[1]))
        {
        case UWOP_PUSH_NONVOL:
       switch (PEX64_UNWCODE_CODE (dta[1]))
        {
        case UWOP_PUSH_NONVOL:
-         fprintf (file, "push %s.\n", pex_regs[PEX64_UNWCODE_INFO (dta[1])]);
+         fprintf (file, "push %s", pex_regs[info]);
          break;
          break;
+
        case UWOP_ALLOC_LARGE:
        case UWOP_ALLOC_LARGE:
-         if (PEX64_UNWCODE_INFO (dta[1]) == 0)
+         if (info == 0)
            {
            {
-             tmp = (bfd_vma) (*((unsigned short *) &dta[2]));
-             tmp *= 8;
+             if (dta + 4 > ui->rawUnwindCodesEnd)
+               {
+                 fprintf (file, _("warning: corrupt unwind data\n"));
+                 return;
+               }
+             tmp = bfd_get_16 (abfd, dta + 2) * 8;
+             i++;
            }
          else
            }
          else
-           tmp = (bfd_vma) (*((unsigned int *)&dta[2]));
-         fprintf (file, "save stack region of size 0x");
-         fprintf_vma (file, tmp);
-         fprintf (file,".\n");
+           {
+             if (dta + 6 > ui->rawUnwindCodesEnd)
+               {
+                 fprintf (file, _("warning: corrupt unwind data\n"));
+                 return;
+               }
+             tmp = bfd_get_32 (abfd, dta + 2);
+             i += 2;
+           }
+         fprintf (file, "alloc large area: rsp = rsp - 0x%x", tmp);
          break;
          break;
+
        case UWOP_ALLOC_SMALL:
        case UWOP_ALLOC_SMALL:
-         tmp = (bfd_vma) PEX64_UNWCODE_INFO (dta[1]);
-         tmp += 1;
-         tmp *= 8;
-         fprintf (file, "save stack region of size 0x");
-         fprintf_vma (file, tmp);
-         fprintf (file,".\n");
+         fprintf (file, "alloc small area: rsp = rsp - 0x%x", (info + 1) * 8);
          break;
          break;
+
        case UWOP_SET_FPREG:
        case UWOP_SET_FPREG:
-         tmp = (bfd_vma) PEX64_UNWCODE_INFO (dta[1]);
-         tmp *= 16;
-         fprintf (file, "FPReg = (FrameReg) + 0x");
-         fprintf_vma (file, tmp);
-         fprintf (file, ".\n");
+         /* According to the documentation, info field is unused.  */
+         fprintf (file, "FPReg: %s = rsp + 0x%x (info = 0x%x)",
+                  pex_regs[ui->FrameRegister],
+                  (unsigned int) ui->FrameOffset * 16, info);
+         unexpected = ui->FrameRegister == 0;
+         save_allowed = FALSE;
          break;
          break;
+
        case UWOP_SAVE_NONVOL:
        case UWOP_SAVE_NONVOL:
-         fprintf (file, "mov %s at 0x",
-                  pex_regs[PEX64_UNWCODE_INFO (dta[1])]);
-         tmp = (bfd_vma) (*((unsigned short *) &dta[2]));
-         tmp *= 8;
-         fprintf_vma (file, tmp);
-         fprintf (file, ".\n");
+         if (dta + 4 > ui->rawUnwindCodesEnd)
+           {
+             fprintf (file, _("warning: corrupt unwind data\n"));
+             return;
+           }
+         tmp = bfd_get_16 (abfd, dta + 2) * 8;
+         i++;
+         fprintf (file, "save %s at rsp + 0x%x", pex_regs[info], tmp);
+         unexpected = !save_allowed;
          break;
          break;
+
        case UWOP_SAVE_NONVOL_FAR:
        case UWOP_SAVE_NONVOL_FAR:
-         fprintf (file, "mov %s at 0x",
-                  pex_regs[PEX64_UNWCODE_INFO (dta[1])]);
-         tmp = (bfd_vma) (*((unsigned int *) &dta[2]));
-         fprintf_vma (file, tmp);
-         fprintf (file, ".\n");
+         if (dta + 6 > ui->rawUnwindCodesEnd)
+           {
+             fprintf (file, _("warning: corrupt unwind data\n"));
+             return;
+           }
+         tmp = bfd_get_32 (abfd, dta + 2);
+         i += 2;
+         fprintf (file, "save %s at rsp + 0x%x", pex_regs[info], tmp);
+         unexpected = !save_allowed;
          break;
          break;
+
        case UWOP_SAVE_XMM:
        case UWOP_SAVE_XMM:
-         tmp = (bfd_vma) (*((unsigned short *) &dta[2]));
-         tmp *= 8;
-         fprintf (file, "mov mm%u at 0x",
-                  (unsigned int) PEX64_UNWCODE_INFO (dta[1]));
-         fprintf_vma (file, tmp);
-         fprintf (file, ".\n");
+         if (ui->Version == 1)
+           {
+             if (dta + 4 > ui->rawUnwindCodesEnd)
+               {
+                 fprintf (file, _("warning: corrupt unwind data\n"));
+                 return;
+               }
+             tmp = bfd_get_16 (abfd, dta + 2) * 8;
+             i++;
+             fprintf (file, "save mm%u at rsp + 0x%x", info, tmp);
+             unexpected = !save_allowed;
+           }
+         else if (ui->Version == 2)
+           {
+             fprintf (file, "epilog %02x %01x", dta[0], info);
+             unexpected = TRUE;
+           }
          break;
          break;
+
        case UWOP_SAVE_XMM_FAR:
        case UWOP_SAVE_XMM_FAR:
-         tmp = (bfd_vma) (*((unsigned int *) &dta[2]));
-         fprintf (file, "mov mm%u at 0x",
-                  (unsigned int) PEX64_UNWCODE_INFO (dta[1]));
-         fprintf_vma (file, tmp);
-         fprintf (file, ".\n");
+         if (dta + 6 > ui->rawUnwindCodesEnd)
+           {
+             fprintf (file, _("warning: corrupt unwind data\n"));
+             return;
+           }
+         tmp = bfd_get_32 (abfd, dta + 2) * 8;
+         i += 2;
+         fprintf (file, "save mm%u at rsp + 0x%x", info, tmp);
+         unexpected = !save_allowed;
          break;
          break;
+
        case UWOP_SAVE_XMM128:
        case UWOP_SAVE_XMM128:
-         tmp = (bfd_vma) (*((unsigned short *) &dta[2]));
-         tmp *= 16;
-         fprintf (file, "mov xmm%u at 0x",
-                  (unsigned int) PEX64_UNWCODE_INFO ( dta[1]));
-         fprintf_vma (file, tmp);
-         fprintf (file, ".\n");
+         if (dta + 4 > ui->rawUnwindCodesEnd)
+           {
+             fprintf (file, _("warning: corrupt unwind data\n"));
+             return;
+           }
+         tmp = bfd_get_16 (abfd, dta + 2) * 16;
+         i++;
+         fprintf (file, "save xmm%u at rsp + 0x%x", info, tmp);
+         unexpected = !save_allowed;
          break;
          break;
+
        case UWOP_SAVE_XMM128_FAR:
        case UWOP_SAVE_XMM128_FAR:
-         tmp = (bfd_vma) (*((unsigned int *) &dta[2]));
-         fprintf (file, "mov xmm%u at 0x",
-                  (unsigned int) PEX64_UNWCODE_INFO (dta[1]));
-         fprintf_vma (file, tmp);
-         fprintf (file, ".\n");
+         if (dta + 6 > ui->rawUnwindCodesEnd)
+           {
+             fprintf (file, _("warning: corrupt unwind data\n"));
+             return;
+           }
+         tmp = bfd_get_32 (abfd, dta + 2) * 16;
+         i += 2;
+         fprintf (file, "save xmm%u at rsp + 0x%x", info, tmp);
+         unexpected = !save_allowed;
          break;
          break;
+
        case UWOP_PUSH_MACHFRAME:
          fprintf (file, "interrupt entry (SS, old RSP, EFLAGS, CS, RIP");
        case UWOP_PUSH_MACHFRAME:
          fprintf (file, "interrupt entry (SS, old RSP, EFLAGS, CS, RIP");
-         if (PEX64_UNWCODE_INFO (dta[1]) == 0)
-           {
-             fprintf (file, ")");
-           }
-         else if (PEX64_UNWCODE_INFO (dta[1]) == 1)
-           {
-             fprintf (file, ",ErrorCode)");
-           }
+         if (info == 0)
+           fprintf (file, ")");
+         else if (info == 1)
+           fprintf (file, ",ErrorCode)");
          else
          else
-           fprintf (file, ", unknown(%u))",
-                    (unsigned int) PEX64_UNWCODE_INFO (dta[1]));
-         fprintf (file,".\n");
+           fprintf (file, ", unknown(%u))", info);
          break;
          break;
+
        default:
        default:
-         fprintf (file, "unknown code %u.\n",
-                  (unsigned int) PEX64_UNWCODE_INFO (dta[1]));
+         /* PR 17512: file: 2245-7442-0.004.  */
+         fprintf (file, _("Unknown: %x"), PEX64_UNWCODE_CODE (dta[1]));
          break;
          break;
-      }
+       }
+
+      if (unexpected)
+       fprintf (file, " [Unexpected!]");
+      fputc ('\n', file);
     }
 }
 
     }
 }
 
+/* Check wether section SEC_NAME contains the xdata at address ADDR.  */
+
 static asection *
 pex64_get_section_by_rva (bfd *abfd, bfd_vma addr, const char *sec_name)
 {
 static asection *
 pex64_get_section_by_rva (bfd *abfd, bfd_vma addr, const char *sec_name)
 {
@@ -334,202 +394,463 @@ pex64_get_section_by_rva (bfd *abfd, bfd_vma addr, const char *sec_name)
   return section;
 }
 
   return section;
 }
 
+/* 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
 static void
-pex64_dump_xdata (FILE *file, bfd *abfd, bfd_vma addr, bfd_vma pc_addr)
+pex64_dump_xdata (FILE *file, bfd *abfd,
+                 asection *xdata_section, bfd_byte *xdata, bfd_vma *endx,
+                 struct pex64_runtime_function *rf)
 {
 {
-  asection *section = pex64_get_section_by_rva (abfd, addr, ".rdata");
-  bfd_vma vsize;
-  bfd_byte *data = NULL;
-  bfd_vma i;
-
-  if (!section)
-    section = pex64_get_section_by_rva (abfd, addr, ".data");
-  if (!section)
-    section = pex64_get_section_by_rva (abfd, addr, ".xdata");
-  if (!section)
+  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)
     {
     {
-      section = pex64_get_section_by_rva (abfd, addr, ".pdata");
-      if (section)
+      end_addr = endx[0] - vaddr;
+      /* PR 17512: file: 2245-7442-0.004.  */
+      if (end_addr > sec_size)
        {
        {
-         fprintf (file, "\t Shares information with pdata element at 0x");
-         fprintf_vma (file, addr + pe_data (abfd)->pe_opthdr.ImageBase);
-         fprintf (file, ".\n");
+         fprintf (file, _("warning: xdata section corrupt\n"));
+         end_addr = sec_size;
        }
     }
        }
     }
-  if (!section)
-    return;
-  vsize = section->vma - pe_data (abfd)->pe_opthdr.ImageBase;
-  addr -= vsize;
-  if (bfd_malloc_and_get_section (abfd, section, &data))
-    {
-      struct pex64_unwind_info ui;
+  else
+    end_addr = sec_size;
 
 
-      if (!data)
-       return;
-
-      pex64_get_unwind_info (abfd, &ui, &data[addr]);
+  if (! pex64_get_unwind_info (abfd, &ui, xdata + addr, xdata + end_addr))
+    {
+      fprintf (file, _("warning: xdata section corrupt\n"));
+      return;
+    }
 
 
-      if (ui.Version != 1)
+  if (ui.Version != 1 && ui.Version != 2)
+    {
+      unsigned int i;
+      fprintf (file, "\tVersion %u (unknown).\n",
+              (unsigned int) ui.Version);
+      for (i = 0; addr < end_addr; addr += 1, i++)
        {
        {
-         fprintf (file, "\tVersion %u (unknown).\n", (unsigned int) ui.Version);
-         return;
+         if ((i & 15) == 0)
+           fprintf (file, "\t  %03x:", i);
+         fprintf (file, " %02x", xdata[addr]);
+         if ((i & 15) == 15)
+           fprintf (file, "\n");
        }
        }
+      if ((i & 15) != 0)
+       fprintf (file, "\n");
+      return;
+    }
 
 
-      fprintf (file, "\tFlags: ");
-      switch (ui.Flags)
-       {
-       case UNW_FLAG_NHANDLER:
-         fprintf (file, "UNW_FLAG_NHANDLER");
-         break;
-       case UNW_FLAG_EHANDLER:
-         fprintf (file, "UNW_FLAG_EHANDLER");
-         break;
-       case UNW_FLAG_UHANDLER:
-         fprintf (file, "UNW_FLAG_UHANDLER");
-         break;
-       case UNW_FLAG_FHANDLER:
-         fprintf (file, "UNW_FLAG_FHANDLER = (UNW_FLAG_EHANDLER | UNW_FLAG_UHANDLER)");
-         break;
-       case UNW_FLAG_CHAININFO:
-         fprintf (file, "UNW_FLAG_CHAININFO");
-         break;
-       default:
-         fprintf (file, "unknown flags value 0x%x", (unsigned int) ui.Flags);
-         break;
-       }
+  fprintf (file, "\tVersion: %d, Flags: ", ui.Version);
+  switch (ui.Flags)
+    {
+    case UNW_FLAG_NHANDLER:
+      fprintf (file, "none");
+      break;
+    case UNW_FLAG_EHANDLER:
+      fprintf (file, "UNW_FLAG_EHANDLER");
+      break;
+    case UNW_FLAG_UHANDLER:
+      fprintf (file, "UNW_FLAG_UHANDLER");
+      break;
+    case UNW_FLAG_FHANDLER:
+      fprintf
+       (file, "UNW_FLAG_EHANDLER | UNW_FLAG_UHANDLER");
+      break;
+    case UNW_FLAG_CHAININFO:
+      fprintf (file, "UNW_FLAG_CHAININFO");
+      break;
+    default:
+      fprintf (file, "unknown flags value 0x%x", (unsigned int) ui.Flags);
+      break;
+    }
+  fputc ('\n', file);
+  fprintf (file, "\tNbr codes: %u, ", (unsigned int) ui.CountOfCodes);
+  fprintf (file, "Prologue size: 0x%02x, Frame offset: 0x%x, ",
+          (unsigned int) ui.SizeOfPrologue, (unsigned int) ui.FrameOffset);
+  fprintf (file, "Frame reg: %s\n",
+          ui.FrameRegister == 0 ? "none"
+          : pex_regs[(unsigned int) ui.FrameRegister]);
+
+  /* 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)
+    {
+    case UNW_FLAG_EHANDLER:
+    case UNW_FLAG_UHANDLER:
+    case UNW_FLAG_FHANDLER:
+      fprintf (file, "\tHandler: ");
+      fprintf_vma (file, (ui.rva_ExceptionHandler
+                         + pe_data (abfd)->pe_opthdr.ImageBase));
       fprintf (file, ".\n");
       fprintf (file, ".\n");
-      if (ui.CountOfCodes != 0)
-       fprintf (file, "\tEntry has %u codes.", (unsigned int) ui.CountOfCodes);
-      fprintf (file, "\tPrologue size: %u, Frame offset = 0x%x.\n",
-              (unsigned int) ui.SizeOfPrologue, (unsigned int) ui.FrameOffset);
-      fprintf (file, "\tFrame register is %s.\n",
-       ui.FrameRegister == 0 ? "CFA"
-                             : pex_regs[(unsigned int) ui.FrameRegister]);
-
-      pex64_xdata_print_uwd_codes (file, &ui, pc_addr);
-      
-      switch (ui.Flags)
-       {
-       case UNW_FLAG_NHANDLER:
-         return;
-       case UNW_FLAG_EHANDLER:
-         fprintf (file, "\texception_handler at 0x%x.\n", (unsigned int) ui.rva_ExceptionHandler);
-         break;
-       case UNW_FLAG_UHANDLER:
-         fprintf (file, "\ttermination_handler at 0x%x.\n", (unsigned int) ui.rva_TerminationHandler);
-       case UNW_FLAG_FHANDLER:
-         fprintf (file, "\tframe_handler at 0x%x.\n", (unsigned int) ui.rva_FrameHandler);
-         fprintf (file, "\t Argument for FrameHandler: 0x%x.\n",
-                  (unsigned int) ui.FrameHandlerArgument);
-         return;
-       case UNW_FLAG_CHAININFO:
-         fprintf (file, "\t Function Entry: 0x%x\n", (unsigned int) ui.rva_FunctionEntry);
-         return;
-       default:
-         fprintf (file, "\t Unknown flag value of 0x%x\n", (unsigned int) ui.Flags);
-         return;
-       }
-      fprintf (file, "\t 0x%x # of scope(s)\n", (unsigned int) ui.CountOfScopes);
-      for (i = 0; i < ui.CountOfScopes; i++)
+      break;
+    case UNW_FLAG_CHAININFO:
+      fprintf (file, "\tChain: start: ");
+      fprintf_vma (file, ui.rva_BeginAddress);
+      fprintf (file, ", end: ");
+      fprintf_vma (file, ui.rva_EndAddress);
+      fprintf (file, "\n\t unwind data: ");
+      fprintf_vma (file, ui.rva_UnwindData);
+      fprintf (file, ".\n");
+      break;
+    }
+
+  /* Now we need end of this xdata block.  */
+  addr += ui.SizeOfBlock;
+  if (addr < end_addr)
+    {
+      unsigned int i;
+      fprintf (file,"\tUser data:\n");
+      for (i = 0; addr < end_addr; addr += 1, i++)
        {
        {
-         struct pex64_scope_entry se;
-         pex64_get_scope_entry (abfd, &se, i, ui.rawScopeEntries);
-         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) se.rva_BeginAddress,
-                  (unsigned int) se.rva_EndAddress,
-                  (unsigned int) se.rva_HandlerAddress,
-                  (unsigned int) se.rva_JumpAddress);
+         if ((i & 15) == 0)
+           fprintf (file, "\t  %03x:", i);
+         fprintf (file, " %02x", xdata[addr]);
+         if ((i & 15) == 15)
+           fprintf (file, "\n");
        }
        }
+      if ((i & 15) != 0)
+       fprintf (file, "\n");
     }
     }
-  if (data != NULL)
-    free (data);
 }
 
 }
 
+/* Helper function to sort xdata.  The entries of xdata are sorted to know
+   the size of each entry.  */
+
+static int
+sort_xdata_arr (const void *l, const void *r)
+{
+  const bfd_vma *lp = (const bfd_vma *) l;
+  const bfd_vma *rp = (const bfd_vma *) r;
+
+  if (*lp == *rp)
+    return 0;
+  return (*lp < *rp ? -1 : 1);
+}
+
+/* Display unwind tables for x86-64.  */
+
 static bfd_boolean
 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;
 {
   FILE *file = (FILE *) vfile;
-  bfd_byte *data = NULL;
-  asection *section = bfd_get_section_by_name (abfd, ".pdata");
-  bfd_size_type datasize = 0;
+  bfd_byte *pdata = NULL;
+  bfd_byte *xdata = NULL;
+  asection *xdata_section = NULL;
+  bfd_vma xdata_base;
   bfd_size_type i;
   bfd_size_type i;
-  bfd_size_type start, stop;
+  bfd_size_type datasize;
+  bfd_size_type stop;
+  bfd_vma prev_beginaddress = (bfd_vma) -1;
+  bfd_vma prev_unwinddata_rva = (bfd_vma) -1;
+  bfd_vma imagebase;
   int onaline = PDATA_ROW_SIZE;
   int onaline = PDATA_ROW_SIZE;
-
-  if (section == NULL
-      || coff_section_data (abfd, section) == NULL
-      || pei_section_data (abfd, section) == NULL)
+  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
+      || coff_section_data (abfd, pdata_section) == NULL
+      || pei_section_data (abfd, pdata_section) == NULL)
     return TRUE;
 
     return TRUE;
 
-  stop = pei_section_data (abfd, section)->virt_size;
+  stop = pei_section_data (abfd, pdata_section)->virt_size;
   if ((stop % onaline) != 0)
     fprintf (file,
   if ((stop % onaline) != 0)
     fprintf (file,
-            _("warning: .pdata section size (%ld) is not a multiple of %d\n"),
-            (long) stop, onaline);
+            /* 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)
+    {
+      if (stop)
+       fprintf (file, _("Warning: %s section size is zero\n"),
+                pdata_section->name);
+      return TRUE;
+    }
+
+  /* virt_size might be zero for objects.  */
+  if (stop == 0 && strcmp (abfd->xvec->name, "pe-x86-64") == 0)
+    {
+      stop = datasize;
+      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 past datasize.  */
+       stop = datasize;
+      }
+
+  /* Display functions table.  */
   fprintf (file,
   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"));
 
 
   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, pdata_section, &pdata))
+    goto done;
 
 
-  if (!bfd_malloc_and_get_section (abfd, section, &data))
+  /* Table of xdata entries.  */
+  xdata_arr = (bfd_vma *) xmalloc (sizeof (bfd_vma) * ((stop / onaline) + 1));
+  xdata_arr_cnt = 0;
+
+  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)
     {
     {
-      if (data != NULL)
-       free (data);
-      return FALSE;
+      struct pex64_runtime_function rf;
+
+      if (i + PDATA_ROW_SIZE > stop)
+       break;
+
+      pex64_get_runtime_function (abfd, &rf, &pdata[i]);
+
+      if (rf.rva_BeginAddress == 0 && rf.rva_EndAddress == 0
+         && rf.rva_UnwindData == 0)
+       /* We are probably into the padding of the section now.  */
+       break;
+      fputc (' ', file);
+      fprintf_vma (file, i + pdata_section->vma);
+      fprintf (file, ":\t");
+      fprintf_vma (file, imagebase + rf.rva_BeginAddress);
+      fprintf (file, " ");
+      fprintf_vma (file, imagebase + rf.rva_EndAddress);
+      fprintf (file, " ");
+      fprintf_vma (file, imagebase + rf.rva_UnwindData);
+      fprintf (file, "\n");
+      if (i != 0 && rf.rva_BeginAddress <= prev_beginaddress)
+       {
+         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)
+       {
+         seen_error = 1;
+         fprintf (file, "  has negative begin address\n");
+       }
+      if ((rf.rva_EndAddress & 0x80000000) != 0)
+       {
+         seen_error = 1;
+         fprintf (file, "  has negative end address\n");
+       }
+      if ((rf.rva_UnwindData & 0x80000000) != 0)
+       {
+         seen_error = 1;
+         fprintf (file, "  has negative unwind address\n");
+       }
+      else if ((rf.rva_UnwindData && !PEX64_IS_RUNTIME_FUNCTION_CHAINED (&rf))
+               || virt_size_is_zero)
+       xdata_arr[xdata_arr_cnt++] = rf.rva_UnwindData;
     }
 
     }
 
-  start = 0;
+  if (seen_error)
+    goto done;
 
 
-  for (i = start; i < stop; i += onaline)
+  /* Add end of list marker.  */
+  xdata_arr[xdata_arr_cnt++] = ~((bfd_vma) 0);
+
+  /* Sort start RVAs of xdata.  */
+  if (xdata_arr_cnt > 1)
+    qsort (xdata_arr, (size_t) xdata_arr_cnt, sizeof (bfd_vma),
+          sort_xdata_arr);
+
+  /* Find the section containing the unwind data (.xdata).  */
+  xdata_base = xdata_arr[0];
+  /* 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");
+  /* 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 && 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)
     {
       struct pex64_runtime_function rf;
 
       if (i + PDATA_ROW_SIZE > stop)
        break;
     {
       struct pex64_runtime_function rf;
 
       if (i + PDATA_ROW_SIZE > stop)
        break;
-      pex64_get_runtime_function (abfd, &rf, &data[i]);
+
+      pex64_get_runtime_function (abfd, &rf, &pdata[i]);
 
       if (rf.rva_BeginAddress == 0 && rf.rva_EndAddress == 0
          && rf.rva_UnwindData == 0)
        /* We are probably into the padding of the section now.  */
        break;
 
       if (rf.rva_BeginAddress == 0 && rf.rva_EndAddress == 0
          && rf.rva_UnwindData == 0)
        /* We are probably into the padding of the section now.  */
        break;
+      if (i == 0)
+       fprintf (file, _("\nDump of %s\n"), xdata_section->name);
 
       fputc (' ', file);
 
       fputc (' ', file);
-      fprintf_vma (file, i + section->vma);
-      fprintf (file, ":\t");
-      rf.rva_BeginAddress += pe_data (abfd)->pe_opthdr.ImageBase;
-      fprintf_vma (file, rf.rva_BeginAddress);
-      fputc (' ', file);
-      rf.rva_EndAddress += pe_data (abfd)->pe_opthdr.ImageBase;
-      fprintf_vma (file, rf.rva_EndAddress);
-      fputc (' ', file);
-      fprintf_vma (file, rf.rva_UnwindData);
-      fprintf (file, "\n");
+      fprintf_vma (file, rf.rva_UnwindData + imagebase);
 
 
-      if (rf.rva_UnwindData != 0)
+      if (prev_unwinddata_rva == rf.rva_UnwindData)
        {
        {
-         if (rf.isChained)
+         /* Do not dump again the xdata for the same entry.  */
+         fprintf (file, " also used for function at ");
+         fprintf_vma (file, rf.rva_BeginAddress + imagebase);
+         fputc ('\n', file);
+         continue;
+       }
+      else
+       prev_unwinddata_rva = rf.rva_UnwindData;
+
+      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 || virt_size_is_zero)
+       {
+         if (PEX64_IS_RUNTIME_FUNCTION_CHAINED (&rf))
            {
            {
-             fprintf (file, "\t shares information with pdata element at 0x");
-             fprintf_vma (file, rf.rva_UnwindData + pe_data (abfd)->pe_opthdr.ImageBase);
+             bfd_vma altent = PEX64_GET_UNWINDDATA_UNIFIED_RVA (&rf);
+             bfd_vma pdata_vma = bfd_section_vma (pdata_section);
+             struct pex64_runtime_function arf;
+
+             fprintf (file, "\t shares information with ");
+             altent += imagebase;
+
+             if (altent >= pdata_vma
+                 && altent - pdata_vma + PDATA_ROW_SIZE <= stop)
+               {
+                 pex64_get_runtime_function
+                   (abfd, &arf, &pdata[altent - pdata_vma]);
+                 fprintf (file, "pdata element at 0x");
+                 fprintf_vma (file, arf.rva_UnwindData);
+               }
+             else
+               fprintf (file, "unknown pdata element");
              fprintf (file, ".\n");
            }
          else
              fprintf (file, ".\n");
            }
          else
-           pex64_dump_xdata (file, abfd, rf.rva_UnwindData, rf.rva_BeginAddress);
+           {
+             bfd_vma *p;
+
+             /* Search for the current entry in the sorted array.  */
+             p = (bfd_vma *)
+                 bsearch (&rf.rva_UnwindData, xdata_arr,
+                          (size_t) xdata_arr_cnt, sizeof (bfd_vma),
+                          sort_xdata_arr);
+
+             /* Advance to the next pointer into the xdata section.  We may
+                have shared xdata entries, which will result in a string of
+                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;
+
+             pex64_dump_xdata (file, abfd, xdata_section, xdata, p, &rf);
+           }
        }
     }
 
        }
     }
 
-  free (data);
+ done:
+  free (pdata);
+  free (xdata_arr);
+  free (xdata);
 
   return TRUE;
 }
 
 
   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_pe_print_pdata   pex64_bfd_print_pdata
+#define bfd_coff_std_swap_table bfd_coff_pei_swap_table
 
 #include "coff-x86_64.c"
 
 #include "coff-x86_64.c"
This page took 0.048867 seconds and 4 git commands to generate.