1 /* PEF support for BFD.
2 Copyright 1999, 2000, 2001, 2002, 2003, 2004
3 Free Software Foundation, Inc.
5 This file is part of BFD, the Binary File Descriptor library.
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 2 of the License, or
10 (at your option) any later version.
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.
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
21 #include "safe-ctype.h"
24 #include "pef-traceback.h"
30 #include "libiberty.h"
33 #define BFD_IO_FUNCS 0
36 #define bfd_pef_close_and_cleanup _bfd_generic_close_and_cleanup
37 #define bfd_pef_bfd_free_cached_info _bfd_generic_bfd_free_cached_info
38 #define bfd_pef_new_section_hook _bfd_generic_new_section_hook
39 #define bfd_pef_bfd_is_local_label_name bfd_generic_is_local_label_name
40 #define bfd_pef_get_lineno _bfd_nosymbols_get_lineno
41 #define bfd_pef_find_nearest_line _bfd_nosymbols_find_nearest_line
42 #define bfd_pef_bfd_make_debug_symbol _bfd_nosymbols_bfd_make_debug_symbol
43 #define bfd_pef_read_minisymbols _bfd_generic_read_minisymbols
44 #define bfd_pef_minisymbol_to_symbol _bfd_generic_minisymbol_to_symbol
45 #define bfd_pef_get_reloc_upper_bound _bfd_norelocs_get_reloc_upper_bound
46 #define bfd_pef_canonicalize_reloc _bfd_norelocs_canonicalize_reloc
47 #define bfd_pef_bfd_reloc_type_lookup _bfd_norelocs_bfd_reloc_type_lookup
48 #define bfd_pef_set_arch_mach _bfd_generic_set_arch_mach
49 #define bfd_pef_get_section_contents _bfd_generic_get_section_contents
50 #define bfd_pef_set_section_contents _bfd_generic_set_section_contents
51 #define bfd_pef_bfd_get_relocated_section_contents bfd_generic_get_relocated_section_contents
52 #define bfd_pef_bfd_relax_section bfd_generic_relax_section
53 #define bfd_pef_bfd_gc_sections bfd_generic_gc_sections
54 #define bfd_pef_bfd_merge_sections bfd_generic_merge_sections
55 #define bfd_pef_bfd_is_group_section bfd_generic_is_group_section
56 #define bfd_pef_bfd_discard_group bfd_generic_discard_group
57 #define bfd_pef_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
58 #define bfd_pef_bfd_link_hash_table_free _bfd_generic_link_hash_table_free
59 #define bfd_pef_bfd_link_add_symbols _bfd_generic_link_add_symbols
60 #define bfd_pef_bfd_link_just_syms _bfd_generic_link_just_syms
61 #define bfd_pef_bfd_final_link _bfd_generic_final_link
62 #define bfd_pef_bfd_link_split_section _bfd_generic_link_split_section
63 #define bfd_pef_get_section_contents_in_window _bfd_generic_get_section_contents_in_window
65 static void bfd_pef_print_symbol
PARAMS ((bfd
*, PTR
, asymbol
*, bfd_print_symbol_type
));
66 static void bfd_pef_convert_architecture
PARAMS ((unsigned long, enum bfd_architecture
*, unsigned long *));
67 static bfd_boolean bfd_pef_mkobject
PARAMS ((bfd
*));
68 static int bfd_pef_parse_traceback_table
PARAMS ((bfd
*, asection
*, unsigned char *, size_t, size_t, asymbol
*, FILE *));
69 static const char *bfd_pef_section_name
PARAMS ((bfd_pef_section
*));
70 static unsigned long bfd_pef_section_flags
PARAMS ((bfd_pef_section
*));
71 static asection
*bfd_pef_make_bfd_section
PARAMS ((bfd
*, bfd_pef_section
*));
72 static int bfd_pef_read_header
PARAMS ((bfd
*, bfd_pef_header
*));
73 static const bfd_target
*bfd_pef_object_p
PARAMS ((bfd
*));
74 static int bfd_pef_parse_traceback_tables
PARAMS ((bfd
*, asection
*, unsigned char *, size_t, long *, asymbol
**));
75 static int bfd_pef_parse_function_stub
PARAMS ((bfd
*, unsigned char *, size_t, unsigned long *));
76 static int bfd_pef_parse_function_stubs
PARAMS ((bfd
*, asection
*, unsigned char *, size_t, unsigned char *, size_t, unsigned long *, asymbol
**));
77 static long bfd_pef_parse_symbols
PARAMS ((bfd
*, asymbol
**));
78 static long bfd_pef_count_symbols
PARAMS ((bfd
*));
79 static long bfd_pef_get_symtab_upper_bound
PARAMS ((bfd
*));
80 static long bfd_pef_canonicalize_symtab
PARAMS ((bfd
*, asymbol
**));
81 static asymbol
*bfd_pef_make_empty_symbol
PARAMS ((bfd
*));
82 static void bfd_pef_get_symbol_info
PARAMS ((bfd
*, asymbol
*, symbol_info
*));
83 static int bfd_pef_sizeof_headers
PARAMS ((bfd
*, bfd_boolean
));
84 static int bfd_pef_xlib_read_header
PARAMS ((bfd
*, bfd_pef_xlib_header
*));
85 static int bfd_pef_xlib_scan
PARAMS ((bfd
*, bfd_pef_xlib_header
*));
86 static const bfd_target
*bfd_pef_xlib_object_p
PARAMS ((bfd
*));
89 bfd_pef_print_symbol (abfd
, afile
, symbol
, how
)
93 bfd_print_symbol_type how
;
95 FILE *file
= (FILE *) afile
;
99 case bfd_print_symbol_name
:
100 fprintf (file
, "%s", symbol
->name
);
103 bfd_print_symbol_vandf (abfd
, (PTR
) file
, symbol
);
104 fprintf (file
, " %-5s %s", symbol
->section
->name
, symbol
->name
);
105 if (strncmp (symbol
->name
, "__traceback_", strlen ("__traceback_")) == 0)
107 char *buf
= alloca (symbol
->udata
.i
);
108 size_t offset
= symbol
->value
+ 4;
109 size_t len
= symbol
->udata
.i
;
112 bfd_get_section_contents (abfd
, symbol
->section
, buf
, offset
, len
);
113 ret
= bfd_pef_parse_traceback_table (abfd
, symbol
->section
, buf
,
116 fprintf (file
, " [ERROR]");
122 bfd_pef_convert_architecture (architecture
, type
, subtype
)
123 unsigned long architecture
;
124 enum bfd_architecture
*type
;
125 unsigned long *subtype
;
127 const unsigned long ARCH_POWERPC
= 0x70777063; /* 'pwpc' */
128 const unsigned long ARCH_M68K
= 0x6d36386b; /* 'm68k' */
130 *subtype
= bfd_arch_unknown
;
131 *type
= bfd_arch_unknown
;
133 if (architecture
== ARCH_POWERPC
)
134 *type
= bfd_arch_powerpc
;
135 else if (architecture
== ARCH_M68K
)
136 *type
= bfd_arch_m68k
;
140 bfd_pef_mkobject (abfd
)
141 bfd
*abfd ATTRIBUTE_UNUSED
;
147 bfd_pef_parse_traceback_table (abfd
, section
, buf
, len
, pos
, sym
, file
)
156 struct traceback_table table
;
167 sym
->section
= section
;
171 /* memcpy is fine since all fields are unsigned char. */
175 memcpy (&table
, buf
+ pos
, 8);
177 /* Calling code relies on returned symbols having a name and
180 if ((table
.lang
!= TB_C
) && (table
.lang
!= TB_CPLUSPLUS
))
183 if (! (table
.flags2
& TB_NAME_PRESENT
))
186 if (! table
.flags1
& TB_HAS_TBOFF
)
191 if ((table
.flags5
& TB_FLOATPARAMS
) || (table
.fixedparams
))
194 if (table
.flags1
& TB_HAS_TBOFF
)
196 struct traceback_table_tboff off
;
198 if ((pos
+ offset
+ 4) > len
)
200 off
.tb_offset
= bfd_getb32 (buf
+ pos
+ offset
);
203 /* Need to subtract 4 because the offset includes the 0x0L
204 preceding the table. */
207 fprintf (file
, " [offset = 0x%lx]", off
.tb_offset
);
209 if ((file
== NULL
) && ((off
.tb_offset
+ 4) > (pos
+ offset
)))
212 sym
->value
= pos
- off
.tb_offset
- 4;
215 if (table
.flags2
& TB_INT_HNDL
)
218 if (table
.flags1
& TB_HAS_CTL
)
220 struct traceback_table_anchors anchors
;
222 if ((pos
+ offset
+ 4) > len
)
224 anchors
.ctl_info
= bfd_getb32 (buf
+ pos
+ offset
);
227 if (anchors
.ctl_info
> 1024)
230 offset
+= anchors
.ctl_info
* 4;
233 if (table
.flags2
& TB_NAME_PRESENT
)
235 struct traceback_table_routine name
;
238 if ((pos
+ offset
+ 2) > len
)
240 name
.name_len
= bfd_getb16 (buf
+ pos
+ offset
);
243 if (name
.name_len
> 4096)
246 if ((pos
+ offset
+ name
.name_len
) > len
)
249 namebuf
= (char *) bfd_alloc (abfd
, name
.name_len
+ 1);
253 memcpy (namebuf
, buf
+ pos
+ offset
, name
.name_len
);
254 namebuf
[name
.name_len
] = '\0';
256 /* Strip leading period inserted by compiler. */
257 if (namebuf
[0] == '.')
258 memmove (namebuf
, namebuf
+ 1, name
.name_len
+ 1);
262 for (s
= sym
->name
; (*s
!= '\0'); s
++)
266 offset
+= name
.name_len
;
269 if (table
.flags2
& TB_USES_ALLOCA
)
272 if (table
.flags4
& TB_HAS_VEC_INFO
)
276 fprintf (file
, " [length = 0x%lx]", (long) offset
);
281 static const char *bfd_pef_section_name (section
)
282 bfd_pef_section
*section
;
284 switch (section
->section_kind
)
286 case BFD_PEF_SECTION_CODE
: return "code";
287 case BFD_PEF_SECTION_UNPACKED_DATA
: return "unpacked-data";
288 case BFD_PEF_SECTION_PACKED_DATA
: return "packed-data";
289 case BFD_PEF_SECTION_CONSTANT
: return "constant";
290 case BFD_PEF_SECTION_LOADER
: return "loader";
291 case BFD_PEF_SECTION_DEBUG
: return "debug";
292 case BFD_PEF_SECTION_EXEC_DATA
: return "exec-data";
293 case BFD_PEF_SECTION_EXCEPTION
: return "exception";
294 case BFD_PEF_SECTION_TRACEBACK
: return "traceback";
295 default: return "unknown";
299 static unsigned long bfd_pef_section_flags (section
)
300 bfd_pef_section
*section
;
302 switch (section
->section_kind
)
304 case BFD_PEF_SECTION_CODE
:
305 return SEC_HAS_CONTENTS
| SEC_LOAD
| SEC_ALLOC
| SEC_CODE
;
306 case BFD_PEF_SECTION_UNPACKED_DATA
:
307 case BFD_PEF_SECTION_PACKED_DATA
:
308 case BFD_PEF_SECTION_CONSTANT
:
309 case BFD_PEF_SECTION_LOADER
:
310 case BFD_PEF_SECTION_DEBUG
:
311 case BFD_PEF_SECTION_EXEC_DATA
:
312 case BFD_PEF_SECTION_EXCEPTION
:
313 case BFD_PEF_SECTION_TRACEBACK
:
315 return SEC_HAS_CONTENTS
| SEC_LOAD
| SEC_ALLOC
;
320 bfd_pef_make_bfd_section (abfd
, section
)
322 bfd_pef_section
*section
;
325 const char *name
= bfd_pef_section_name (section
);
327 bfdsec
= bfd_make_section_anyway (abfd
, name
);
331 bfdsec
->vma
= section
->default_address
+ section
->container_offset
;
332 bfdsec
->lma
= section
->default_address
+ section
->container_offset
;
333 bfdsec
->_raw_size
= section
->container_length
;
334 bfdsec
->filepos
= section
->container_offset
;
335 bfdsec
->alignment_power
= section
->alignment
;
337 bfdsec
->flags
= bfd_pef_section_flags (section
);
342 int bfd_pef_parse_loader_header (abfd
, buf
, len
, header
)
343 bfd
*abfd ATTRIBUTE_UNUSED
;
346 bfd_pef_loader_header
*header
;
348 BFD_ASSERT (len
== 56);
350 header
->main_section
= bfd_getb32 (buf
);
351 header
->main_offset
= bfd_getb32 (buf
+ 4);
352 header
->init_section
= bfd_getb32 (buf
+ 8);
353 header
->init_offset
= bfd_getb32 (buf
+ 12);
354 header
->term_section
= bfd_getb32 (buf
+ 16);
355 header
->term_offset
= bfd_getb32 (buf
+ 20);
356 header
->imported_library_count
= bfd_getb32 (buf
+ 24);
357 header
->total_imported_symbol_count
= bfd_getb32 (buf
+ 28);
358 header
->reloc_section_count
= bfd_getb32 (buf
+ 32);
359 header
->reloc_instr_offset
= bfd_getb32 (buf
+ 36);
360 header
->loader_strings_offset
= bfd_getb32 (buf
+ 40);
361 header
->export_hash_offset
= bfd_getb32 (buf
+ 44);
362 header
->export_hash_table_power
= bfd_getb32 (buf
+ 48);
363 header
->exported_symbol_count
= bfd_getb32 (buf
+ 52);
368 int bfd_pef_parse_imported_library (abfd
, buf
, len
, header
)
369 bfd
*abfd ATTRIBUTE_UNUSED
;
372 bfd_pef_imported_library
*header
;
374 BFD_ASSERT (len
== 24);
376 header
->name_offset
= bfd_getb32 (buf
);
377 header
->old_implementation_version
= bfd_getb32 (buf
+ 4);
378 header
->current_version
= bfd_getb32 (buf
+ 8);
379 header
->imported_symbol_count
= bfd_getb32 (buf
+ 12);
380 header
->first_imported_symbol
= bfd_getb32 (buf
+ 16);
381 header
->options
= buf
[20];
382 header
->reserved_a
= buf
[21];
383 header
->reserved_b
= bfd_getb16 (buf
+ 22);
388 int bfd_pef_parse_imported_symbol (abfd
, buf
, len
, symbol
)
389 bfd
*abfd ATTRIBUTE_UNUSED
;
392 bfd_pef_imported_symbol
*symbol
;
396 BFD_ASSERT (len
== 4);
398 value
= bfd_getb32 (buf
);
399 symbol
->class = value
>> 24;
400 symbol
->name
= value
& 0x00ffffff;
405 int bfd_pef_scan_section (abfd
, section
)
407 bfd_pef_section
*section
;
409 unsigned char buf
[28];
411 bfd_seek (abfd
, section
->header_offset
, SEEK_SET
);
412 if (bfd_bread ((PTR
) buf
, 28, abfd
) != 28)
415 section
->name_offset
= bfd_h_get_32 (abfd
, buf
);
416 section
->default_address
= bfd_h_get_32 (abfd
, buf
+ 4);
417 section
->total_length
= bfd_h_get_32 (abfd
, buf
+ 8);
418 section
->unpacked_length
= bfd_h_get_32 (abfd
, buf
+ 12);
419 section
->container_length
= bfd_h_get_32 (abfd
, buf
+ 16);
420 section
->container_offset
= bfd_h_get_32 (abfd
, buf
+ 20);
421 section
->section_kind
= buf
[24];
422 section
->share_kind
= buf
[25];
423 section
->alignment
= buf
[26];
424 section
->reserved
= buf
[27];
426 section
->bfd_section
= bfd_pef_make_bfd_section (abfd
, section
);
427 if (section
->bfd_section
== NULL
)
434 bfd_pef_print_loader_header (abfd
, header
, file
)
435 bfd
*abfd ATTRIBUTE_UNUSED
;
436 bfd_pef_loader_header
*header
;
439 fprintf (file
, "main_section: %ld\n", header
->main_section
);
440 fprintf (file
, "main_offset: %lu\n", header
->main_offset
);
441 fprintf (file
, "init_section: %ld\n", header
->init_section
);
442 fprintf (file
, "init_offset: %lu\n", header
->init_offset
);
443 fprintf (file
, "term_section: %ld\n", header
->term_section
);
444 fprintf (file
, "term_offset: %lu\n", header
->term_offset
);
445 fprintf (file
, "imported_library_count: %lu\n",
446 header
->imported_library_count
);
447 fprintf (file
, "total_imported_symbol_count: %lu\n",
448 header
->total_imported_symbol_count
);
449 fprintf (file
, "reloc_section_count: %lu\n", header
->reloc_section_count
);
450 fprintf (file
, "reloc_instr_offset: %lu\n", header
->reloc_instr_offset
);
451 fprintf (file
, "loader_strings_offset: %lu\n",
452 header
->loader_strings_offset
);
453 fprintf (file
, "export_hash_offset: %lu\n", header
->export_hash_offset
);
454 fprintf (file
, "export_hash_table_power: %lu\n",
455 header
->export_hash_table_power
);
456 fprintf (file
, "exported_symbol_count: %lu\n",
457 header
->exported_symbol_count
);
461 bfd_pef_print_loader_section (abfd
, file
)
465 bfd_pef_loader_header header
;
466 asection
*loadersec
= NULL
;
467 unsigned char *loaderbuf
= NULL
;
468 size_t loaderlen
= 0;
471 loadersec
= bfd_get_section_by_name (abfd
, "loader");
472 if (loadersec
== NULL
)
475 loaderlen
= bfd_section_size (abfd
, loadersec
);
476 loaderbuf
= (unsigned char *) bfd_malloc (loaderlen
);
477 if (bfd_seek (abfd
, loadersec
->filepos
, SEEK_SET
) < 0)
482 if (bfd_bread ((PTR
) loaderbuf
, loaderlen
, abfd
) != loaderlen
)
493 ret
= bfd_pef_parse_loader_header (abfd
, loaderbuf
, 56, &header
);
500 bfd_pef_print_loader_header (abfd
, &header
, file
);
505 bfd_pef_scan_start_address (abfd
)
508 bfd_pef_loader_header header
;
511 asection
*loadersec
= NULL
;
512 unsigned char *loaderbuf
= NULL
;
513 size_t loaderlen
= 0;
516 loadersec
= bfd_get_section_by_name (abfd
, "loader");
517 if (loadersec
== NULL
)
520 loaderlen
= bfd_section_size (abfd
, loadersec
);
521 loaderbuf
= (unsigned char *) bfd_malloc (loaderlen
);
522 if (bfd_seek (abfd
, loadersec
->filepos
, SEEK_SET
) < 0)
524 if (bfd_bread ((PTR
) loaderbuf
, loaderlen
, abfd
) != loaderlen
)
529 ret
= bfd_pef_parse_loader_header (abfd
, loaderbuf
, 56, &header
);
533 if (header
.main_section
< 0)
536 for (section
= abfd
->sections
; section
!= NULL
; section
= section
->next
)
537 if ((section
->index
+ 1) == header
.main_section
)
543 abfd
->start_address
= section
->vma
+ header
.main_offset
;
546 if (loaderbuf
!= NULL
)
551 if (loaderbuf
!= NULL
)
557 bfd_pef_scan (abfd
, header
, mdata
)
559 bfd_pef_header
*header
;
560 bfd_pef_data_struct
*mdata
;
563 enum bfd_architecture cputype
;
564 unsigned long cpusubtype
;
566 mdata
->header
= *header
;
568 bfd_pef_convert_architecture (header
->architecture
, &cputype
, &cpusubtype
);
569 if (cputype
== bfd_arch_unknown
)
571 fprintf (stderr
, "bfd_pef_scan: unknown architecture 0x%lx\n",
572 header
->architecture
);
575 bfd_set_arch_mach (abfd
, cputype
, cpusubtype
);
577 mdata
->header
= *header
;
579 abfd
->flags
= (abfd
->xvec
->object_flags
580 | (abfd
->flags
& (BFD_IN_MEMORY
| BFD_IO_FUNCS
)));
582 if (header
->section_count
!= 0)
586 bfd_alloc (abfd
, header
->section_count
* sizeof (bfd_pef_section
)));
588 if (mdata
->sections
== NULL
)
591 for (i
= 0; i
< header
->section_count
; i
++)
593 bfd_pef_section
*cur
= &mdata
->sections
[i
];
594 cur
->header_offset
= 40 + (i
* 28);
595 if (bfd_pef_scan_section (abfd
, cur
) < 0)
600 if (bfd_pef_scan_start_address (abfd
) < 0)
603 fprintf (stderr
, "bfd_pef_scan: unable to scan start address: %s\n",
604 bfd_errmsg (bfd_get_error ()));
609 abfd
->tdata
.pef_data
= mdata
;
615 bfd_pef_read_header (abfd
, header
)
617 bfd_pef_header
*header
;
619 unsigned char buf
[40];
621 bfd_seek (abfd
, 0, SEEK_SET
);
623 if (bfd_bread ((PTR
) buf
, 40, abfd
) != 40)
626 header
->tag1
= bfd_getb32 (buf
);
627 header
->tag2
= bfd_getb32 (buf
+ 4);
628 header
->architecture
= bfd_getb32 (buf
+ 8);
629 header
->format_version
= bfd_getb32 (buf
+ 12);
630 header
->timestamp
= bfd_getb32 (buf
+ 16);
631 header
->old_definition_version
= bfd_getb32 (buf
+ 20);
632 header
->old_implementation_version
= bfd_getb32 (buf
+ 24);
633 header
->current_version
= bfd_getb32 (buf
+ 28);
634 header
->section_count
= bfd_getb32 (buf
+ 32) + 1;
635 header
->instantiated_section_count
= bfd_getb32 (buf
+ 34);
636 header
->reserved
= bfd_getb32 (buf
+ 36);
641 static const bfd_target
*
642 bfd_pef_object_p (abfd
)
645 struct bfd_preserve preserve
;
646 bfd_pef_header header
;
648 preserve
.marker
= NULL
;
649 if (bfd_pef_read_header (abfd
, &header
) != 0)
652 if (header
.tag1
!= BFD_PEF_TAG1
|| header
.tag2
!= BFD_PEF_TAG2
)
655 preserve
.marker
= bfd_zalloc (abfd
, sizeof (bfd_pef_data_struct
));
656 if (preserve
.marker
== NULL
657 || !bfd_preserve_save (abfd
, &preserve
))
660 if (bfd_pef_scan (abfd
, &header
,
661 (bfd_pef_data_struct
*) preserve
.marker
) != 0)
664 bfd_preserve_finish (abfd
, &preserve
);
668 bfd_set_error (bfd_error_wrong_format
);
671 if (preserve
.marker
!= NULL
)
672 bfd_preserve_restore (abfd
, &preserve
);
676 static int bfd_pef_parse_traceback_tables (abfd
, sec
, buf
, len
, nsym
, csym
)
689 const char *const tbprefix
= "__traceback_";
693 unsigned long count
= 0;
698 /* We're reading symbols two at a time. */
699 if (csym
&& ((csym
[count
] == NULL
) || (csym
[count
+ 1] == NULL
)))
705 while ((pos
+ 4) <= len
)
707 if (bfd_getb32 (buf
+ pos
) == 0)
715 ret
= bfd_pef_parse_traceback_table (abfd
, sec
, buf
, len
, pos
+ 4,
719 /* Skip over 0x0L to advance to next possible traceback table. */
724 BFD_ASSERT (function
.name
!= NULL
);
726 /* Don't bother to compute the name if we are just
731 tbnamelen
= strlen (tbprefix
) + strlen (function
.name
);
732 name
= bfd_alloc (abfd
, tbnamelen
+ 1);
735 bfd_release (abfd
, (PTR
) function
.name
);
736 function
.name
= NULL
;
739 snprintf (name
, tbnamelen
+ 1, "%s%s", tbprefix
, function
.name
);
740 traceback
.name
= name
;
741 traceback
.value
= pos
;
742 traceback
.the_bfd
= abfd
;
743 traceback
.section
= sec
;
745 traceback
.udata
.i
= ret
;
747 *(csym
[count
]) = function
;
748 *(csym
[count
+ 1]) = traceback
;
759 static int bfd_pef_parse_function_stub (abfd
, buf
, len
, offset
)
760 bfd
*abfd ATTRIBUTE_UNUSED
;
763 unsigned long *offset
;
765 BFD_ASSERT (len
== 24);
767 if ((bfd_getb32 (buf
) & 0xffff0000) != 0x81820000)
769 if (bfd_getb32 (buf
+ 4) != 0x90410014)
771 if (bfd_getb32 (buf
+ 8) != 0x800c0000)
773 if (bfd_getb32 (buf
+ 12) != 0x804c0004)
775 if (bfd_getb32 (buf
+ 16) != 0x7c0903a6)
777 if (bfd_getb32 (buf
+ 20) != 0x4e800420)
781 *offset
= (bfd_getb32 (buf
) & 0x0000ffff) / 4;
786 static int bfd_pef_parse_function_stubs (abfd
, codesec
, codebuf
, codelen
,
787 loaderbuf
, loaderlen
, nsym
, csym
)
790 unsigned char *codebuf
;
792 unsigned char *loaderbuf
;
797 const char *const sprefix
= "__stub_";
800 unsigned long count
= 0;
802 bfd_pef_loader_header header
;
803 bfd_pef_imported_library
*libraries
= NULL
;
804 bfd_pef_imported_symbol
*imports
= NULL
;
812 ret
= bfd_pef_parse_loader_header (abfd
, loaderbuf
, 56, &header
);
816 libraries
= (bfd_pef_imported_library
*) bfd_malloc
817 (header
.imported_library_count
* sizeof (bfd_pef_imported_library
));
818 imports
= (bfd_pef_imported_symbol
*) bfd_malloc
819 (header
.total_imported_symbol_count
* sizeof (bfd_pef_imported_symbol
));
821 if (loaderlen
< (56 + (header
.imported_library_count
* 24)))
823 for (i
= 0; i
< header
.imported_library_count
; i
++)
825 ret
= bfd_pef_parse_imported_library
826 (abfd
, loaderbuf
+ 56 + (i
* 24), 24, &libraries
[i
]);
831 if (loaderlen
< (56 + (header
.imported_library_count
* 24)
832 + (header
.total_imported_symbol_count
* 4)))
834 for (i
= 0; i
< header
.total_imported_symbol_count
; i
++)
836 ret
= (bfd_pef_parse_imported_symbol
838 loaderbuf
+ 56 + (header
.imported_library_count
* 24) + (i
* 4),
854 if (csym
&& (csym
[count
] == NULL
))
858 codepos
-= (codepos
% 4);
860 while ((codepos
+ 4) <= codelen
)
862 if ((bfd_getb32 (codebuf
+ codepos
) & 0xffff0000) == 0x81820000)
867 if ((codepos
+ 4) > codelen
)
870 ret
= bfd_pef_parse_function_stub (abfd
, codebuf
+ codepos
, 24, &index
);
877 if (index
>= header
.total_imported_symbol_count
)
887 if (loaderlen
< (header
.loader_strings_offset
+ imports
[index
].name
))
890 max
= loaderlen
- (header
.loader_strings_offset
+ imports
[index
].name
);
891 symname
= loaderbuf
+ header
.loader_strings_offset
+ imports
[index
].name
;
893 for (s
= symname
; s
< (symname
+ max
); s
++)
904 name
= bfd_alloc (abfd
, strlen (sprefix
) + namelen
+ 1);
908 snprintf (name
, strlen (sprefix
) + namelen
+ 1, "%s%s",
915 sym
.section
= codesec
;
922 *(csym
[count
]) = sym
;
930 if (libraries
!= NULL
)
938 if (libraries
!= NULL
)
946 static long bfd_pef_parse_symbols (abfd
, csym
)
950 unsigned long count
= 0;
952 asection
*codesec
= NULL
;
953 unsigned char *codebuf
= NULL
;
956 asection
*loadersec
= NULL
;
957 unsigned char *loaderbuf
= NULL
;
958 size_t loaderlen
= 0;
960 codesec
= bfd_get_section_by_name (abfd
, "code");
963 codelen
= bfd_section_size (abfd
, codesec
);
964 codebuf
= (unsigned char *) bfd_malloc (codelen
);
965 if (bfd_seek (abfd
, codesec
->filepos
, SEEK_SET
) < 0)
967 if (bfd_bread ((PTR
) codebuf
, codelen
, abfd
) != codelen
)
971 loadersec
= bfd_get_section_by_name (abfd
, "loader");
972 if (loadersec
!= NULL
)
974 loaderlen
= bfd_section_size (abfd
, loadersec
);
975 loaderbuf
= (unsigned char *) bfd_malloc (loaderlen
);
976 if (bfd_seek (abfd
, loadersec
->filepos
, SEEK_SET
) < 0)
978 if (bfd_bread ((PTR
) loaderbuf
, loaderlen
, abfd
) != loaderlen
)
985 unsigned long ncount
= 0;
986 bfd_pef_parse_traceback_tables (abfd
, codesec
, codebuf
, codelen
,
991 if ((codesec
!= NULL
) && (loadersec
!= NULL
))
993 unsigned long ncount
= 0;
994 bfd_pef_parse_function_stubs
995 (abfd
, codesec
, codebuf
, codelen
, loaderbuf
, loaderlen
, &ncount
,
996 (csym
!= NULL
) ? (csym
+ count
) : NULL
);
1004 if (codebuf
!= NULL
)
1007 if (loaderbuf
!= NULL
)
1014 bfd_pef_count_symbols (abfd
)
1017 return bfd_pef_parse_symbols (abfd
, NULL
);
1021 bfd_pef_get_symtab_upper_bound (abfd
)
1024 long nsyms
= bfd_pef_count_symbols (abfd
);
1027 return ((nsyms
+ 1) * sizeof (asymbol
*));
1031 bfd_pef_canonicalize_symtab (abfd
, alocation
)
1033 asymbol
**alocation
;
1039 long nsyms
= bfd_pef_count_symbols (abfd
);
1043 syms
= bfd_alloc (abfd
, nsyms
* sizeof (asymbol
));
1047 for (i
= 0; i
< nsyms
; i
++)
1048 alocation
[i
] = &syms
[i
];
1050 alocation
[nsyms
] = NULL
;
1052 ret
= bfd_pef_parse_symbols (abfd
, alocation
);
1060 bfd_pef_make_empty_symbol (abfd
)
1063 return (asymbol
*) bfd_alloc (abfd
, sizeof (asymbol
));
1067 bfd_pef_get_symbol_info (abfd
, symbol
, ret
)
1068 bfd
*abfd ATTRIBUTE_UNUSED
;
1072 bfd_symbol_info (symbol
, ret
);
1076 bfd_pef_sizeof_headers (abfd
, exec
)
1077 bfd
*abfd ATTRIBUTE_UNUSED
;
1078 bfd_boolean exec ATTRIBUTE_UNUSED
;
1083 const bfd_target pef_vec
=
1086 bfd_target_pef_flavour
, /* flavour */
1087 BFD_ENDIAN_BIG
, /* byteorder */
1088 BFD_ENDIAN_BIG
, /* header_byteorder */
1089 (HAS_RELOC
| EXEC_P
| /* object flags */
1090 HAS_LINENO
| HAS_DEBUG
|
1091 HAS_SYMS
| HAS_LOCALS
| DYNAMIC
| WP_TEXT
| D_PAGED
),
1092 (SEC_ALLOC
| SEC_LOAD
| SEC_READONLY
| SEC_CODE
| SEC_DATA
1093 | SEC_ROM
| SEC_HAS_CONTENTS
), /* section_flags */
1094 0, /* symbol_leading_char */
1095 ' ', /* ar_pad_char */
1096 16, /* ar_max_namelen */
1097 bfd_getb64
, bfd_getb_signed_64
, bfd_putb64
,
1098 bfd_getb32
, bfd_getb_signed_32
, bfd_putb32
,
1099 bfd_getb16
, bfd_getb_signed_16
, bfd_putb16
, /* data */
1100 bfd_getb64
, bfd_getb_signed_64
, bfd_putb64
,
1101 bfd_getb32
, bfd_getb_signed_32
, bfd_putb32
,
1102 bfd_getb16
, bfd_getb_signed_16
, bfd_putb16
, /* hdrs */
1103 { /* bfd_check_format */
1105 bfd_pef_object_p
, /* bfd_check_format */
1109 { /* bfd_set_format */
1115 { /* bfd_write_contents */
1122 BFD_JUMP_TABLE_GENERIC (bfd_pef
),
1123 BFD_JUMP_TABLE_COPY (_bfd_generic
),
1124 BFD_JUMP_TABLE_CORE (_bfd_nocore
),
1125 BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive
),
1126 BFD_JUMP_TABLE_SYMBOLS (bfd_pef
),
1127 BFD_JUMP_TABLE_RELOCS (bfd_pef
),
1128 BFD_JUMP_TABLE_WRITE (bfd_pef
),
1129 BFD_JUMP_TABLE_LINK (bfd_pef
),
1130 BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic
),
1137 #define bfd_pef_xlib_close_and_cleanup _bfd_generic_close_and_cleanup
1138 #define bfd_pef_xlib_bfd_free_cached_info _bfd_generic_bfd_free_cached_info
1139 #define bfd_pef_xlib_new_section_hook _bfd_generic_new_section_hook
1140 #define bfd_pef_xlib_get_section_contents _bfd_generic_get_section_contents
1141 #define bfd_pef_xlib_set_section_contents _bfd_generic_set_section_contents
1142 #define bfd_pef_xlib_get_section_contents_in_window _bfd_generic_get_section_contents_in_window
1143 #define bfd_pef_xlib_set_section_contents_in_window _bfd_generic_set_section_contents_in_window
1146 bfd_pef_xlib_read_header (abfd
, header
)
1148 bfd_pef_xlib_header
*header
;
1150 unsigned char buf
[76];
1152 bfd_seek (abfd
, 0, SEEK_SET
);
1154 if (bfd_bread ((PTR
) buf
, 76, abfd
) != 76)
1157 header
->tag1
= bfd_getb32 (buf
);
1158 header
->tag2
= bfd_getb32 (buf
+ 4);
1159 header
->current_format
= bfd_getb32 (buf
+ 8);
1160 header
->container_strings_offset
= bfd_getb32 (buf
+ 12);
1161 header
->export_hash_offset
= bfd_getb32 (buf
+ 16);
1162 header
->export_key_offset
= bfd_getb32 (buf
+ 20);
1163 header
->export_symbol_offset
= bfd_getb32 (buf
+ 24);
1164 header
->export_names_offset
= bfd_getb32 (buf
+ 28);
1165 header
->export_hash_table_power
= bfd_getb32 (buf
+ 32);
1166 header
->exported_symbol_count
= bfd_getb32 (buf
+ 36);
1167 header
->frag_name_offset
= bfd_getb32 (buf
+ 40);
1168 header
->frag_name_length
= bfd_getb32 (buf
+ 44);
1169 header
->dylib_path_offset
= bfd_getb32 (buf
+ 48);
1170 header
->dylib_path_length
= bfd_getb32 (buf
+ 52);
1171 header
->cpu_family
= bfd_getb32 (buf
+ 56);
1172 header
->cpu_model
= bfd_getb32 (buf
+ 60);
1173 header
->date_time_stamp
= bfd_getb32 (buf
+ 64);
1174 header
->current_version
= bfd_getb32 (buf
+ 68);
1175 header
->old_definition_version
= bfd_getb32 (buf
+ 72);
1176 header
->old_implementation_version
= bfd_getb32 (buf
+ 76);
1182 bfd_pef_xlib_scan (abfd
, header
)
1184 bfd_pef_xlib_header
*header
;
1186 bfd_pef_xlib_data_struct
*mdata
= NULL
;
1188 mdata
= ((bfd_pef_xlib_data_struct
*)
1189 bfd_alloc (abfd
, sizeof (bfd_pef_xlib_data_struct
)));
1193 mdata
->header
= *header
;
1195 abfd
->flags
= (abfd
->xvec
->object_flags
1196 | (abfd
->flags
& (BFD_IN_MEMORY
| BFD_IO_FUNCS
)));
1198 abfd
->tdata
.pef_xlib_data
= mdata
;
1203 static const bfd_target
*
1204 bfd_pef_xlib_object_p (abfd
)
1207 struct bfd_preserve preserve
;
1208 bfd_pef_xlib_header header
;
1210 if (bfd_pef_xlib_read_header (abfd
, &header
) != 0)
1212 bfd_set_error (bfd_error_wrong_format
);
1216 if ((header
.tag1
!= BFD_PEF_XLIB_TAG1
)
1217 || ((header
.tag2
!= BFD_PEF_VLIB_TAG2
)
1218 && (header
.tag2
!= BFD_PEF_BLIB_TAG2
)))
1220 bfd_set_error (bfd_error_wrong_format
);
1224 if (! bfd_preserve_save (abfd
, &preserve
))
1226 bfd_set_error (bfd_error_wrong_format
);
1230 if (bfd_pef_xlib_scan (abfd
, &header
) != 0)
1232 bfd_preserve_restore (abfd
, &preserve
);
1233 bfd_set_error (bfd_error_wrong_format
);
1237 bfd_preserve_finish (abfd
, &preserve
);
1241 const bfd_target pef_xlib_vec
=
1243 "pef-xlib", /* name */
1244 bfd_target_pef_xlib_flavour
, /* flavour */
1245 BFD_ENDIAN_BIG
, /* byteorder */
1246 BFD_ENDIAN_BIG
, /* header_byteorder */
1247 (HAS_RELOC
| EXEC_P
| /* object flags */
1248 HAS_LINENO
| HAS_DEBUG
|
1249 HAS_SYMS
| HAS_LOCALS
| DYNAMIC
| WP_TEXT
| D_PAGED
),
1250 (SEC_ALLOC
| SEC_LOAD
| SEC_READONLY
| SEC_CODE
| SEC_DATA
1251 | SEC_ROM
| SEC_HAS_CONTENTS
), /* section_flags */
1252 0, /* symbol_leading_char */
1253 ' ', /* ar_pad_char */
1254 16, /* ar_max_namelen */
1255 bfd_getb64
, bfd_getb_signed_64
, bfd_putb64
,
1256 bfd_getb32
, bfd_getb_signed_32
, bfd_putb32
,
1257 bfd_getb16
, bfd_getb_signed_16
, bfd_putb16
, /* data */
1258 bfd_getb64
, bfd_getb_signed_64
, bfd_putb64
,
1259 bfd_getb32
, bfd_getb_signed_32
, bfd_putb32
,
1260 bfd_getb16
, bfd_getb_signed_16
, bfd_putb16
, /* hdrs */
1261 { /* bfd_check_format */
1263 bfd_pef_xlib_object_p
, /* bfd_check_format */
1267 { /* bfd_set_format */
1273 { /* bfd_write_contents */
1280 BFD_JUMP_TABLE_GENERIC (bfd_pef_xlib
),
1281 BFD_JUMP_TABLE_COPY (_bfd_generic
),
1282 BFD_JUMP_TABLE_CORE (_bfd_nocore
),
1283 BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive
),
1284 BFD_JUMP_TABLE_SYMBOLS (_bfd_nosymbols
),
1285 BFD_JUMP_TABLE_RELOCS (_bfd_norelocs
),
1286 BFD_JUMP_TABLE_WRITE (_bfd_nowrite
),
1287 BFD_JUMP_TABLE_LINK (_bfd_nolink
),
1288 BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic
),