Home | History | Annotate | Line # | Download | only in bfd
i386lynx.c revision 1.1.1.6
      1 /* BFD back-end for i386 a.out binaries under LynxOS.
      2    Copyright (C) 1990-2022 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 bool 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 = bfd_log2 (bfd_get_reloc_size (g->howto));
    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       if (r_index < bfd_get_symcount (abfd))				\
    288 	cache_ptr->sym_ptr_ptr = symbols + r_index;			\
    289       cache_ptr->addend = ad;						\
    290     }									\
    291   else									\
    292     {									\
    293       /* defined, section relative. replace symbol with pointer to	\
    294 	 symbol which points to section  */				\
    295       switch (r_index)							\
    296 	{								\
    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   unsigned 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   unsigned 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 bool
    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_and_read (abfd, reloc_size, reloc_size);
    418   if (!relocs && reloc_size != 0)
    419     {
    420       free (reloc_cache);
    421       return false;
    422     }
    423 
    424   if (each_size == RELOC_EXT_SIZE)
    425     {
    426       struct reloc_ext_external *rptr = (struct reloc_ext_external *) relocs;
    427       unsigned int counter = 0;
    428       arelent *cache_ptr = reloc_cache;
    429 
    430       for (; counter < count; counter++, rptr++, cache_ptr++)
    431 	{
    432 	  NAME(lynx,swap_ext_reloc_in) (abfd, rptr, cache_ptr, symbols,
    433 					(bfd_size_type) bfd_get_symcount (abfd));
    434 	}
    435     }
    436   else
    437     {
    438       struct reloc_std_external *rptr = (struct reloc_std_external *) relocs;
    439       unsigned int counter = 0;
    440       arelent *cache_ptr = reloc_cache;
    441 
    442       for (; counter < count; counter++, rptr++, cache_ptr++)
    443 	{
    444 	  NAME(lynx,swap_std_reloc_in) (abfd, rptr, cache_ptr, symbols,
    445 					(bfd_size_type) bfd_get_symcount (abfd));
    446 	}
    447 
    448     }
    449 
    450   bfd_release (abfd, relocs);
    451   asect->relocation = reloc_cache;
    452   asect->reloc_count = count;
    453   return true;
    454 }
    455 
    456 
    457 
    458 /* Write out a relocation section into an object file.  */
    459 
    460 static bool
    461 NAME(lynx,squirt_out_relocs) (bfd *abfd, asection *section)
    462 {
    463   arelent **generic;
    464   unsigned char *native, *natptr;
    465   size_t each_size;
    466   unsigned int count = section->reloc_count;
    467   bfd_size_type natsize;
    468 
    469   if (count == 0)
    470     return true;
    471 
    472   each_size = obj_reloc_entry_size (abfd);
    473   natsize = count;
    474   natsize *= each_size;
    475   native = (unsigned char *) bfd_zalloc (abfd, natsize);
    476   if (!native)
    477     return false;
    478 
    479   generic = section->orelocation;
    480 
    481   if (each_size == RELOC_EXT_SIZE)
    482     {
    483       for (natptr = native;
    484 	   count != 0;
    485 	   --count, natptr += each_size, ++generic)
    486 	NAME(lynx,swap_ext_reloc_out) (abfd, *generic, (struct reloc_ext_external *) natptr);
    487     }
    488   else
    489     {
    490       for (natptr = native;
    491 	   count != 0;
    492 	   --count, natptr += each_size, ++generic)
    493 	NAME(lynx,swap_std_reloc_out) (abfd, *generic, (struct reloc_std_external *) natptr);
    494     }
    495 
    496   if (bfd_bwrite (native, natsize, abfd) != natsize)
    497     {
    498       bfd_release (abfd, native);
    499       return false;
    500     }
    501   bfd_release (abfd, native);
    502 
    503   return true;
    504 }
    505 
    506 /* This is stupid.  This function should be a boolean predicate */
    507 static long
    508 NAME(lynx,canonicalize_reloc) (bfd *abfd,
    509 			       sec_ptr section,
    510 			       arelent **relptr,
    511 			       asymbol **symbols)
    512 {
    513   arelent *tblptr = section->relocation;
    514   unsigned int count;
    515 
    516   if (!(tblptr || NAME(lynx,slurp_reloc_table) (abfd, section, symbols)))
    517     return -1;
    518 
    519   if (section->flags & SEC_CONSTRUCTOR)
    520     {
    521       arelent_chain *chain = section->constructor_chain;
    522       for (count = 0; count < section->reloc_count; count++)
    523 	{
    524 	  *relptr++ = &chain->relent;
    525 	  chain = chain->next;
    526 	}
    527     }
    528   else
    529     {
    530       tblptr = section->relocation;
    531 
    532       for (count = 0; count++ < section->reloc_count;)
    533 	{
    534 	  *relptr++ = tblptr++;
    535 	}
    536     }
    537   *relptr = 0;
    538 
    539   return section->reloc_count;
    540 }
    541 
    542 #define MY_canonicalize_reloc NAME(lynx,canonicalize_reloc)
    543 
    544 #include "aout-target.h"
    545