Coverage Report

Created: 2023-08-28 06:31

/src/binutils-gdb/bfd/pei-x86_64.c
Line
Count
Source (jump to first uncovered line)
1
/* BFD back-end for Intel 386 PE IMAGE COFF files.
2
   Copyright (C) 2006-2023 Free Software Foundation, Inc.
3
4
   This file is part of BFD, the Binary File Descriptor library.
5
6
   This program is free software; you can redistribute it and/or modify
7
   it under the terms of the GNU General Public License as published by
8
   the Free Software Foundation; either version 3 of the License, or
9
   (at your option) any later version.
10
11
   This program is distributed in the hope that it will be useful,
12
   but WITHOUT ANY WARRANTY; without even the implied warranty of
13
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
   GNU General Public License for more details.
15
16
   You should have received a copy of the GNU General Public License
17
   along with this program; if not, write to the Free Software
18
   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
19
   MA 02110-1301, USA.
20
21
   Written by Kai Tietz, OneVision Software GmbH&CoKg.  */
22
23
#include "sysdep.h"
24
#include "bfd.h"
25
26
#define TARGET_SYM    x86_64_pei_vec
27
#define TARGET_NAME   "pei-x86-64"
28
#define COFF_IMAGE_WITH_PE
29
#define COFF_WITH_PE
30
#define COFF_WITH_pex64
31
#define PCRELOFFSET   true
32
#if defined (USE_MINGW64_LEADING_UNDERSCORES)
33
#define TARGET_UNDERSCORE '_'
34
#else
35
1.51k
#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
20.8k
#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
20.7k
{
88
20.7k
  const struct external_pex64_runtime_function *ex_rf =
89
20.7k
    (const struct external_pex64_runtime_function *) data;
90
20.7k
  rf->rva_BeginAddress = bfd_get_32 (abfd, ex_rf->rva_BeginAddress);
91
20.7k
  rf->rva_EndAddress = bfd_get_32 (abfd, ex_rf->rva_EndAddress);
92
20.7k
  rf->rva_UnwindData =  bfd_get_32 (abfd, ex_rf->rva_UnwindData);
93
20.7k
}
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
2.88k
{
101
2.88k
  struct external_pex64_unwind_info *ex_ui =
102
2.88k
    (struct external_pex64_unwind_info *) data;
103
2.88k
  bfd_byte *ex_dta = (bfd_byte *) data;
104
2.88k
  bfd_byte *ex_dta_end = (bfd_byte *) data_end;
105
106
2.88k
  memset (ui, 0, sizeof (struct pex64_unwind_info));
107
108
2.88k
  if (ex_dta_end - ex_dta < 4)
109
1
    return false;
110
111
2.88k
  ui->Version = PEX64_UWI_VERSION (ex_ui->Version_Flags);
112
2.88k
  ui->Flags = PEX64_UWI_FLAGS (ex_ui->Version_Flags);
113
2.88k
  ui->SizeOfPrologue = (bfd_vma) ex_ui->SizeOfPrologue;
114
2.88k
  ui->CountOfCodes = (bfd_vma) ex_ui->CountOfCodes;
115
2.88k
  ui->FrameRegister = PEX64_UWI_FRAMEREG (ex_ui->FrameRegisterOffset);
116
2.88k
  ui->FrameOffset = PEX64_UWI_FRAMEOFF (ex_ui->FrameRegisterOffset);
117
2.88k
  ui->sizeofUnwindCodes = PEX64_UWI_SIZEOF_UWCODE_ARRAY (ui->CountOfCodes);
118
2.88k
  ui->SizeOfBlock = ui->sizeofUnwindCodes + 4;
119
2.88k
  ui->rawUnwindCodes = ex_dta + 4;
120
2.88k
  ui->rawUnwindCodesEnd = ex_dta_end;
121
122
2.88k
  if ((size_t) (ex_dta_end - ex_dta) < ui->SizeOfBlock)
123
1.02k
    return false;
124
1.86k
  ex_dta += ui->SizeOfBlock;
125
126
1.86k
  switch (ui->Flags)
127
1.86k
    {
128
38
    case UNW_FLAG_CHAININFO:
129
38
      if (ex_dta_end - ex_dta < 12)
130
1
  return false;
131
37
      ui->rva_BeginAddress = bfd_get_32 (abfd, ex_dta + 0);
132
37
      ui->rva_EndAddress = bfd_get_32 (abfd, ex_dta + 4);
133
37
      ui->rva_UnwindData = bfd_get_32 (abfd, ex_dta + 8);
134
37
      ui->SizeOfBlock += 12;
135
37
      return true;
136
31
    case UNW_FLAG_EHANDLER:
137
73
    case UNW_FLAG_UHANDLER:
138
303
    case UNW_FLAG_FHANDLER:
139
303
      if (ex_dta_end - ex_dta < 4)
140
1
  return false;
141
302
      ui->rva_ExceptionHandler = bfd_get_32 (abfd, ex_dta);
142
302
      ui->SizeOfBlock += 4;
143
302
      return true;
144
1.52k
    default:
145
1.52k
      return true;
146
1.86k
    }
147
1.86k
}
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
895
{
156
895
  unsigned int i;
157
895
  unsigned int tmp; /* At least 32 bits.  */
158
895
  int save_allowed;
159
160
895
  if (ui->CountOfCodes == 0 || ui->rawUnwindCodes == NULL)
161
70
    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
825
  save_allowed = true;
168
169
825
  i = 0;
170
171
825
  if ((size_t) (ui->rawUnwindCodesEnd - ui->rawUnwindCodes)
172
825
      < ui->CountOfCodes * 2)
173
0
    {
174
0
      fprintf (file, _("warning: corrupt unwind data\n"));
175
0
      return;
176
0
    }
177
178
825
  if (ui->Version == 2
179
825
      && PEX64_UNWCODE_CODE (ui->rawUnwindCodes[1]) == UWOP_EPILOG)
180
2
    {
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
2
      unsigned int func_size = rf->rva_EndAddress - rf->rva_BeginAddress;
185
186
2
      fprintf (file, "\tv2 epilog (length: %02x) at pc+:",
187
2
         ui->rawUnwindCodes[0]);
188
189
2
      if (PEX64_UNWCODE_INFO (ui->rawUnwindCodes[1]))
190
2
  fprintf (file, " 0x%x", func_size - ui->rawUnwindCodes[0]);
191
192
2
      i++;
193
2
      for (; i < ui->CountOfCodes; i++)
194
2
  {
195
2
    const bfd_byte *dta = ui->rawUnwindCodes + 2 * i;
196
2
    unsigned int off;
197
198
2
    if (PEX64_UNWCODE_CODE (dta[1]) != UWOP_EPILOG)
199
2
      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
2
      fputc ('\n', file);
207
2
    }
208
209
10.5k
  for (; i < ui->CountOfCodes; i++)
210
9.67k
    {
211
9.67k
      const bfd_byte *dta = ui->rawUnwindCodes + 2 * i;
212
9.67k
      unsigned int info = PEX64_UNWCODE_INFO (dta[1]);
213
9.67k
      int unexpected = false;
214
215
9.67k
      fprintf (file, "\t  pc+0x%02x: ", (unsigned int) dta[0]);
216
217
9.67k
      switch (PEX64_UNWCODE_CODE (dta[1]))
218
9.67k
  {
219
2.36k
  case UWOP_PUSH_NONVOL:
220
2.36k
    fprintf (file, "push %s", pex_regs[info]);
221
2.36k
    break;
222
223
581
  case UWOP_ALLOC_LARGE:
224
581
    if (info == 0)
225
256
      {
226
256
        if (ui->rawUnwindCodesEnd - dta < 4)
227
0
    {
228
0
      fprintf (file, _("warning: corrupt unwind data\n"));
229
0
      return;
230
0
    }
231
256
        tmp = bfd_get_16 (abfd, dta + 2) * 8;
232
256
        i++;
233
256
      }
234
325
    else
235
325
      {
236
325
        if (ui->rawUnwindCodesEnd - dta < 6)
237
0
    {
238
0
      fprintf (file, _("warning: corrupt unwind data\n"));
239
0
      return;
240
0
    }
241
325
        tmp = bfd_get_32 (abfd, dta + 2);
242
325
        i += 2;
243
325
      }
244
581
    fprintf (file, "alloc large area: rsp = rsp - 0x%x", tmp);
245
581
    break;
246
247
814
  case UWOP_ALLOC_SMALL:
248
814
    fprintf (file, "alloc small area: rsp = rsp - 0x%x", (info + 1) * 8);
249
814
    break;
250
251
368
  case UWOP_SET_FPREG:
252
    /* According to the documentation, info field is unused.  */
253
368
    fprintf (file, "FPReg: %s = rsp + 0x%x (info = 0x%x)",
254
368
       pex_regs[ui->FrameRegister],
255
368
       (unsigned int) ui->FrameOffset * 16, info);
256
368
    unexpected = ui->FrameRegister == 0;
257
368
    save_allowed = false;
258
368
    break;
259
260
1.48k
  case UWOP_SAVE_NONVOL:
261
1.48k
    if (ui->rawUnwindCodesEnd - dta < 4)
262
0
      {
263
0
        fprintf (file, _("warning: corrupt unwind data\n"));
264
0
        return;
265
0
      }
266
1.48k
    tmp = bfd_get_16 (abfd, dta + 2) * 8;
267
1.48k
    i++;
268
1.48k
    fprintf (file, "save %s at rsp + 0x%x", pex_regs[info], tmp);
269
1.48k
    unexpected = !save_allowed;
270
1.48k
    break;
271
272
348
  case UWOP_SAVE_NONVOL_FAR:
273
348
    if (ui->rawUnwindCodesEnd - dta < 6)
274
0
      {
275
0
        fprintf (file, _("warning: corrupt unwind data\n"));
276
0
        return;
277
0
      }
278
348
    tmp = bfd_get_32 (abfd, dta + 2);
279
348
    i += 2;
280
348
    fprintf (file, "save %s at rsp + 0x%x", pex_regs[info], tmp);
281
348
    unexpected = !save_allowed;
282
348
    break;
283
284
263
  case UWOP_SAVE_XMM:
285
263
    if (ui->Version == 1)
286
139
      {
287
139
        if (ui->rawUnwindCodesEnd - dta < 4)
288
0
    {
289
0
      fprintf (file, _("warning: corrupt unwind data\n"));
290
0
      return;
291
0
    }
292
139
        tmp = bfd_get_16 (abfd, dta + 2) * 8;
293
139
        i++;
294
139
        fprintf (file, "save mm%u at rsp + 0x%x", info, tmp);
295
139
        unexpected = !save_allowed;
296
139
      }
297
124
    else if (ui->Version == 2)
298
124
      {
299
124
        fprintf (file, "epilog %02x %01x", dta[0], info);
300
124
        unexpected = true;
301
124
      }
302
263
    break;
303
304
323
  case UWOP_SAVE_XMM_FAR:
305
323
    if (ui->rawUnwindCodesEnd - dta < 6)
306
0
      {
307
0
        fprintf (file, _("warning: corrupt unwind data\n"));
308
0
        return;
309
0
      }
310
323
    tmp = bfd_get_32 (abfd, dta + 2) * 8;
311
323
    i += 2;
312
323
    fprintf (file, "save mm%u at rsp + 0x%x", info, tmp);
313
323
    unexpected = !save_allowed;
314
323
    break;
315
316
444
  case UWOP_SAVE_XMM128:
317
444
    if (ui->rawUnwindCodesEnd - dta < 4)
318
0
      {
319
0
        fprintf (file, _("warning: corrupt unwind data\n"));
320
0
        return;
321
0
      }
322
444
    tmp = bfd_get_16 (abfd, dta + 2) * 16;
323
444
    i++;
324
444
    fprintf (file, "save xmm%u at rsp + 0x%x", info, tmp);
325
444
    unexpected = !save_allowed;
326
444
    break;
327
328
435
  case UWOP_SAVE_XMM128_FAR:
329
435
    if (ui->rawUnwindCodesEnd - dta < 6)
330
1
      {
331
1
        fprintf (file, _("warning: corrupt unwind data\n"));
332
1
        return;
333
1
      }
334
434
    tmp = bfd_get_32 (abfd, dta + 2) * 16;
335
434
    i += 2;
336
434
    fprintf (file, "save xmm%u at rsp + 0x%x", info, tmp);
337
434
    unexpected = !save_allowed;
338
434
    break;
339
340
306
  case UWOP_PUSH_MACHFRAME:
341
306
    fprintf (file, "interrupt entry (SS, old RSP, EFLAGS, CS, RIP");
342
306
    if (info == 0)
343
19
      fprintf (file, ")");
344
287
    else if (info == 1)
345
30
      fprintf (file, ",ErrorCode)");
346
257
    else
347
257
      fprintf (file, ", unknown(%u))", info);
348
306
    break;
349
350
1.95k
  default:
351
    /* PR 17512: file: 2245-7442-0.004.  */
352
1.95k
    fprintf (file, _("Unknown: %x"), PEX64_UNWCODE_CODE (dta[1]));
353
1.95k
    break;
354
9.67k
  }
355
356
9.67k
      if (unexpected)
357
1.72k
  fprintf (file, " [Unexpected!]");
358
9.67k
      fputc ('\n', file);
359
9.67k
    }
360
825
}
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
259
{
367
259
  asection *section = bfd_get_section_by_name (abfd, sec_name);
368
259
  bfd_vma vsize;
369
259
  bfd_size_type datasize = 0;
370
371
259
  if (section == NULL
372
259
      || coff_section_data (abfd, section) == NULL
373
259
      || pei_section_data (abfd, section) == NULL)
374
116
    return NULL;
375
143
  vsize = section->vma - pe_data (abfd)->pe_opthdr.ImageBase;
376
143
  datasize = section->size;
377
143
  if (!datasize || vsize > addr || (vsize + datasize) < addr)
378
105
    return NULL;
379
38
  return section;
380
143
}
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
2.89k
{
391
2.89k
  bfd_vma vaddr;
392
2.89k
  bfd_vma end_addr;
393
2.89k
  bfd_vma addr = rf->rva_UnwindData;
394
2.89k
  bfd_size_type sec_size = xdata_section->rawsize > 0 ? xdata_section->rawsize : xdata_section->size;
395
2.89k
  struct pex64_unwind_info ui;
396
397
2.89k
  vaddr = xdata_section->vma - pe_data (abfd)->pe_opthdr.ImageBase;
398
2.89k
  addr -= vaddr;
399
400
  /* PR 17512: file: 2245-7442-0.004.  */
401
2.89k
  if (addr >= sec_size)
402
7
    {
403
7
      fprintf (file, _("warning: xdata section corrupt\n"));
404
7
      return;
405
7
    }
406
407
2.88k
  if (endx)
408
2.85k
    {
409
2.85k
      end_addr = endx[0] - vaddr;
410
      /* PR 17512: file: 2245-7442-0.004.  */
411
2.85k
      if (end_addr > sec_size)
412
8
  {
413
8
    fprintf (file, _("warning: xdata section corrupt\n"));
414
8
    end_addr = sec_size;
415
8
  }
416
2.85k
    }
417
27
  else
418
27
    end_addr = sec_size;
419
420
2.88k
  if (! pex64_get_unwind_info (abfd, &ui, xdata + addr, xdata + end_addr))
421
1.02k
    {
422
1.02k
      fprintf (file, _("warning: xdata section corrupt\n"));
423
1.02k
      return;
424
1.02k
    }
425
426
1.86k
  if (ui.Version != 1 && ui.Version != 2)
427
965
    {
428
965
      unsigned int i;
429
965
      fprintf (file, "\tVersion %u (unknown).\n",
430
965
         (unsigned int) ui.Version);
431
669k
      for (i = 0; addr < end_addr; addr += 1, i++)
432
668k
  {
433
668k
    if ((i & 15) == 0)
434
42.1k
      fprintf (file, "\t  %03x:", i);
435
668k
    fprintf (file, " %02x", xdata[addr]);
436
668k
    if ((i & 15) == 15)
437
41.3k
      fprintf (file, "\n");
438
668k
  }
439
965
      if ((i & 15) != 0)
440
779
  fprintf (file, "\n");
441
965
      return;
442
965
    }
443
444
895
  fprintf (file, "\tVersion: %d, Flags: ", ui.Version);
445
895
  switch (ui.Flags)
446
895
    {
447
540
    case UNW_FLAG_NHANDLER:
448
540
      fprintf (file, "none");
449
540
      break;
450
11
    case UNW_FLAG_EHANDLER:
451
11
      fprintf (file, "UNW_FLAG_EHANDLER");
452
11
      break;
453
16
    case UNW_FLAG_UHANDLER:
454
16
      fprintf (file, "UNW_FLAG_UHANDLER");
455
16
      break;
456
218
    case UNW_FLAG_FHANDLER:
457
218
      fprintf
458
218
  (file, "UNW_FLAG_EHANDLER | UNW_FLAG_UHANDLER");
459
218
      break;
460
4
    case UNW_FLAG_CHAININFO:
461
4
      fprintf (file, "UNW_FLAG_CHAININFO");
462
4
      break;
463
106
    default:
464
106
      fprintf (file, "unknown flags value 0x%x", (unsigned int) ui.Flags);
465
106
      break;
466
895
    }
467
895
  fputc ('\n', file);
468
895
  fprintf (file, "\tNbr codes: %u, ", (unsigned int) ui.CountOfCodes);
469
895
  fprintf (file, "Prologue size: 0x%02x, Frame offset: 0x%x, ",
470
895
     (unsigned int) ui.SizeOfPrologue, (unsigned int) ui.FrameOffset);
471
895
  fprintf (file, "Frame reg: %s\n",
472
895
     ui.FrameRegister == 0 ? "none"
473
895
     : pex_regs[(unsigned int) ui.FrameRegister]);
474
475
  /* PR 17512: file: 2245-7442-0.004.  */
476
895
  if (ui.CountOfCodes * 2 + ui.rawUnwindCodes > xdata + xdata_section->size)
477
0
    fprintf (file, _("Too many unwind codes (%ld)\n"), (long) ui.CountOfCodes);
478
895
  else
479
895
    pex64_xdata_print_uwd_codes (file, abfd, &ui, rf);
480
481
895
  switch (ui.Flags)
482
895
    {
483
11
    case UNW_FLAG_EHANDLER:
484
27
    case UNW_FLAG_UHANDLER:
485
245
    case UNW_FLAG_FHANDLER:
486
245
      fprintf (file, "\tHandler: %016" PRIx64 ".\n",
487
245
         ui.rva_ExceptionHandler + pe_data (abfd)->pe_opthdr.ImageBase);
488
245
      break;
489
4
    case UNW_FLAG_CHAININFO:
490
4
      fprintf (file, "\tChain: start: %016" PRIx64 ", end: %016" PRIx64,
491
4
         ui.rva_BeginAddress, ui.rva_EndAddress);
492
4
      fprintf (file, "\n\t unwind data: %016" PRIx64 ".\n",
493
4
         ui.rva_UnwindData);
494
4
      break;
495
895
    }
496
497
  /* Now we need end of this xdata block.  */
498
895
  addr += ui.SizeOfBlock;
499
895
  if (addr < end_addr)
500
398
    {
501
398
      unsigned int i;
502
398
      fprintf (file,"\tUser data:\n");
503
60.3k
      for (i = 0; addr < end_addr; addr += 1, i++)
504
59.9k
  {
505
59.9k
    if ((i & 15) == 0)
506
3.88k
      fprintf (file, "\t  %03x:", i);
507
59.9k
    fprintf (file, " %02x", xdata[addr]);
508
59.9k
    if ((i & 15) == 15)
509
3.52k
      fprintf (file, "\n");
510
59.9k
  }
511
398
      if ((i & 15) != 0)
512
359
  fprintf (file, "\n");
513
398
    }
514
895
}
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
39.6k
{
522
39.6k
  const bfd_vma *lp = (const bfd_vma *) l;
523
39.6k
  const bfd_vma *rp = (const bfd_vma *) r;
524
525
39.6k
  if (*lp == *rp)
526
4.57k
    return 0;
527
35.0k
  return (*lp < *rp ? -1 : 1);
528
39.6k
}
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
126
{
535
126
  FILE *file = (FILE *) vfile;
536
126
  bfd_byte *pdata = NULL;
537
126
  bfd_byte *xdata = NULL;
538
126
  asection *xdata_section = NULL;
539
126
  bfd_vma xdata_base;
540
126
  bfd_size_type i;
541
126
  bfd_size_type datasize;
542
126
  bfd_size_type stop;
543
126
  bfd_vma prev_beginaddress = (bfd_vma) -1;
544
126
  bfd_vma prev_unwinddata_rva = (bfd_vma) -1;
545
126
  bfd_vma imagebase;
546
126
  int onaline = PDATA_ROW_SIZE;
547
126
  int seen_error = 0;
548
126
  bfd_vma *xdata_arr = NULL;
549
126
  int xdata_arr_cnt;
550
126
  bool virt_size_is_zero = false;
551
552
  /* Sanity checks.  */
553
126
  if (pdata_section == NULL
554
126
      || (pdata_section->flags & SEC_HAS_CONTENTS) == 0
555
126
      || coff_section_data (abfd, pdata_section) == NULL
556
126
      || pei_section_data (abfd, pdata_section) == NULL)
557
3
    return true;
558
559
123
  stop = pei_section_data (abfd, pdata_section)->virt_size;
560
123
  if ((stop % onaline) != 0)
561
41
    fprintf (file,
562
       /* xgettext:c-format */
563
41
       _("Warning: %s section size (%ld) is not a multiple of %d\n"),
564
41
       pdata_section->name, (long) stop, onaline);
565
566
123
  datasize = pdata_section->size;
567
123
  if (datasize == 0)
568
3
    {
569
3
      if (stop)
570
2
  fprintf (file, _("Warning: %s section size is zero\n"),
571
2
     pdata_section->name);
572
3
      return true;
573
3
    }
574
575
  /* virt_size might be zero for objects.  */
576
120
  if (stop == 0 && strcmp (abfd->xvec->name, "pe-x86-64") == 0)
577
16
    {
578
16
      stop = datasize;
579
16
      virt_size_is_zero = true;
580
16
    }
581
104
  else if (datasize < stop)
582
40
      {
583
40
  fprintf (file,
584
     /* xgettext:c-format */
585
40
     _("Warning: %s section size (%ld) is smaller than virtual size (%ld)\n"),
586
40
     pdata_section->name, (unsigned long) datasize,
587
40
     (unsigned long) stop);
588
  /* Be sure not to read past datasize.  */
589
40
  stop = datasize;
590
40
      }
591
592
  /* Display functions table.  */
593
120
  fprintf (file,
594
120
     _("\nThe Function Table (interpreted %s section contents)\n"),
595
120
     pdata_section->name);
596
597
120
  fprintf (file, _("vma:\t\t\tBeginAddress\t EndAddress\t  UnwindData\n"));
598
599
120
  if (!bfd_malloc_and_get_section (abfd, pdata_section, &pdata))
600
10
    goto done;
601
602
  /* Table of xdata entries.  */
603
110
  xdata_arr = (bfd_vma *) xmalloc (sizeof (bfd_vma) * ((stop / onaline) + 1));
604
110
  xdata_arr_cnt = 0;
605
606
110
  if (strcmp (abfd->xvec->name, "pei-x86-64") == 0)
607
52
    imagebase = pe_data (abfd)->pe_opthdr.ImageBase;
608
58
  else
609
58
    imagebase = 0;
610
611
13.1k
  for (i = 0; i < stop; i += onaline)
612
13.1k
    {
613
13.1k
      struct pex64_runtime_function rf;
614
615
13.1k
      if (i + PDATA_ROW_SIZE > stop)
616
36
  break;
617
618
13.1k
      pex64_get_runtime_function (abfd, &rf, &pdata[i]);
619
620
13.1k
      if (rf.rva_BeginAddress == 0 && rf.rva_EndAddress == 0
621
13.1k
    && rf.rva_UnwindData == 0)
622
  /* We are probably into the padding of the section now.  */
623
55
  break;
624
13.0k
      fprintf (file, " %016" PRIx64, i + pdata_section->vma);
625
13.0k
      fprintf (file, ":\t%016" PRIx64, imagebase + rf.rva_BeginAddress);
626
13.0k
      fprintf (file, " %016" PRIx64, imagebase + rf.rva_EndAddress);
627
13.0k
      fprintf (file, " %016" PRIx64 "\n", imagebase + rf.rva_UnwindData);
628
13.0k
      if (i != 0 && rf.rva_BeginAddress <= prev_beginaddress)
629
2.53k
  {
630
2.53k
    seen_error = 1;
631
2.53k
    fprintf (file, "  has %s begin address as predecessor\n",
632
2.53k
      (rf.rva_BeginAddress < prev_beginaddress ? "smaller" : "same"));
633
2.53k
  }
634
13.0k
      prev_beginaddress = rf.rva_BeginAddress;
635
      /* Now we check for negative addresses.  */
636
13.0k
      if ((prev_beginaddress & 0x80000000) != 0)
637
1.73k
  {
638
1.73k
    seen_error = 1;
639
1.73k
    fprintf (file, "  has negative begin address\n");
640
1.73k
  }
641
13.0k
      if ((rf.rva_EndAddress & 0x80000000) != 0)
642
1.66k
  {
643
1.66k
    seen_error = 1;
644
1.66k
    fprintf (file, "  has negative end address\n");
645
1.66k
  }
646
13.0k
      if ((rf.rva_UnwindData & 0x80000000) != 0)
647
2.18k
  {
648
2.18k
    seen_error = 1;
649
2.18k
    fprintf (file, "  has negative unwind address\n");
650
2.18k
  }
651
10.8k
      else if ((rf.rva_UnwindData && !PEX64_IS_RUNTIME_FUNCTION_CHAINED (&rf))
652
10.8k
    || virt_size_is_zero)
653
6.37k
  xdata_arr[xdata_arr_cnt++] = rf.rva_UnwindData;
654
13.0k
    }
655
656
110
  if (seen_error)
657
47
    goto done;
658
659
  /* Add end of list marker.  */
660
63
  xdata_arr[xdata_arr_cnt++] = ~((bfd_vma) 0);
661
662
  /* Sort start RVAs of xdata.  */
663
63
  if (xdata_arr_cnt > 1)
664
45
    qsort (xdata_arr, (size_t) xdata_arr_cnt, sizeof (bfd_vma),
665
45
     sort_xdata_arr);
666
667
  /* Find the section containing the unwind data (.xdata).  */
668
63
  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
63
  if (strcmp (pdata_section->name, ".pdata") != 0)
672
2
    {
673
2
      size_t len = strlen (pdata_section->name);
674
2
      char *xdata_name = xmalloc (len + 1);
675
676
2
      xdata_name = memcpy (xdata_name, pdata_section->name, len + 1);
677
      /* Transform .pdata prefix into .xdata prefix.  */
678
2
      if (len > 1)
679
2
  xdata_name [1] = 'x';
680
2
      xdata_section = pex64_get_section_by_rva (abfd, xdata_base,
681
2
            xdata_name);
682
2
      free (xdata_name);
683
2
    }
684
  /* Second, try the .xdata section itself.  */
685
63
  if (!xdata_section)
686
63
    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
63
  if (!xdata_section && xdata_base)
690
60
    xdata_section = pex64_get_section_by_rva (abfd, xdata_base, ".rdata");
691
63
  if (!xdata_section && xdata_base)
692
51
    xdata_section = pex64_get_section_by_rva (abfd, xdata_base, ".data");
693
63
  if (!xdata_section && xdata_base)
694
51
    xdata_section = pex64_get_section_by_rva (abfd, xdata_base, ".pdata");
695
63
  if (!xdata_section && xdata_base)
696
32
    xdata_section = pex64_get_section_by_rva (abfd, xdata_base, ".text");
697
  /* Transfer xdata section into xdata array.  */
698
63
  if (!xdata_section
699
63
      || (xdata_section->flags & SEC_HAS_CONTENTS) == 0
700
63
      || !bfd_malloc_and_get_section (abfd, xdata_section, &xdata))
701
26
    goto done;
702
703
  /* Avoid "also used "... ouput for single unwind info
704
     in object file.  */
705
37
  prev_unwinddata_rva = (bfd_vma) -1;
706
707
  /* Do dump of pdata related xdata.  */
708
5.62k
  for (i = 0; i < stop; i += onaline)
709
5.61k
    {
710
5.61k
      struct pex64_runtime_function rf;
711
712
5.61k
      if (i + PDATA_ROW_SIZE > stop)
713
9
  break;
714
715
5.60k
      pex64_get_runtime_function (abfd, &rf, &pdata[i]);
716
717
5.60k
      if (rf.rva_BeginAddress == 0 && rf.rva_EndAddress == 0
718
5.60k
    && rf.rva_UnwindData == 0)
719
  /* We are probably into the padding of the section now.  */
720
15
  break;
721
5.59k
      if (i == 0)
722
37
  fprintf (file, _("\nDump of %s\n"), xdata_section->name);
723
724
5.59k
      fprintf (file, " %016" PRIx64, rf.rva_UnwindData + imagebase);
725
726
5.59k
      if (prev_unwinddata_rva == rf.rva_UnwindData)
727
112
  {
728
    /* Do not dump again the xdata for the same entry.  */
729
112
    fprintf (file, " also used for function at %016" PRIx64 "\n",
730
112
       rf.rva_BeginAddress + imagebase);
731
112
    continue;
732
112
  }
733
5.47k
      else
734
5.47k
  prev_unwinddata_rva = rf.rva_UnwindData;
735
736
5.47k
      fprintf (file, " (rva: %08x): %016" PRIx64 " - %016" PRIx64 "\n",
737
5.47k
         (unsigned int) rf.rva_UnwindData,
738
5.47k
         rf.rva_BeginAddress + imagebase,
739
5.47k
         rf.rva_EndAddress + imagebase);
740
741
5.47k
      if (rf.rva_UnwindData != 0 || virt_size_is_zero)
742
5.47k
  {
743
5.47k
    if (PEX64_IS_RUNTIME_FUNCTION_CHAINED (&rf))
744
2.57k
      {
745
2.57k
        bfd_vma altent = PEX64_GET_UNWINDDATA_UNIFIED_RVA (&rf);
746
2.57k
        bfd_vma pdata_vma = bfd_section_vma (pdata_section);
747
2.57k
        struct pex64_runtime_function arf;
748
749
2.57k
        fprintf (file, "\t shares information with ");
750
2.57k
        altent += imagebase;
751
752
2.57k
        if (altent >= pdata_vma
753
2.57k
      && altent - pdata_vma + PDATA_ROW_SIZE <= stop)
754
1.97k
    {
755
1.97k
      pex64_get_runtime_function
756
1.97k
        (abfd, &arf, &pdata[altent - pdata_vma]);
757
1.97k
      fprintf (file, "pdata element at 0x%016" PRIx64,
758
1.97k
         arf.rva_UnwindData);
759
1.97k
    }
760
601
        else
761
601
    fprintf (file, "unknown pdata element");
762
2.57k
        fprintf (file, ".\n");
763
2.57k
      }
764
2.89k
    else
765
2.89k
      {
766
2.89k
        bfd_vma *p;
767
768
        /* Search for the current entry in the sorted array.  */
769
2.89k
        p = (bfd_vma *)
770
2.89k
      bsearch (&rf.rva_UnwindData, xdata_arr,
771
2.89k
         (size_t) xdata_arr_cnt, sizeof (bfd_vma),
772
2.89k
         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
9.64k
        while (p[0] <= rf.rva_UnwindData)
778
6.75k
    ++p;
779
780
2.89k
        if (p[0] == ~((bfd_vma) 0))
781
30
    p = NULL;
782
783
2.89k
        pex64_dump_xdata (file, abfd, xdata_section, xdata, p, &rf);
784
2.89k
      }
785
5.47k
  }
786
5.47k
    }
787
788
120
 done:
789
120
  free (pdata);
790
120
  free (xdata_arr);
791
120
  free (xdata);
792
793
120
  return true;
794
37
}
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.99k
{
810
2.99k
  struct pex64_paps *paps = arg;
811
2.99k
  if (startswith (pdata->name, ".pdata"))
812
31
    {
813
31
      if (pex64_bfd_print_pdata_section (abfd, paps->obj, pdata))
814
31
  paps->pdata_count++;
815
31
    }
816
2.99k
}
817
818
bool
819
pex64_bfd_print_pdata (bfd *abfd, void *vfile)
820
935
{
821
935
  asection *pdata_section = bfd_get_section_by_name (abfd, ".pdata");
822
935
  struct pex64_paps paps;
823
824
935
  if (pdata_section)
825
95
    return pex64_bfd_print_pdata_section (abfd, vfile, pdata_section);
826
827
840
  paps.obj = vfile;
828
840
  paps.pdata_count = 0;
829
840
  bfd_map_over_sections (abfd, pex64_print_all_pdata_sections, &paps);
830
840
  return paps.pdata_count != 0;
831
935
}
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"