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