Coverage Report

Created: 2024-05-21 06:29

/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-2024 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
27.3k
#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
5.97k
#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
5.92k
{
88
5.92k
  const struct external_pex64_runtime_function *ex_rf =
89
5.92k
    (const struct external_pex64_runtime_function *) data;
90
5.92k
  rf->rva_BeginAddress = bfd_get_32 (abfd, ex_rf->rva_BeginAddress);
91
5.92k
  rf->rva_EndAddress = bfd_get_32 (abfd, ex_rf->rva_EndAddress);
92
5.92k
  rf->rva_UnwindData =  bfd_get_32 (abfd, ex_rf->rva_UnwindData);
93
5.92k
}
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
739
{
101
739
  struct external_pex64_unwind_info *ex_ui =
102
739
    (struct external_pex64_unwind_info *) data;
103
739
  bfd_byte *ex_dta = (bfd_byte *) data;
104
739
  bfd_byte *ex_dta_end = (bfd_byte *) data_end;
105
106
739
  memset (ui, 0, sizeof (struct pex64_unwind_info));
107
108
739
  if (ex_dta_end - ex_dta < 4)
109
0
    return false;
110
111
739
  ui->Version = PEX64_UWI_VERSION (ex_ui->Version_Flags);
112
739
  ui->Flags = PEX64_UWI_FLAGS (ex_ui->Version_Flags);
113
739
  ui->SizeOfPrologue = (bfd_vma) ex_ui->SizeOfPrologue;
114
739
  ui->CountOfCodes = (bfd_vma) ex_ui->CountOfCodes;
115
739
  ui->FrameRegister = PEX64_UWI_FRAMEREG (ex_ui->FrameRegisterOffset);
116
739
  ui->FrameOffset = PEX64_UWI_FRAMEOFF (ex_ui->FrameRegisterOffset);
117
739
  ui->sizeofUnwindCodes = PEX64_UWI_SIZEOF_UWCODE_ARRAY (ui->CountOfCodes);
118
739
  ui->SizeOfBlock = ui->sizeofUnwindCodes + 4;
119
739
  ui->rawUnwindCodes = ex_dta + 4;
120
739
  ui->rawUnwindCodesEnd = ex_dta_end;
121
122
739
  if ((size_t) (ex_dta_end - ex_dta) < ui->SizeOfBlock)
123
97
    return false;
124
642
  ex_dta += ui->SizeOfBlock;
125
126
642
  switch (ui->Flags)
127
642
    {
128
3
    case UNW_FLAG_CHAININFO:
129
3
      if (ex_dta_end - ex_dta < 12)
130
1
  return false;
131
2
      ui->rva_BeginAddress = bfd_get_32 (abfd, ex_dta + 0);
132
2
      ui->rva_EndAddress = bfd_get_32 (abfd, ex_dta + 4);
133
2
      ui->rva_UnwindData = bfd_get_32 (abfd, ex_dta + 8);
134
2
      ui->SizeOfBlock += 12;
135
2
      return true;
136
6
    case UNW_FLAG_EHANDLER:
137
16
    case UNW_FLAG_UHANDLER:
138
115
    case UNW_FLAG_FHANDLER:
139
115
      if (ex_dta_end - ex_dta < 4)
140
0
  return false;
141
115
      ui->rva_ExceptionHandler = bfd_get_32 (abfd, ex_dta);
142
115
      ui->SizeOfBlock += 4;
143
115
      return true;
144
524
    default:
145
524
      return true;
146
642
    }
147
642
}
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
532
{
156
532
  unsigned int i;
157
532
  unsigned int tmp; /* At least 32 bits.  */
158
532
  int save_allowed;
159
160
532
  if (ui->CountOfCodes == 0 || ui->rawUnwindCodes == NULL)
161
118
    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
414
  save_allowed = true;
168
169
414
  i = 0;
170
171
414
  if ((size_t) (ui->rawUnwindCodesEnd - ui->rawUnwindCodes)
172
414
      < ui->CountOfCodes * 2)
173
0
    {
174
0
      fprintf (file, _("warning: corrupt unwind data\n"));
175
0
      return;
176
0
    }
177
178
414
  if (ui->Version == 2
179
414
      && 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
2.74k
  for (; i < ui->CountOfCodes; i++)
210
2.33k
    {
211
2.33k
      const bfd_byte *dta = ui->rawUnwindCodes + 2 * i;
212
2.33k
      unsigned int info = PEX64_UNWCODE_INFO (dta[1]);
213
2.33k
      int unexpected = false;
214
215
2.33k
      fprintf (file, "\t  pc+0x%02x: ", (unsigned int) dta[0]);
216
217
2.33k
      switch (PEX64_UNWCODE_CODE (dta[1]))
218
2.33k
  {
219
951
  case UWOP_PUSH_NONVOL:
220
951
    fprintf (file, "push %s", pex_regs[info]);
221
951
    break;
222
223
130
  case UWOP_ALLOC_LARGE:
224
130
    if (info == 0)
225
99
      {
226
99
        if (ui->rawUnwindCodesEnd - dta < 4)
227
0
    {
228
0
      fprintf (file, _("warning: corrupt unwind data\n"));
229
0
      return;
230
0
    }
231
99
        tmp = bfd_get_16 (abfd, dta + 2) * 8;
232
99
        i++;
233
99
      }
234
31
    else
235
31
      {
236
31
        if (ui->rawUnwindCodesEnd - dta < 6)
237
0
    {
238
0
      fprintf (file, _("warning: corrupt unwind data\n"));
239
0
      return;
240
0
    }
241
31
        tmp = bfd_get_32 (abfd, dta + 2);
242
31
        i += 2;
243
31
      }
244
130
    fprintf (file, "alloc large area: rsp = rsp - 0x%x", tmp);
245
130
    break;
246
247
356
  case UWOP_ALLOC_SMALL:
248
356
    fprintf (file, "alloc small area: rsp = rsp - 0x%x", (info + 1) * 8);
249
356
    break;
250
251
35
  case UWOP_SET_FPREG:
252
    /* According to the documentation, info field is unused.  */
253
35
    fprintf (file, "FPReg: %s = rsp + 0x%x (info = 0x%x)",
254
35
       pex_regs[ui->FrameRegister],
255
35
       (unsigned int) ui->FrameOffset * 16, info);
256
35
    unexpected = ui->FrameRegister == 0;
257
35
    save_allowed = false;
258
35
    break;
259
260
517
  case UWOP_SAVE_NONVOL:
261
517
    if (ui->rawUnwindCodesEnd - dta < 4)
262
0
      {
263
0
        fprintf (file, _("warning: corrupt unwind data\n"));
264
0
        return;
265
0
      }
266
517
    tmp = bfd_get_16 (abfd, dta + 2) * 8;
267
517
    i++;
268
517
    fprintf (file, "save %s at rsp + 0x%x", pex_regs[info], tmp);
269
517
    unexpected = !save_allowed;
270
517
    break;
271
272
22
  case UWOP_SAVE_NONVOL_FAR:
273
22
    if (ui->rawUnwindCodesEnd - dta < 6)
274
0
      {
275
0
        fprintf (file, _("warning: corrupt unwind data\n"));
276
0
        return;
277
0
      }
278
22
    tmp = bfd_get_32 (abfd, dta + 2);
279
22
    i += 2;
280
22
    fprintf (file, "save %s at rsp + 0x%x", pex_regs[info], tmp);
281
22
    unexpected = !save_allowed;
282
22
    break;
283
284
21
  case UWOP_SAVE_XMM:
285
21
    if (ui->Version == 1)
286
13
      {
287
13
        if (ui->rawUnwindCodesEnd - dta < 4)
288
0
    {
289
0
      fprintf (file, _("warning: corrupt unwind data\n"));
290
0
      return;
291
0
    }
292
13
        tmp = bfd_get_16 (abfd, dta + 2) * 8;
293
13
        i++;
294
13
        fprintf (file, "save mm%u at rsp + 0x%x", info, tmp);
295
13
        unexpected = !save_allowed;
296
13
      }
297
8
    else if (ui->Version == 2)
298
8
      {
299
8
        fprintf (file, "epilog %02x %01x", dta[0], info);
300
8
        unexpected = true;
301
8
      }
302
21
    break;
303
304
30
  case UWOP_SAVE_XMM_FAR:
305
30
    if (ui->rawUnwindCodesEnd - dta < 6)
306
0
      {
307
0
        fprintf (file, _("warning: corrupt unwind data\n"));
308
0
        return;
309
0
      }
310
30
    tmp = bfd_get_32 (abfd, dta + 2) * 8;
311
30
    i += 2;
312
30
    fprintf (file, "save mm%u at rsp + 0x%x", info, tmp);
313
30
    unexpected = !save_allowed;
314
30
    break;
315
316
43
  case UWOP_SAVE_XMM128:
317
43
    if (ui->rawUnwindCodesEnd - dta < 4)
318
0
      {
319
0
        fprintf (file, _("warning: corrupt unwind data\n"));
320
0
        return;
321
0
      }
322
43
    tmp = bfd_get_16 (abfd, dta + 2) * 16;
323
43
    i++;
324
43
    fprintf (file, "save xmm%u at rsp + 0x%x", info, tmp);
325
43
    unexpected = !save_allowed;
326
43
    break;
327
328
28
  case UWOP_SAVE_XMM128_FAR:
329
28
    if (ui->rawUnwindCodesEnd - dta < 6)
330
0
      {
331
0
        fprintf (file, _("warning: corrupt unwind data\n"));
332
0
        return;
333
0
      }
334
28
    tmp = bfd_get_32 (abfd, dta + 2) * 16;
335
28
    i += 2;
336
28
    fprintf (file, "save xmm%u at rsp + 0x%x", info, tmp);
337
28
    unexpected = !save_allowed;
338
28
    break;
339
340
26
  case UWOP_PUSH_MACHFRAME:
341
26
    fprintf (file, "interrupt entry (SS, old RSP, EFLAGS, CS, RIP");
342
26
    if (info == 0)
343
1
      fprintf (file, ")");
344
25
    else if (info == 1)
345
0
      fprintf (file, ",ErrorCode)");
346
25
    else
347
25
      fprintf (file, ", unknown(%u))", info);
348
26
    break;
349
350
176
  default:
351
    /* PR 17512: file: 2245-7442-0.004.  */
352
176
    fprintf (file, _("Unknown: %x"), PEX64_UNWCODE_CODE (dta[1]));
353
176
    break;
354
2.33k
  }
355
356
2.33k
      if (unexpected)
357
138
  fprintf (file, " [Unexpected!]");
358
2.33k
      fputc ('\n', file);
359
2.33k
    }
360
414
}
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
55
{
367
55
  asection *section = bfd_get_section_by_name (abfd, sec_name);
368
55
  bfd_vma vsize;
369
55
  bfd_size_type datasize = 0;
370
371
55
  if (section == NULL
372
55
      || coff_section_data (abfd, section) == NULL
373
55
      || pei_section_data (abfd, section) == NULL)
374
2
    return NULL;
375
53
  vsize = section->vma - pe_data (abfd)->pe_opthdr.ImageBase;
376
53
  datasize = section->size;
377
53
  if (!datasize || vsize > addr || (vsize + datasize) < addr)
378
38
    return NULL;
379
15
  return section;
380
53
}
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
739
{
391
739
  bfd_vma vaddr;
392
739
  bfd_vma end_addr;
393
739
  bfd_vma addr = rf->rva_UnwindData;
394
739
  bfd_size_type sec_size = xdata_section->rawsize > 0 ? xdata_section->rawsize : xdata_section->size;
395
739
  struct pex64_unwind_info ui;
396
397
739
  vaddr = xdata_section->vma - pe_data (abfd)->pe_opthdr.ImageBase;
398
739
  addr -= vaddr;
399
400
  /* PR 17512: file: 2245-7442-0.004.  */
401
739
  if (addr >= sec_size)
402
0
    {
403
0
      fprintf (file, _("warning: xdata section corrupt\n"));
404
0
      return;
405
0
    }
406
407
739
  if (endx)
408
724
    {
409
724
      end_addr = endx[0] - vaddr;
410
      /* PR 17512: file: 2245-7442-0.004.  */
411
724
      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
724
    }
417
15
  else
418
15
    end_addr = sec_size;
419
420
739
  if (! pex64_get_unwind_info (abfd, &ui, xdata + addr, xdata + end_addr))
421
98
    {
422
98
      fprintf (file, _("warning: xdata section corrupt\n"));
423
98
      return;
424
98
    }
425
426
641
  if (ui.Version != 1 && ui.Version != 2)
427
109
    {
428
109
      unsigned int i;
429
109
      fprintf (file, "\tVersion %u (unknown).\n",
430
109
         (unsigned int) ui.Version);
431
54.3k
      for (i = 0; addr < end_addr; addr += 1, i++)
432
54.1k
  {
433
54.1k
    if ((i & 15) == 0)
434
3.43k
      fprintf (file, "\t  %03x:", i);
435
54.1k
    fprintf (file, " %02x", xdata[addr]);
436
54.1k
    if ((i & 15) == 15)
437
3.34k
      fprintf (file, "\n");
438
54.1k
  }
439
109
      if ((i & 15) != 0)
440
90
  fprintf (file, "\n");
441
109
      return;
442
109
    }
443
444
532
  fprintf (file, "\tVersion: %d, Flags: ", ui.Version);
445
532
  switch (ui.Flags)
446
532
    {
447
416
    case UNW_FLAG_NHANDLER:
448
416
      fprintf (file, "none");
449
416
      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
10
    default:
464
10
      fprintf (file, "unknown flags value 0x%x", (unsigned int) ui.Flags);
465
10
      break;
466
532
    }
467
532
  fputc ('\n', file);
468
532
  fprintf (file, "\tNbr codes: %u, ", (unsigned int) ui.CountOfCodes);
469
532
  fprintf (file, "Prologue size: 0x%02x, Frame offset: 0x%x, ",
470
532
     (unsigned int) ui.SizeOfPrologue, (unsigned int) ui.FrameOffset);
471
532
  fprintf (file, "Frame reg: %s\n",
472
532
     ui.FrameRegister == 0 ? "none"
473
532
     : pex_regs[(unsigned int) ui.FrameRegister]);
474
475
  /* PR 17512: file: 2245-7442-0.004.  */
476
532
  if (ui.CountOfCodes * 2 + ui.rawUnwindCodes > xdata + xdata_section->size)
477
0
    fprintf (file, _("Too many unwind codes (%ld)\n"), (long) ui.CountOfCodes);
478
532
  else
479
532
    pex64_xdata_print_uwd_codes (file, abfd, &ui, rf);
480
481
532
  switch (ui.Flags)
482
532
    {
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
532
    }
496
497
  /* Now we need end of this xdata block.  */
498
532
  addr += ui.SizeOfBlock;
499
532
  if (addr < end_addr)
500
121
    {
501
121
      unsigned int i;
502
121
      fprintf (file,"\tUser data:\n");
503
6.73k
      for (i = 0; addr < end_addr; addr += 1, i++)
504
6.61k
  {
505
6.61k
    if ((i & 15) == 0)
506
453
      fprintf (file, "\t  %03x:", i);
507
6.61k
    fprintf (file, " %02x", xdata[addr]);
508
6.61k
    if ((i & 15) == 15)
509
334
      fprintf (file, "\n");
510
6.61k
  }
511
121
      if ((i & 15) != 0)
512
119
  fprintf (file, "\n");
513
121
    }
514
532
}
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
7.53k
{
522
7.53k
  const bfd_vma *lp = (const bfd_vma *) l;
523
7.53k
  const bfd_vma *rp = (const bfd_vma *) r;
524
525
7.53k
  if (*lp == *rp)
526
1.13k
    return 0;
527
6.40k
  return (*lp < *rp ? -1 : 1);
528
7.53k
}
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
54
{
535
54
  FILE *file = (FILE *) vfile;
536
54
  bfd_byte *pdata = NULL;
537
54
  bfd_byte *xdata = NULL;
538
54
  asection *xdata_section = NULL;
539
54
  bfd_vma xdata_base;
540
54
  bfd_size_type i;
541
54
  bfd_size_type datasize;
542
54
  bfd_size_type stop;
543
54
  bfd_vma prev_beginaddress = (bfd_vma) -1;
544
54
  bfd_vma prev_unwinddata_rva = (bfd_vma) -1;
545
54
  bfd_vma imagebase;
546
54
  int onaline = PDATA_ROW_SIZE;
547
54
  int seen_error = 0;
548
54
  bfd_vma *xdata_arr = NULL;
549
54
  int xdata_arr_cnt;
550
54
  bool virt_size_is_zero = false;
551
552
  /* Sanity checks.  */
553
54
  if (pdata_section == NULL
554
54
      || (pdata_section->flags & SEC_HAS_CONTENTS) == 0
555
54
      || coff_section_data (abfd, pdata_section) == NULL
556
54
      || pei_section_data (abfd, pdata_section) == NULL)
557
0
    return true;
558
559
54
  stop = pei_section_data (abfd, pdata_section)->virt_size;
560
54
  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
54
  datasize = pdata_section->size;
567
54
  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
54
  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
54
  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
54
  fprintf (file,
594
54
     _("\nThe Function Table (interpreted %s section contents)\n"),
595
54
     pdata_section->name);
596
597
54
  fprintf (file, _("vma:\t\t\tBeginAddress\t EndAddress\t  UnwindData\n"));
598
599
54
  if (!bfd_malloc_and_get_section (abfd, pdata_section, &pdata))
600
2
    goto done;
601
602
  /* Table of xdata entries.  */
603
52
  xdata_arr = (bfd_vma *) xmalloc (sizeof (bfd_vma) * ((stop / onaline) + 1));
604
52
  xdata_arr_cnt = 0;
605
606
52
  if (strcmp (abfd->xvec->name, "pei-x86-64") == 0)
607
52
    imagebase = pe_data (abfd)->pe_opthdr.ImageBase;
608
0
  else
609
0
    imagebase = 0;
610
611
4.16k
  for (i = 0; i < stop; i += onaline)
612
4.12k
    {
613
4.12k
      struct pex64_runtime_function rf;
614
615
4.12k
      if (i + PDATA_ROW_SIZE > stop)
616
0
  break;
617
618
4.12k
      pex64_get_runtime_function (abfd, &rf, &pdata[i]);
619
620
4.12k
      if (rf.rva_BeginAddress == 0 && rf.rva_EndAddress == 0
621
4.12k
    && rf.rva_UnwindData == 0)
622
  /* We are probably into the padding of the section now.  */
623
13
  break;
624
4.11k
      fprintf (file, " %016" PRIx64, i + pdata_section->vma);
625
4.11k
      fprintf (file, ":\t%016" PRIx64, imagebase + rf.rva_BeginAddress);
626
4.11k
      fprintf (file, " %016" PRIx64, imagebase + rf.rva_EndAddress);
627
4.11k
      fprintf (file, " %016" PRIx64 "\n", imagebase + rf.rva_UnwindData);
628
4.11k
      if (i != 0 && rf.rva_BeginAddress <= prev_beginaddress)
629
1.25k
  {
630
1.25k
    seen_error = 1;
631
1.25k
    fprintf (file, "  has %s begin address as predecessor\n",
632
1.25k
      (rf.rva_BeginAddress < prev_beginaddress ? "smaller" : "same"));
633
1.25k
  }
634
4.11k
      prev_beginaddress = rf.rva_BeginAddress;
635
      /* Now we check for negative addresses.  */
636
4.11k
      if ((prev_beginaddress & 0x80000000) != 0)
637
1.35k
  {
638
1.35k
    seen_error = 1;
639
1.35k
    fprintf (file, "  has negative begin address\n");
640
1.35k
  }
641
4.11k
      if ((rf.rva_EndAddress & 0x80000000) != 0)
642
1.41k
  {
643
1.41k
    seen_error = 1;
644
1.41k
    fprintf (file, "  has negative end address\n");
645
1.41k
  }
646
4.11k
      if ((rf.rva_UnwindData & 0x80000000) != 0)
647
1.33k
  {
648
1.33k
    seen_error = 1;
649
1.33k
    fprintf (file, "  has negative unwind address\n");
650
1.33k
  }
651
2.77k
      else if ((rf.rva_UnwindData && !PEX64_IS_RUNTIME_FUNCTION_CHAINED (&rf))
652
2.77k
    || virt_size_is_zero)
653
1.47k
  xdata_arr[xdata_arr_cnt++] = rf.rva_UnwindData;
654
4.11k
    }
655
656
52
  if (seen_error)
657
30
    goto done;
658
659
  /* Add end of list marker.  */
660
22
  xdata_arr[xdata_arr_cnt++] = ~((bfd_vma) 0);
661
662
  /* Sort start RVAs of xdata.  */
663
22
  if (xdata_arr_cnt > 1)
664
16
    qsort (xdata_arr, (size_t) xdata_arr_cnt, sizeof (bfd_vma),
665
16
     sort_xdata_arr);
666
667
  /* Find the section containing the unwind data (.xdata).  */
668
22
  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
22
  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
22
  if (!xdata_section)
686
22
    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
22
  if (!xdata_section && xdata_base)
690
9
    xdata_section = pex64_get_section_by_rva (abfd, xdata_base, ".rdata");
691
22
  if (!xdata_section && xdata_base)
692
8
    xdata_section = pex64_get_section_by_rva (abfd, xdata_base, ".data");
693
22
  if (!xdata_section && xdata_base)
694
8
    xdata_section = pex64_get_section_by_rva (abfd, xdata_base, ".pdata");
695
22
  if (!xdata_section && xdata_base)
696
8
    xdata_section = pex64_get_section_by_rva (abfd, xdata_base, ".text");
697
  /* Transfer xdata section into xdata array.  */
698
22
  if (!xdata_section
699
22
      || (xdata_section->flags & SEC_HAS_CONTENTS) == 0
700
22
      || !bfd_malloc_and_get_section (abfd, xdata_section, &xdata))
701
7
    goto done;
702
703
  /* Avoid "also used "... ouput for single unwind info
704
     in object file.  */
705
15
  prev_unwinddata_rva = (bfd_vma) -1;
706
707
  /* Do dump of pdata related xdata.  */
708
1.34k
  for (i = 0; i < stop; i += onaline)
709
1.32k
    {
710
1.32k
      struct pex64_runtime_function rf;
711
712
1.32k
      if (i + PDATA_ROW_SIZE > stop)
713
0
  break;
714
715
1.32k
      pex64_get_runtime_function (abfd, &rf, &pdata[i]);
716
717
1.32k
      if (rf.rva_BeginAddress == 0 && rf.rva_EndAddress == 0
718
1.32k
    && rf.rva_UnwindData == 0)
719
  /* We are probably into the padding of the section now.  */
720
1
  break;
721
1.32k
      if (i == 0)
722
15
  fprintf (file, _("\nDump of %s\n"), xdata_section->name);
723
724
1.32k
      fprintf (file, " %016" PRIx64, rf.rva_UnwindData + imagebase);
725
726
1.32k
      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
1.30k
      else
734
1.30k
  prev_unwinddata_rva = rf.rva_UnwindData;
735
736
1.30k
      fprintf (file, " (rva: %08x): %016" PRIx64 " - %016" PRIx64 "\n",
737
1.30k
         (unsigned int) rf.rva_UnwindData,
738
1.30k
         rf.rva_BeginAddress + imagebase,
739
1.30k
         rf.rva_EndAddress + imagebase);
740
741
1.30k
      if (rf.rva_UnwindData != 0 || virt_size_is_zero)
742
1.30k
  {
743
1.30k
    if (PEX64_IS_RUNTIME_FUNCTION_CHAINED (&rf))
744
566
      {
745
566
        bfd_vma altent = PEX64_GET_UNWINDDATA_UNIFIED_RVA (&rf);
746
566
        bfd_vma pdata_vma = bfd_section_vma (pdata_section);
747
566
        struct pex64_runtime_function arf;
748
749
566
        fprintf (file, "\t shares information with ");
750
566
        altent += imagebase;
751
752
566
        if (altent >= pdata_vma
753
566
      && 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
94
        else
761
94
    fprintf (file, "unknown pdata element");
762
566
        fprintf (file, ".\n");
763
566
      }
764
739
    else
765
739
      {
766
739
        bfd_vma *p;
767
768
        /* Search for the current entry in the sorted array.  */
769
739
        p = (bfd_vma *)
770
739
      bsearch (&rf.rva_UnwindData, xdata_arr,
771
739
         (size_t) xdata_arr_cnt, sizeof (bfd_vma),
772
739
         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.88k
        while (p[0] <= rf.rva_UnwindData)
778
2.14k
    ++p;
779
780
739
        if (p[0] == ~((bfd_vma) 0))
781
15
    p = NULL;
782
783
739
        pex64_dump_xdata (file, abfd, xdata_section, xdata, p, &rf);
784
739
      }
785
1.30k
  }
786
1.30k
    }
787
788
54
 done:
789
54
  free (pdata);
790
54
  free (xdata_arr);
791
54
  free (xdata);
792
793
54
  return true;
794
15
}
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
2.89k
{
810
2.89k
  struct pex64_paps *paps = arg;
811
2.89k
  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
2.89k
}
817
818
bool
819
pex64_bfd_print_pdata (bfd *abfd, void *vfile)
820
510
{
821
510
  asection *pdata_section = bfd_get_section_by_name (abfd, ".pdata");
822
510
  struct pex64_paps paps;
823
824
510
  if (pdata_section)
825
54
    return pex64_bfd_print_pdata_section (abfd, vfile, pdata_section);
826
827
456
  paps.obj = vfile;
828
456
  paps.pdata_count = 0;
829
456
  bfd_map_over_sections (abfd, pex64_print_all_pdata_sections, &paps);
830
456
  return paps.pdata_count != 0;
831
510
}
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"