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