OpenCores
URL https://opencores.org/ocsvn/open8_urisc/open8_urisc/trunk

Subversion Repositories open8_urisc

[/] [open8_urisc/] [trunk/] [gnu/] [binutils/] [bfd/] [pef.c] - Blame information for rev 241

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.