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