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