Coverage Report

Created: 2023-08-28 06:25

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