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