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