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