Coverage Report

Created: 2023-06-29 07:13

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