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