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