Home | History | Annotate | Line # | Download | only in bfd
i386lynx.c revision 1.1.1.2
      1 /* BFD back-end for i386 a.out binaries under LynxOS.
      2    Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1999, 2001, 2002,
      3    2003, 2005, 2007, 2009, 2010 Free Software Foundation, Inc.
      4 
      5    This file is part of BFD, the Binary File Descriptor library.
      6 
      7    This program is free software; you can redistribute it and/or modify
      8    it under the terms of the GNU General Public License as published by
      9    the Free Software Foundation; either version 3 of the License, or
     10    (at your option) any later version.
     11 
     12    This program is distributed in the hope that it will be useful,
     13    but WITHOUT ANY WARRANTY; without even the implied warranty of
     14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15    GNU General Public License for more details.
     16 
     17    You should have received a copy of the GNU General Public License
     18    along with this program; if not, write to the Free Software
     19    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
     20    MA 02110-1301, USA.  */
     21 
     22 #define TEXT_START_ADDR 0
     23 #define TARGET_PAGE_SIZE 4096
     24 #define SEGMENT_SIZE TARGET_PAGE_SIZE
     25 #define DEFAULT_ARCH bfd_arch_i386
     26 
     27 /* Do not "beautify" the CONCAT* macro args.  Traditional C will not
     28    remove whitespace added here, and thus will fail to concatenate
     29    the tokens.  */
     30 #define MY(OP) CONCAT2 (i386lynx_aout_,OP)
     31 #define TARGETNAME "a.out-i386-lynx"
     32 
     33 #include "sysdep.h"
     34 #include "bfd.h"
     35 #include "libbfd.h"
     36 
     37 #ifndef WRITE_HEADERS
     38 #define WRITE_HEADERS(abfd, execp)					      \
     39       {									      \
     40 	bfd_size_type text_size; /* dummy vars */			      \
     41 	file_ptr text_end;						      \
     42 	if (adata(abfd).magic == undecided_magic)			      \
     43 	  NAME(aout,adjust_sizes_and_vmas) (abfd, &text_size, &text_end);     \
     44     									      \
     45 	execp->a_syms = bfd_get_symcount (abfd) * EXTERNAL_NLIST_SIZE;	      \
     46 	execp->a_entry = bfd_get_start_address (abfd);			      \
     47     									      \
     48 	execp->a_trsize = ((obj_textsec (abfd)->reloc_count) *		      \
     49 			   obj_reloc_entry_size (abfd));		      \
     50 	execp->a_drsize = ((obj_datasec (abfd)->reloc_count) *		      \
     51 			   obj_reloc_entry_size (abfd));		      \
     52 	NAME(aout,swap_exec_header_out) (abfd, execp, &exec_bytes);	      \
     53 									      \
     54 	if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0		      \
     55 	    || bfd_bwrite ((PTR) &exec_bytes, (bfd_size_type) EXEC_BYTES_SIZE, \
     56 			  abfd) != EXEC_BYTES_SIZE)			      \
     57 	  return FALSE;							      \
     58 	/* Now write out reloc info, followed by syms and strings */	      \
     59   									      \
     60 	if (bfd_get_symcount (abfd) != 0) 				      \
     61 	    {								      \
     62 	      if (bfd_seek (abfd, (file_ptr) (N_SYMOFF(*execp)), SEEK_SET)    \
     63 		  != 0)							      \
     64 	        return FALSE;						      \
     65 									      \
     66 	      if (! NAME(aout,write_syms) (abfd)) return FALSE;		      \
     67 									      \
     68 	      if (bfd_seek (abfd, (file_ptr) (N_TRELOFF(*execp)), SEEK_SET)   \
     69 		  != 0)							      \
     70 	        return FALSE;						      \
     71 									      \
     72 	      if (!NAME(lynx,squirt_out_relocs) (abfd, obj_textsec (abfd)))   \
     73 		return FALSE;						      \
     74 	      if (bfd_seek (abfd, (file_ptr) (N_DRELOFF(*execp)), SEEK_SET)   \
     75 		  != 0)							      \
     76 	        return 0;						      \
     77 									      \
     78 	      if (!NAME(lynx,squirt_out_relocs) (abfd, obj_datasec (abfd)))   \
     79 		return FALSE;						      \
     80 	    }								      \
     81       }
     82 #endif
     83 
     84 #include "libaout.h"
     85 #include "aout/aout64.h"
     86 
     87 void NAME (lynx,swap_std_reloc_out)
     88   PARAMS ((bfd *, arelent *, struct reloc_std_external *));
     89 void NAME (lynx,swap_ext_reloc_out)
     90   PARAMS ((bfd *, arelent *, struct reloc_ext_external *));
     91 void NAME (lynx,swap_ext_reloc_in)
     92   PARAMS ((bfd *, struct reloc_ext_external *, arelent *, asymbol **,
     93 	   bfd_size_type));
     94 void NAME (lynx,swap_std_reloc_in)
     95   PARAMS ((bfd *, struct reloc_std_external *, arelent *, asymbol **,
     96 	   bfd_size_type));
     97 bfd_boolean NAME (lynx,slurp_reloc_table)
     98   PARAMS ((bfd *, sec_ptr, asymbol **));
     99 bfd_boolean NAME (lynx,squirt_out_relocs)
    100   PARAMS ((bfd *, asection *));
    101 long NAME (lynx,canonicalize_reloc)
    102   PARAMS ((bfd *, sec_ptr, arelent **, asymbol **));
    103 
    104 #ifdef LYNX_CORE
    105 
    106 char *lynx_core_file_failing_command ();
    107 int lynx_core_file_failing_signal ();
    108 bfd_boolean lynx_core_file_matches_executable_p ();
    109 const bfd_target *lynx_core_file_p ();
    110 
    111 #define	MY_core_file_failing_command lynx_core_file_failing_command
    112 #define	MY_core_file_failing_signal lynx_core_file_failing_signal
    113 #define	MY_core_file_matches_executable_p lynx_core_file_matches_executable_p
    114 #define	MY_core_file_p lynx_core_file_p
    115 
    116 #endif /* LYNX_CORE */
    117 
    118 
    120 #define KEEPIT udata.i
    121 
    122 extern reloc_howto_type aout_32_ext_howto_table[];
    123 extern reloc_howto_type aout_32_std_howto_table[];
    124 
    125 /* Standard reloc stuff */
    126 /* Output standard relocation information to a file in target byte order. */
    127 
    128 void
    129 NAME(lynx,swap_std_reloc_out) (abfd, g, natptr)
    130      bfd *abfd;
    131      arelent *g;
    132      struct reloc_std_external *natptr;
    133 {
    134   int r_index;
    135   asymbol *sym = *(g->sym_ptr_ptr);
    136   int r_extern;
    137   unsigned int r_length;
    138   int r_pcrel;
    139   int r_baserel, r_jmptable, r_relative;
    140   asection *output_section = sym->section->output_section;
    141 
    142   PUT_WORD (abfd, g->address, natptr->r_address);
    143 
    144   r_length = g->howto->size;	/* Size as a power of two */
    145   r_pcrel = (int) g->howto->pc_relative;	/* Relative to PC? */
    146   /* r_baserel, r_jmptable, r_relative???  FIXME-soon */
    147   r_baserel = 0;
    148   r_jmptable = 0;
    149   r_relative = 0;
    150 
    151   /* name was clobbered by aout_write_syms to be symbol index */
    152 
    153   /* If this relocation is relative to a symbol then set the
    154      r_index to the symbols index, and the r_extern bit.
    155 
    156      Absolute symbols can come in in two ways, either as an offset
    157      from the abs section, or as a symbol which has an abs value.
    158      check for that here
    159   */
    160 
    161 
    162   if (bfd_is_com_section (output_section)
    163       || bfd_is_abs_section (output_section)
    164       || bfd_is_und_section (output_section))
    165     {
    166       if (bfd_abs_section_ptr->symbol == sym)
    167 	{
    168 	  /* Whoops, looked like an abs symbol, but is really an offset
    169 	     from the abs section */
    170 	  r_index = 0;
    171 	  r_extern = 0;
    172 	}
    173       else
    174 	{
    175 	  /* Fill in symbol */
    176 	  r_extern = 1;
    177 	  r_index = (*g->sym_ptr_ptr)->KEEPIT;
    178 	}
    179     }
    180   else
    181     {
    182       /* Just an ordinary section */
    183       r_extern = 0;
    184       r_index = output_section->target_index;
    185     }
    186 
    187   /* now the fun stuff */
    188   if (bfd_header_big_endian (abfd))
    189     {
    190       natptr->r_index[0] = r_index >> 16;
    191       natptr->r_index[1] = r_index >> 8;
    192       natptr->r_index[2] = r_index;
    193       natptr->r_type[0] =
    194 	(r_extern ? RELOC_STD_BITS_EXTERN_BIG : 0)
    195 	| (r_pcrel ? RELOC_STD_BITS_PCREL_BIG : 0)
    196 	| (r_baserel ? RELOC_STD_BITS_BASEREL_BIG : 0)
    197 	| (r_jmptable ? RELOC_STD_BITS_JMPTABLE_BIG : 0)
    198 	| (r_relative ? RELOC_STD_BITS_RELATIVE_BIG : 0)
    199 	| (r_length << RELOC_STD_BITS_LENGTH_SH_BIG);
    200     }
    201   else
    202     {
    203       natptr->r_index[2] = r_index >> 16;
    204       natptr->r_index[1] = r_index >> 8;
    205       natptr->r_index[0] = r_index;
    206       natptr->r_type[0] =
    207 	(r_extern ? RELOC_STD_BITS_EXTERN_LITTLE : 0)
    208 	| (r_pcrel ? RELOC_STD_BITS_PCREL_LITTLE : 0)
    209 	| (r_baserel ? RELOC_STD_BITS_BASEREL_LITTLE : 0)
    210 	| (r_jmptable ? RELOC_STD_BITS_JMPTABLE_LITTLE : 0)
    211 	| (r_relative ? RELOC_STD_BITS_RELATIVE_LITTLE : 0)
    212 	| (r_length << RELOC_STD_BITS_LENGTH_SH_LITTLE);
    213     }
    214 }
    215 
    216 
    217 /* Extended stuff */
    218 /* Output extended relocation information to a file in target byte order. */
    219 
    220 void
    221 NAME(lynx,swap_ext_reloc_out) (abfd, g, natptr)
    222      bfd *abfd;
    223      arelent *g;
    224      register struct reloc_ext_external *natptr;
    225 {
    226   int r_index;
    227   int r_extern;
    228   unsigned int r_type;
    229   unsigned int r_addend;
    230   asymbol *sym = *(g->sym_ptr_ptr);
    231   asection *output_section = sym->section->output_section;
    232 
    233   PUT_WORD (abfd, g->address, natptr->r_address);
    234 
    235   r_type = (unsigned int) g->howto->type;
    236 
    237   r_addend = g->addend + (*(g->sym_ptr_ptr))->section->output_section->vma;
    238 
    239 
    240   /* If this relocation is relative to a symbol then set the
    241      r_index to the symbols index, and the r_extern bit.
    242 
    243      Absolute symbols can come in in two ways, either as an offset
    244      from the abs section, or as a symbol which has an abs value.
    245      check for that here
    246      */
    247 
    248   if (bfd_is_com_section (output_section)
    249       || bfd_is_abs_section (output_section)
    250       || bfd_is_und_section (output_section))
    251     {
    252       if (bfd_abs_section_ptr->symbol == sym)
    253 	{
    254 	  /* Whoops, looked like an abs symbol, but is really an offset
    255 	 from the abs section */
    256 	  r_index = 0;
    257 	  r_extern = 0;
    258 	}
    259       else
    260 	{
    261 	  r_extern = 1;
    262 	  r_index = (*g->sym_ptr_ptr)->KEEPIT;
    263 	}
    264     }
    265   else
    266     {
    267       /* Just an ordinary section */
    268       r_extern = 0;
    269       r_index = output_section->target_index;
    270     }
    271 
    272 
    273   /* now the fun stuff */
    274   if (bfd_header_big_endian (abfd))
    275     {
    276       natptr->r_index[0] = r_index >> 16;
    277       natptr->r_index[1] = r_index >> 8;
    278       natptr->r_index[2] = r_index;
    279       natptr->r_type[0] =
    280 	(r_extern ? RELOC_EXT_BITS_EXTERN_BIG : 0)
    281 	| (r_type << RELOC_EXT_BITS_TYPE_SH_BIG);
    282     }
    283   else
    284     {
    285       natptr->r_index[2] = r_index >> 16;
    286       natptr->r_index[1] = r_index >> 8;
    287       natptr->r_index[0] = r_index;
    288       natptr->r_type[0] =
    289 	(r_extern ? RELOC_EXT_BITS_EXTERN_LITTLE : 0)
    290 	| (r_type << RELOC_EXT_BITS_TYPE_SH_LITTLE);
    291     }
    292 
    293   PUT_WORD (abfd, r_addend, natptr->r_addend);
    294 }
    295 
    296 /* BFD deals internally with all things based from the section they're
    297    in. so, something in 10 bytes into a text section  with a base of
    298    50 would have a symbol (.text+10) and know .text vma was 50.
    299 
    300    Aout keeps all it's symbols based from zero, so the symbol would
    301    contain 60. This macro subs the base of each section from the value
    302    to give the true offset from the section */
    303 
    304 
    305 #define MOVE_ADDRESS(ad)       						\
    306   if (r_extern) {							\
    307    /* undefined symbol */						\
    308      cache_ptr->sym_ptr_ptr = symbols + r_index;			\
    309      cache_ptr->addend = ad;						\
    310      } else {								\
    311     /* defined, section relative. replace symbol with pointer to    	\
    312        symbol which points to section  */				\
    313     switch (r_index) {							\
    314     case N_TEXT:							\
    315     case N_TEXT | N_EXT:						\
    316       cache_ptr->sym_ptr_ptr  = obj_textsec(abfd)->symbol_ptr_ptr;	\
    317       cache_ptr->addend = ad  - su->textsec->vma;			\
    318       break;								\
    319     case N_DATA:							\
    320     case N_DATA | N_EXT:						\
    321       cache_ptr->sym_ptr_ptr  = obj_datasec(abfd)->symbol_ptr_ptr;	\
    322       cache_ptr->addend = ad - su->datasec->vma;			\
    323       break;								\
    324     case N_BSS:								\
    325     case N_BSS | N_EXT:							\
    326       cache_ptr->sym_ptr_ptr  = obj_bsssec(abfd)->symbol_ptr_ptr;	\
    327       cache_ptr->addend = ad - su->bsssec->vma;				\
    328       break;								\
    329     default:								\
    330     case N_ABS:								\
    331     case N_ABS | N_EXT:							\
    332      cache_ptr->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;	\
    333       cache_ptr->addend = ad;						\
    334       break;								\
    335     }									\
    336   }     								\
    337 
    338 void
    339 NAME(lynx,swap_ext_reloc_in) (abfd, bytes, cache_ptr, symbols, symcount)
    340      bfd *abfd;
    341      struct reloc_ext_external *bytes;
    342      arelent *cache_ptr;
    343      asymbol **symbols;
    344      bfd_size_type symcount ATTRIBUTE_UNUSED;
    345 {
    346   int r_index;
    347   int r_extern;
    348   unsigned int r_type;
    349   struct aoutdata *su = &(abfd->tdata.aout_data->a);
    350 
    351   cache_ptr->address = (GET_SWORD (abfd, bytes->r_address));
    352 
    353   r_index = bytes->r_index[1];
    354   r_extern = (0 != (bytes->r_index[0] & RELOC_EXT_BITS_EXTERN_BIG));
    355   r_type = (bytes->r_index[0] & RELOC_EXT_BITS_TYPE_BIG)
    356     >> RELOC_EXT_BITS_TYPE_SH_BIG;
    357 
    358   cache_ptr->howto = aout_32_ext_howto_table + r_type;
    359   MOVE_ADDRESS (GET_SWORD (abfd, bytes->r_addend));
    360 }
    361 
    362 void
    363 NAME(lynx,swap_std_reloc_in) (abfd, bytes, cache_ptr, symbols, symcount)
    364      bfd *abfd;
    365      struct reloc_std_external *bytes;
    366      arelent *cache_ptr;
    367      asymbol **symbols;
    368      bfd_size_type symcount ATTRIBUTE_UNUSED;
    369 {
    370   int r_index;
    371   int r_extern;
    372   unsigned int r_length;
    373   int r_pcrel;
    374   struct aoutdata *su = &(abfd->tdata.aout_data->a);
    375 
    376   cache_ptr->address = H_GET_32 (abfd, bytes->r_address);
    377 
    378   r_index = bytes->r_index[1];
    379   r_extern = (0 != (bytes->r_index[0] & RELOC_STD_BITS_EXTERN_BIG));
    380   r_pcrel = (0 != (bytes->r_index[0] & RELOC_STD_BITS_PCREL_BIG));
    381   r_length = (bytes->r_index[0] & RELOC_STD_BITS_LENGTH_BIG)
    382     >> RELOC_STD_BITS_LENGTH_SH_BIG;
    383 
    384   cache_ptr->howto = aout_32_std_howto_table + r_length + 4 * r_pcrel;
    385   /* FIXME-soon:  Roll baserel, jmptable, relative bits into howto setting */
    386 
    387   MOVE_ADDRESS (0);
    388 }
    389 
    390 /* Reloc hackery */
    391 
    392 bfd_boolean
    393 NAME(lynx,slurp_reloc_table) (abfd, asect, symbols)
    394      bfd *abfd;
    395      sec_ptr asect;
    396      asymbol **symbols;
    397 {
    398   bfd_size_type count;
    399   bfd_size_type reloc_size;
    400   PTR relocs;
    401   arelent *reloc_cache;
    402   size_t each_size;
    403 
    404   if (asect->relocation)
    405     return TRUE;
    406 
    407   if (asect->flags & SEC_CONSTRUCTOR)
    408     return TRUE;
    409 
    410   if (asect == obj_datasec (abfd))
    411     {
    412       reloc_size = exec_hdr (abfd)->a_drsize;
    413       goto doit;
    414     }
    415 
    416   if (asect == obj_textsec (abfd))
    417     {
    418       reloc_size = exec_hdr (abfd)->a_trsize;
    419       goto doit;
    420     }
    421 
    422   bfd_set_error (bfd_error_invalid_operation);
    423   return FALSE;
    424 
    425 doit:
    426   if (bfd_seek (abfd, asect->rel_filepos, SEEK_SET) != 0)
    427     return FALSE;
    428   each_size = obj_reloc_entry_size (abfd);
    429 
    430   count = reloc_size / each_size;
    431 
    432 
    433   reloc_cache = (arelent *) bfd_zmalloc (count * sizeof (arelent));
    434   if (!reloc_cache && count != 0)
    435     return FALSE;
    436 
    437   relocs = (PTR) bfd_alloc (abfd, reloc_size);
    438   if (!relocs && reloc_size != 0)
    439     {
    440       free (reloc_cache);
    441       return FALSE;
    442     }
    443 
    444   if (bfd_bread (relocs, reloc_size, abfd) != reloc_size)
    445     {
    446       bfd_release (abfd, relocs);
    447       free (reloc_cache);
    448       return FALSE;
    449     }
    450 
    451   if (each_size == RELOC_EXT_SIZE)
    452     {
    453       register struct reloc_ext_external *rptr = (struct reloc_ext_external *) relocs;
    454       unsigned int counter = 0;
    455       arelent *cache_ptr = reloc_cache;
    456 
    457       for (; counter < count; counter++, rptr++, cache_ptr++)
    458 	{
    459 	  NAME(lynx,swap_ext_reloc_in) (abfd, rptr, cache_ptr, symbols,
    460 					(bfd_size_type) bfd_get_symcount (abfd));
    461 	}
    462     }
    463   else
    464     {
    465       register struct reloc_std_external *rptr = (struct reloc_std_external *) relocs;
    466       unsigned int counter = 0;
    467       arelent *cache_ptr = reloc_cache;
    468 
    469       for (; counter < count; counter++, rptr++, cache_ptr++)
    470 	{
    471 	  NAME(lynx,swap_std_reloc_in) (abfd, rptr, cache_ptr, symbols,
    472 					(bfd_size_type) bfd_get_symcount (abfd));
    473 	}
    474 
    475     }
    476 
    477   bfd_release (abfd, relocs);
    478   asect->relocation = reloc_cache;
    479   asect->reloc_count = count;
    480   return TRUE;
    481 }
    482 
    483 
    484 
    485 /* Write out a relocation section into an object file.  */
    486 
    487 bfd_boolean
    488 NAME(lynx,squirt_out_relocs) (abfd, section)
    489      bfd *abfd;
    490      asection *section;
    491 {
    492   arelent **generic;
    493   unsigned char *native, *natptr;
    494   size_t each_size;
    495 
    496   unsigned int count = section->reloc_count;
    497   bfd_size_type natsize;
    498 
    499   if (count == 0)
    500     return TRUE;
    501 
    502   each_size = obj_reloc_entry_size (abfd);
    503   natsize = count;
    504   natsize *= each_size;
    505   native = (unsigned char *) bfd_zalloc (abfd, natsize);
    506   if (!native)
    507     return FALSE;
    508 
    509   generic = section->orelocation;
    510 
    511   if (each_size == RELOC_EXT_SIZE)
    512     {
    513       for (natptr = native;
    514 	   count != 0;
    515 	   --count, natptr += each_size, ++generic)
    516 	NAME(lynx,swap_ext_reloc_out) (abfd, *generic, (struct reloc_ext_external *) natptr);
    517     }
    518   else
    519     {
    520       for (natptr = native;
    521 	   count != 0;
    522 	   --count, natptr += each_size, ++generic)
    523 	NAME(lynx,swap_std_reloc_out) (abfd, *generic, (struct reloc_std_external *) natptr);
    524     }
    525 
    526   if (bfd_bwrite ((PTR) native, natsize, abfd) != natsize)
    527     {
    528       bfd_release (abfd, native);
    529       return FALSE;
    530     }
    531   bfd_release (abfd, native);
    532 
    533   return TRUE;
    534 }
    535 
    536 /* This is stupid.  This function should be a boolean predicate */
    537 long
    538 NAME(lynx,canonicalize_reloc) (abfd, section, relptr, symbols)
    539      bfd *abfd;
    540      sec_ptr section;
    541      arelent **relptr;
    542      asymbol **symbols;
    543 {
    544   arelent *tblptr = section->relocation;
    545   unsigned int count;
    546 
    547   if (!(tblptr || NAME(lynx,slurp_reloc_table) (abfd, section, symbols)))
    548     return -1;
    549 
    550   if (section->flags & SEC_CONSTRUCTOR)
    551     {
    552       arelent_chain *chain = section->constructor_chain;
    553       for (count = 0; count < section->reloc_count; count++)
    554 	{
    555 	  *relptr++ = &chain->relent;
    556 	  chain = chain->next;
    557 	}
    558     }
    559   else
    560     {
    561       tblptr = section->relocation;
    562 
    563       for (count = 0; count++ < section->reloc_count;)
    564 	{
    565 	  *relptr++ = tblptr++;
    566 	}
    567     }
    568   *relptr = 0;
    569 
    570   return section->reloc_count;
    571 }
    572 
    573 #define MY_canonicalize_reloc NAME(lynx,canonicalize_reloc)
    574 
    575 #include "aout-target.h"
    576