Coverage Report

Created: 2025-06-24 06:45

/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
17.4k
#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
143k
#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
142k
{
90
142k
  const struct external_pex64_runtime_function *ex_rf =
91
142k
    (const struct external_pex64_runtime_function *) data;
92
142k
  rf->rva_BeginAddress = bfd_get_32 (abfd, ex_rf->rva_BeginAddress);
93
142k
  rf->rva_EndAddress = bfd_get_32 (abfd, ex_rf->rva_EndAddress);
94
142k
  rf->rva_UnwindData =  bfd_get_32 (abfd, ex_rf->rva_UnwindData);
95
142k
}
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
25.8k
{
103
25.8k
  struct external_pex64_unwind_info *ex_ui =
104
25.8k
    (struct external_pex64_unwind_info *) data;
105
25.8k
  bfd_byte *ex_dta = (bfd_byte *) data;
106
25.8k
  bfd_byte *ex_dta_end = (bfd_byte *) data_end;
107
108
25.8k
  memset (ui, 0, sizeof (struct pex64_unwind_info));
109
110
25.8k
  if (ex_dta_end - ex_dta < 4)
111
3
    return false;
112
113
25.8k
  ui->Version = PEX64_UWI_VERSION (ex_ui->Version_Flags);
114
25.8k
  ui->Flags = PEX64_UWI_FLAGS (ex_ui->Version_Flags);
115
25.8k
  ui->SizeOfPrologue = (bfd_vma) ex_ui->SizeOfPrologue;
116
25.8k
  ui->CountOfCodes = (bfd_vma) ex_ui->CountOfCodes;
117
25.8k
  ui->FrameRegister = PEX64_UWI_FRAMEREG (ex_ui->FrameRegisterOffset);
118
25.8k
  ui->FrameOffset = PEX64_UWI_FRAMEOFF (ex_ui->FrameRegisterOffset);
119
25.8k
  ui->sizeofUnwindCodes = PEX64_UWI_SIZEOF_UWCODE_ARRAY (ui->CountOfCodes);
120
25.8k
  ui->SizeOfBlock = ui->sizeofUnwindCodes + 4;
121
25.8k
  ui->rawUnwindCodes = ex_dta + 4;
122
25.8k
  ui->rawUnwindCodesEnd = ex_dta_end;
123
124
25.8k
  if ((size_t) (ex_dta_end - ex_dta) < ui->SizeOfBlock)
125
8.16k
    return false;
126
17.6k
  ex_dta += ui->SizeOfBlock;
127
128
17.6k
  switch (ui->Flags)
129
17.6k
    {
130
449
    case UNW_FLAG_CHAININFO:
131
449
      if (ex_dta_end - ex_dta < 12)
132
85
  return false;
133
364
      ui->rva_BeginAddress = bfd_get_32 (abfd, ex_dta + 0);
134
364
      ui->rva_EndAddress = bfd_get_32 (abfd, ex_dta + 4);
135
364
      ui->rva_UnwindData = bfd_get_32 (abfd, ex_dta + 8);
136
364
      ui->SizeOfBlock += 12;
137
364
      return true;
138
1.75k
    case UNW_FLAG_EHANDLER:
139
2.28k
    case UNW_FLAG_UHANDLER:
140
2.80k
    case UNW_FLAG_FHANDLER:
141
2.80k
      if (ex_dta_end - ex_dta < 4)
142
123
  return false;
143
2.67k
      ui->rva_ExceptionHandler = bfd_get_32 (abfd, ex_dta);
144
2.67k
      ui->SizeOfBlock += 4;
145
2.67k
      return true;
146
14.4k
    default:
147
14.4k
      return true;
148
17.6k
    }
149
17.6k
}
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
6.14k
{
158
6.14k
  unsigned int i;
159
6.14k
  unsigned int tmp; /* At least 32 bits.  */
160
6.14k
  int save_allowed;
161
162
6.14k
  if (ui->CountOfCodes == 0 || ui->rawUnwindCodes == NULL)
163
1.20k
    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.93k
  save_allowed = true;
170
171
4.93k
  i = 0;
172
173
4.93k
  if ((size_t) (ui->rawUnwindCodesEnd - ui->rawUnwindCodes)
174
4.93k
      < ui->CountOfCodes * 2)
175
0
    {
176
0
      fprintf (file, _("warning: corrupt unwind data\n"));
177
0
      return;
178
0
    }
179
180
4.93k
  if (ui->Version == 2
181
4.93k
      && PEX64_UNWCODE_CODE (ui->rawUnwindCodes[1]) == UWOP_EPILOG)
182
162
    {
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
162
      unsigned int func_size = rf->rva_EndAddress - rf->rva_BeginAddress;
187
188
162
      fprintf (file, "\tv2 epilog (length: %02x) at pc+:",
189
162
         ui->rawUnwindCodes[0]);
190
191
162
      if (PEX64_UNWCODE_INFO (ui->rawUnwindCodes[1]))
192
159
  fprintf (file, " 0x%x", func_size - ui->rawUnwindCodes[0]);
193
194
162
      i++;
195
183
      for (; i < ui->CountOfCodes; i++)
196
157
  {
197
157
    const bfd_byte *dta = ui->rawUnwindCodes + 2 * i;
198
157
    unsigned int off;
199
200
157
    if (PEX64_UNWCODE_CODE (dta[1]) != UWOP_EPILOG)
201
136
      break;
202
21
    off = dta[0] | (PEX64_UNWCODE_INFO (dta[1]) << 8);
203
21
    if (off == 0)
204
0
      fprintf (file, " [pad]");
205
21
    else
206
21
      fprintf (file, " 0x%x", func_size - off);
207
21
  }
208
162
      fputc ('\n', file);
209
162
    }
210
211
62.1k
  for (; i < ui->CountOfCodes; i++)
212
57.5k
    {
213
57.5k
      const bfd_byte *dta = ui->rawUnwindCodes + 2 * i;
214
57.5k
      unsigned int info = PEX64_UNWCODE_INFO (dta[1]);
215
57.5k
      int unexpected = false;
216
217
57.5k
      fprintf (file, "\t  pc+0x%02x: ", (unsigned int) dta[0]);
218
219
57.5k
      switch (PEX64_UNWCODE_CODE (dta[1]))
220
57.5k
  {
221
13.0k
  case UWOP_PUSH_NONVOL:
222
13.0k
    fprintf (file, "push %s", pex_regs[info]);
223
13.0k
    break;
224
225
3.44k
  case UWOP_ALLOC_LARGE:
226
3.44k
    if (info == 0)
227
1.89k
      {
228
1.89k
        if (ui->rawUnwindCodesEnd - dta < 4)
229
60
    {
230
60
      fprintf (file, _("warning: corrupt unwind data\n"));
231
60
      return;
232
60
    }
233
1.83k
        tmp = bfd_get_16 (abfd, dta + 2) * 8;
234
1.83k
        i++;
235
1.83k
      }
236
1.55k
    else
237
1.55k
      {
238
1.55k
        if (ui->rawUnwindCodesEnd - dta < 6)
239
33
    {
240
33
      fprintf (file, _("warning: corrupt unwind data\n"));
241
33
      return;
242
33
    }
243
1.52k
        tmp = bfd_get_32 (abfd, dta + 2);
244
1.52k
        i += 2;
245
1.52k
      }
246
3.35k
    fprintf (file, "alloc large area: rsp = rsp - 0x%x", tmp);
247
3.35k
    break;
248
249
5.52k
  case UWOP_ALLOC_SMALL:
250
5.52k
    fprintf (file, "alloc small area: rsp = rsp - 0x%x", (info + 1) * 8);
251
5.52k
    break;
252
253
3.16k
  case UWOP_SET_FPREG:
254
    /* According to the documentation, info field is unused.  */
255
3.16k
    fprintf (file, "FPReg: %s = rsp + 0x%x (info = 0x%x)",
256
3.16k
       pex_regs[ui->FrameRegister],
257
3.16k
       (unsigned int) ui->FrameOffset * 16, info);
258
3.16k
    unexpected = ui->FrameRegister == 0;
259
3.16k
    save_allowed = false;
260
3.16k
    break;
261
262
4.07k
  case UWOP_SAVE_NONVOL:
263
4.07k
    if (ui->rawUnwindCodesEnd - dta < 4)
264
1
      {
265
1
        fprintf (file, _("warning: corrupt unwind data\n"));
266
1
        return;
267
1
      }
268
4.07k
    tmp = bfd_get_16 (abfd, dta + 2) * 8;
269
4.07k
    i++;
270
4.07k
    fprintf (file, "save %s at rsp + 0x%x", pex_regs[info], tmp);
271
4.07k
    unexpected = !save_allowed;
272
4.07k
    break;
273
274
3.59k
  case UWOP_SAVE_NONVOL_FAR:
275
3.59k
    if (ui->rawUnwindCodesEnd - dta < 6)
276
186
      {
277
186
        fprintf (file, _("warning: corrupt unwind data\n"));
278
186
        return;
279
186
      }
280
3.40k
    tmp = bfd_get_32 (abfd, dta + 2);
281
3.40k
    i += 2;
282
3.40k
    fprintf (file, "save %s at rsp + 0x%x", pex_regs[info], tmp);
283
3.40k
    unexpected = !save_allowed;
284
3.40k
    break;
285
286
1.81k
  case UWOP_SAVE_XMM:
287
1.81k
    if (ui->Version == 1)
288
875
      {
289
875
        if (ui->rawUnwindCodesEnd - dta < 4)
290
0
    {
291
0
      fprintf (file, _("warning: corrupt unwind data\n"));
292
0
      return;
293
0
    }
294
875
        tmp = bfd_get_16 (abfd, dta + 2) * 8;
295
875
        i++;
296
875
        fprintf (file, "save mm%u at rsp + 0x%x", info, tmp);
297
875
        unexpected = !save_allowed;
298
875
      }
299
935
    else if (ui->Version == 2)
300
935
      {
301
935
        fprintf (file, "epilog %02x %01x", dta[0], info);
302
935
        unexpected = true;
303
935
      }
304
1.81k
    break;
305
306
1.81k
  case UWOP_SAVE_XMM_FAR:
307
1.50k
    if (ui->rawUnwindCodesEnd - dta < 6)
308
42
      {
309
42
        fprintf (file, _("warning: corrupt unwind data\n"));
310
42
        return;
311
42
      }
312
1.46k
    tmp = bfd_get_32 (abfd, dta + 2) * 8;
313
1.46k
    i += 2;
314
1.46k
    fprintf (file, "save mm%u at rsp + 0x%x", info, tmp);
315
1.46k
    unexpected = !save_allowed;
316
1.46k
    break;
317
318
2.96k
  case UWOP_SAVE_XMM128:
319
2.96k
    if (ui->rawUnwindCodesEnd - dta < 4)
320
1
      {
321
1
        fprintf (file, _("warning: corrupt unwind data\n"));
322
1
        return;
323
1
      }
324
2.96k
    tmp = bfd_get_16 (abfd, dta + 2) * 16;
325
2.96k
    i++;
326
2.96k
    fprintf (file, "save xmm%u at rsp + 0x%x", info, tmp);
327
2.96k
    unexpected = !save_allowed;
328
2.96k
    break;
329
330
6.19k
  case UWOP_SAVE_XMM128_FAR:
331
6.19k
    if (ui->rawUnwindCodesEnd - dta < 6)
332
9
      {
333
9
        fprintf (file, _("warning: corrupt unwind data\n"));
334
9
        return;
335
9
      }
336
6.18k
    tmp = bfd_get_32 (abfd, dta + 2) * 16;
337
6.18k
    i += 2;
338
6.18k
    fprintf (file, "save xmm%u at rsp + 0x%x", info, tmp);
339
6.18k
    unexpected = !save_allowed;
340
6.18k
    break;
341
342
1.46k
  case UWOP_PUSH_MACHFRAME:
343
1.46k
    fprintf (file, "interrupt entry (SS, old RSP, EFLAGS, CS, RIP");
344
1.46k
    if (info == 0)
345
275
      fprintf (file, ")");
346
1.18k
    else if (info == 1)
347
207
      fprintf (file, ",ErrorCode)");
348
981
    else
349
981
      fprintf (file, ", unknown(%u))", info);
350
1.46k
    break;
351
352
10.8k
  default:
353
    /* PR 17512: file: 2245-7442-0.004.  */
354
10.8k
    fprintf (file, _("Unknown: %x"), PEX64_UNWCODE_CODE (dta[1]));
355
10.8k
    break;
356
57.5k
  }
357
358
57.2k
      if (unexpected)
359
10.5k
  fprintf (file, " [Unexpected!]");
360
57.2k
      fputc ('\n', file);
361
57.2k
    }
362
4.93k
}
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.12k
{
369
1.12k
  asection *section = bfd_get_section_by_name (abfd, sec_name);
370
1.12k
  bfd_vma vsize;
371
1.12k
  bfd_size_type datasize = 0;
372
373
1.12k
  if (section == NULL
374
1.12k
      || coff_section_data (abfd, section) == NULL
375
1.12k
      || pei_section_data (abfd, section) == NULL)
376
477
    return NULL;
377
648
  vsize = section->vma - pe_data (abfd)->pe_opthdr.ImageBase;
378
648
  datasize = section->size;
379
648
  if (!datasize || vsize > addr || (vsize + datasize) < addr)
380
374
    return NULL;
381
274
  return section;
382
648
}
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
26.2k
{
393
26.2k
  bfd_vma vaddr;
394
26.2k
  bfd_vma end_addr;
395
26.2k
  bfd_vma addr = rf->rva_UnwindData;
396
26.2k
  bfd_size_type sec_size = xdata_section->rawsize > 0 ? xdata_section->rawsize : xdata_section->size;
397
26.2k
  struct pex64_unwind_info ui;
398
399
26.2k
  vaddr = xdata_section->vma - pe_data (abfd)->pe_opthdr.ImageBase;
400
26.2k
  addr -= vaddr;
401
402
  /* PR 17512: file: 2245-7442-0.004.  */
403
26.2k
  if (addr >= sec_size)
404
456
    {
405
456
      fprintf (file, _("warning: xdata section corrupt\n"));
406
456
      return;
407
456
    }
408
409
25.8k
  if (endx)
410
25.5k
    {
411
25.5k
      end_addr = endx[0] - vaddr;
412
      /* PR 17512: file: 2245-7442-0.004.  */
413
25.5k
      if (end_addr > sec_size)
414
31
  {
415
31
    fprintf (file, _("warning: xdata section corrupt\n"));
416
31
    end_addr = sec_size;
417
31
  }
418
25.5k
    }
419
239
  else
420
239
    end_addr = sec_size;
421
422
25.8k
  if (! pex64_get_unwind_info (abfd, &ui, xdata + addr, xdata + end_addr))
423
8.37k
    {
424
8.37k
      fprintf (file, _("warning: xdata section corrupt\n"));
425
8.37k
      return;
426
8.37k
    }
427
428
17.4k
  if (ui.Version != 1 && ui.Version != 2)
429
11.3k
    {
430
11.3k
      unsigned int i;
431
11.3k
      fprintf (file, "\tVersion %u (unknown).\n",
432
11.3k
         (unsigned int) ui.Version);
433
3.50M
      for (i = 0; addr < end_addr; addr += 1, i++)
434
3.49M
  {
435
3.49M
    if ((i & 15) == 0)
436
222k
      fprintf (file, "\t  %03x:", i);
437
3.49M
    fprintf (file, " %02x", xdata[addr]);
438
3.49M
    if ((i & 15) == 15)
439
213k
      fprintf (file, "\n");
440
3.49M
  }
441
11.3k
      if ((i & 15) != 0)
442
9.12k
  fprintf (file, "\n");
443
11.3k
      return;
444
11.3k
    }
445
446
6.14k
  fprintf (file, "\tVersion: %d, Flags: ", ui.Version);
447
6.14k
  switch (ui.Flags)
448
6.14k
    {
449
3.28k
    case UNW_FLAG_NHANDLER:
450
3.28k
      fprintf (file, "none");
451
3.28k
      break;
452
1.42k
    case UNW_FLAG_EHANDLER:
453
1.42k
      fprintf (file, "UNW_FLAG_EHANDLER");
454
1.42k
      break;
455
96
    case UNW_FLAG_UHANDLER:
456
96
      fprintf (file, "UNW_FLAG_UHANDLER");
457
96
      break;
458
303
    case UNW_FLAG_FHANDLER:
459
303
      fprintf
460
303
  (file, "UNW_FLAG_EHANDLER | UNW_FLAG_UHANDLER");
461
303
      break;
462
55
    case UNW_FLAG_CHAININFO:
463
55
      fprintf (file, "UNW_FLAG_CHAININFO");
464
55
      break;
465
987
    default:
466
987
      fprintf (file, "unknown flags value 0x%x", (unsigned int) ui.Flags);
467
987
      break;
468
6.14k
    }
469
6.14k
  fputc ('\n', file);
470
6.14k
  fprintf (file, "\tNbr codes: %u, ", (unsigned int) ui.CountOfCodes);
471
6.14k
  fprintf (file, "Prologue size: 0x%02x, Frame offset: 0x%x, ",
472
6.14k
     (unsigned int) ui.SizeOfPrologue, (unsigned int) ui.FrameOffset);
473
6.14k
  fprintf (file, "Frame reg: %s\n",
474
6.14k
     ui.FrameRegister == 0 ? "none"
475
6.14k
     : pex_regs[(unsigned int) ui.FrameRegister]);
476
477
  /* PR 17512: file: 2245-7442-0.004.  */
478
6.14k
  if (ui.CountOfCodes * 2 + ui.rawUnwindCodes > xdata + xdata_section->size)
479
0
    fprintf (file, _("Too many unwind codes (%ld)\n"), (long) ui.CountOfCodes);
480
6.14k
  else
481
6.14k
    pex64_xdata_print_uwd_codes (file, abfd, &ui, rf);
482
483
6.14k
  switch (ui.Flags)
484
6.14k
    {
485
1.42k
    case UNW_FLAG_EHANDLER:
486
1.51k
    case UNW_FLAG_UHANDLER:
487
1.81k
    case UNW_FLAG_FHANDLER:
488
1.81k
      fprintf (file, "\tHandler: %016" PRIx64 ".\n",
489
1.81k
         ui.rva_ExceptionHandler + pe_data (abfd)->pe_opthdr.ImageBase);
490
1.81k
      break;
491
55
    case UNW_FLAG_CHAININFO:
492
55
      fprintf (file, "\tChain: start: %016" PRIx64 ", end: %016" PRIx64,
493
55
         ui.rva_BeginAddress, ui.rva_EndAddress);
494
55
      fprintf (file, "\n\t unwind data: %016" PRIx64 ".\n",
495
55
         ui.rva_UnwindData);
496
55
      break;
497
6.14k
    }
498
499
  /* Now we need end of this xdata block.  */
500
6.14k
  addr += ui.SizeOfBlock;
501
6.14k
  if (addr < end_addr)
502
4.21k
    {
503
4.21k
      unsigned int i;
504
4.21k
      fprintf (file,"\tUser data:\n");
505
869k
      for (i = 0; addr < end_addr; addr += 1, i++)
506
865k
  {
507
865k
    if ((i & 15) == 0)
508
55.7k
      fprintf (file, "\t  %03x:", i);
509
865k
    fprintf (file, " %02x", xdata[addr]);
510
865k
    if ((i & 15) == 15)
511
52.4k
      fprintf (file, "\n");
512
865k
  }
513
4.21k
      if ((i & 15) != 0)
514
3.37k
  fprintf (file, "\n");
515
4.21k
    }
516
6.14k
}
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
320k
{
524
320k
  const bfd_vma *lp = (const bfd_vma *) l;
525
320k
  const bfd_vma *rp = (const bfd_vma *) r;
526
527
320k
  if (*lp == *rp)
528
38.5k
    return 0;
529
281k
  return (*lp < *rp ? -1 : 1);
530
320k
}
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
523
{
537
523
  FILE *file = (FILE *) vfile;
538
523
  bfd_byte *pdata = NULL;
539
523
  bfd_byte *xdata = NULL;
540
523
  asection *xdata_section = NULL;
541
523
  bfd_vma xdata_base;
542
523
  bfd_size_type i;
543
523
  bfd_size_type datasize;
544
523
  bfd_size_type stop;
545
523
  bfd_vma prev_beginaddress = (bfd_vma) -1;
546
523
  bfd_vma prev_unwinddata_rva = (bfd_vma) -1;
547
523
  bfd_vma imagebase;
548
523
  int onaline = PDATA_ROW_SIZE;
549
523
  int seen_error = 0;
550
523
  bfd_vma *xdata_arr = NULL;
551
523
  int xdata_arr_cnt;
552
523
  bool virt_size_is_zero = false;
553
554
  /* Sanity checks.  */
555
523
  if (pdata_section == NULL
556
523
      || (pdata_section->flags & SEC_HAS_CONTENTS) == 0
557
523
      || coff_section_data (abfd, pdata_section) == NULL
558
523
      || pei_section_data (abfd, pdata_section) == NULL)
559
3
    return true;
560
561
520
  stop = pei_section_data (abfd, pdata_section)->virt_size;
562
520
  if ((stop % onaline) != 0)
563
46
    fprintf (file,
564
       /* xgettext:c-format */
565
46
       _("Warning: %s section size (%ld) is not a multiple of %d\n"),
566
46
       pdata_section->name, (long) stop, onaline);
567
568
520
  datasize = pdata_section->size;
569
520
  if (datasize == 0)
570
3
    {
571
3
      if (stop)
572
1
  fprintf (file, _("Warning: %s section size is zero\n"),
573
1
     pdata_section->name);
574
3
      return true;
575
3
    }
576
577
  /* virt_size might be zero for objects.  */
578
517
  if (stop == 0 && strcmp (abfd->xvec->name, "pe-x86-64") == 0)
579
123
    {
580
123
      stop = datasize;
581
123
      virt_size_is_zero = true;
582
123
    }
583
394
  else if (datasize < stop)
584
49
      {
585
49
  fprintf (file,
586
     /* xgettext:c-format */
587
49
     _("Warning: %s section size (%ld) is smaller than virtual size (%ld)\n"),
588
49
     pdata_section->name, (unsigned long) datasize,
589
49
     (unsigned long) stop);
590
  /* Be sure not to read past datasize.  */
591
49
  stop = datasize;
592
49
      }
593
594
  /* Display functions table.  */
595
517
  fprintf (file,
596
517
     _("\nThe Function Table (interpreted %s section contents)\n"),
597
517
     pdata_section->name);
598
599
517
  fprintf (file, _("vma:\t\t\tBeginAddress\t EndAddress\t  UnwindData\n"));
600
601
517
  if (!bfd_malloc_and_get_section (abfd, pdata_section, &pdata))
602
49
    goto done;
603
604
  /* Table of xdata entries.  */
605
468
  xdata_arr = (bfd_vma *) xmalloc (sizeof (bfd_vma) * ((stop / onaline) + 1));
606
468
  xdata_arr_cnt = 0;
607
608
468
  if (strcmp (abfd->xvec->name, "pei-x86-64") == 0)
609
307
    imagebase = pe_data (abfd)->pe_opthdr.ImageBase;
610
161
  else
611
161
    imagebase = 0;
612
613
81.0k
  for (i = 0; i < stop; i += onaline)
614
80.9k
    {
615
80.9k
      struct pex64_runtime_function rf;
616
617
80.9k
      if (i + PDATA_ROW_SIZE > stop)
618
46
  break;
619
620
80.8k
      pex64_get_runtime_function (abfd, &rf, &pdata[i]);
621
622
80.8k
      if (rf.rva_BeginAddress == 0 && rf.rva_EndAddress == 0
623
80.8k
    && rf.rva_UnwindData == 0)
624
  /* We are probably into the padding of the section now.  */
625
261
  break;
626
80.6k
      fprintf (file, " %016" PRIx64, i + pdata_section->vma);
627
80.6k
      fprintf (file, ":\t%016" PRIx64, imagebase + rf.rva_BeginAddress);
628
80.6k
      fprintf (file, " %016" PRIx64, imagebase + rf.rva_EndAddress);
629
80.6k
      fprintf (file, " %016" PRIx64 "\n", imagebase + rf.rva_UnwindData);
630
80.6k
      if (i != 0 && rf.rva_BeginAddress <= prev_beginaddress)
631
13.0k
  {
632
13.0k
    seen_error = 1;
633
13.0k
    fprintf (file, "  has %s begin address as predecessor\n",
634
13.0k
      (rf.rva_BeginAddress < prev_beginaddress ? "smaller" : "same"));
635
13.0k
  }
636
80.6k
      prev_beginaddress = rf.rva_BeginAddress;
637
      /* Now we check for negative addresses.  */
638
80.6k
      if ((prev_beginaddress & 0x80000000) != 0)
639
8.97k
  {
640
8.97k
    seen_error = 1;
641
8.97k
    fprintf (file, "  has negative begin address\n");
642
8.97k
  }
643
80.6k
      if ((rf.rva_EndAddress & 0x80000000) != 0)
644
8.64k
  {
645
8.64k
    seen_error = 1;
646
8.64k
    fprintf (file, "  has negative end address\n");
647
8.64k
  }
648
80.6k
      if ((rf.rva_UnwindData & 0x80000000) != 0)
649
8.88k
  {
650
8.88k
    seen_error = 1;
651
8.88k
    fprintf (file, "  has negative unwind address\n");
652
8.88k
  }
653
71.7k
      else if ((rf.rva_UnwindData && !PEX64_IS_RUNTIME_FUNCTION_CHAINED (&rf))
654
71.7k
    || virt_size_is_zero)
655
45.7k
  xdata_arr[xdata_arr_cnt++] = rf.rva_UnwindData;
656
80.6k
    }
657
658
468
  if (seen_error)
659
138
    goto done;
660
661
  /* Add end of list marker.  */
662
330
  xdata_arr[xdata_arr_cnt++] = ~((bfd_vma) 0);
663
664
  /* Sort start RVAs of xdata.  */
665
330
  if (xdata_arr_cnt > 1)
666
296
    qsort (xdata_arr, (size_t) xdata_arr_cnt, sizeof (bfd_vma),
667
296
     sort_xdata_arr);
668
669
  /* Find the section containing the unwind data (.xdata).  */
670
330
  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
330
  if (strcmp (pdata_section->name, ".pdata") != 0)
674
3
    {
675
3
      size_t len = strlen (pdata_section->name);
676
3
      char *xdata_name = xmalloc (len + 1);
677
678
3
      xdata_name = memcpy (xdata_name, pdata_section->name, len + 1);
679
      /* Transform .pdata prefix into .xdata prefix.  */
680
3
      if (len > 1)
681
3
  xdata_name [1] = 'x';
682
3
      xdata_section = pex64_get_section_by_rva (abfd, xdata_base,
683
3
            xdata_name);
684
3
      free (xdata_name);
685
3
    }
686
  /* Second, try the .xdata section itself.  */
687
330
  if (!xdata_section)
688
330
    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
330
  if (!xdata_section && xdata_base)
692
260
    xdata_section = pex64_get_section_by_rva (abfd, xdata_base, ".rdata");
693
330
  if (!xdata_section && xdata_base)
694
211
    xdata_section = pex64_get_section_by_rva (abfd, xdata_base, ".data");
695
330
  if (!xdata_section && xdata_base)
696
211
    xdata_section = pex64_get_section_by_rva (abfd, xdata_base, ".pdata");
697
330
  if (!xdata_section && xdata_base)
698
110
    xdata_section = pex64_get_section_by_rva (abfd, xdata_base, ".text");
699
  /* Transfer xdata section into xdata array.  */
700
330
  if (!xdata_section
701
330
      || (xdata_section->flags & SEC_HAS_CONTENTS) == 0
702
330
      || !bfd_malloc_and_get_section (abfd, xdata_section, &xdata))
703
56
    goto done;
704
705
  /* Avoid "also used "... ouput for single unwind info
706
     in object file.  */
707
274
  prev_unwinddata_rva = (bfd_vma) -1;
708
709
  /* Do dump of pdata related xdata.  */
710
47.1k
  for (i = 0; i < stop; i += onaline)
711
47.0k
    {
712
47.0k
      struct pex64_runtime_function rf;
713
714
47.0k
      if (i + PDATA_ROW_SIZE > stop)
715
10
  break;
716
717
47.0k
      pex64_get_runtime_function (abfd, &rf, &pdata[i]);
718
719
47.0k
      if (rf.rva_BeginAddress == 0 && rf.rva_EndAddress == 0
720
47.0k
    && rf.rva_UnwindData == 0)
721
  /* We are probably into the padding of the section now.  */
722
181
  break;
723
46.8k
      if (i == 0)
724
274
  fprintf (file, _("\nDump of %s\n"), xdata_section->name);
725
726
46.8k
      fprintf (file, " %016" PRIx64, rf.rva_UnwindData + imagebase);
727
728
46.8k
      if (prev_unwinddata_rva == rf.rva_UnwindData)
729
721
  {
730
    /* Do not dump again the xdata for the same entry.  */
731
721
    fprintf (file, " also used for function at %016" PRIx64 "\n",
732
721
       rf.rva_BeginAddress + imagebase);
733
721
    continue;
734
721
  }
735
46.1k
      else
736
46.1k
  prev_unwinddata_rva = rf.rva_UnwindData;
737
738
46.1k
      fprintf (file, " (rva: %08x): %016" PRIx64 " - %016" PRIx64 "\n",
739
46.1k
         (unsigned int) rf.rva_UnwindData,
740
46.1k
         rf.rva_BeginAddress + imagebase,
741
46.1k
         rf.rva_EndAddress + imagebase);
742
743
46.1k
      if (rf.rva_UnwindData != 0 || virt_size_is_zero)
744
46.0k
  {
745
46.0k
    if (PEX64_IS_RUNTIME_FUNCTION_CHAINED (&rf))
746
19.8k
      {
747
19.8k
        bfd_vma altent = PEX64_GET_UNWINDDATA_UNIFIED_RVA (&rf);
748
19.8k
        bfd_vma pdata_vma = bfd_section_vma (pdata_section);
749
19.8k
        struct pex64_runtime_function arf;
750
751
19.8k
        fprintf (file, "\t shares information with ");
752
19.8k
        altent += imagebase;
753
754
19.8k
        if (altent >= pdata_vma
755
19.8k
      && altent - pdata_vma + PDATA_ROW_SIZE <= stop)
756
14.6k
    {
757
14.6k
      pex64_get_runtime_function
758
14.6k
        (abfd, &arf, &pdata[altent - pdata_vma]);
759
14.6k
      fprintf (file, "pdata element at 0x%016" PRIx64,
760
14.6k
         arf.rva_UnwindData);
761
14.6k
    }
762
5.18k
        else
763
5.18k
    fprintf (file, "unknown pdata element");
764
19.8k
        fprintf (file, ".\n");
765
19.8k
      }
766
26.2k
    else
767
26.2k
      {
768
26.2k
        bfd_vma *p;
769
770
        /* Search for the current entry in the sorted array.  */
771
26.2k
        p = (bfd_vma *)
772
26.2k
      bsearch (&rf.rva_UnwindData, xdata_arr,
773
26.2k
         (size_t) xdata_arr_cnt, sizeof (bfd_vma),
774
26.2k
         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
82.9k
        while (p[0] <= rf.rva_UnwindData)
780
56.6k
    ++p;
781
782
26.2k
        if (p[0] == ~((bfd_vma) 0))
783
266
    p = NULL;
784
785
26.2k
        pex64_dump_xdata (file, abfd, xdata_section, xdata, p, &rf);
786
26.2k
      }
787
46.0k
  }
788
46.1k
    }
789
790
517
 done:
791
517
  free (pdata);
792
517
  free (xdata_arr);
793
517
  free (xdata);
794
795
517
  return true;
796
274
}
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
8.99k
{
812
8.99k
  struct pex64_paps *paps = arg;
813
8.99k
  if (startswith (pdata->name, ".pdata"))
814
42
    {
815
42
      if (pex64_bfd_print_pdata_section (abfd, paps->obj, pdata))
816
42
  paps->pdata_count++;
817
42
    }
818
8.99k
}
819
820
bool
821
pex64_bfd_print_pdata (bfd *abfd, void *vfile)
822
1.89k
{
823
1.89k
  asection *pdata_section = bfd_get_section_by_name (abfd, ".pdata");
824
1.89k
  struct pex64_paps paps;
825
826
1.89k
  if (pdata_section)
827
481
    return pex64_bfd_print_pdata_section (abfd, vfile, pdata_section);
828
829
1.41k
  paps.obj = vfile;
830
1.41k
  paps.pdata_count = 0;
831
1.41k
  bfd_map_over_sections (abfd, pex64_print_all_pdata_sections, &paps);
832
1.41k
  return paps.pdata_count != 0;
833
1.89k
}
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"