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