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