Support ARM Cortex-M7
[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:
48d5accb
TG
279 /* Already caught by the previous scan. */
280 abort ();
e48570bb 281 }
48d5accb
TG
282 if (unexpected)
283 fprintf (file, " [Unexpected!]");
284 fputc ('\n', file);
e48570bb
DK
285 }
286}
287
48d5accb
TG
288/* Check wether section SEC_NAME contains the xdata at address ADDR. */
289
e48570bb
DK
290static asection *
291pex64_get_section_by_rva (bfd *abfd, bfd_vma addr, const char *sec_name)
292{
293 asection *section = bfd_get_section_by_name (abfd, sec_name);
294 bfd_vma vsize;
295 bfd_size_type datasize = 0;
296
297 if (section == NULL
298 || coff_section_data (abfd, section) == NULL
299 || pei_section_data (abfd, section) == NULL)
300 return NULL;
301 vsize = section->vma - pe_data (abfd)->pe_opthdr.ImageBase;
302 datasize = section->size;
303 if (!datasize || vsize > addr || (vsize + datasize) < addr)
304 return NULL;
305 return section;
306}
307
2b597f54
TG
308/* Dump xdata at for function RF to FILE. The argument XDATA_SECTION
309 designate the bfd section containing the xdata, XDATA is its content,
310 and ENDX the size if known (or NULL). */
48d5accb 311
e48570bb 312static void
48d5accb 313pex64_dump_xdata (FILE *file, bfd *abfd,
2b597f54
TG
314 asection *xdata_section, bfd_byte *xdata, bfd_vma *endx,
315 struct pex64_runtime_function *rf)
e48570bb 316{
48d5accb 317 bfd_vma vaddr;
2eb03909 318 bfd_vma end_addr;
2b597f54 319 bfd_vma addr = rf->rva_UnwindData;
48d5accb 320 struct pex64_unwind_info ui;
e48570bb 321
48d5accb
TG
322 vaddr = xdata_section->vma - pe_data (abfd)->pe_opthdr.ImageBase;
323 addr -= vaddr;
2eb03909 324
1360ae66 325 if (endx)
48d5accb 326 end_addr = endx[0] - vaddr;
1360ae66 327 else
48d5accb
TG
328 end_addr = (xdata_section->rawsize != 0 ?
329 xdata_section->rawsize : xdata_section->size);
e48570bb 330
e48570bb 331
48d5accb 332 pex64_get_unwind_info (abfd, &ui, &xdata[addr]);
e48570bb 333
48d5accb
TG
334 if (ui.Version != 1 && ui.Version != 2)
335 {
336 unsigned int i;
337 fprintf (file, "\tVersion %u (unknown).\n",
338 (unsigned int) ui.Version);
339 for (i = 0; addr < end_addr; addr += 1, i++)
e48570bb 340 {
48d5accb
TG
341 if ((i & 15) == 0)
342 fprintf (file, "\t %03x:", i);
343 fprintf (file, " %02x", xdata[addr]);
344 if ((i & 15) == 15)
345 fprintf (file, "\n");
e48570bb 346 }
48d5accb
TG
347 if ((i & 15) != 0)
348 fprintf (file, "\n");
349 return;
350 }
e48570bb 351
48d5accb
TG
352 fprintf (file, "\tVersion: %d, Flags: ", ui.Version);
353 switch (ui.Flags)
354 {
355 case UNW_FLAG_NHANDLER:
356 fprintf (file, "none");
357 break;
358 case UNW_FLAG_EHANDLER:
359 fprintf (file, "UNW_FLAG_EHANDLER");
360 break;
361 case UNW_FLAG_UHANDLER:
362 fprintf (file, "UNW_FLAG_UHANDLER");
363 break;
364 case UNW_FLAG_FHANDLER:
365 fprintf
366 (file, "UNW_FLAG_EHANDLER | UNW_FLAG_UHANDLER");
367 break;
368 case UNW_FLAG_CHAININFO:
369 fprintf (file, "UNW_FLAG_CHAININFO");
370 break;
371 default:
372 fprintf (file, "unknown flags value 0x%x", (unsigned int) ui.Flags);
373 break;
374 }
375 fputc ('\n', file);
376 fprintf (file, "\tNbr codes: %u, ", (unsigned int) ui.CountOfCodes);
377 fprintf (file, "Prologue size: 0x%02x, Frame offset: 0x%x, ",
378 (unsigned int) ui.SizeOfPrologue, (unsigned int) ui.FrameOffset);
379 fprintf (file, "Frame reg: %s\n",
380 ui.FrameRegister == 0 ? "none"
381 : pex_regs[(unsigned int) ui.FrameRegister]);
382
2b597f54 383 pex64_xdata_print_uwd_codes (file, abfd, &ui, rf);
48d5accb
TG
384
385 switch (ui.Flags)
386 {
387 case UNW_FLAG_EHANDLER:
388 case UNW_FLAG_UHANDLER:
389 case UNW_FLAG_FHANDLER:
390 fprintf (file, "\tHandler: ");
391 fprintf_vma (file, (ui.rva_ExceptionHandler
392 + pe_data (abfd)->pe_opthdr.ImageBase));
e48570bb 393 fprintf (file, ".\n");
48d5accb
TG
394 break;
395 case UNW_FLAG_CHAININFO:
396 fprintf (file, "\tChain: start: ");
397 fprintf_vma (file, ui.rva_BeginAddress);
398 fprintf (file, ", end: ");
399 fprintf_vma (file, ui.rva_EndAddress);
400 fprintf (file, "\n\t unwind data: ");
401 fprintf_vma (file, ui.rva_UnwindData);
402 fprintf (file, ".\n");
403 break;
404 }
405
406 /* Now we need end of this xdata block. */
407 addr += ui.SizeOfBlock;
408 if (addr < end_addr)
409 {
410 unsigned int i;
411 fprintf (file,"\tUser data:\n");
412 for (i = 0; addr < end_addr; addr += 1, i++)
413 {
414 if ((i & 15) == 0)
415 fprintf (file, "\t %03x:", i);
416 fprintf (file, " %02x", xdata[addr]);
417 if ((i & 15) == 15)
2eb03909 418 fprintf (file, "\n");
48d5accb
TG
419 }
420 if ((i & 15) != 0)
421 fprintf (file, "\n");
e48570bb 422 }
e48570bb
DK
423}
424
48d5accb
TG
425/* Helper function to sort xdata. The entries of xdata are sorted to know
426 the size of each entry. */
427
1360ae66
KT
428static int
429sort_xdata_arr (const void *l, const void *r)
430{
431 const bfd_vma *lp = (const bfd_vma *) l;
432 const bfd_vma *rp = (const bfd_vma *) r;
433
434 if (*lp == *rp)
435 return 0;
436 return (*lp < *rp ? -1 : 1);
437}
438
48d5accb
TG
439/* Display unwind tables for x86-64. */
440
e48570bb
DK
441static bfd_boolean
442pex64_bfd_print_pdata (bfd *abfd, void *vfile)
443{
444 FILE *file = (FILE *) vfile;
48d5accb
TG
445 bfd_byte *pdata = NULL;
446 bfd_byte *xdata = NULL;
447 asection *pdata_section = bfd_get_section_by_name (abfd, ".pdata");
448 asection *xdata_section;
449 bfd_vma xdata_base;
e48570bb 450 bfd_size_type i;
2eb03909
KT
451 bfd_size_type stop;
452 bfd_vma prev_beginaddress = 0;
48d5accb
TG
453 bfd_vma prev_unwinddata_rva = 0;
454 bfd_vma imagebase;
e48570bb 455 int onaline = PDATA_ROW_SIZE;
2eb03909 456 int seen_error = 0;
48d5accb 457 bfd_vma *xdata_arr = NULL;
1360ae66 458 int xdata_arr_cnt;
e48570bb 459
48d5accb
TG
460 /* Sanity checks. */
461 if (pdata_section == NULL
462 || coff_section_data (abfd, pdata_section) == NULL
463 || pei_section_data (abfd, pdata_section) == NULL)
e48570bb
DK
464 return TRUE;
465
48d5accb 466 stop = pei_section_data (abfd, pdata_section)->virt_size;
6937bb54
NC
467 /* PR 17512: file: 005-181405-0.004. */
468 if (stop == 0 || pdata_section->size == 0)
469 {
470 fprintf (file, _("No unwind data in .pdata section\n"));
471 return TRUE;
472 }
e48570bb
DK
473 if ((stop % onaline) != 0)
474 fprintf (file,
475 _("warning: .pdata section size (%ld) is not a multiple of %d\n"),
476 (long) stop, onaline);
477
48d5accb 478 /* Display functions table. */
e48570bb
DK
479 fprintf (file,
480 _("\nThe Function Table (interpreted .pdata section contents)\n"));
481
482 fprintf (file, _("vma:\t\t\tBeginAddress\t EndAddress\t UnwindData\n"));
483
48d5accb
TG
484 if (!bfd_malloc_and_get_section (abfd, pdata_section, &pdata))
485 goto done;
e48570bb 486
48d5accb 487 /* Table of xdata entries. */
1360ae66
KT
488 xdata_arr = (bfd_vma *) xmalloc (sizeof (bfd_vma) * ((stop / onaline) + 1));
489 xdata_arr_cnt = 0;
48d5accb
TG
490
491 imagebase = pe_data (abfd)->pe_opthdr.ImageBase;
492
2eb03909 493 for (i = 0; i < stop; i += onaline)
e48570bb
DK
494 {
495 struct pex64_runtime_function rf;
496
497 if (i + PDATA_ROW_SIZE > stop)
498 break;
6937bb54 499
48d5accb 500 pex64_get_runtime_function (abfd, &rf, &pdata[i]);
e48570bb
DK
501
502 if (rf.rva_BeginAddress == 0 && rf.rva_EndAddress == 0
503 && rf.rva_UnwindData == 0)
504 /* We are probably into the padding of the section now. */
505 break;
e48570bb 506 fputc (' ', file);
48d5accb 507 fprintf_vma (file, i + pdata_section->vma);
e48570bb 508 fprintf (file, ":\t");
48d5accb
TG
509 fprintf_vma (file, imagebase + rf.rva_BeginAddress);
510 fprintf (file, " ");
511 fprintf_vma (file, imagebase + rf.rva_EndAddress);
512 fprintf (file, " ");
513 fprintf_vma (file, imagebase + rf.rva_UnwindData);
e48570bb 514 fprintf (file, "\n");
2eb03909
KT
515 if (i != 0 && rf.rva_BeginAddress <= prev_beginaddress)
516 {
517 seen_error = 1;
518 fprintf (file, " has %s begin address as predecessor\n",
519 (rf.rva_BeginAddress < prev_beginaddress ? "smaller" : "same"));
520 }
521 prev_beginaddress = rf.rva_BeginAddress;
522 /* Now we check for negative addresses. */
523 if ((prev_beginaddress & 0x80000000) != 0)
524 {
525 seen_error = 1;
526 fprintf (file, " has negative begin address\n");
527 }
528 if ((rf.rva_EndAddress & 0x80000000) != 0)
529 {
530 seen_error = 1;
531 fprintf (file, " has negative end address\n");
532 }
533 if ((rf.rva_UnwindData & 0x80000000) != 0)
534 {
535 seen_error = 1;
536 fprintf (file, " has negative unwind address\n");
537 }
48d5accb 538 if (rf.rva_UnwindData && !PEX64_IS_RUNTIME_FUNCTION_CHAINED (&rf))
1360ae66 539 xdata_arr[xdata_arr_cnt++] = rf.rva_UnwindData;
2eb03909
KT
540 }
541
542 if (seen_error)
48d5accb 543 goto done;
1360ae66
KT
544
545 /* Add end of list marker. */
546 xdata_arr[xdata_arr_cnt++] = ~((bfd_vma) 0);
547
548 /* Sort start RVAs of xdata. */
549 if (xdata_arr_cnt > 1)
550 qsort (xdata_arr, (size_t) xdata_arr_cnt, sizeof (bfd_vma),
551 sort_xdata_arr);
552
48d5accb
TG
553 /* Find the section containing the unwind data (.xdata). */
554 xdata_base = xdata_arr[0];
555 xdata_section = pex64_get_section_by_rva (abfd, xdata_base, ".rdata");
556
557 if (!xdata_section)
558 xdata_section = pex64_get_section_by_rva (abfd, xdata_base, ".data");
559 if (!xdata_section)
560 xdata_section = pex64_get_section_by_rva (abfd, xdata_base, ".xdata");
561 if (!xdata_section)
562 xdata_section = pex64_get_section_by_rva (abfd, xdata_base, ".pdata");
563 if (!xdata_section)
564 xdata_section = pex64_get_section_by_rva (abfd, xdata_base, ".text");
565 if (!xdata_section
566 || !bfd_malloc_and_get_section (abfd, xdata_section, &xdata))
567 goto done;
2eb03909 568
48d5accb 569 /* Do dump of pdata related xdata. */
2eb03909
KT
570 for (i = 0; i < stop; i += onaline)
571 {
572 struct pex64_runtime_function rf;
573
574 if (i + PDATA_ROW_SIZE > stop)
575 break;
48d5accb 576 pex64_get_runtime_function (abfd, &rf, &pdata[i]);
2eb03909
KT
577
578 if (rf.rva_BeginAddress == 0 && rf.rva_EndAddress == 0
579 && rf.rva_UnwindData == 0)
580 /* We are probably into the padding of the section now. */
581 break;
582 if (i == 0)
583 fprintf (file, "\nDump of .xdata\n");
48d5accb 584
2eb03909 585 fputc (' ', file);
48d5accb
TG
586 fprintf_vma (file, rf.rva_UnwindData + imagebase);
587
588 if (prev_unwinddata_rva == rf.rva_UnwindData)
589 {
590 /* Do not dump again the xdata for the same entry. */
591 fprintf (file, " also used for function at ");
592 fprintf_vma (file, rf.rva_BeginAddress + imagebase);
593 fputc ('\n', file);
594 continue;
595 }
596 else
597 prev_unwinddata_rva = rf.rva_UnwindData;
2eb03909 598
2b597f54 599 fprintf (file, " (rva: %08x): ",
48d5accb
TG
600 (unsigned int) rf.rva_UnwindData);
601 fprintf_vma (file, rf.rva_BeginAddress + imagebase);
2b597f54
TG
602 fprintf (file, " - ");
603 fprintf_vma (file, rf.rva_EndAddress + imagebase);
48d5accb 604 fputc ('\n', file);
e48570bb
DK
605
606 if (rf.rva_UnwindData != 0)
607 {
48d5accb 608 if (PEX64_IS_RUNTIME_FUNCTION_CHAINED (&rf))
e48570bb 609 {
48d5accb
TG
610 bfd_vma altent = PEX64_GET_UNWINDDATA_UNIFIED_RVA (&rf);
611 bfd_vma pdata_vma = bfd_get_section_vma (abfd, pdata_section);
612 struct pex64_runtime_function arf;
613
614 fprintf (file, "\t shares information with ");
615 altent += imagebase;
616
617 if (altent >= pdata_vma
618 && (altent + PDATA_ROW_SIZE <= pdata_vma
619 + pei_section_data (abfd, pdata_section)->virt_size))
620 {
621 pex64_get_runtime_function
622 (abfd, &arf, &pdata[altent - pdata_vma]);
623 fprintf (file, "pdata element at 0x");
624 fprintf_vma (file, arf.rva_UnwindData);
625 }
626 else
627 fprintf (file, "unknown pdata element");
e48570bb
DK
628 fprintf (file, ".\n");
629 }
630 else
1360ae66
KT
631 {
632 bfd_vma *p;
633
634 /* Search for the current entry in the sorted array. */
635 p = (bfd_vma *)
636 bsearch (&rf.rva_UnwindData, xdata_arr,
637 (size_t) xdata_arr_cnt, sizeof (bfd_vma),
638 sort_xdata_arr);
639
640 /* Advance to the next pointer into the xdata section. We may
641 have shared xdata entries, which will result in a string of
642 identical pointers in the array; advance past all of them. */
643 while (p[0] <= rf.rva_UnwindData)
644 ++p;
645 if (p[0] == ~((bfd_vma) 0))
646 p = NULL;
647
2b597f54 648 pex64_dump_xdata (file, abfd, xdata_section, xdata, p, &rf);
1360ae66 649 }
e48570bb
DK
650 }
651 }
652
48d5accb
TG
653 done:
654 free (pdata);
1360ae66 655 free (xdata_arr);
48d5accb 656 free (xdata);
e48570bb
DK
657
658 return TRUE;
659}
660
661#define bfd_pe_print_pdata pex64_bfd_print_pdata
662
99ad8390 663#include "coff-x86_64.c"
This page took 0.477646 seconds and 4 git commands to generate.