Home | History | Annotate | Line # | Download | only in bfd
i386lynx.c revision 1.1.1.1
      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, 2012  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 (&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 
     88 #ifdef LYNX_CORE
     89 
     90 char *lynx_core_file_failing_command ();
     91 int lynx_core_file_failing_signal ();
     92 bfd_boolean lynx_core_file_matches_executable_p ();
     93 const bfd_target *lynx_core_file_p ();
     94 
     95 #define	MY_core_file_failing_command lynx_core_file_failing_command
     96 #define	MY_core_file_failing_signal lynx_core_file_failing_signal
     97 #define	MY_core_file_matches_executable_p lynx_core_file_matches_executable_p
     98 #define	MY_core_file_p lynx_core_file_p
     99 
    100 #endif /* LYNX_CORE */
    101 
    102 
    104 #define KEEPIT udata.i
    105 
    106 extern reloc_howto_type aout_32_ext_howto_table[];
    107 extern reloc_howto_type aout_32_std_howto_table[];
    108 
    109 /* Standard reloc stuff */
    110 /* Output standard relocation information to a file in target byte order. */
    111 
    112 static void
    113 NAME(lynx,swap_std_reloc_out) (bfd *abfd,
    114 			       arelent *g,
    115 			       struct reloc_std_external *natptr)
    116 {
    117   int r_index;
    118   asymbol *sym = *(g->sym_ptr_ptr);
    119   int r_extern;
    120   unsigned int r_length;
    121   int r_pcrel;
    122   int r_baserel, r_jmptable, r_relative;
    123   asection *output_section = sym->section->output_section;
    124 
    125   PUT_WORD (abfd, g->address, natptr->r_address);
    126 
    127   r_length = g->howto->size;	/* Size as a power of two */
    128   r_pcrel = (int) g->howto->pc_relative;	/* Relative to PC? */
    129   /* r_baserel, r_jmptable, r_relative???  FIXME-soon */
    130   r_baserel = 0;
    131   r_jmptable = 0;
    132   r_relative = 0;
    133 
    134   /* name was clobbered by aout_write_syms to be symbol index */
    135 
    136   /* If this relocation is relative to a symbol then set the
    137      r_index to the symbols index, and the r_extern bit.
    138 
    139      Absolute symbols can come in in two ways, either as an offset
    140      from the abs section, or as a symbol which has an abs value.
    141      check for that here
    142   */
    143 
    144   if (bfd_is_com_section (output_section)
    145       || bfd_is_abs_section (output_section)
    146       || bfd_is_und_section (output_section))
    147     {
    148       if (bfd_abs_section_ptr->symbol == sym)
    149 	{
    150 	  /* Whoops, looked like an abs symbol, but is really an offset
    151 	     from the abs section */
    152 	  r_index = 0;
    153 	  r_extern = 0;
    154 	}
    155       else
    156 	{
    157 	  /* Fill in symbol */
    158 	  r_extern = 1;
    159 	  r_index = (*g->sym_ptr_ptr)->KEEPIT;
    160 	}
    161     }
    162   else
    163     {
    164       /* Just an ordinary section */
    165       r_extern = 0;
    166       r_index = output_section->target_index;
    167     }
    168 
    169   /* now the fun stuff */
    170   if (bfd_header_big_endian (abfd))
    171     {
    172       natptr->r_index[0] = r_index >> 16;
    173       natptr->r_index[1] = r_index >> 8;
    174       natptr->r_index[2] = r_index;
    175       natptr->r_type[0] =
    176 	(r_extern ? RELOC_STD_BITS_EXTERN_BIG : 0)
    177 	| (r_pcrel ? RELOC_STD_BITS_PCREL_BIG : 0)
    178 	| (r_baserel ? RELOC_STD_BITS_BASEREL_BIG : 0)
    179 	| (r_jmptable ? RELOC_STD_BITS_JMPTABLE_BIG : 0)
    180 	| (r_relative ? RELOC_STD_BITS_RELATIVE_BIG : 0)
    181 	| (r_length << RELOC_STD_BITS_LENGTH_SH_BIG);
    182     }
    183   else
    184     {
    185       natptr->r_index[2] = r_index >> 16;
    186       natptr->r_index[1] = r_index >> 8;
    187       natptr->r_index[0] = r_index;
    188       natptr->r_type[0] =
    189 	(r_extern ? RELOC_STD_BITS_EXTERN_LITTLE : 0)
    190 	| (r_pcrel ? RELOC_STD_BITS_PCREL_LITTLE : 0)
    191 	| (r_baserel ? RELOC_STD_BITS_BASEREL_LITTLE : 0)
    192 	| (r_jmptable ? RELOC_STD_BITS_JMPTABLE_LITTLE : 0)
    193 	| (r_relative ? RELOC_STD_BITS_RELATIVE_LITTLE : 0)
    194 	| (r_length << RELOC_STD_BITS_LENGTH_SH_LITTLE);
    195     }
    196 }
    197 
    198 
    199 /* Extended stuff */
    200 /* Output extended relocation information to a file in target byte order. */
    201 
    202 static void
    203 NAME(lynx,swap_ext_reloc_out) (bfd *abfd,
    204 			       arelent *g,
    205 			       struct reloc_ext_external *natptr)
    206 {
    207   int r_index;
    208   int r_extern;
    209   unsigned int r_type;
    210   unsigned int r_addend;
    211   asymbol *sym = *(g->sym_ptr_ptr);
    212   asection *output_section = sym->section->output_section;
    213 
    214   PUT_WORD (abfd, g->address, natptr->r_address);
    215 
    216   r_type = (unsigned int) g->howto->type;
    217 
    218   r_addend = g->addend + (*(g->sym_ptr_ptr))->section->output_section->vma;
    219 
    220 
    221   /* If this relocation is relative to a symbol then set the
    222      r_index to the symbols index, and the r_extern bit.
    223 
    224      Absolute symbols can come in in two ways, either as an offset
    225      from the abs section, or as a symbol which has an abs value.
    226      check for that here
    227      */
    228 
    229   if (bfd_is_com_section (output_section)
    230       || bfd_is_abs_section (output_section)
    231       || bfd_is_und_section (output_section))
    232     {
    233       if (bfd_abs_section_ptr->symbol == sym)
    234 	{
    235 	  /* Whoops, looked like an abs symbol, but is really an offset
    236 	 from the abs section */
    237 	  r_index = 0;
    238 	  r_extern = 0;
    239 	}
    240       else
    241 	{
    242 	  r_extern = 1;
    243 	  r_index = (*g->sym_ptr_ptr)->KEEPIT;
    244 	}
    245     }
    246   else
    247     {
    248       /* Just an ordinary section */
    249       r_extern = 0;
    250       r_index = output_section->target_index;
    251     }
    252 
    253 
    254   /* now the fun stuff */
    255   if (bfd_header_big_endian (abfd))
    256     {
    257       natptr->r_index[0] = r_index >> 16;
    258       natptr->r_index[1] = r_index >> 8;
    259       natptr->r_index[2] = r_index;
    260       natptr->r_type[0] =
    261 	(r_extern ? RELOC_EXT_BITS_EXTERN_BIG : 0)
    262 	| (r_type << RELOC_EXT_BITS_TYPE_SH_BIG);
    263     }
    264   else
    265     {
    266       natptr->r_index[2] = r_index >> 16;
    267       natptr->r_index[1] = r_index >> 8;
    268       natptr->r_index[0] = r_index;
    269       natptr->r_type[0] =
    270 	(r_extern ? RELOC_EXT_BITS_EXTERN_LITTLE : 0)
    271 	| (r_type << RELOC_EXT_BITS_TYPE_SH_LITTLE);
    272     }
    273 
    274   PUT_WORD (abfd, r_addend, natptr->r_addend);
    275 }
    276 
    277 /* BFD deals internally with all things based from the section they're
    278    in. so, something in 10 bytes into a text section  with a base of
    279    50 would have a symbol (.text+10) and know .text vma was 50.
    280 
    281    Aout keeps all it's symbols based from zero, so the symbol would
    282    contain 60. This macro subs the base of each section from the value
    283    to give the true offset from the section */
    284 
    285 
    286 #define MOVE_ADDRESS(ad)       						\
    287   if (r_extern)								\
    288     {									\
    289    /* undefined symbol */						\
    290      cache_ptr->sym_ptr_ptr = symbols + r_index;			\
    291      cache_ptr->addend = ad;						\
    292     }									\
    293   else									\
    294     {									\
    295     /* defined, section relative. replace symbol with pointer to    	\
    296        symbol which points to section  */				\
    297     switch (r_index) {							\
    298     case N_TEXT:							\
    299     case N_TEXT | N_EXT:						\
    300       cache_ptr->sym_ptr_ptr  = obj_textsec(abfd)->symbol_ptr_ptr;	\
    301       cache_ptr->addend = ad  - su->textsec->vma;			\
    302       break;								\
    303     case N_DATA:							\
    304     case N_DATA | N_EXT:						\
    305       cache_ptr->sym_ptr_ptr  = obj_datasec(abfd)->symbol_ptr_ptr;	\
    306       cache_ptr->addend = ad - su->datasec->vma;			\
    307       break;								\
    308     case N_BSS:								\
    309     case N_BSS | N_EXT:							\
    310       cache_ptr->sym_ptr_ptr  = obj_bsssec(abfd)->symbol_ptr_ptr;	\
    311       cache_ptr->addend = ad - su->bsssec->vma;				\
    312       break;								\
    313     default:								\
    314     case N_ABS:								\
    315     case N_ABS | N_EXT:							\
    316      cache_ptr->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;	\
    317       cache_ptr->addend = ad;						\
    318       break;								\
    319     }									\
    320   }     								\
    321 
    322 static void
    323 NAME(lynx,swap_ext_reloc_in) (bfd *abfd,
    324 			      struct reloc_ext_external *bytes,
    325 			      arelent *cache_ptr,
    326 			      asymbol **symbols,
    327 			      bfd_size_type symcount ATTRIBUTE_UNUSED)
    328 {
    329   int r_index;
    330   int r_extern;
    331   unsigned int r_type;
    332   struct aoutdata *su = &(abfd->tdata.aout_data->a);
    333 
    334   cache_ptr->address = (GET_SWORD (abfd, bytes->r_address));
    335 
    336   r_index = bytes->r_index[1];
    337   r_extern = (0 != (bytes->r_index[0] & RELOC_EXT_BITS_EXTERN_BIG));
    338   r_type = (bytes->r_index[0] & RELOC_EXT_BITS_TYPE_BIG)
    339     >> RELOC_EXT_BITS_TYPE_SH_BIG;
    340 
    341   cache_ptr->howto = aout_32_ext_howto_table + r_type;
    342   MOVE_ADDRESS (GET_SWORD (abfd, bytes->r_addend));
    343 }
    344 
    345 static void
    346 NAME(lynx,swap_std_reloc_in) (bfd *abfd,
    347 			      struct reloc_std_external *bytes,
    348 			      arelent *cache_ptr,
    349 			      asymbol **symbols,
    350 			      bfd_size_type symcount ATTRIBUTE_UNUSED)
    351 {
    352   int r_index;
    353   int r_extern;
    354   unsigned int r_length;
    355   int r_pcrel;
    356   struct aoutdata *su = &(abfd->tdata.aout_data->a);
    357 
    358   cache_ptr->address = H_GET_32 (abfd, bytes->r_address);
    359 
    360   r_index = bytes->r_index[1];
    361   r_extern = (0 != (bytes->r_index[0] & RELOC_STD_BITS_EXTERN_BIG));
    362   r_pcrel = (0 != (bytes->r_index[0] & RELOC_STD_BITS_PCREL_BIG));
    363   r_length = (bytes->r_index[0] & RELOC_STD_BITS_LENGTH_BIG)
    364     >> RELOC_STD_BITS_LENGTH_SH_BIG;
    365 
    366   cache_ptr->howto = aout_32_std_howto_table + r_length + 4 * r_pcrel;
    367   /* FIXME-soon:  Roll baserel, jmptable, relative bits into howto setting */
    368 
    369   MOVE_ADDRESS (0);
    370 }
    371 
    372 /* Reloc hackery */
    373 
    374 static bfd_boolean
    375 NAME(lynx,slurp_reloc_table) (bfd *abfd,
    376 			      sec_ptr asect,
    377 			      asymbol **symbols)
    378 {
    379   bfd_size_type count;
    380   bfd_size_type reloc_size;
    381   void * relocs;
    382   arelent *reloc_cache;
    383   size_t each_size;
    384 
    385   if (asect->relocation)
    386     return TRUE;
    387 
    388   if (asect->flags & SEC_CONSTRUCTOR)
    389     return TRUE;
    390 
    391   if (asect == obj_datasec (abfd))
    392     {
    393       reloc_size = exec_hdr (abfd)->a_drsize;
    394       goto doit;
    395     }
    396 
    397   if (asect == obj_textsec (abfd))
    398     {
    399       reloc_size = exec_hdr (abfd)->a_trsize;
    400       goto doit;
    401     }
    402 
    403   bfd_set_error (bfd_error_invalid_operation);
    404   return FALSE;
    405 
    406 doit:
    407   if (bfd_seek (abfd, asect->rel_filepos, SEEK_SET) != 0)
    408     return FALSE;
    409   each_size = obj_reloc_entry_size (abfd);
    410 
    411   count = reloc_size / each_size;
    412 
    413 
    414   reloc_cache = (arelent *) bfd_zmalloc (count * sizeof (arelent));
    415   if (!reloc_cache && count != 0)
    416     return FALSE;
    417 
    418   relocs = bfd_alloc (abfd, reloc_size);
    419   if (!relocs && reloc_size != 0)
    420     {
    421       free (reloc_cache);
    422       return FALSE;
    423     }
    424 
    425   if (bfd_bread (relocs, reloc_size, abfd) != reloc_size)
    426     {
    427       bfd_release (abfd, relocs);
    428       free (reloc_cache);
    429       return FALSE;
    430     }
    431 
    432   if (each_size == RELOC_EXT_SIZE)
    433     {
    434       struct reloc_ext_external *rptr = (struct reloc_ext_external *) relocs;
    435       unsigned int counter = 0;
    436       arelent *cache_ptr = reloc_cache;
    437 
    438       for (; counter < count; counter++, rptr++, cache_ptr++)
    439 	{
    440 	  NAME(lynx,swap_ext_reloc_in) (abfd, rptr, cache_ptr, symbols,
    441 					(bfd_size_type) bfd_get_symcount (abfd));
    442 	}
    443     }
    444   else
    445     {
    446       struct reloc_std_external *rptr = (struct reloc_std_external *) relocs;
    447       unsigned int counter = 0;
    448       arelent *cache_ptr = reloc_cache;
    449 
    450       for (; counter < count; counter++, rptr++, cache_ptr++)
    451 	{
    452 	  NAME(lynx,swap_std_reloc_in) (abfd, rptr, cache_ptr, symbols,
    453 					(bfd_size_type) bfd_get_symcount (abfd));
    454 	}
    455 
    456     }
    457 
    458   bfd_release (abfd, relocs);
    459   asect->relocation = reloc_cache;
    460   asect->reloc_count = count;
    461   return TRUE;
    462 }
    463 
    464 
    465 
    466 /* Write out a relocation section into an object file.  */
    467 
    468 static bfd_boolean
    469 NAME(lynx,squirt_out_relocs) (bfd *abfd, asection *section)
    470 {
    471   arelent **generic;
    472   unsigned char *native, *natptr;
    473   size_t each_size;
    474   unsigned int count = section->reloc_count;
    475   bfd_size_type natsize;
    476 
    477   if (count == 0)
    478     return TRUE;
    479 
    480   each_size = obj_reloc_entry_size (abfd);
    481   natsize = count;
    482   natsize *= each_size;
    483   native = (unsigned char *) bfd_zalloc (abfd, natsize);
    484   if (!native)
    485     return FALSE;
    486 
    487   generic = section->orelocation;
    488 
    489   if (each_size == RELOC_EXT_SIZE)
    490     {
    491       for (natptr = native;
    492 	   count != 0;
    493 	   --count, natptr += each_size, ++generic)
    494 	NAME(lynx,swap_ext_reloc_out) (abfd, *generic, (struct reloc_ext_external *) natptr);
    495     }
    496   else
    497     {
    498       for (natptr = native;
    499 	   count != 0;
    500 	   --count, natptr += each_size, ++generic)
    501 	NAME(lynx,swap_std_reloc_out) (abfd, *generic, (struct reloc_std_external *) natptr);
    502     }
    503 
    504   if (bfd_bwrite (native, natsize, abfd) != natsize)
    505     {
    506       bfd_release (abfd, native);
    507       return FALSE;
    508     }
    509   bfd_release (abfd, native);
    510 
    511   return TRUE;
    512 }
    513 
    514 /* This is stupid.  This function should be a boolean predicate */
    515 static long
    516 NAME(lynx,canonicalize_reloc) (bfd *abfd,
    517 			       sec_ptr section,
    518 			       arelent **relptr,
    519 			       asymbol **symbols)
    520 {
    521   arelent *tblptr = section->relocation;
    522   unsigned int count;
    523 
    524   if (!(tblptr || NAME(lynx,slurp_reloc_table) (abfd, section, symbols)))
    525     return -1;
    526 
    527   if (section->flags & SEC_CONSTRUCTOR)
    528     {
    529       arelent_chain *chain = section->constructor_chain;
    530       for (count = 0; count < section->reloc_count; count++)
    531 	{
    532 	  *relptr++ = &chain->relent;
    533 	  chain = chain->next;
    534 	}
    535     }
    536   else
    537     {
    538       tblptr = section->relocation;
    539 
    540       for (count = 0; count++ < section->reloc_count;)
    541 	{
    542 	  *relptr++ = tblptr++;
    543 	}
    544     }
    545   *relptr = 0;
    546 
    547   return section->reloc_count;
    548 }
    549 
    550 #define MY_canonicalize_reloc NAME(lynx,canonicalize_reloc)
    551 
    552 #include "aout-target.h"
    553