Home | History | Annotate | Line # | Download | only in bfd
      1   1.1  christos /* BFD back-end for Intel 386 PE IMAGE COFF files.
      2  1.10  christos    Copyright (C) 2006-2025 Free Software Foundation, Inc.
      3   1.1  christos 
      4   1.1  christos    This file is part of BFD, the Binary File Descriptor library.
      5   1.1  christos 
      6   1.1  christos    This program is free software; you can redistribute it and/or modify
      7   1.1  christos    it under the terms of the GNU General Public License as published by
      8   1.1  christos    the Free Software Foundation; either version 3 of the License, or
      9   1.1  christos    (at your option) any later version.
     10   1.1  christos 
     11   1.1  christos    This program is distributed in the hope that it will be useful,
     12   1.1  christos    but WITHOUT ANY WARRANTY; without even the implied warranty of
     13   1.1  christos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     14   1.1  christos    GNU General Public License for more details.
     15   1.1  christos 
     16   1.1  christos    You should have received a copy of the GNU General Public License
     17   1.1  christos    along with this program; if not, write to the Free Software
     18   1.1  christos    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
     19   1.1  christos    MA 02110-1301, USA.
     20   1.3  christos 
     21   1.1  christos    Written by Kai Tietz, OneVision Software GmbH&CoKg.  */
     22   1.1  christos 
     23   1.1  christos #include "sysdep.h"
     24   1.1  christos #include "bfd.h"
     25   1.1  christos 
     26   1.6  christos #define TARGET_SYM		x86_64_pei_vec
     27   1.6  christos #define TARGET_NAME		"pei-x86-64"
     28   1.1  christos #define COFF_IMAGE_WITH_PE
     29   1.1  christos #define COFF_WITH_PE
     30   1.1  christos #define COFF_WITH_pex64
     31   1.8  christos #define PCRELOFFSET		true
     32   1.1  christos #if defined (USE_MINGW64_LEADING_UNDERSCORES)
     33   1.6  christos #define TARGET_UNDERSCORE	'_'
     34   1.1  christos #else
     35   1.6  christos #define TARGET_UNDERSCORE	0
     36   1.1  christos #endif
     37   1.1  christos /* Long section names not allowed in executable images, only object files.  */
     38   1.1  christos #define COFF_LONG_SECTION_NAMES 0
     39   1.1  christos #define COFF_SUPPORT_GNU_LINKONCE
     40   1.1  christos #define COFF_LONG_FILENAMES
     41   1.1  christos #define PDATA_ROW_SIZE	(3 * 4)
     42   1.1  christos 
     43   1.1  christos #define COFF_SECTION_ALIGNMENT_ENTRIES \
     44   1.1  christos { COFF_SECTION_NAME_EXACT_MATCH (".bss"), \
     45   1.1  christos   COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 4 }, \
     46   1.1  christos { COFF_SECTION_NAME_PARTIAL_MATCH (".data"), \
     47   1.1  christos   COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 4 }, \
     48   1.1  christos { COFF_SECTION_NAME_PARTIAL_MATCH (".rdata"), \
     49   1.1  christos   COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 4 }, \
     50   1.1  christos { COFF_SECTION_NAME_PARTIAL_MATCH (".text"), \
     51   1.1  christos   COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 4 }, \
     52   1.1  christos { COFF_SECTION_NAME_PARTIAL_MATCH (".idata"), \
     53   1.1  christos   COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 2 }, \
     54  1.10  christos { COFF_SECTION_NAME_PARTIAL_MATCH (".didat"), \
     55  1.10  christos   COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 2 }, \
     56   1.1  christos { COFF_SECTION_NAME_EXACT_MATCH (".pdata"), \
     57   1.1  christos   COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 2 }, \
     58   1.1  christos { COFF_SECTION_NAME_PARTIAL_MATCH (".debug"), \
     59   1.1  christos   COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 0 }, \
     60   1.1  christos { COFF_SECTION_NAME_PARTIAL_MATCH (".gnu.linkonce.wi."), \
     61   1.1  christos   COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 0 }
     62   1.1  christos 
     63   1.1  christos #include "sysdep.h"
     64   1.1  christos #include "bfd.h"
     65   1.1  christos #include "libbfd.h"
     66   1.1  christos #include "coff/x86_64.h"
     67   1.1  christos #include "coff/internal.h"
     68   1.1  christos #include "coff/pe.h"
     69   1.1  christos #include "libcoff.h"
     70   1.1  christos #include "libpei.h"
     71   1.1  christos #include "libiberty.h"
     72   1.1  christos 
     73   1.1  christos #undef AOUTSZ
     74   1.1  christos #define AOUTSZ		PEPAOUTSZ
     75   1.1  christos #define PEAOUTHDR	PEPAOUTHDR
     76   1.1  christos 
     77   1.3  christos /* Name of registers according to SEH conventions.  */
     78   1.3  christos 
     79   1.3  christos static const char * const pex_regs[16] = {
     80   1.1  christos   "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi",
     81   1.1  christos   "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"
     82   1.1  christos };
     83   1.1  christos 
     84   1.3  christos /* Swap in a runtime function.  */
     85   1.3  christos 
     86   1.1  christos static void
     87   1.1  christos pex64_get_runtime_function (bfd *abfd, struct pex64_runtime_function *rf,
     88   1.1  christos 			    const void *data)
     89   1.1  christos {
     90   1.1  christos   const struct external_pex64_runtime_function *ex_rf =
     91   1.1  christos     (const struct external_pex64_runtime_function *) data;
     92   1.1  christos   rf->rva_BeginAddress = bfd_get_32 (abfd, ex_rf->rva_BeginAddress);
     93   1.1  christos   rf->rva_EndAddress = bfd_get_32 (abfd, ex_rf->rva_EndAddress);
     94   1.1  christos   rf->rva_UnwindData =	bfd_get_32 (abfd, ex_rf->rva_UnwindData);
     95   1.1  christos }
     96   1.1  christos 
     97   1.3  christos /* Swap in unwind info header.  */
     98   1.3  christos 
     99   1.8  christos static bool
    100   1.6  christos pex64_get_unwind_info (bfd *abfd, struct pex64_unwind_info *ui,
    101   1.6  christos 		       void *data, void *data_end)
    102   1.1  christos {
    103   1.1  christos   struct external_pex64_unwind_info *ex_ui =
    104   1.1  christos     (struct external_pex64_unwind_info *) data;
    105   1.1  christos   bfd_byte *ex_dta = (bfd_byte *) data;
    106   1.6  christos   bfd_byte *ex_dta_end = (bfd_byte *) data_end;
    107   1.1  christos 
    108   1.1  christos   memset (ui, 0, sizeof (struct pex64_unwind_info));
    109   1.6  christos 
    110   1.9  christos   if (ex_dta_end - ex_dta < 4)
    111   1.8  christos     return false;
    112   1.6  christos 
    113   1.1  christos   ui->Version = PEX64_UWI_VERSION (ex_ui->Version_Flags);
    114   1.1  christos   ui->Flags = PEX64_UWI_FLAGS (ex_ui->Version_Flags);
    115   1.1  christos   ui->SizeOfPrologue = (bfd_vma) ex_ui->SizeOfPrologue;
    116   1.1  christos   ui->CountOfCodes = (bfd_vma) ex_ui->CountOfCodes;
    117   1.1  christos   ui->FrameRegister = PEX64_UWI_FRAMEREG (ex_ui->FrameRegisterOffset);
    118   1.1  christos   ui->FrameOffset = PEX64_UWI_FRAMEOFF (ex_ui->FrameRegisterOffset);
    119   1.1  christos   ui->sizeofUnwindCodes = PEX64_UWI_SIZEOF_UWCODE_ARRAY (ui->CountOfCodes);
    120   1.1  christos   ui->SizeOfBlock = ui->sizeofUnwindCodes + 4;
    121   1.6  christos   ui->rawUnwindCodes = ex_dta + 4;
    122   1.6  christos   ui->rawUnwindCodesEnd = ex_dta_end;
    123   1.3  christos 
    124   1.9  christos   if ((size_t) (ex_dta_end - ex_dta) < ui->SizeOfBlock)
    125   1.9  christos     return false;
    126   1.1  christos   ex_dta += ui->SizeOfBlock;
    127   1.7  christos 
    128   1.1  christos   switch (ui->Flags)
    129   1.1  christos     {
    130   1.1  christos     case UNW_FLAG_CHAININFO:
    131   1.9  christos       if (ex_dta_end - ex_dta < 12)
    132   1.8  christos 	return false;
    133   1.3  christos       ui->rva_BeginAddress = bfd_get_32 (abfd, ex_dta + 0);
    134   1.3  christos       ui->rva_EndAddress = bfd_get_32 (abfd, ex_dta + 4);
    135   1.3  christos       ui->rva_UnwindData = bfd_get_32 (abfd, ex_dta + 8);
    136   1.3  christos       ui->SizeOfBlock += 12;
    137   1.8  christos       return true;
    138   1.3  christos     case UNW_FLAG_EHANDLER:
    139   1.3  christos     case UNW_FLAG_UHANDLER:
    140   1.3  christos     case UNW_FLAG_FHANDLER:
    141   1.9  christos       if (ex_dta_end - ex_dta < 4)
    142   1.8  christos 	return false;
    143   1.3  christos       ui->rva_ExceptionHandler = bfd_get_32 (abfd, ex_dta);
    144   1.1  christos       ui->SizeOfBlock += 4;
    145   1.8  christos       return true;
    146   1.1  christos     default:
    147   1.8  christos       return true;
    148   1.1  christos     }
    149   1.1  christos }
    150   1.1  christos 
    151   1.3  christos /* Display unwind codes.  */
    152   1.3  christos 
    153   1.1  christos static void
    154   1.3  christos pex64_xdata_print_uwd_codes (FILE *file, bfd *abfd,
    155   1.3  christos 			     struct pex64_unwind_info *ui,
    156   1.3  christos 			     struct pex64_runtime_function *rf)
    157   1.1  christos {
    158   1.3  christos   unsigned int i;
    159   1.3  christos   unsigned int tmp; /* At least 32 bits.  */
    160   1.3  christos   int save_allowed;
    161   1.1  christos 
    162   1.3  christos   if (ui->CountOfCodes == 0 || ui->rawUnwindCodes == NULL)
    163   1.1  christos     return;
    164   1.1  christos 
    165   1.3  christos   /* According to UNWIND_CODE documentation:
    166   1.3  christos       If an FP reg is used, the any unwind code taking an offset must only be
    167   1.3  christos       used after the FP reg is established in the prolog.
    168   1.3  christos      But there are counter examples of that in system dlls...  */
    169   1.8  christos   save_allowed = true;
    170   1.3  christos 
    171   1.3  christos   i = 0;
    172   1.3  christos 
    173   1.9  christos   if ((size_t) (ui->rawUnwindCodesEnd - ui->rawUnwindCodes)
    174   1.9  christos       < ui->CountOfCodes * 2)
    175   1.6  christos     {
    176   1.6  christos       fprintf (file, _("warning: corrupt unwind data\n"));
    177   1.6  christos       return;
    178   1.6  christos     }
    179   1.6  christos 
    180   1.3  christos   if (ui->Version == 2
    181   1.3  christos       && PEX64_UNWCODE_CODE (ui->rawUnwindCodes[1]) == UWOP_EPILOG)
    182   1.1  christos     {
    183   1.3  christos       /* Display epilog opcode (whose docoding is not fully documented).
    184   1.6  christos 	 Looks to be designed to speed-up unwinding, as there is no need
    185   1.3  christos 	 to decode instruction flow if outside an epilog.  */
    186   1.3  christos       unsigned int func_size = rf->rva_EndAddress - rf->rva_BeginAddress;
    187   1.3  christos 
    188   1.3  christos       fprintf (file, "\tv2 epilog (length: %02x) at pc+:",
    189   1.3  christos 	       ui->rawUnwindCodes[0]);
    190   1.6  christos 
    191   1.3  christos       if (PEX64_UNWCODE_INFO (ui->rawUnwindCodes[1]))
    192   1.3  christos 	fprintf (file, " 0x%x", func_size - ui->rawUnwindCodes[0]);
    193   1.6  christos 
    194   1.3  christos       i++;
    195   1.3  christos       for (; i < ui->CountOfCodes; i++)
    196   1.3  christos 	{
    197   1.3  christos 	  const bfd_byte *dta = ui->rawUnwindCodes + 2 * i;
    198   1.3  christos 	  unsigned int off;
    199   1.1  christos 
    200   1.3  christos 	  if (PEX64_UNWCODE_CODE (dta[1]) != UWOP_EPILOG)
    201   1.3  christos 	    break;
    202   1.3  christos 	  off = dta[0] | (PEX64_UNWCODE_INFO (dta[1]) << 8);
    203   1.3  christos 	  if (off == 0)
    204   1.3  christos 	    fprintf (file, " [pad]");
    205   1.3  christos 	  else
    206   1.3  christos 	    fprintf (file, " 0x%x", func_size - off);
    207   1.1  christos 	}
    208   1.3  christos       fputc ('\n', file);
    209   1.1  christos     }
    210   1.3  christos 
    211   1.3  christos   for (; i < ui->CountOfCodes; i++)
    212   1.3  christos     {
    213   1.3  christos       const bfd_byte *dta = ui->rawUnwindCodes + 2 * i;
    214   1.3  christos       unsigned int info = PEX64_UNWCODE_INFO (dta[1]);
    215   1.8  christos       int unexpected = false;
    216   1.3  christos 
    217   1.3  christos       fprintf (file, "\t  pc+0x%02x: ", (unsigned int) dta[0]);
    218   1.7  christos 
    219   1.1  christos       switch (PEX64_UNWCODE_CODE (dta[1]))
    220   1.1  christos 	{
    221   1.1  christos 	case UWOP_PUSH_NONVOL:
    222   1.3  christos 	  fprintf (file, "push %s", pex_regs[info]);
    223   1.1  christos 	  break;
    224   1.7  christos 
    225   1.1  christos 	case UWOP_ALLOC_LARGE:
    226   1.3  christos 	  if (info == 0)
    227   1.1  christos 	    {
    228   1.9  christos 	      if (ui->rawUnwindCodesEnd - dta < 4)
    229   1.7  christos 		{
    230   1.7  christos 		  fprintf (file, _("warning: corrupt unwind data\n"));
    231   1.7  christos 		  return;
    232   1.7  christos 		}
    233   1.7  christos 	      tmp = bfd_get_16 (abfd, dta + 2) * 8;
    234   1.3  christos 	      i++;
    235   1.1  christos 	    }
    236   1.1  christos 	  else
    237   1.3  christos 	    {
    238   1.9  christos 	      if (ui->rawUnwindCodesEnd - dta < 6)
    239   1.7  christos 		{
    240   1.7  christos 		  fprintf (file, _("warning: corrupt unwind data\n"));
    241   1.7  christos 		  return;
    242   1.7  christos 		}
    243   1.7  christos 	      tmp = bfd_get_32 (abfd, dta + 2);
    244   1.3  christos 	      i += 2;
    245   1.3  christos 	    }
    246   1.3  christos 	  fprintf (file, "alloc large area: rsp = rsp - 0x%x", tmp);
    247   1.1  christos 	  break;
    248   1.7  christos 
    249   1.1  christos 	case UWOP_ALLOC_SMALL:
    250   1.3  christos 	  fprintf (file, "alloc small area: rsp = rsp - 0x%x", (info + 1) * 8);
    251   1.1  christos 	  break;
    252   1.7  christos 
    253   1.1  christos 	case UWOP_SET_FPREG:
    254   1.3  christos 	  /* According to the documentation, info field is unused.  */
    255   1.3  christos 	  fprintf (file, "FPReg: %s = rsp + 0x%x (info = 0x%x)",
    256   1.3  christos 		   pex_regs[ui->FrameRegister],
    257   1.3  christos 		   (unsigned int) ui->FrameOffset * 16, info);
    258   1.3  christos 	  unexpected = ui->FrameRegister == 0;
    259   1.8  christos 	  save_allowed = false;
    260   1.1  christos 	  break;
    261   1.7  christos 
    262   1.1  christos 	case UWOP_SAVE_NONVOL:
    263   1.9  christos 	  if (ui->rawUnwindCodesEnd - dta < 4)
    264   1.7  christos 	    {
    265   1.7  christos 	      fprintf (file, _("warning: corrupt unwind data\n"));
    266   1.7  christos 	      return;
    267   1.7  christos 	    }
    268   1.7  christos 	  tmp = bfd_get_16 (abfd, dta + 2) * 8;
    269   1.3  christos 	  i++;
    270   1.3  christos 	  fprintf (file, "save %s at rsp + 0x%x", pex_regs[info], tmp);
    271   1.3  christos 	  unexpected = !save_allowed;
    272   1.1  christos 	  break;
    273   1.7  christos 
    274   1.1  christos 	case UWOP_SAVE_NONVOL_FAR:
    275   1.9  christos 	  if (ui->rawUnwindCodesEnd - dta < 6)
    276   1.7  christos 	    {
    277   1.7  christos 	      fprintf (file, _("warning: corrupt unwind data\n"));
    278   1.7  christos 	      return;
    279   1.7  christos 	    }
    280   1.7  christos 	  tmp = bfd_get_32 (abfd, dta + 2);
    281   1.3  christos 	  i += 2;
    282   1.3  christos 	  fprintf (file, "save %s at rsp + 0x%x", pex_regs[info], tmp);
    283   1.3  christos 	  unexpected = !save_allowed;
    284   1.1  christos 	  break;
    285   1.7  christos 
    286   1.1  christos 	case UWOP_SAVE_XMM:
    287   1.3  christos 	  if (ui->Version == 1)
    288   1.3  christos 	    {
    289   1.9  christos 	      if (ui->rawUnwindCodesEnd - dta < 4)
    290   1.7  christos 		{
    291   1.7  christos 		  fprintf (file, _("warning: corrupt unwind data\n"));
    292   1.7  christos 		  return;
    293   1.7  christos 		}
    294   1.7  christos 	      tmp = bfd_get_16 (abfd, dta + 2) * 8;
    295   1.3  christos 	      i++;
    296   1.3  christos 	      fprintf (file, "save mm%u at rsp + 0x%x", info, tmp);
    297   1.3  christos 	      unexpected = !save_allowed;
    298   1.3  christos 	    }
    299   1.3  christos 	  else if (ui->Version == 2)
    300   1.3  christos 	    {
    301   1.3  christos 	      fprintf (file, "epilog %02x %01x", dta[0], info);
    302   1.8  christos 	      unexpected = true;
    303   1.3  christos 	    }
    304   1.1  christos 	  break;
    305   1.7  christos 
    306   1.1  christos 	case UWOP_SAVE_XMM_FAR:
    307   1.9  christos 	  if (ui->rawUnwindCodesEnd - dta < 6)
    308   1.7  christos 	    {
    309   1.7  christos 	      fprintf (file, _("warning: corrupt unwind data\n"));
    310   1.7  christos 	      return;
    311   1.7  christos 	    }
    312   1.7  christos 	  tmp = bfd_get_32 (abfd, dta + 2) * 8;
    313   1.3  christos 	  i += 2;
    314   1.3  christos 	  fprintf (file, "save mm%u at rsp + 0x%x", info, tmp);
    315   1.3  christos 	  unexpected = !save_allowed;
    316   1.1  christos 	  break;
    317   1.7  christos 
    318   1.1  christos 	case UWOP_SAVE_XMM128:
    319   1.9  christos 	  if (ui->rawUnwindCodesEnd - dta < 4)
    320   1.7  christos 	    {
    321   1.7  christos 	      fprintf (file, _("warning: corrupt unwind data\n"));
    322   1.7  christos 	      return;
    323   1.7  christos 	    }
    324   1.7  christos 	  tmp = bfd_get_16 (abfd, dta + 2) * 16;
    325   1.3  christos 	  i++;
    326   1.3  christos 	  fprintf (file, "save xmm%u at rsp + 0x%x", info, tmp);
    327   1.3  christos 	  unexpected = !save_allowed;
    328   1.1  christos 	  break;
    329   1.7  christos 
    330   1.1  christos 	case UWOP_SAVE_XMM128_FAR:
    331   1.9  christos 	  if (ui->rawUnwindCodesEnd - dta < 6)
    332   1.7  christos 	    {
    333   1.7  christos 	      fprintf (file, _("warning: corrupt unwind data\n"));
    334   1.7  christos 	      return;
    335   1.7  christos 	    }
    336   1.7  christos 	  tmp = bfd_get_32 (abfd, dta + 2) * 16;
    337   1.3  christos 	  i += 2;
    338   1.3  christos 	  fprintf (file, "save xmm%u at rsp + 0x%x", info, tmp);
    339   1.3  christos 	  unexpected = !save_allowed;
    340   1.1  christos 	  break;
    341   1.7  christos 
    342   1.1  christos 	case UWOP_PUSH_MACHFRAME:
    343   1.1  christos 	  fprintf (file, "interrupt entry (SS, old RSP, EFLAGS, CS, RIP");
    344   1.3  christos 	  if (info == 0)
    345   1.3  christos 	    fprintf (file, ")");
    346   1.3  christos 	  else if (info == 1)
    347   1.3  christos 	    fprintf (file, ",ErrorCode)");
    348   1.1  christos 	  else
    349   1.3  christos 	    fprintf (file, ", unknown(%u))", info);
    350   1.1  christos 	  break;
    351   1.7  christos 
    352   1.1  christos 	default:
    353   1.3  christos 	  /* PR 17512: file: 2245-7442-0.004.  */
    354   1.3  christos 	  fprintf (file, _("Unknown: %x"), PEX64_UNWCODE_CODE (dta[1]));
    355   1.1  christos 	  break;
    356   1.7  christos 	}
    357   1.7  christos 
    358   1.3  christos       if (unexpected)
    359   1.3  christos 	fprintf (file, " [Unexpected!]");
    360   1.3  christos       fputc ('\n', file);
    361   1.1  christos     }
    362   1.1  christos }
    363   1.1  christos 
    364   1.3  christos /* Check wether section SEC_NAME contains the xdata at address ADDR.  */
    365   1.3  christos 
    366   1.1  christos static asection *
    367   1.1  christos pex64_get_section_by_rva (bfd *abfd, bfd_vma addr, const char *sec_name)
    368   1.1  christos {
    369   1.1  christos   asection *section = bfd_get_section_by_name (abfd, sec_name);
    370   1.1  christos   bfd_vma vsize;
    371   1.1  christos   bfd_size_type datasize = 0;
    372   1.1  christos 
    373   1.1  christos   if (section == NULL
    374   1.1  christos       || coff_section_data (abfd, section) == NULL
    375   1.1  christos       || pei_section_data (abfd, section) == NULL)
    376   1.1  christos     return NULL;
    377   1.1  christos   vsize = section->vma - pe_data (abfd)->pe_opthdr.ImageBase;
    378   1.1  christos   datasize = section->size;
    379   1.1  christos   if (!datasize || vsize > addr || (vsize + datasize) < addr)
    380   1.1  christos     return NULL;
    381   1.1  christos   return section;
    382   1.1  christos }
    383   1.1  christos 
    384   1.3  christos /* Dump xdata at for function RF to FILE.  The argument XDATA_SECTION
    385   1.3  christos    designate the bfd section containing the xdata, XDATA is its content,
    386   1.3  christos    and ENDX the size if known (or NULL).  */
    387   1.3  christos 
    388   1.1  christos static void
    389   1.3  christos pex64_dump_xdata (FILE *file, bfd *abfd,
    390   1.3  christos 		  asection *xdata_section, bfd_byte *xdata, bfd_vma *endx,
    391   1.3  christos 		  struct pex64_runtime_function *rf)
    392   1.1  christos {
    393   1.3  christos   bfd_vma vaddr;
    394   1.1  christos   bfd_vma end_addr;
    395   1.3  christos   bfd_vma addr = rf->rva_UnwindData;
    396   1.3  christos   bfd_size_type sec_size = xdata_section->rawsize > 0 ? xdata_section->rawsize : xdata_section->size;
    397   1.3  christos   struct pex64_unwind_info ui;
    398   1.3  christos 
    399   1.3  christos   vaddr = xdata_section->vma - pe_data (abfd)->pe_opthdr.ImageBase;
    400   1.3  christos   addr -= vaddr;
    401   1.1  christos 
    402   1.3  christos   /* PR 17512: file: 2245-7442-0.004.  */
    403   1.3  christos   if (addr >= sec_size)
    404   1.3  christos     {
    405   1.3  christos       fprintf (file, _("warning: xdata section corrupt\n"));
    406   1.3  christos       return;
    407   1.1  christos     }
    408   1.1  christos 
    409   1.1  christos   if (endx)
    410   1.3  christos     {
    411   1.3  christos       end_addr = endx[0] - vaddr;
    412   1.3  christos       /* PR 17512: file: 2245-7442-0.004.  */
    413   1.3  christos       if (end_addr > sec_size)
    414   1.3  christos 	{
    415   1.6  christos 	  fprintf (file, _("warning: xdata section corrupt\n"));
    416   1.3  christos 	  end_addr = sec_size;
    417   1.3  christos 	}
    418   1.3  christos     }
    419   1.1  christos   else
    420   1.3  christos     end_addr = sec_size;
    421   1.3  christos 
    422   1.6  christos   if (! pex64_get_unwind_info (abfd, &ui, xdata + addr, xdata + end_addr))
    423   1.6  christos     {
    424   1.6  christos       fprintf (file, _("warning: xdata section corrupt\n"));
    425   1.6  christos       return;
    426   1.6  christos     }
    427   1.1  christos 
    428   1.3  christos   if (ui.Version != 1 && ui.Version != 2)
    429   1.1  christos     {
    430   1.3  christos       unsigned int i;
    431   1.3  christos       fprintf (file, "\tVersion %u (unknown).\n",
    432   1.3  christos 	       (unsigned int) ui.Version);
    433   1.3  christos       for (i = 0; addr < end_addr; addr += 1, i++)
    434   1.3  christos 	{
    435   1.3  christos 	  if ((i & 15) == 0)
    436   1.3  christos 	    fprintf (file, "\t  %03x:", i);
    437   1.3  christos 	  fprintf (file, " %02x", xdata[addr]);
    438   1.3  christos 	  if ((i & 15) == 15)
    439   1.3  christos 	    fprintf (file, "\n");
    440   1.3  christos 	}
    441   1.3  christos       if ((i & 15) != 0)
    442   1.3  christos 	fprintf (file, "\n");
    443   1.3  christos       return;
    444   1.3  christos     }
    445   1.1  christos 
    446   1.3  christos   fprintf (file, "\tVersion: %d, Flags: ", ui.Version);
    447   1.3  christos   switch (ui.Flags)
    448   1.3  christos     {
    449   1.3  christos     case UNW_FLAG_NHANDLER:
    450   1.3  christos       fprintf (file, "none");
    451   1.3  christos       break;
    452   1.3  christos     case UNW_FLAG_EHANDLER:
    453   1.3  christos       fprintf (file, "UNW_FLAG_EHANDLER");
    454   1.3  christos       break;
    455   1.3  christos     case UNW_FLAG_UHANDLER:
    456   1.3  christos       fprintf (file, "UNW_FLAG_UHANDLER");
    457   1.3  christos       break;
    458   1.3  christos     case UNW_FLAG_FHANDLER:
    459   1.3  christos       fprintf
    460   1.3  christos 	(file, "UNW_FLAG_EHANDLER | UNW_FLAG_UHANDLER");
    461   1.3  christos       break;
    462   1.3  christos     case UNW_FLAG_CHAININFO:
    463   1.3  christos       fprintf (file, "UNW_FLAG_CHAININFO");
    464   1.3  christos       break;
    465   1.3  christos     default:
    466   1.3  christos       fprintf (file, "unknown flags value 0x%x", (unsigned int) ui.Flags);
    467   1.3  christos       break;
    468   1.3  christos     }
    469   1.3  christos   fputc ('\n', file);
    470   1.3  christos   fprintf (file, "\tNbr codes: %u, ", (unsigned int) ui.CountOfCodes);
    471   1.3  christos   fprintf (file, "Prologue size: 0x%02x, Frame offset: 0x%x, ",
    472   1.3  christos 	   (unsigned int) ui.SizeOfPrologue, (unsigned int) ui.FrameOffset);
    473   1.3  christos   fprintf (file, "Frame reg: %s\n",
    474   1.3  christos 	   ui.FrameRegister == 0 ? "none"
    475   1.3  christos 	   : pex_regs[(unsigned int) ui.FrameRegister]);
    476   1.3  christos 
    477   1.3  christos   /* PR 17512: file: 2245-7442-0.004.  */
    478   1.3  christos   if (ui.CountOfCodes * 2 + ui.rawUnwindCodes > xdata + xdata_section->size)
    479   1.3  christos     fprintf (file, _("Too many unwind codes (%ld)\n"), (long) ui.CountOfCodes);
    480   1.3  christos   else
    481   1.3  christos     pex64_xdata_print_uwd_codes (file, abfd, &ui, rf);
    482   1.1  christos 
    483   1.3  christos   switch (ui.Flags)
    484   1.3  christos     {
    485   1.3  christos     case UNW_FLAG_EHANDLER:
    486   1.3  christos     case UNW_FLAG_UHANDLER:
    487   1.3  christos     case UNW_FLAG_FHANDLER:
    488   1.9  christos       fprintf (file, "\tHandler: %016" PRIx64 ".\n",
    489   1.9  christos 	       ui.rva_ExceptionHandler + pe_data (abfd)->pe_opthdr.ImageBase);
    490   1.3  christos       break;
    491   1.3  christos     case UNW_FLAG_CHAININFO:
    492   1.9  christos       fprintf (file, "\tChain: start: %016" PRIx64 ", end: %016" PRIx64,
    493   1.9  christos 	       ui.rva_BeginAddress, ui.rva_EndAddress);
    494   1.9  christos       fprintf (file, "\n\t unwind data: %016" PRIx64 ".\n",
    495   1.9  christos 	       ui.rva_UnwindData);
    496   1.3  christos       break;
    497   1.3  christos     }
    498   1.1  christos 
    499   1.3  christos   /* Now we need end of this xdata block.  */
    500   1.3  christos   addr += ui.SizeOfBlock;
    501   1.3  christos   if (addr < end_addr)
    502   1.3  christos     {
    503   1.3  christos       unsigned int i;
    504   1.3  christos       fprintf (file,"\tUser data:\n");
    505   1.3  christos       for (i = 0; addr < end_addr; addr += 1, i++)
    506   1.1  christos 	{
    507   1.3  christos 	  if ((i & 15) == 0)
    508   1.3  christos 	    fprintf (file, "\t  %03x:", i);
    509   1.3  christos 	  fprintf (file, " %02x", xdata[addr]);
    510   1.3  christos 	  if ((i & 15) == 15)
    511   1.3  christos 	    fprintf (file, "\n");
    512   1.1  christos 	}
    513   1.3  christos       if ((i & 15) != 0)
    514   1.3  christos 	fprintf (file, "\n");
    515   1.1  christos     }
    516   1.1  christos }
    517   1.1  christos 
    518   1.3  christos /* Helper function to sort xdata.  The entries of xdata are sorted to know
    519   1.3  christos    the size of each entry.  */
    520   1.3  christos 
    521   1.1  christos static int
    522   1.1  christos sort_xdata_arr (const void *l, const void *r)
    523   1.1  christos {
    524   1.1  christos   const bfd_vma *lp = (const bfd_vma *) l;
    525   1.1  christos   const bfd_vma *rp = (const bfd_vma *) r;
    526   1.1  christos 
    527   1.1  christos   if (*lp == *rp)
    528   1.1  christos     return 0;
    529   1.1  christos   return (*lp < *rp ? -1 : 1);
    530   1.1  christos }
    531   1.1  christos 
    532   1.3  christos /* Display unwind tables for x86-64.  */
    533   1.3  christos 
    534   1.8  christos static bool
    535   1.3  christos pex64_bfd_print_pdata_section (bfd *abfd, void *vfile, asection *pdata_section)
    536   1.1  christos {
    537   1.1  christos   FILE *file = (FILE *) vfile;
    538   1.3  christos   bfd_byte *pdata = NULL;
    539   1.3  christos   bfd_byte *xdata = NULL;
    540   1.3  christos   asection *xdata_section = NULL;
    541   1.3  christos   bfd_vma xdata_base;
    542   1.1  christos   bfd_size_type i;
    543   1.3  christos   bfd_size_type datasize;
    544   1.1  christos   bfd_size_type stop;
    545   1.3  christos   bfd_vma prev_beginaddress = (bfd_vma) -1;
    546   1.3  christos   bfd_vma prev_unwinddata_rva = (bfd_vma) -1;
    547   1.3  christos   bfd_vma imagebase;
    548   1.1  christos   int onaline = PDATA_ROW_SIZE;
    549   1.1  christos   int seen_error = 0;
    550   1.3  christos   bfd_vma *xdata_arr = NULL;
    551   1.1  christos   int xdata_arr_cnt;
    552   1.8  christos   bool virt_size_is_zero = false;
    553   1.1  christos 
    554   1.3  christos   /* Sanity checks.  */
    555   1.3  christos   if (pdata_section == NULL
    556   1.9  christos       || (pdata_section->flags & SEC_HAS_CONTENTS) == 0
    557   1.3  christos       || coff_section_data (abfd, pdata_section) == NULL
    558   1.3  christos       || pei_section_data (abfd, pdata_section) == NULL)
    559   1.8  christos     return true;
    560   1.1  christos 
    561   1.3  christos   stop = pei_section_data (abfd, pdata_section)->virt_size;
    562   1.1  christos   if ((stop % onaline) != 0)
    563   1.1  christos     fprintf (file,
    564   1.6  christos 	     /* xgettext:c-format */
    565   1.3  christos 	     _("Warning: %s section size (%ld) is not a multiple of %d\n"),
    566   1.3  christos 	     pdata_section->name, (long) stop, onaline);
    567   1.1  christos 
    568   1.3  christos   datasize = pdata_section->size;
    569   1.3  christos   if (datasize == 0)
    570   1.3  christos     {
    571   1.3  christos       if (stop)
    572   1.3  christos 	fprintf (file, _("Warning: %s section size is zero\n"),
    573   1.3  christos 		 pdata_section->name);
    574   1.8  christos       return true;
    575   1.3  christos     }
    576   1.3  christos 
    577   1.3  christos   /* virt_size might be zero for objects.  */
    578   1.3  christos   if (stop == 0 && strcmp (abfd->xvec->name, "pe-x86-64") == 0)
    579   1.3  christos     {
    580   1.7  christos       stop = datasize;
    581   1.8  christos       virt_size_is_zero = true;
    582   1.3  christos     }
    583   1.3  christos   else if (datasize < stop)
    584   1.3  christos       {
    585   1.3  christos 	fprintf (file,
    586   1.6  christos 		 /* xgettext:c-format */
    587   1.3  christos 		 _("Warning: %s section size (%ld) is smaller than virtual size (%ld)\n"),
    588   1.3  christos 		 pdata_section->name, (unsigned long) datasize,
    589   1.3  christos 		 (unsigned long) stop);
    590   1.7  christos 	/* Be sure not to read past datasize.  */
    591   1.7  christos 	stop = datasize;
    592   1.3  christos       }
    593   1.3  christos 
    594   1.3  christos   /* Display functions table.  */
    595   1.1  christos   fprintf (file,
    596   1.3  christos 	   _("\nThe Function Table (interpreted %s section contents)\n"),
    597   1.3  christos 	   pdata_section->name);
    598   1.1  christos 
    599   1.1  christos   fprintf (file, _("vma:\t\t\tBeginAddress\t EndAddress\t  UnwindData\n"));
    600   1.1  christos 
    601   1.3  christos   if (!bfd_malloc_and_get_section (abfd, pdata_section, &pdata))
    602   1.3  christos     goto done;
    603   1.1  christos 
    604   1.3  christos   /* Table of xdata entries.  */
    605   1.1  christos   xdata_arr = (bfd_vma *) xmalloc (sizeof (bfd_vma) * ((stop / onaline) + 1));
    606   1.1  christos   xdata_arr_cnt = 0;
    607   1.3  christos 
    608   1.3  christos   if (strcmp (abfd->xvec->name, "pei-x86-64") == 0)
    609   1.3  christos     imagebase = pe_data (abfd)->pe_opthdr.ImageBase;
    610   1.3  christos   else
    611   1.3  christos     imagebase = 0;
    612   1.3  christos 
    613   1.1  christos   for (i = 0; i < stop; i += onaline)
    614   1.1  christos     {
    615   1.1  christos       struct pex64_runtime_function rf;
    616   1.1  christos 
    617   1.1  christos       if (i + PDATA_ROW_SIZE > stop)
    618   1.1  christos 	break;
    619   1.3  christos 
    620   1.3  christos       pex64_get_runtime_function (abfd, &rf, &pdata[i]);
    621   1.1  christos 
    622   1.1  christos       if (rf.rva_BeginAddress == 0 && rf.rva_EndAddress == 0
    623   1.1  christos 	  && rf.rva_UnwindData == 0)
    624   1.1  christos 	/* We are probably into the padding of the section now.  */
    625   1.1  christos 	break;
    626   1.9  christos       fprintf (file, " %016" PRIx64, i + pdata_section->vma);
    627   1.9  christos       fprintf (file, ":\t%016" PRIx64, imagebase + rf.rva_BeginAddress);
    628   1.9  christos       fprintf (file, " %016" PRIx64, imagebase + rf.rva_EndAddress);
    629   1.9  christos       fprintf (file, " %016" PRIx64 "\n", imagebase + rf.rva_UnwindData);
    630   1.1  christos       if (i != 0 && rf.rva_BeginAddress <= prev_beginaddress)
    631   1.1  christos 	{
    632   1.1  christos 	  seen_error = 1;
    633   1.1  christos 	  fprintf (file, "  has %s begin address as predecessor\n",
    634   1.1  christos 	    (rf.rva_BeginAddress < prev_beginaddress ? "smaller" : "same"));
    635   1.6  christos 	}
    636   1.1  christos       prev_beginaddress = rf.rva_BeginAddress;
    637   1.1  christos       /* Now we check for negative addresses.  */
    638   1.1  christos       if ((prev_beginaddress & 0x80000000) != 0)
    639   1.1  christos 	{
    640   1.1  christos 	  seen_error = 1;
    641   1.1  christos 	  fprintf (file, "  has negative begin address\n");
    642   1.1  christos 	}
    643   1.1  christos       if ((rf.rva_EndAddress & 0x80000000) != 0)
    644   1.1  christos 	{
    645   1.1  christos 	  seen_error = 1;
    646   1.1  christos 	  fprintf (file, "  has negative end address\n");
    647   1.1  christos 	}
    648   1.1  christos       if ((rf.rva_UnwindData & 0x80000000) != 0)
    649   1.1  christos 	{
    650   1.1  christos 	  seen_error = 1;
    651   1.1  christos 	  fprintf (file, "  has negative unwind address\n");
    652   1.1  christos 	}
    653   1.3  christos       else if ((rf.rva_UnwindData && !PEX64_IS_RUNTIME_FUNCTION_CHAINED (&rf))
    654   1.3  christos 		|| virt_size_is_zero)
    655   1.3  christos 	xdata_arr[xdata_arr_cnt++] = rf.rva_UnwindData;
    656   1.1  christos     }
    657   1.1  christos 
    658   1.1  christos   if (seen_error)
    659   1.3  christos     goto done;
    660   1.1  christos 
    661   1.1  christos   /* Add end of list marker.  */
    662   1.1  christos   xdata_arr[xdata_arr_cnt++] = ~((bfd_vma) 0);
    663   1.1  christos 
    664   1.1  christos   /* Sort start RVAs of xdata.  */
    665   1.1  christos   if (xdata_arr_cnt > 1)
    666   1.1  christos     qsort (xdata_arr, (size_t) xdata_arr_cnt, sizeof (bfd_vma),
    667   1.1  christos 	   sort_xdata_arr);
    668   1.1  christos 
    669   1.3  christos   /* Find the section containing the unwind data (.xdata).  */
    670   1.3  christos   xdata_base = xdata_arr[0];
    671   1.3  christos   /* For sections with long names, first look for the same
    672   1.3  christos      section name, replacing .pdata by .xdata prefix.  */
    673   1.3  christos   if (strcmp (pdata_section->name, ".pdata") != 0)
    674   1.3  christos     {
    675   1.3  christos       size_t len = strlen (pdata_section->name);
    676   1.5  christos       char *xdata_name = xmalloc (len + 1);
    677   1.3  christos 
    678   1.3  christos       xdata_name = memcpy (xdata_name, pdata_section->name, len + 1);
    679   1.3  christos       /* Transform .pdata prefix into .xdata prefix.  */
    680   1.3  christos       if (len > 1)
    681   1.3  christos 	xdata_name [1] = 'x';
    682   1.3  christos       xdata_section = pex64_get_section_by_rva (abfd, xdata_base,
    683   1.3  christos 						xdata_name);
    684   1.5  christos       free (xdata_name);
    685   1.3  christos     }
    686   1.3  christos   /* Second, try the .xdata section itself.  */
    687   1.3  christos   if (!xdata_section)
    688   1.3  christos     xdata_section = pex64_get_section_by_rva (abfd, xdata_base, ".xdata");
    689   1.3  christos   /* Otherwise, if xdata_base is non zero, search also inside
    690   1.3  christos      other standard sections.  */
    691   1.3  christos   if (!xdata_section && xdata_base)
    692   1.3  christos     xdata_section = pex64_get_section_by_rva (abfd, xdata_base, ".rdata");
    693   1.3  christos   if (!xdata_section && xdata_base)
    694   1.3  christos     xdata_section = pex64_get_section_by_rva (abfd, xdata_base, ".data");
    695   1.3  christos   if (!xdata_section && xdata_base)
    696   1.3  christos     xdata_section = pex64_get_section_by_rva (abfd, xdata_base, ".pdata");
    697   1.3  christos   if (!xdata_section && xdata_base)
    698   1.3  christos     xdata_section = pex64_get_section_by_rva (abfd, xdata_base, ".text");
    699   1.3  christos   /* Transfer xdata section into xdata array.  */
    700   1.3  christos   if (!xdata_section
    701   1.9  christos       || (xdata_section->flags & SEC_HAS_CONTENTS) == 0
    702   1.3  christos       || !bfd_malloc_and_get_section (abfd, xdata_section, &xdata))
    703   1.3  christos     goto done;
    704   1.3  christos 
    705   1.3  christos   /* Avoid "also used "... ouput for single unwind info
    706   1.3  christos      in object file.  */
    707   1.3  christos   prev_unwinddata_rva = (bfd_vma) -1;
    708   1.3  christos 
    709   1.1  christos   /* Do dump of pdata related xdata.  */
    710   1.1  christos   for (i = 0; i < stop; i += onaline)
    711   1.1  christos     {
    712   1.1  christos       struct pex64_runtime_function rf;
    713   1.1  christos 
    714   1.1  christos       if (i + PDATA_ROW_SIZE > stop)
    715   1.1  christos 	break;
    716   1.3  christos 
    717   1.3  christos       pex64_get_runtime_function (abfd, &rf, &pdata[i]);
    718   1.1  christos 
    719   1.1  christos       if (rf.rva_BeginAddress == 0 && rf.rva_EndAddress == 0
    720   1.1  christos 	  && rf.rva_UnwindData == 0)
    721   1.1  christos 	/* We are probably into the padding of the section now.  */
    722   1.1  christos 	break;
    723   1.1  christos       if (i == 0)
    724   1.6  christos 	fprintf (file, _("\nDump of %s\n"), xdata_section->name);
    725   1.3  christos 
    726   1.9  christos       fprintf (file, " %016" PRIx64, rf.rva_UnwindData + imagebase);
    727   1.1  christos 
    728   1.3  christos       if (prev_unwinddata_rva == rf.rva_UnwindData)
    729   1.3  christos 	{
    730   1.3  christos 	  /* Do not dump again the xdata for the same entry.  */
    731   1.9  christos 	  fprintf (file, " also used for function at %016" PRIx64 "\n",
    732   1.9  christos 		   rf.rva_BeginAddress + imagebase);
    733   1.3  christos 	  continue;
    734   1.3  christos 	}
    735   1.3  christos       else
    736   1.3  christos 	prev_unwinddata_rva = rf.rva_UnwindData;
    737   1.1  christos 
    738   1.9  christos       fprintf (file, " (rva: %08x): %016" PRIx64 " - %016" PRIx64 "\n",
    739   1.9  christos 	       (unsigned int) rf.rva_UnwindData,
    740   1.9  christos 	       rf.rva_BeginAddress + imagebase,
    741   1.9  christos 	       rf.rva_EndAddress + imagebase);
    742   1.3  christos 
    743   1.3  christos       if (rf.rva_UnwindData != 0 || virt_size_is_zero)
    744   1.1  christos 	{
    745   1.3  christos 	  if (PEX64_IS_RUNTIME_FUNCTION_CHAINED (&rf))
    746   1.1  christos 	    {
    747   1.3  christos 	      bfd_vma altent = PEX64_GET_UNWINDDATA_UNIFIED_RVA (&rf);
    748   1.7  christos 	      bfd_vma pdata_vma = bfd_section_vma (pdata_section);
    749   1.3  christos 	      struct pex64_runtime_function arf;
    750   1.3  christos 
    751   1.3  christos 	      fprintf (file, "\t shares information with ");
    752   1.3  christos 	      altent += imagebase;
    753   1.3  christos 
    754   1.3  christos 	      if (altent >= pdata_vma
    755   1.7  christos 		  && altent - pdata_vma + PDATA_ROW_SIZE <= stop)
    756   1.3  christos 		{
    757   1.3  christos 		  pex64_get_runtime_function
    758   1.3  christos 		    (abfd, &arf, &pdata[altent - pdata_vma]);
    759   1.9  christos 		  fprintf (file, "pdata element at 0x%016" PRIx64,
    760   1.9  christos 			   arf.rva_UnwindData);
    761   1.3  christos 		}
    762   1.3  christos 	      else
    763   1.3  christos 		fprintf (file, "unknown pdata element");
    764   1.1  christos 	      fprintf (file, ".\n");
    765   1.1  christos 	    }
    766   1.1  christos 	  else
    767   1.1  christos 	    {
    768   1.1  christos 	      bfd_vma *p;
    769   1.1  christos 
    770   1.1  christos 	      /* Search for the current entry in the sorted array.  */
    771   1.1  christos 	      p = (bfd_vma *)
    772   1.6  christos 		  bsearch (&rf.rva_UnwindData, xdata_arr,
    773   1.1  christos 			   (size_t) xdata_arr_cnt, sizeof (bfd_vma),
    774   1.1  christos 			   sort_xdata_arr);
    775   1.1  christos 
    776   1.1  christos 	      /* Advance to the next pointer into the xdata section.  We may
    777   1.1  christos 		 have shared xdata entries, which will result in a string of
    778   1.1  christos 		 identical pointers in the array; advance past all of them.  */
    779   1.1  christos 	      while (p[0] <= rf.rva_UnwindData)
    780   1.1  christos 		++p;
    781   1.3  christos 
    782   1.1  christos 	      if (p[0] == ~((bfd_vma) 0))
    783   1.1  christos 		p = NULL;
    784   1.1  christos 
    785   1.3  christos 	      pex64_dump_xdata (file, abfd, xdata_section, xdata, p, &rf);
    786   1.1  christos 	    }
    787   1.1  christos 	}
    788   1.1  christos     }
    789   1.1  christos 
    790   1.3  christos  done:
    791   1.3  christos   free (pdata);
    792   1.1  christos   free (xdata_arr);
    793   1.3  christos   free (xdata);
    794   1.1  christos 
    795   1.8  christos   return true;
    796   1.1  christos }
    797   1.1  christos 
    798   1.8  christos struct pex64_paps
    799   1.8  christos {
    800   1.8  christos   void *obj;
    801   1.8  christos   /* Number of found pdata sections.  */
    802   1.8  christos   unsigned int pdata_count;
    803   1.8  christos };
    804   1.3  christos 
    805   1.3  christos /* Functionn prototype.  */
    806   1.8  christos bool pex64_bfd_print_pdata (bfd *, void *);
    807   1.3  christos 
    808   1.3  christos /* Helper function for bfd_map_over_section.  */
    809   1.3  christos static void
    810   1.8  christos pex64_print_all_pdata_sections (bfd *abfd, asection *pdata, void *arg)
    811   1.3  christos {
    812   1.8  christos   struct pex64_paps *paps = arg;
    813   1.8  christos   if (startswith (pdata->name, ".pdata"))
    814   1.3  christos     {
    815   1.8  christos       if (pex64_bfd_print_pdata_section (abfd, paps->obj, pdata))
    816   1.8  christos 	paps->pdata_count++;
    817   1.3  christos     }
    818   1.3  christos }
    819   1.3  christos 
    820   1.8  christos bool
    821   1.3  christos pex64_bfd_print_pdata (bfd *abfd, void *vfile)
    822   1.3  christos {
    823   1.3  christos   asection *pdata_section = bfd_get_section_by_name (abfd, ".pdata");
    824   1.8  christos   struct pex64_paps paps;
    825   1.3  christos 
    826   1.3  christos   if (pdata_section)
    827   1.3  christos     return pex64_bfd_print_pdata_section (abfd, vfile, pdata_section);
    828   1.3  christos 
    829   1.8  christos   paps.obj = vfile;
    830   1.8  christos   paps.pdata_count = 0;
    831   1.8  christos   bfd_map_over_sections (abfd, pex64_print_all_pdata_sections, &paps);
    832   1.8  christos   return paps.pdata_count != 0;
    833   1.3  christos }
    834   1.3  christos 
    835   1.1  christos #define bfd_pe_print_pdata   pex64_bfd_print_pdata
    836   1.3  christos #define bfd_coff_std_swap_table bfd_coff_pei_swap_table
    837   1.1  christos 
    838   1.1  christos #include "coff-x86_64.c"
    839