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