Coverage Report

Created: 2023-08-28 06:30

/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
0
#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
2.33k
#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
2.31k
{
88
2.31k
  const struct external_pex64_runtime_function *ex_rf =
89
2.31k
    (const struct external_pex64_runtime_function *) data;
90
2.31k
  rf->rva_BeginAddress = bfd_get_32 (abfd, ex_rf->rva_BeginAddress);
91
2.31k
  rf->rva_EndAddress = bfd_get_32 (abfd, ex_rf->rva_EndAddress);
92
2.31k
  rf->rva_UnwindData =  bfd_get_32 (abfd, ex_rf->rva_UnwindData);
93
2.31k
}
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
369
{
101
369
  struct external_pex64_unwind_info *ex_ui =
102
369
    (struct external_pex64_unwind_info *) data;
103
369
  bfd_byte *ex_dta = (bfd_byte *) data;
104
369
  bfd_byte *ex_dta_end = (bfd_byte *) data_end;
105
106
369
  memset (ui, 0, sizeof (struct pex64_unwind_info));
107
108
369
  if (ex_dta_end - ex_dta < 4)
109
0
    return false;
110
111
369
  ui->Version = PEX64_UWI_VERSION (ex_ui->Version_Flags);
112
369
  ui->Flags = PEX64_UWI_FLAGS (ex_ui->Version_Flags);
113
369
  ui->SizeOfPrologue = (bfd_vma) ex_ui->SizeOfPrologue;
114
369
  ui->CountOfCodes = (bfd_vma) ex_ui->CountOfCodes;
115
369
  ui->FrameRegister = PEX64_UWI_FRAMEREG (ex_ui->FrameRegisterOffset);
116
369
  ui->FrameOffset = PEX64_UWI_FRAMEOFF (ex_ui->FrameRegisterOffset);
117
369
  ui->sizeofUnwindCodes = PEX64_UWI_SIZEOF_UWCODE_ARRAY (ui->CountOfCodes);
118
369
  ui->SizeOfBlock = ui->sizeofUnwindCodes + 4;
119
369
  ui->rawUnwindCodes = ex_dta + 4;
120
369
  ui->rawUnwindCodesEnd = ex_dta_end;
121
122
369
  if ((size_t) (ex_dta_end - ex_dta) < ui->SizeOfBlock)
123
0
    return false;
124
369
  ex_dta += ui->SizeOfBlock;
125
126
369
  switch (ui->Flags)
127
369
    {
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
4
    case UNW_FLAG_EHANDLER:
137
9
    case UNW_FLAG_UHANDLER:
138
106
    case UNW_FLAG_FHANDLER:
139
106
      if (ex_dta_end - ex_dta < 4)
140
0
  return false;
141
106
      ui->rva_ExceptionHandler = bfd_get_32 (abfd, ex_dta);
142
106
      ui->SizeOfBlock += 4;
143
106
      return true;
144
263
    default:
145
263
      return true;
146
369
    }
147
369
}
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
369
{
156
369
  unsigned int i;
157
369
  unsigned int tmp; /* At least 32 bits.  */
158
369
  int save_allowed;
159
160
369
  if (ui->CountOfCodes == 0 || ui->rawUnwindCodes == NULL)
161
20
    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
349
  save_allowed = true;
168
169
349
  i = 0;
170
171
349
  if ((size_t) (ui->rawUnwindCodesEnd - ui->rawUnwindCodes)
172
349
      < ui->CountOfCodes * 2)
173
0
    {
174
0
      fprintf (file, _("warning: corrupt unwind data\n"));
175
0
      return;
176
0
    }
177
178
349
  if (ui->Version == 2
179
349
      && 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
1.98k
  for (; i < ui->CountOfCodes; i++)
210
1.63k
    {
211
1.63k
      const bfd_byte *dta = ui->rawUnwindCodes + 2 * i;
212
1.63k
      unsigned int info = PEX64_UNWCODE_INFO (dta[1]);
213
1.63k
      int unexpected = false;
214
215
1.63k
      fprintf (file, "\t  pc+0x%02x: ", (unsigned int) dta[0]);
216
217
1.63k
      switch (PEX64_UNWCODE_CODE (dta[1]))
218
1.63k
  {
219
794
  case UWOP_PUSH_NONVOL:
220
794
    fprintf (file, "push %s", pex_regs[info]);
221
794
    break;
222
223
88
  case UWOP_ALLOC_LARGE:
224
88
    if (info == 0)
225
88
      {
226
88
        if (ui->rawUnwindCodesEnd - dta < 4)
227
0
    {
228
0
      fprintf (file, _("warning: corrupt unwind data\n"));
229
0
      return;
230
0
    }
231
88
        tmp = bfd_get_16 (abfd, dta + 2) * 8;
232
88
        i++;
233
88
      }
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
88
    fprintf (file, "alloc large area: rsp = rsp - 0x%x", tmp);
245
88
    break;
246
247
259
  case UWOP_ALLOC_SMALL:
248
259
    fprintf (file, "alloc small area: rsp = rsp - 0x%x", (info + 1) * 8);
249
259
    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
494
  case UWOP_SAVE_NONVOL:
261
494
    if (ui->rawUnwindCodesEnd - dta < 4)
262
0
      {
263
0
        fprintf (file, _("warning: corrupt unwind data\n"));
264
0
        return;
265
0
      }
266
494
    tmp = bfd_get_16 (abfd, dta + 2) * 8;
267
494
    i++;
268
494
    fprintf (file, "save %s at rsp + 0x%x", pex_regs[info], tmp);
269
494
    unexpected = !save_allowed;
270
494
    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
1
  case UWOP_SAVE_XMM128:
317
1
    if (ui->rawUnwindCodesEnd - dta < 4)
318
0
      {
319
0
        fprintf (file, _("warning: corrupt unwind data\n"));
320
0
        return;
321
0
      }
322
1
    tmp = bfd_get_16 (abfd, dta + 2) * 16;
323
1
    i++;
324
1
    fprintf (file, "save xmm%u at rsp + 0x%x", info, tmp);
325
1
    unexpected = !save_allowed;
326
1
    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
1.63k
  }
355
356
1.63k
      if (unexpected)
357
0
  fprintf (file, " [Unexpected!]");
358
1.63k
      fputc ('\n', file);
359
1.63k
    }
360
349
}
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
24
{
367
24
  asection *section = bfd_get_section_by_name (abfd, sec_name);
368
24
  bfd_vma vsize;
369
24
  bfd_size_type datasize = 0;
370
371
24
  if (section == NULL
372
24
      || coff_section_data (abfd, section) == NULL
373
24
      || pei_section_data (abfd, section) == NULL)
374
5
    return NULL;
375
19
  vsize = section->vma - pe_data (abfd)->pe_opthdr.ImageBase;
376
19
  datasize = section->size;
377
19
  if (!datasize || vsize > addr || (vsize + datasize) < addr)
378
16
    return NULL;
379
3
  return section;
380
19
}
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
369
{
391
369
  bfd_vma vaddr;
392
369
  bfd_vma end_addr;
393
369
  bfd_vma addr = rf->rva_UnwindData;
394
369
  bfd_size_type sec_size = xdata_section->rawsize > 0 ? xdata_section->rawsize : xdata_section->size;
395
369
  struct pex64_unwind_info ui;
396
397
369
  vaddr = xdata_section->vma - pe_data (abfd)->pe_opthdr.ImageBase;
398
369
  addr -= vaddr;
399
400
  /* PR 17512: file: 2245-7442-0.004.  */
401
369
  if (addr >= sec_size)
402
0
    {
403
0
      fprintf (file, _("warning: xdata section corrupt\n"));
404
0
      return;
405
0
    }
406
407
369
  if (endx)
408
366
    {
409
366
      end_addr = endx[0] - vaddr;
410
      /* PR 17512: file: 2245-7442-0.004.  */
411
366
      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
366
    }
417
3
  else
418
3
    end_addr = sec_size;
419
420
369
  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
369
  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
369
  fprintf (file, "\tVersion: %d, Flags: ", ui.Version);
445
369
  switch (ui.Flags)
446
369
    {
447
263
    case UNW_FLAG_NHANDLER:
448
263
      fprintf (file, "none");
449
263
      break;
450
4
    case UNW_FLAG_EHANDLER:
451
4
      fprintf (file, "UNW_FLAG_EHANDLER");
452
4
      break;
453
5
    case UNW_FLAG_UHANDLER:
454
5
      fprintf (file, "UNW_FLAG_UHANDLER");
455
5
      break;
456
97
    case UNW_FLAG_FHANDLER:
457
97
      fprintf
458
97
  (file, "UNW_FLAG_EHANDLER | UNW_FLAG_UHANDLER");
459
97
      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
369
    }
467
369
  fputc ('\n', file);
468
369
  fprintf (file, "\tNbr codes: %u, ", (unsigned int) ui.CountOfCodes);
469
369
  fprintf (file, "Prologue size: 0x%02x, Frame offset: 0x%x, ",
470
369
     (unsigned int) ui.SizeOfPrologue, (unsigned int) ui.FrameOffset);
471
369
  fprintf (file, "Frame reg: %s\n",
472
369
     ui.FrameRegister == 0 ? "none"
473
369
     : pex_regs[(unsigned int) ui.FrameRegister]);
474
475
  /* PR 17512: file: 2245-7442-0.004.  */
476
369
  if (ui.CountOfCodes * 2 + ui.rawUnwindCodes > xdata + xdata_section->size)
477
0
    fprintf (file, _("Too many unwind codes (%ld)\n"), (long) ui.CountOfCodes);
478
369
  else
479
369
    pex64_xdata_print_uwd_codes (file, abfd, &ui, rf);
480
481
369
  switch (ui.Flags)
482
369
    {
483
4
    case UNW_FLAG_EHANDLER:
484
9
    case UNW_FLAG_UHANDLER:
485
106
    case UNW_FLAG_FHANDLER:
486
106
      fprintf (file, "\tHandler: %016" PRIx64 ".\n",
487
106
         ui.rva_ExceptionHandler + pe_data (abfd)->pe_opthdr.ImageBase);
488
106
      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
369
    }
496
497
  /* Now we need end of this xdata block.  */
498
369
  addr += ui.SizeOfBlock;
499
369
  if (addr < end_addr)
500
106
    {
501
106
      unsigned int i;
502
106
      fprintf (file,"\tUser data:\n");
503
2.66k
      for (i = 0; addr < end_addr; addr += 1, i++)
504
2.55k
  {
505
2.55k
    if ((i & 15) == 0)
506
193
      fprintf (file, "\t  %03x:", i);
507
2.55k
    fprintf (file, " %02x", xdata[addr]);
508
2.55k
    if ((i & 15) == 15)
509
87
      fprintf (file, "\n");
510
2.55k
  }
511
106
      if ((i & 15) != 0)
512
106
  fprintf (file, "\n");
513
106
    }
514
369
}
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
4.55k
{
522
4.55k
  const bfd_vma *lp = (const bfd_vma *) l;
523
4.55k
  const bfd_vma *rp = (const bfd_vma *) r;
524
525
4.55k
  if (*lp == *rp)
526
763
    return 0;
527
3.78k
  return (*lp < *rp ? -1 : 1);
528
4.55k
}
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
17
{
535
17
  FILE *file = (FILE *) vfile;
536
17
  bfd_byte *pdata = NULL;
537
17
  bfd_byte *xdata = NULL;
538
17
  asection *xdata_section = NULL;
539
17
  bfd_vma xdata_base;
540
17
  bfd_size_type i;
541
17
  bfd_size_type datasize;
542
17
  bfd_size_type stop;
543
17
  bfd_vma prev_beginaddress = (bfd_vma) -1;
544
17
  bfd_vma prev_unwinddata_rva = (bfd_vma) -1;
545
17
  bfd_vma imagebase;
546
17
  int onaline = PDATA_ROW_SIZE;
547
17
  int seen_error = 0;
548
17
  bfd_vma *xdata_arr = NULL;
549
17
  int xdata_arr_cnt;
550
17
  bool virt_size_is_zero = false;
551
552
  /* Sanity checks.  */
553
17
  if (pdata_section == NULL
554
17
      || (pdata_section->flags & SEC_HAS_CONTENTS) == 0
555
17
      || coff_section_data (abfd, pdata_section) == NULL
556
17
      || pei_section_data (abfd, pdata_section) == NULL)
557
0
    return true;
558
559
17
  stop = pei_section_data (abfd, pdata_section)->virt_size;
560
17
  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
17
  datasize = pdata_section->size;
567
17
  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
17
  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
17
  else if (datasize < stop)
582
5
      {
583
5
  fprintf (file,
584
     /* xgettext:c-format */
585
5
     _("Warning: %s section size (%ld) is smaller than virtual size (%ld)\n"),
586
5
     pdata_section->name, (unsigned long) datasize,
587
5
     (unsigned long) stop);
588
  /* Be sure not to read past datasize.  */
589
5
  stop = datasize;
590
5
      }
591
592
  /* Display functions table.  */
593
17
  fprintf (file,
594
17
     _("\nThe Function Table (interpreted %s section contents)\n"),
595
17
     pdata_section->name);
596
597
17
  fprintf (file, _("vma:\t\t\tBeginAddress\t EndAddress\t  UnwindData\n"));
598
599
17
  if (!bfd_malloc_and_get_section (abfd, pdata_section, &pdata))
600
4
    goto done;
601
602
  /* Table of xdata entries.  */
603
13
  xdata_arr = (bfd_vma *) xmalloc (sizeof (bfd_vma) * ((stop / onaline) + 1));
604
13
  xdata_arr_cnt = 0;
605
606
13
  if (strcmp (abfd->xvec->name, "pei-x86-64") == 0)
607
8
    imagebase = pe_data (abfd)->pe_opthdr.ImageBase;
608
5
  else
609
5
    imagebase = 0;
610
611
988
  for (i = 0; i < stop; i += onaline)
612
985
    {
613
985
      struct pex64_runtime_function rf;
614
615
985
      if (i + PDATA_ROW_SIZE > stop)
616
0
  break;
617
618
985
      pex64_get_runtime_function (abfd, &rf, &pdata[i]);
619
620
985
      if (rf.rva_BeginAddress == 0 && rf.rva_EndAddress == 0
621
985
    && rf.rva_UnwindData == 0)
622
  /* We are probably into the padding of the section now.  */
623
10
  break;
624
975
      fprintf (file, " %016" PRIx64, i + pdata_section->vma);
625
975
      fprintf (file, ":\t%016" PRIx64, imagebase + rf.rva_BeginAddress);
626
975
      fprintf (file, " %016" PRIx64, imagebase + rf.rva_EndAddress);
627
975
      fprintf (file, " %016" PRIx64 "\n", imagebase + rf.rva_UnwindData);
628
975
      if (i != 0 && rf.rva_BeginAddress <= prev_beginaddress)
629
68
  {
630
68
    seen_error = 1;
631
68
    fprintf (file, "  has %s begin address as predecessor\n",
632
68
      (rf.rva_BeginAddress < prev_beginaddress ? "smaller" : "same"));
633
68
  }
634
975
      prev_beginaddress = rf.rva_BeginAddress;
635
      /* Now we check for negative addresses.  */
636
975
      if ((prev_beginaddress & 0x80000000) != 0)
637
14
  {
638
14
    seen_error = 1;
639
14
    fprintf (file, "  has negative begin address\n");
640
14
  }
641
975
      if ((rf.rva_EndAddress & 0x80000000) != 0)
642
18
  {
643
18
    seen_error = 1;
644
18
    fprintf (file, "  has negative end address\n");
645
18
  }
646
975
      if ((rf.rva_UnwindData & 0x80000000) != 0)
647
11
  {
648
11
    seen_error = 1;
649
11
    fprintf (file, "  has negative unwind address\n");
650
11
  }
651
964
      else if ((rf.rva_UnwindData && !PEX64_IS_RUNTIME_FUNCTION_CHAINED (&rf))
652
964
    || virt_size_is_zero)
653
451
  xdata_arr[xdata_arr_cnt++] = rf.rva_UnwindData;
654
975
    }
655
656
13
  if (seen_error)
657
6
    goto done;
658
659
  /* Add end of list marker.  */
660
7
  xdata_arr[xdata_arr_cnt++] = ~((bfd_vma) 0);
661
662
  /* Sort start RVAs of xdata.  */
663
7
  if (xdata_arr_cnt > 1)
664
3
    qsort (xdata_arr, (size_t) xdata_arr_cnt, sizeof (bfd_vma),
665
3
     sort_xdata_arr);
666
667
  /* Find the section containing the unwind data (.xdata).  */
668
7
  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
7
  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
7
  if (!xdata_section)
686
7
    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
7
  if (!xdata_section && xdata_base)
690
5
    xdata_section = pex64_get_section_by_rva (abfd, xdata_base, ".rdata");
691
7
  if (!xdata_section && xdata_base)
692
4
    xdata_section = pex64_get_section_by_rva (abfd, xdata_base, ".data");
693
7
  if (!xdata_section && xdata_base)
694
4
    xdata_section = pex64_get_section_by_rva (abfd, xdata_base, ".pdata");
695
7
  if (!xdata_section && xdata_base)
696
4
    xdata_section = pex64_get_section_by_rva (abfd, xdata_base, ".text");
697
  /* Transfer xdata section into xdata array.  */
698
7
  if (!xdata_section
699
7
      || (xdata_section->flags & SEC_HAS_CONTENTS) == 0
700
7
      || !bfd_malloc_and_get_section (abfd, xdata_section, &xdata))
701
4
    goto done;
702
703
  /* Avoid "also used "... ouput for single unwind info
704
     in object file.  */
705
3
  prev_unwinddata_rva = (bfd_vma) -1;
706
707
  /* Do dump of pdata related xdata.  */
708
864
  for (i = 0; i < stop; i += onaline)
709
861
    {
710
861
      struct pex64_runtime_function rf;
711
712
861
      if (i + PDATA_ROW_SIZE > stop)
713
0
  break;
714
715
861
      pex64_get_runtime_function (abfd, &rf, &pdata[i]);
716
717
861
      if (rf.rva_BeginAddress == 0 && rf.rva_EndAddress == 0
718
861
    && rf.rva_UnwindData == 0)
719
  /* We are probably into the padding of the section now.  */
720
0
  break;
721
861
      if (i == 0)
722
3
  fprintf (file, _("\nDump of %s\n"), xdata_section->name);
723
724
861
      fprintf (file, " %016" PRIx64, rf.rva_UnwindData + imagebase);
725
726
861
      if (prev_unwinddata_rva == rf.rva_UnwindData)
727
20
  {
728
    /* Do not dump again the xdata for the same entry.  */
729
20
    fprintf (file, " also used for function at %016" PRIx64 "\n",
730
20
       rf.rva_BeginAddress + imagebase);
731
20
    continue;
732
20
  }
733
841
      else
734
841
  prev_unwinddata_rva = rf.rva_UnwindData;
735
736
841
      fprintf (file, " (rva: %08x): %016" PRIx64 " - %016" PRIx64 "\n",
737
841
         (unsigned int) rf.rva_UnwindData,
738
841
         rf.rva_BeginAddress + imagebase,
739
841
         rf.rva_EndAddress + imagebase);
740
741
841
      if (rf.rva_UnwindData != 0 || virt_size_is_zero)
742
841
  {
743
841
    if (PEX64_IS_RUNTIME_FUNCTION_CHAINED (&rf))
744
472
      {
745
472
        bfd_vma altent = PEX64_GET_UNWINDDATA_UNIFIED_RVA (&rf);
746
472
        bfd_vma pdata_vma = bfd_section_vma (pdata_section);
747
472
        struct pex64_runtime_function arf;
748
749
472
        fprintf (file, "\t shares information with ");
750
472
        altent += imagebase;
751
752
472
        if (altent >= pdata_vma
753
472
      && altent - pdata_vma + PDATA_ROW_SIZE <= stop)
754
472
    {
755
472
      pex64_get_runtime_function
756
472
        (abfd, &arf, &pdata[altent - pdata_vma]);
757
472
      fprintf (file, "pdata element at 0x%016" PRIx64,
758
472
         arf.rva_UnwindData);
759
472
    }
760
0
        else
761
0
    fprintf (file, "unknown pdata element");
762
472
        fprintf (file, ".\n");
763
472
      }
764
369
    else
765
369
      {
766
369
        bfd_vma *p;
767
768
        /* Search for the current entry in the sorted array.  */
769
369
        p = (bfd_vma *)
770
369
      bsearch (&rf.rva_UnwindData, xdata_arr,
771
369
         (size_t) xdata_arr_cnt, sizeof (bfd_vma),
772
369
         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
2.14k
        while (p[0] <= rf.rva_UnwindData)
778
1.77k
    ++p;
779
780
369
        if (p[0] == ~((bfd_vma) 0))
781
3
    p = NULL;
782
783
369
        pex64_dump_xdata (file, abfd, xdata_section, xdata, p, &rf);
784
369
      }
785
841
  }
786
841
    }
787
788
17
 done:
789
17
  free (pdata);
790
17
  free (xdata_arr);
791
17
  free (xdata);
792
793
17
  return true;
794
3
}
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
775
{
810
775
  struct pex64_paps *paps = arg;
811
775
  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
775
}
817
818
bool
819
pex64_bfd_print_pdata (bfd *abfd, void *vfile)
820
215
{
821
215
  asection *pdata_section = bfd_get_section_by_name (abfd, ".pdata");
822
215
  struct pex64_paps paps;
823
824
215
  if (pdata_section)
825
17
    return pex64_bfd_print_pdata_section (abfd, vfile, pdata_section);
826
827
198
  paps.obj = vfile;
828
198
  paps.pdata_count = 0;
829
198
  bfd_map_over_sections (abfd, pex64_print_all_pdata_sections, &paps);
830
198
  return paps.pdata_count != 0;
831
215
}
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"