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