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