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