Coverage Report

Created: 2025-07-08 11:15

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