Coverage Report

Created: 2023-08-28 06:28

/src/binutils-gdb/bfd/pef.c
Line
Count
Source (jump to first uncovered line)
1
/* PEF support for BFD.
2
   Copyright (C) 1999-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
/* PEF (Preferred Executable Format) is the binary file format for late
22
   classic Mac OS versions (before Darwin).  It is supported by both m68k
23
   and PowerPc.  It is also called CFM (Code Fragment Manager).  */
24
25
#include "sysdep.h"
26
#include "safe-ctype.h"
27
#include "pef.h"
28
#include "pef-traceback.h"
29
#include "bfd.h"
30
#include "libbfd.h"
31
#include "libiberty.h"
32
33
#ifndef BFD_IO_FUNCS
34
351
#define BFD_IO_FUNCS 0
35
#endif
36
37
#define bfd_pef_close_and_cleanup       _bfd_generic_close_and_cleanup
38
#define bfd_pef_bfd_free_cached_info        _bfd_generic_bfd_free_cached_info
39
#define bfd_pef_new_section_hook        _bfd_generic_new_section_hook
40
#define bfd_pef_bfd_is_local_label_name       bfd_generic_is_local_label_name
41
#define bfd_pef_bfd_is_target_special_symbol        _bfd_bool_bfd_asymbol_false
42
#define bfd_pef_get_lineno          _bfd_nosymbols_get_lineno
43
#define bfd_pef_find_nearest_line       _bfd_nosymbols_find_nearest_line
44
#define bfd_pef_find_nearest_line_with_alt      _bfd_nosymbols_find_nearest_line_with_alt
45
#define bfd_pef_find_line         _bfd_nosymbols_find_line
46
#define bfd_pef_find_inliner_info       _bfd_nosymbols_find_inliner_info
47
#define bfd_pef_get_symbol_version_string     _bfd_nosymbols_get_symbol_version_string
48
#define bfd_pef_bfd_make_debug_symbol       _bfd_nosymbols_bfd_make_debug_symbol
49
#define bfd_pef_read_minisymbols        _bfd_generic_read_minisymbols
50
#define bfd_pef_minisymbol_to_symbol        _bfd_generic_minisymbol_to_symbol
51
#define bfd_pef_set_arch_mach         _bfd_generic_set_arch_mach
52
#define bfd_pef_get_section_contents        _bfd_generic_get_section_contents
53
#define bfd_pef_set_section_contents        _bfd_generic_set_section_contents
54
#define bfd_pef_bfd_get_relocated_section_contents  bfd_generic_get_relocated_section_contents
55
#define bfd_pef_bfd_relax_section       bfd_generic_relax_section
56
#define bfd_pef_bfd_gc_sections         bfd_generic_gc_sections
57
#define bfd_pef_bfd_lookup_section_flags      bfd_generic_lookup_section_flags
58
#define bfd_pef_bfd_merge_sections        bfd_generic_merge_sections
59
#define bfd_pef_bfd_is_group_section        bfd_generic_is_group_section
60
#define bfd_pef_bfd_group_name          bfd_generic_group_name
61
#define bfd_pef_bfd_discard_group       bfd_generic_discard_group
62
#define bfd_pef_section_already_linked        _bfd_generic_section_already_linked
63
#define bfd_pef_bfd_define_common_symbol      bfd_generic_define_common_symbol
64
#define bfd_pef_bfd_link_hide_symbol        _bfd_generic_link_hide_symbol
65
#define bfd_pef_bfd_define_start_stop       bfd_generic_define_start_stop
66
#define bfd_pef_bfd_link_hash_table_create      _bfd_generic_link_hash_table_create
67
#define bfd_pef_bfd_link_add_symbols        _bfd_generic_link_add_symbols
68
#define bfd_pef_bfd_link_just_syms        _bfd_generic_link_just_syms
69
#define bfd_pef_bfd_copy_link_hash_symbol_type \
70
  _bfd_generic_copy_link_hash_symbol_type
71
#define bfd_pef_bfd_final_link          _bfd_generic_final_link
72
#define bfd_pef_bfd_link_split_section        _bfd_generic_link_split_section
73
#define bfd_pef_get_section_contents_in_window      _bfd_generic_get_section_contents_in_window
74
#define bfd_pef_bfd_link_check_relocs       _bfd_generic_link_check_relocs
75
76
static int
77
bfd_pef_parse_traceback_table (bfd *abfd,
78
             asection *section,
79
             unsigned char *buf,
80
             size_t len,
81
             size_t pos,
82
             asymbol *sym,
83
             FILE *file)
84
463k
{
85
463k
  struct traceback_table table;
86
463k
  size_t offset;
87
463k
  const char *s;
88
463k
  asymbol tmpsymbol;
89
90
463k
  if (sym == NULL)
91
0
    sym = & tmpsymbol;
92
93
463k
  sym->name = NULL;
94
463k
  sym->value = 0;
95
463k
  sym->the_bfd = abfd;
96
463k
  sym->section = section;
97
463k
  sym->flags = 0;
98
463k
  sym->udata.i = 0;
99
100
  /* memcpy is fine since all fields are unsigned char.  */
101
463k
  if ((pos + 8) > len)
102
106
    return -1;
103
463k
  memcpy (&table, buf + pos, 8);
104
105
  /* Calling code relies on returned symbols having a name and
106
     correct offset.  */
107
463k
  if ((table.lang != TB_C) && (table.lang != TB_CPLUSPLUS))
108
84.5k
    return -1;
109
110
379k
  if (! (table.flags2 & TB_NAME_PRESENT))
111
351k
    return -1;
112
113
27.9k
  if (! (table.flags1 & TB_HAS_TBOFF))
114
12.6k
    return -1;
115
116
15.2k
  offset = 8;
117
118
15.2k
  if ((table.flags5 & TB_FLOATPARAMS) || (table.fixedparams))
119
13.8k
    offset += 4;
120
121
15.2k
  if (table.flags1 & TB_HAS_TBOFF)
122
15.2k
    {
123
15.2k
      struct traceback_table_tboff off;
124
125
15.2k
      if ((pos + offset + 4) > len)
126
12
  return -1;
127
15.2k
      off.tb_offset = bfd_getb32 (buf + pos + offset);
128
15.2k
      offset += 4;
129
130
      /* Need to subtract 4 because the offset includes the 0x0L
131
   preceding the table.  */
132
15.2k
      if (file != NULL)
133
0
  fprintf (file, " [offset = 0x%lx]", off.tb_offset);
134
135
15.2k
      if ((file == NULL) && ((off.tb_offset + 4) > (pos + offset)))
136
4.87k
  return -1;
137
138
10.3k
      sym->value = pos - off.tb_offset - 4;
139
10.3k
    }
140
141
10.3k
  if (table.flags2 & TB_INT_HNDL)
142
4.91k
    offset += 4;
143
144
10.3k
  if (table.flags1 & TB_HAS_CTL)
145
6.22k
    {
146
6.22k
      struct traceback_table_anchors anchors;
147
148
6.22k
      if ((pos + offset + 4) > len)
149
4
  return -1;
150
6.22k
      anchors.ctl_info = bfd_getb32 (buf + pos + offset);
151
6.22k
      offset += 4;
152
153
6.22k
      if (anchors.ctl_info > 1024)
154
1.85k
  return -1;
155
156
4.36k
      offset += anchors.ctl_info * 4;
157
4.36k
    }
158
159
8.53k
  if (table.flags2 & TB_NAME_PRESENT)
160
8.53k
    {
161
8.53k
      struct traceback_table_routine name;
162
8.53k
      char *namebuf;
163
164
8.53k
      if ((pos + offset + 2) > len)
165
34
  return -1;
166
8.49k
      name.name_len = bfd_getb16 (buf + pos + offset);
167
8.49k
      offset += 2;
168
169
8.49k
      if (name.name_len > 4096)
170
287
  return -1;
171
172
8.21k
      if ((pos + offset + name.name_len) > len)
173
59
  return -1;
174
175
8.15k
      namebuf = bfd_alloc (abfd, name.name_len + 1);
176
8.15k
      if (namebuf == NULL)
177
0
  return -1;
178
179
8.15k
      memcpy (namebuf, buf + pos + offset, name.name_len);
180
8.15k
      namebuf[name.name_len] = '\0';
181
182
      /* Strip leading period inserted by compiler.  */
183
8.15k
      if (namebuf[0] == '.')
184
53
  memmove (namebuf, namebuf + 1, name.name_len);
185
186
8.15k
      sym->name = namebuf;
187
188
9.00k
      for (s = sym->name; (*s != '\0'); s++)
189
2.82k
  if (! ISPRINT (*s))
190
1.97k
    return -1;
191
192
6.17k
      offset += name.name_len;
193
6.17k
    }
194
195
6.17k
  if (table.flags2 & TB_USES_ALLOCA)
196
4.77k
    offset += 4;
197
198
6.17k
  if (table.flags4 & TB_HAS_VEC_INFO)
199
2.63k
    offset += 4;
200
201
6.17k
  if (file != NULL)
202
0
    fprintf (file, " [length = 0x%lx]", (unsigned long) offset);
203
204
6.17k
  return offset;
205
8.53k
}
206
207
static void
208
bfd_pef_print_symbol (bfd *abfd,
209
          void * afile,
210
          asymbol *symbol,
211
          bfd_print_symbol_type how)
212
0
{
213
0
  FILE *file = (FILE *) afile;
214
215
0
  switch (how)
216
0
    {
217
0
    case bfd_print_symbol_name:
218
0
      fprintf (file, "%s", symbol->name);
219
0
      break;
220
0
    default:
221
0
      bfd_print_symbol_vandf (abfd, (void *) file, symbol);
222
0
      fprintf (file, " %-5s %s", symbol->section->name, symbol->name);
223
0
      if (startswith (symbol->name, "__traceback_"))
224
0
  {
225
0
    unsigned char *buf;
226
0
    size_t offset = symbol->value + 4;
227
0
    size_t len = symbol->udata.i;
228
229
0
    buf = bfd_malloc (len);
230
0
    if (buf == NULL
231
0
        || !bfd_get_section_contents (abfd, symbol->section, buf,
232
0
              offset, len)
233
0
        || bfd_pef_parse_traceback_table (abfd, symbol->section, buf,
234
0
            len, 0, NULL, file) < 0)
235
0
      fprintf (file, " [ERROR]");
236
0
    free (buf);
237
0
  }
238
0
    }
239
0
}
240
241
static void
242
bfd_pef_convert_architecture (unsigned long architecture,
243
            enum bfd_architecture *type,
244
            unsigned long *subtype)
245
357
{
246
357
  const unsigned long ARCH_POWERPC = 0x70777063; /* 'pwpc'.  */
247
357
  const unsigned long ARCH_M68K = 0x6d36386b; /* 'm68k'.  */
248
249
357
  *subtype = bfd_arch_unknown;
250
357
  *type = bfd_arch_unknown;
251
252
357
  if (architecture == ARCH_POWERPC)
253
0
    *type = bfd_arch_powerpc;
254
357
  else if (architecture == ARCH_M68K)
255
351
    *type = bfd_arch_m68k;
256
357
}
257
258
static bool
259
bfd_pef_mkobject (bfd *abfd ATTRIBUTE_UNUSED)
260
0
{
261
0
  return true;
262
0
}
263
264
static const char *bfd_pef_section_name (bfd_pef_section *section)
265
2.21k
{
266
2.21k
  switch (section->section_kind)
267
2.21k
    {
268
1.06k
    case BFD_PEF_SECTION_CODE: return "code";
269
69
    case BFD_PEF_SECTION_UNPACKED_DATA: return "unpacked-data";
270
20
    case BFD_PEF_SECTION_PACKED_DATA: return "packed-data";
271
2
    case BFD_PEF_SECTION_CONSTANT: return "constant";
272
21
    case BFD_PEF_SECTION_LOADER: return "loader";
273
5
    case BFD_PEF_SECTION_DEBUG: return "debug";
274
27
    case BFD_PEF_SECTION_EXEC_DATA: return "exec-data";
275
6
    case BFD_PEF_SECTION_EXCEPTION: return "exception";
276
3
    case BFD_PEF_SECTION_TRACEBACK: return "traceback";
277
1.00k
    default: return "unknown";
278
2.21k
    }
279
2.21k
}
280
281
static unsigned long bfd_pef_section_flags (bfd_pef_section *section)
282
2.21k
{
283
2.21k
  switch (section->section_kind)
284
2.21k
    {
285
1.06k
    case BFD_PEF_SECTION_CODE:
286
1.06k
      return SEC_HAS_CONTENTS | SEC_LOAD | SEC_ALLOC | SEC_CODE;
287
69
    case BFD_PEF_SECTION_UNPACKED_DATA:
288
89
    case BFD_PEF_SECTION_PACKED_DATA:
289
91
    case BFD_PEF_SECTION_CONSTANT:
290
112
    case BFD_PEF_SECTION_LOADER:
291
117
    case BFD_PEF_SECTION_DEBUG:
292
144
    case BFD_PEF_SECTION_EXEC_DATA:
293
150
    case BFD_PEF_SECTION_EXCEPTION:
294
153
    case BFD_PEF_SECTION_TRACEBACK:
295
1.15k
    default:
296
1.15k
      return SEC_HAS_CONTENTS | SEC_LOAD | SEC_ALLOC;
297
2.21k
    }
298
2.21k
}
299
300
static asection *
301
bfd_pef_make_bfd_section (bfd *abfd, bfd_pef_section *section)
302
2.21k
{
303
2.21k
  asection *bfdsec;
304
2.21k
  const char *name = bfd_pef_section_name (section);
305
306
2.21k
  bfdsec = bfd_make_section_anyway (abfd, name);
307
2.21k
  if (bfdsec == NULL)
308
0
    return NULL;
309
310
2.21k
  bfdsec->vma = section->default_address + section->container_offset;
311
2.21k
  bfdsec->lma = section->default_address + section->container_offset;
312
2.21k
  bfdsec->size = section->container_length;
313
2.21k
  bfdsec->filepos = section->container_offset;
314
2.21k
  bfdsec->alignment_power = section->alignment;
315
316
2.21k
  bfdsec->flags = bfd_pef_section_flags (section);
317
318
2.21k
  return bfdsec;
319
2.21k
}
320
321
int
322
bfd_pef_parse_loader_header (bfd *abfd ATTRIBUTE_UNUSED,
323
           unsigned char *buf,
324
           size_t len,
325
           bfd_pef_loader_header *header)
326
37
{
327
37
  BFD_ASSERT (len == 56);
328
329
37
  header->main_section = bfd_getb32 (buf);
330
37
  header->main_offset = bfd_getb32 (buf + 4);
331
37
  header->init_section = bfd_getb32 (buf + 8);
332
37
  header->init_offset = bfd_getb32 (buf + 12);
333
37
  header->term_section = bfd_getb32 (buf + 16);
334
37
  header->term_offset = bfd_getb32 (buf + 20);
335
37
  header->imported_library_count = bfd_getb32 (buf + 24);
336
37
  header->total_imported_symbol_count = bfd_getb32 (buf + 28);
337
37
  header->reloc_section_count = bfd_getb32 (buf + 32);
338
37
  header->reloc_instr_offset = bfd_getb32 (buf + 36);
339
37
  header->loader_strings_offset = bfd_getb32 (buf + 40);
340
37
  header->export_hash_offset = bfd_getb32 (buf + 44);
341
37
  header->export_hash_table_power = bfd_getb32 (buf + 48);
342
37
  header->exported_symbol_count = bfd_getb32 (buf + 52);
343
344
37
  return 0;
345
37
}
346
347
int
348
bfd_pef_parse_imported_library (bfd *abfd ATTRIBUTE_UNUSED,
349
        unsigned char *buf,
350
        size_t len,
351
        bfd_pef_imported_library *header)
352
27
{
353
27
  BFD_ASSERT (len == 24);
354
355
27
  header->name_offset = bfd_getb32 (buf);
356
27
  header->old_implementation_version = bfd_getb32 (buf + 4);
357
27
  header->current_version = bfd_getb32 (buf + 8);
358
27
  header->imported_symbol_count = bfd_getb32 (buf + 12);
359
27
  header->first_imported_symbol = bfd_getb32 (buf + 16);
360
27
  header->options = buf[20];
361
27
  header->reserved_a = buf[21];
362
27
  header->reserved_b = bfd_getb16 (buf + 22);
363
364
27
  return 0;
365
27
}
366
367
int
368
bfd_pef_parse_imported_symbol (bfd *abfd ATTRIBUTE_UNUSED,
369
             unsigned char *buf,
370
             size_t len,
371
             bfd_pef_imported_symbol *symbol)
372
33
{
373
33
  unsigned long value;
374
375
33
  BFD_ASSERT (len == 4);
376
377
33
  value = bfd_getb32 (buf);
378
33
  symbol->symbol_class = value >> 24;
379
33
  symbol->name = value & 0x00ffffff;
380
381
33
  return 0;
382
33
}
383
384
int
385
bfd_pef_scan_section (bfd *abfd, bfd_pef_section *section)
386
2.33k
{
387
2.33k
  unsigned char buf[28];
388
389
2.33k
  if (bfd_seek (abfd, section->header_offset, SEEK_SET) != 0
390
2.33k
      || bfd_read (buf, 28, abfd) != 28)
391
121
    return -1;
392
393
2.21k
  section->name_offset = bfd_h_get_32 (abfd, buf);
394
2.21k
  section->default_address = bfd_h_get_32 (abfd, buf + 4);
395
2.21k
  section->total_length = bfd_h_get_32 (abfd, buf + 8);
396
2.21k
  section->unpacked_length = bfd_h_get_32 (abfd, buf + 12);
397
2.21k
  section->container_length = bfd_h_get_32 (abfd, buf + 16);
398
2.21k
  section->container_offset = bfd_h_get_32 (abfd, buf + 20);
399
2.21k
  section->section_kind = buf[24];
400
2.21k
  section->share_kind = buf[25];
401
2.21k
  section->alignment = buf[26];
402
2.21k
  section->reserved = buf[27];
403
404
2.21k
  section->bfd_section = bfd_pef_make_bfd_section (abfd, section);
405
2.21k
  if (section->bfd_section == NULL)
406
0
    return -1;
407
408
2.21k
  return 0;
409
2.21k
}
410
411
void
412
bfd_pef_print_loader_header (bfd *abfd ATTRIBUTE_UNUSED,
413
           bfd_pef_loader_header *header,
414
           FILE *file)
415
0
{
416
0
  fprintf (file, "main_section: %ld\n", header->main_section);
417
0
  fprintf (file, "main_offset: %lu\n", header->main_offset);
418
0
  fprintf (file, "init_section: %ld\n", header->init_section);
419
0
  fprintf (file, "init_offset: %lu\n", header->init_offset);
420
0
  fprintf (file, "term_section: %ld\n", header->term_section);
421
0
  fprintf (file, "term_offset: %lu\n", header->term_offset);
422
0
  fprintf (file, "imported_library_count: %lu\n",
423
0
     header->imported_library_count);
424
0
  fprintf (file, "total_imported_symbol_count: %lu\n",
425
0
     header->total_imported_symbol_count);
426
0
  fprintf (file, "reloc_section_count: %lu\n", header->reloc_section_count);
427
0
  fprintf (file, "reloc_instr_offset: %lu\n", header->reloc_instr_offset);
428
0
  fprintf (file, "loader_strings_offset: %lu\n",
429
0
     header->loader_strings_offset);
430
0
  fprintf (file, "export_hash_offset: %lu\n", header->export_hash_offset);
431
0
  fprintf (file, "export_hash_table_power: %lu\n",
432
0
     header->export_hash_table_power);
433
0
  fprintf (file, "exported_symbol_count: %lu\n",
434
0
     header->exported_symbol_count);
435
0
}
436
437
int
438
bfd_pef_print_loader_section (bfd *abfd, FILE *file)
439
0
{
440
0
  bfd_pef_loader_header header;
441
0
  asection *loadersec = NULL;
442
0
  unsigned char *loaderbuf = NULL;
443
0
  size_t loaderlen = 0;
444
445
0
  loadersec = bfd_get_section_by_name (abfd, "loader");
446
0
  if (loadersec == NULL)
447
0
    return -1;
448
449
0
  loaderlen = loadersec->size;
450
0
  if (loaderlen < 56)
451
0
    return -1;
452
0
  if (bfd_seek (abfd, loadersec->filepos, SEEK_SET) != 0)
453
0
    return -1;
454
0
  loaderbuf = _bfd_malloc_and_read (abfd, loaderlen, loaderlen);
455
0
  if (loaderbuf == NULL)
456
0
    return -1;
457
458
0
  if (bfd_pef_parse_loader_header (abfd, loaderbuf, 56, &header) < 0)
459
0
    {
460
0
      free (loaderbuf);
461
0
      return -1;
462
0
    }
463
464
0
  bfd_pef_print_loader_header (abfd, &header, file);
465
0
  return 0;
466
0
}
467
468
int
469
bfd_pef_scan_start_address (bfd *abfd)
470
230
{
471
230
  bfd_pef_loader_header header;
472
230
  asection *section;
473
474
230
  asection *loadersec = NULL;
475
230
  unsigned char *loaderbuf = NULL;
476
230
  size_t loaderlen = 0;
477
230
  int ret;
478
479
230
  loadersec = bfd_get_section_by_name (abfd, "loader");
480
230
  if (loadersec == NULL)
481
214
    goto end;
482
483
16
  loaderlen = loadersec->size;
484
16
  if (loaderlen < 56)
485
1
    goto error;
486
15
  if (bfd_seek (abfd, loadersec->filepos, SEEK_SET) != 0)
487
0
    goto error;
488
15
  loaderbuf = _bfd_malloc_and_read (abfd, loaderlen, loaderlen);
489
15
  if (loaderbuf == NULL)
490
2
    goto error;
491
492
13
  ret = bfd_pef_parse_loader_header (abfd, loaderbuf, 56, &header);
493
13
  if (ret < 0)
494
0
    goto error;
495
496
13
  if (header.main_section < 0)
497
0
    goto end;
498
499
69
  for (section = abfd->sections; section != NULL; section = section->next)
500
65
    if ((long) (section->index + 1) == header.main_section)
501
9
      break;
502
503
13
  if (section == NULL)
504
4
    goto error;
505
506
9
  abfd->start_address = section->vma + header.main_offset;
507
508
223
 end:
509
223
  free (loaderbuf);
510
223
  return 0;
511
512
7
 error:
513
7
  free (loaderbuf);
514
7
  return -1;
515
9
}
516
517
int
518
bfd_pef_scan (bfd *abfd,
519
        bfd_pef_header *header,
520
        bfd_pef_data_struct *mdata)
521
357
{
522
357
  unsigned int i;
523
357
  enum bfd_architecture cputype;
524
357
  unsigned long cpusubtype;
525
526
357
  mdata->header = *header;
527
528
357
  bfd_pef_convert_architecture (header->architecture, &cputype, &cpusubtype);
529
357
  if (cputype == bfd_arch_unknown)
530
6
    {
531
6
      _bfd_error_handler (_("bfd_pef_scan: unknown architecture 0x%lx"),
532
6
        header->architecture);
533
6
      return -1;
534
6
    }
535
351
  bfd_set_arch_mach (abfd, cputype, cpusubtype);
536
537
351
  mdata->header = *header;
538
539
351
  abfd->flags = (abfd->xvec->object_flags
540
351
     | (abfd->flags & (BFD_IN_MEMORY | BFD_IO_FUNCS)));
541
542
351
  if (header->section_count != 0)
543
350
    {
544
350
      mdata->sections = bfd_alloc (abfd, header->section_count * sizeof (bfd_pef_section));
545
546
350
      if (mdata->sections == NULL)
547
0
  return -1;
548
549
2.56k
      for (i = 0; i < header->section_count; i++)
550
2.33k
  {
551
2.33k
    bfd_pef_section *cur = &mdata->sections[i];
552
2.33k
    cur->header_offset = 40 + (i * 28);
553
2.33k
    if (bfd_pef_scan_section (abfd, cur) < 0)
554
121
      return -1;
555
2.33k
  }
556
350
    }
557
558
230
  if (bfd_pef_scan_start_address (abfd) < 0)
559
7
    return -1;
560
561
223
  abfd->tdata.pef_data = mdata;
562
563
223
  return 0;
564
230
}
565
566
static int
567
bfd_pef_read_header (bfd *abfd, bfd_pef_header *header)
568
262k
{
569
262k
  unsigned char buf[40];
570
571
262k
  if (bfd_seek (abfd, 0, SEEK_SET) != 0
572
262k
      || bfd_read (buf, 40, abfd) != 40)
573
11.8k
    return -1;
574
575
250k
  header->tag1 = bfd_getb32 (buf);
576
250k
  header->tag2 = bfd_getb32 (buf + 4);
577
250k
  header->architecture = bfd_getb32 (buf + 8);
578
250k
  header->format_version = bfd_getb32 (buf + 12);
579
250k
  header->timestamp = bfd_getb32 (buf + 16);
580
250k
  header->old_definition_version = bfd_getb32 (buf + 20);
581
250k
  header->old_implementation_version = bfd_getb32 (buf + 24);
582
250k
  header->current_version = bfd_getb32 (buf + 28);
583
250k
  header->section_count = bfd_getb32 (buf + 32) + 1;
584
250k
  header->instantiated_section_count = bfd_getb32 (buf + 34);
585
250k
  header->reserved = bfd_getb32 (buf + 36);
586
587
250k
  return 0;
588
262k
}
589
590
static bfd_cleanup
591
bfd_pef_object_p (bfd *abfd)
592
262k
{
593
262k
  bfd_pef_header header;
594
262k
  bfd_pef_data_struct *mdata;
595
596
262k
  if (bfd_pef_read_header (abfd, &header) != 0)
597
11.8k
    goto wrong;
598
599
250k
  if (header.tag1 != BFD_PEF_TAG1 || header.tag2 != BFD_PEF_TAG2)
600
250k
    goto wrong;
601
602
357
  mdata = (bfd_pef_data_struct *) bfd_zalloc (abfd, sizeof (*mdata));
603
357
  if (mdata == NULL)
604
0
    goto fail;
605
606
357
  if (bfd_pef_scan (abfd, &header, mdata))
607
134
    goto wrong;
608
609
223
  return _bfd_no_cleanup;
610
611
262k
 wrong:
612
262k
  bfd_set_error (bfd_error_wrong_format);
613
614
262k
 fail:
615
262k
  return NULL;
616
262k
}
617
618
static int
619
bfd_pef_parse_traceback_tables (bfd *abfd,
620
        asection *sec,
621
        unsigned char *buf,
622
        size_t len,
623
        long *nsym,
624
        asymbol **csym)
625
339
{
626
339
  char *name;
627
628
339
  asymbol function;
629
339
  asymbol traceback;
630
631
339
  const char *const tbprefix = "__traceback_";
632
339
  size_t tbnamelen;
633
634
339
  size_t pos = 0;
635
339
  unsigned long count = 0;
636
339
  int ret;
637
638
339
  for (;;)
639
464k
    {
640
      /* We're reading symbols two at a time.  */
641
464k
      if (csym && ((csym[count] == NULL) || (csym[count + 1] == NULL)))
642
113
  break;
643
644
463k
      pos += 3;
645
463k
      pos -= (pos % 4);
646
647
1.30M
      while ((pos + 4) <= len)
648
1.30M
  {
649
1.30M
    if (bfd_getb32 (buf + pos) == 0)
650
463k
      break;
651
840k
    pos += 4;
652
840k
  }
653
654
463k
      if ((pos + 4) > len)
655
226
  break;
656
657
463k
      ret = bfd_pef_parse_traceback_table (abfd, sec, buf, len, pos + 4,
658
463k
             &function, 0);
659
463k
      if (ret < 0)
660
457k
  {
661
    /* Skip over 0x0L to advance to next possible traceback table.  */
662
457k
    pos += 4;
663
457k
    continue;
664
457k
  }
665
666
6.17k
      BFD_ASSERT (function.name != NULL);
667
668
      /* Don't bother to compute the name if we are just
669
   counting symbols.  */
670
6.17k
      if (csym)
671
2.05k
  {
672
2.05k
    tbnamelen = strlen (tbprefix) + strlen (function.name);
673
2.05k
    name = bfd_alloc (abfd, tbnamelen + 1);
674
2.05k
    if (name == NULL)
675
0
      {
676
0
        bfd_release (abfd, (void *) function.name);
677
0
        function.name = NULL;
678
0
        break;
679
0
      }
680
2.05k
    snprintf (name, tbnamelen + 1, "%s%s", tbprefix, function.name);
681
2.05k
    traceback.name = name;
682
2.05k
    traceback.value = pos;
683
2.05k
    traceback.the_bfd = abfd;
684
2.05k
    traceback.section = sec;
685
2.05k
    traceback.flags = 0;
686
2.05k
    traceback.udata.i = ret;
687
688
2.05k
    *(csym[count]) = function;
689
2.05k
    *(csym[count + 1]) = traceback;
690
2.05k
  }
691
692
6.17k
      pos += ret;
693
6.17k
      count += 2;
694
6.17k
    }
695
696
339
  *nsym = count;
697
339
  return 0;
698
339
}
699
700
static int
701
bfd_pef_parse_function_stub (bfd *abfd ATTRIBUTE_UNUSED,
702
           unsigned char *buf,
703
           size_t len,
704
           unsigned long *offset)
705
0
{
706
0
  BFD_ASSERT (len == 24);
707
708
0
  if ((bfd_getb32 (buf) & 0xffff0000) != 0x81820000)
709
0
    return -1;
710
0
  if (bfd_getb32 (buf + 4) != 0x90410014)
711
0
    return -1;
712
0
  if (bfd_getb32 (buf + 8) != 0x800c0000)
713
0
    return -1;
714
0
  if (bfd_getb32 (buf + 12) != 0x804c0004)
715
0
    return -1;
716
0
  if (bfd_getb32 (buf + 16) != 0x7c0903a6)
717
0
    return -1;
718
0
  if (bfd_getb32 (buf + 20) != 0x4e800420)
719
0
    return -1;
720
721
0
  if (offset != NULL)
722
0
    *offset = (bfd_getb32 (buf) & 0x0000ffff) / 4;
723
724
0
  return 0;
725
0
}
726
727
static int
728
bfd_pef_parse_function_stubs (bfd *abfd,
729
            asection *codesec,
730
            unsigned char *codebuf,
731
            size_t codelen,
732
            unsigned char *loaderbuf,
733
            size_t loaderlen,
734
            unsigned long *nsym,
735
            asymbol **csym)
736
24
{
737
24
  const char *const sprefix = "__stub_";
738
24
  size_t codepos = 0;
739
24
  unsigned long count = 0;
740
24
  bfd_pef_loader_header header;
741
24
  bfd_pef_imported_library *libraries = NULL;
742
24
  bfd_pef_imported_symbol *imports = NULL;
743
24
  unsigned long i;
744
24
  int ret;
745
746
24
  if (loaderlen < 56)
747
0
    goto error;
748
749
24
  ret = bfd_pef_parse_loader_header (abfd, loaderbuf, 56, &header);
750
24
  if (ret < 0)
751
0
    goto error;
752
753
24
  if ((loaderlen - 56) / 24 < header.imported_library_count)
754
3
    goto error;
755
756
21
  if ((loaderlen - 56 - header.imported_library_count * 24) / 4
757
21
      < header.total_imported_symbol_count)
758
3
    goto error;
759
760
18
  libraries = bfd_malloc
761
18
    (header.imported_library_count * sizeof (bfd_pef_imported_library));
762
18
  imports = bfd_malloc
763
18
    (header.total_imported_symbol_count * sizeof (bfd_pef_imported_symbol));
764
18
  if (libraries == NULL || imports == NULL)
765
0
    goto error;
766
767
45
  for (i = 0; i < header.imported_library_count; i++)
768
27
    {
769
27
      ret = bfd_pef_parse_imported_library
770
27
  (abfd, loaderbuf + 56 + (i * 24), 24, &libraries[i]);
771
27
      if (ret < 0)
772
0
  goto error;
773
27
    }
774
775
51
  for (i = 0; i < header.total_imported_symbol_count; i++)
776
33
    {
777
33
      ret = (bfd_pef_parse_imported_symbol
778
33
       (abfd,
779
33
        loaderbuf + 56 + (header.imported_library_count * 24) + (i * 4),
780
33
        4, &imports[i]));
781
33
      if (ret < 0)
782
0
  goto error;
783
33
    }
784
785
18
  codepos = 0;
786
787
18
  for (;;)
788
18
    {
789
18
      asymbol sym;
790
18
      const char *symname;
791
18
      char *name;
792
18
      unsigned long sym_index;
793
794
18
      if (csym && (csym[count] == NULL))
795
6
  break;
796
797
12
      codepos += 3;
798
12
      codepos -= (codepos % 4);
799
800
66
      while ((codepos + 4) <= codelen)
801
54
  {
802
54
    if ((bfd_getb32 (codebuf + codepos) & 0xffff0000) == 0x81820000)
803
0
      break;
804
54
    codepos += 4;
805
54
  }
806
807
12
      if ((codepos + 24) > codelen)
808
12
  break;
809
810
0
      ret = bfd_pef_parse_function_stub (abfd, codebuf + codepos, 24, &sym_index);
811
0
      if (ret < 0)
812
0
  {
813
0
    codepos += 24;
814
0
    continue;
815
0
  }
816
817
0
      if (sym_index >= header.total_imported_symbol_count)
818
0
  {
819
0
    codepos += 24;
820
0
    continue;
821
0
  }
822
823
0
      {
824
0
  size_t max, namelen;
825
0
  const char *s;
826
827
0
  if (loaderlen < (header.loader_strings_offset + imports[sym_index].name))
828
0
    goto error;
829
830
0
  max = loaderlen - (header.loader_strings_offset + imports[sym_index].name);
831
0
  symname = (char *) loaderbuf;
832
0
  symname += header.loader_strings_offset + imports[sym_index].name;
833
0
  namelen = 0;
834
0
  for (s = symname; s < (symname + max); s++)
835
0
    {
836
0
      if (*s == '\0')
837
0
        break;
838
0
      if (! ISPRINT (*s))
839
0
        goto error;
840
0
      namelen++;
841
0
    }
842
0
  if (*s != '\0')
843
0
    goto error;
844
845
0
  name = bfd_alloc (abfd, strlen (sprefix) + namelen + 1);
846
0
  if (name == NULL)
847
0
    break;
848
849
0
  snprintf (name, strlen (sprefix) + namelen + 1, "%s%s",
850
0
      sprefix, symname);
851
0
  sym.name = name;
852
0
      }
853
854
0
      sym.value = codepos;
855
0
      sym.the_bfd = abfd;
856
0
      sym.section = codesec;
857
0
      sym.flags = 0;
858
0
      sym.udata.i = 0;
859
860
0
      codepos += 24;
861
862
0
      if (csym != NULL)
863
0
  *(csym[count]) = sym;
864
865
0
      count++;
866
0
    }
867
868
18
  goto end;
869
870
18
 end:
871
18
  free (libraries);
872
18
  free (imports);
873
18
  *nsym = count;
874
18
  return 0;
875
876
6
 error:
877
6
  free (libraries);
878
6
  free (imports);
879
6
  *nsym = count;
880
6
  return -1;
881
18
}
882
883
static long
884
bfd_pef_parse_symbols (bfd *abfd, asymbol **csym)
885
366
{
886
366
  unsigned long count = 0;
887
888
366
  asection *codesec = NULL;
889
366
  unsigned char *codebuf = NULL;
890
366
  size_t codelen = 0;
891
892
366
  asection *loadersec = NULL;
893
366
  unsigned char *loaderbuf = NULL;
894
366
  size_t loaderlen = 0;
895
896
366
  codesec = bfd_get_section_by_name (abfd, "code");
897
366
  if (codesec != NULL)
898
363
    {
899
363
      codelen = codesec->size;
900
363
      if (bfd_seek (abfd, codesec->filepos, SEEK_SET) != 0)
901
0
  goto end;
902
363
      codebuf = _bfd_malloc_and_read (abfd, codelen, codelen);
903
363
      if (codebuf == NULL)
904
24
  goto end;
905
363
    }
906
907
342
  loadersec = bfd_get_section_by_name (abfd, "loader");
908
342
  if (loadersec != NULL)
909
24
    {
910
24
      loaderlen = loadersec->size;
911
24
      if (bfd_seek (abfd, loadersec->filepos, SEEK_SET) != 0)
912
0
  goto end;
913
24
      loaderbuf = _bfd_malloc_and_read (abfd, loaderlen, loaderlen);
914
24
      if (loaderbuf == NULL)
915
0
  goto end;
916
24
    }
917
918
342
  count = 0;
919
342
  if (codesec != NULL)
920
339
    {
921
339
      long ncount = 0;
922
339
      bfd_pef_parse_traceback_tables (abfd, codesec, codebuf, codelen,
923
339
              &ncount, csym);
924
339
      count += ncount;
925
339
    }
926
927
342
  if ((codesec != NULL) && (loadersec != NULL))
928
24
    {
929
24
      unsigned long ncount = 0;
930
24
      bfd_pef_parse_function_stubs
931
24
  (abfd, codesec, codebuf, codelen, loaderbuf, loaderlen, &ncount,
932
24
   (csym != NULL) ? (csym + count) : NULL);
933
24
      count += ncount;
934
24
    }
935
936
342
  if (csym != NULL)
937
114
    csym[count] = NULL;
938
939
366
 end:
940
366
  free (codebuf);
941
366
  free (loaderbuf);
942
366
  return count;
943
342
}
944
945
static long
946
bfd_pef_count_symbols (bfd *abfd)
947
244
{
948
244
  return bfd_pef_parse_symbols (abfd, NULL);
949
244
}
950
951
static long
952
bfd_pef_get_symtab_upper_bound (bfd *abfd)
953
122
{
954
122
  long nsyms = bfd_pef_count_symbols (abfd);
955
956
122
  if (nsyms < 0)
957
0
    return nsyms;
958
122
  return ((nsyms + 1) * sizeof (asymbol *));
959
122
}
960
961
static long
962
bfd_pef_canonicalize_symtab (bfd *abfd, asymbol **alocation)
963
122
{
964
122
  long i;
965
122
  asymbol *syms;
966
122
  long ret;
967
122
  long nsyms = bfd_pef_count_symbols (abfd);
968
969
122
  if (nsyms < 0)
970
0
    return nsyms;
971
972
122
  syms = bfd_alloc (abfd, nsyms * sizeof (asymbol));
973
122
  if (syms == NULL)
974
0
    return -1;
975
976
4.23k
  for (i = 0; i < nsyms; i++)
977
4.11k
    alocation[i] = &syms[i];
978
979
122
  alocation[nsyms] = NULL;
980
981
122
  ret = bfd_pef_parse_symbols (abfd, alocation);
982
122
  if (ret != nsyms)
983
0
    return 0;
984
985
122
  return ret;
986
122
}
987
988
#define bfd_pef_make_empty_symbol _bfd_generic_make_empty_symbol
989
990
static void
991
bfd_pef_get_symbol_info (bfd *abfd ATTRIBUTE_UNUSED,
992
       asymbol *symbol,
993
       symbol_info *ret)
994
0
{
995
0
  bfd_symbol_info (symbol, ret);
996
0
}
997
998
static int
999
bfd_pef_sizeof_headers (bfd *abfd ATTRIBUTE_UNUSED,
1000
      struct bfd_link_info *info ATTRIBUTE_UNUSED)
1001
0
{
1002
0
  return 0;
1003
0
}
1004
1005
const bfd_target pef_vec =
1006
{
1007
  "pef",      /* Name.  */
1008
  bfd_target_pef_flavour, /* Flavour.  */
1009
  BFD_ENDIAN_BIG,   /* Byteorder.  */
1010
  BFD_ENDIAN_BIG,   /* Header_byteorder.  */
1011
  (HAS_RELOC | EXEC_P |   /* Object flags.  */
1012
   HAS_LINENO | HAS_DEBUG |
1013
   HAS_SYMS | HAS_LOCALS | DYNAMIC | WP_TEXT | D_PAGED),
1014
  (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE | SEC_DATA
1015
   | SEC_ROM | SEC_HAS_CONTENTS), /* Section_flags.  */
1016
  0,        /* Symbol_leading_char.  */
1017
  ' ',        /* AR_pad_char.  */
1018
  16,       /* AR_max_namelen.  */
1019
  0,        /* match priority.  */
1020
  TARGET_KEEP_UNUSED_SECTION_SYMBOLS, /* keep unused section symbols.  */
1021
  bfd_getb64, bfd_getb_signed_64, bfd_putb64,
1022
  bfd_getb32, bfd_getb_signed_32, bfd_putb32,
1023
  bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* Data.  */
1024
  bfd_getb64, bfd_getb_signed_64, bfd_putb64,
1025
  bfd_getb32, bfd_getb_signed_32, bfd_putb32,
1026
  bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* Headers.  */
1027
  {       /* bfd_check_format.  */
1028
    _bfd_dummy_target,
1029
    bfd_pef_object_p,   /* bfd_check_format.  */
1030
    _bfd_dummy_target,
1031
    _bfd_dummy_target,
1032
  },
1033
  {       /* bfd_set_format.  */
1034
    _bfd_bool_bfd_false_error,
1035
    bfd_pef_mkobject,
1036
    _bfd_bool_bfd_false_error,
1037
    _bfd_bool_bfd_false_error,
1038
  },
1039
  {       /* bfd_write_contents.  */
1040
    _bfd_bool_bfd_false_error,
1041
    _bfd_bool_bfd_true,
1042
    _bfd_bool_bfd_false_error,
1043
    _bfd_bool_bfd_false_error,
1044
  },
1045
1046
  BFD_JUMP_TABLE_GENERIC (bfd_pef),
1047
  BFD_JUMP_TABLE_COPY (_bfd_generic),
1048
  BFD_JUMP_TABLE_CORE (_bfd_nocore),
1049
  BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
1050
  BFD_JUMP_TABLE_SYMBOLS (bfd_pef),
1051
  BFD_JUMP_TABLE_RELOCS (_bfd_norelocs),
1052
  BFD_JUMP_TABLE_WRITE (bfd_pef),
1053
  BFD_JUMP_TABLE_LINK (bfd_pef),
1054
  BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
1055
1056
  NULL,
1057
1058
  NULL
1059
};
1060
1061
#define bfd_pef_xlib_close_and_cleanup        _bfd_generic_close_and_cleanup
1062
#define bfd_pef_xlib_bfd_free_cached_info     _bfd_generic_bfd_free_cached_info
1063
#define bfd_pef_xlib_new_section_hook       _bfd_generic_new_section_hook
1064
#define bfd_pef_xlib_get_section_contents     _bfd_generic_get_section_contents
1065
#define bfd_pef_xlib_set_section_contents     _bfd_generic_set_section_contents
1066
#define bfd_pef_xlib_get_section_contents_in_window _bfd_generic_get_section_contents_in_window
1067
#define bfd_pef_xlib_set_section_contents_in_window _bfd_generic_set_section_contents_in_window
1068
1069
static int
1070
bfd_pef_xlib_read_header (bfd *abfd, bfd_pef_xlib_header *header)
1071
262k
{
1072
262k
  unsigned char buf[80];
1073
1074
262k
  if (bfd_seek (abfd, 0, SEEK_SET) != 0
1075
262k
      || bfd_read (buf, sizeof buf, abfd) != sizeof buf)
1076
42.0k
    return -1;
1077
1078
220k
  header->tag1 = bfd_getb32 (buf);
1079
220k
  header->tag2 = bfd_getb32 (buf + 4);
1080
220k
  header->current_format = bfd_getb32 (buf + 8);
1081
220k
  header->container_strings_offset = bfd_getb32 (buf + 12);
1082
220k
  header->export_hash_offset = bfd_getb32 (buf + 16);
1083
220k
  header->export_key_offset = bfd_getb32 (buf + 20);
1084
220k
  header->export_symbol_offset = bfd_getb32 (buf + 24);
1085
220k
  header->export_names_offset = bfd_getb32 (buf + 28);
1086
220k
  header->export_hash_table_power = bfd_getb32 (buf + 32);
1087
220k
  header->exported_symbol_count = bfd_getb32 (buf + 36);
1088
220k
  header->frag_name_offset = bfd_getb32 (buf + 40);
1089
220k
  header->frag_name_length = bfd_getb32 (buf + 44);
1090
220k
  header->dylib_path_offset = bfd_getb32 (buf + 48);
1091
220k
  header->dylib_path_length = bfd_getb32 (buf + 52);
1092
220k
  header->cpu_family = bfd_getb32 (buf + 56);
1093
220k
  header->cpu_model = bfd_getb32 (buf + 60);
1094
220k
  header->date_time_stamp = bfd_getb32 (buf + 64);
1095
220k
  header->current_version = bfd_getb32 (buf + 68);
1096
220k
  header->old_definition_version = bfd_getb32 (buf + 72);
1097
220k
  header->old_implementation_version = bfd_getb32 (buf + 76);
1098
1099
220k
  return 0;
1100
262k
}
1101
1102
static int
1103
bfd_pef_xlib_scan (bfd *abfd, bfd_pef_xlib_header *header)
1104
0
{
1105
0
  bfd_pef_xlib_data_struct *mdata = NULL;
1106
1107
0
  mdata = bfd_alloc (abfd, sizeof (* mdata));
1108
0
  if (mdata == NULL)
1109
0
    return -1;
1110
1111
0
  mdata->header = *header;
1112
1113
0
  abfd->flags = (abfd->xvec->object_flags
1114
0
     | (abfd->flags & (BFD_IN_MEMORY | BFD_IO_FUNCS)));
1115
1116
0
  abfd->tdata.pef_xlib_data = mdata;
1117
1118
0
  return 0;
1119
0
}
1120
1121
static bfd_cleanup
1122
bfd_pef_xlib_object_p (bfd *abfd)
1123
262k
{
1124
262k
  bfd_pef_xlib_header header;
1125
1126
262k
  if (bfd_pef_xlib_read_header (abfd, &header) != 0)
1127
42.0k
    {
1128
42.0k
      bfd_set_error (bfd_error_wrong_format);
1129
42.0k
      return NULL;
1130
42.0k
    }
1131
1132
220k
  if ((header.tag1 != BFD_PEF_XLIB_TAG1)
1133
220k
      || ((header.tag2 != BFD_PEF_VLIB_TAG2)
1134
0
    && (header.tag2 != BFD_PEF_BLIB_TAG2)))
1135
220k
    {
1136
220k
      bfd_set_error (bfd_error_wrong_format);
1137
220k
      return NULL;
1138
220k
    }
1139
1140
0
  if (bfd_pef_xlib_scan (abfd, &header) != 0)
1141
0
    {
1142
0
      bfd_set_error (bfd_error_wrong_format);
1143
0
      return NULL;
1144
0
    }
1145
1146
0
  return _bfd_no_cleanup;
1147
0
}
1148
1149
const bfd_target pef_xlib_vec =
1150
{
1151
  "pef-xlib",     /* Name.  */
1152
  bfd_target_pef_xlib_flavour,  /* Flavour.  */
1153
  BFD_ENDIAN_BIG,   /* Byteorder */
1154
  BFD_ENDIAN_BIG,   /* Header_byteorder.  */
1155
  (HAS_RELOC | EXEC_P |   /* Object flags.  */
1156
   HAS_LINENO | HAS_DEBUG |
1157
   HAS_SYMS | HAS_LOCALS | DYNAMIC | WP_TEXT | D_PAGED),
1158
  (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE | SEC_DATA
1159
   | SEC_ROM | SEC_HAS_CONTENTS),/* Section_flags.  */
1160
  0,        /* Symbol_leading_char.  */
1161
  ' ',        /* AR_pad_char.  */
1162
  16,       /* AR_max_namelen.  */
1163
  0,        /* match priority.  */
1164
  TARGET_KEEP_UNUSED_SECTION_SYMBOLS, /* keep unused section symbols.  */
1165
  bfd_getb64, bfd_getb_signed_64, bfd_putb64,
1166
  bfd_getb32, bfd_getb_signed_32, bfd_putb32,
1167
  bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* Data.  */
1168
  bfd_getb64, bfd_getb_signed_64, bfd_putb64,
1169
  bfd_getb32, bfd_getb_signed_32, bfd_putb32,
1170
  bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* Headers.  */
1171
  {       /* bfd_check_format.  */
1172
    _bfd_dummy_target,
1173
    bfd_pef_xlib_object_p,  /* bfd_check_format.  */
1174
    _bfd_dummy_target,
1175
    _bfd_dummy_target,
1176
  },
1177
  {       /* bfd_set_format.  */
1178
    _bfd_bool_bfd_false_error,
1179
    bfd_pef_mkobject,
1180
    _bfd_bool_bfd_false_error,
1181
    _bfd_bool_bfd_false_error,
1182
  },
1183
  {       /* bfd_write_contents.  */
1184
    _bfd_bool_bfd_false_error,
1185
    _bfd_bool_bfd_true,
1186
    _bfd_bool_bfd_false_error,
1187
    _bfd_bool_bfd_false_error,
1188
  },
1189
1190
  BFD_JUMP_TABLE_GENERIC (bfd_pef_xlib),
1191
  BFD_JUMP_TABLE_COPY (_bfd_generic),
1192
  BFD_JUMP_TABLE_CORE (_bfd_nocore),
1193
  BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
1194
  BFD_JUMP_TABLE_SYMBOLS (_bfd_nosymbols),
1195
  BFD_JUMP_TABLE_RELOCS (_bfd_norelocs),
1196
  BFD_JUMP_TABLE_WRITE (_bfd_nowrite),
1197
  BFD_JUMP_TABLE_LINK (_bfd_nolink),
1198
  BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
1199
1200
  NULL,
1201
1202
  NULL
1203
};