Home | History | Annotate | Line # | Download | only in bfd
i386lynx.c revision 1.1.1.9
      1 /* BFD back-end for i386 a.out binaries under LynxOS.
      2    Copyright (C) 1990-2024 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, 0, SEEK_SET) != 0				\
     52 	|| bfd_write (&exec_bytes, 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_outsymbols (abfd) != NULL				\
     58 	&& bfd_get_symcount (abfd) != 0)				\
     59       {									\
     60 	if (bfd_seek (abfd, N_SYMOFF (execp), SEEK_SET) != 0)		\
     61 	  return false;							\
     62 									\
     63 	if (! NAME (aout, write_syms) (abfd))				\
     64 	  return false;							\
     65       }									\
     66 									\
     67     if (bfd_seek (abfd, N_TRELOFF (execp), SEEK_SET) != 0)		\
     68       return false;							\
     69     if (!NAME (lynx, squirt_out_relocs) (abfd, obj_textsec (abfd)))	\
     70       return false;							\
     71 									\
     72     if (bfd_seek (abfd, N_DRELOFF (execp), SEEK_SET) != 0)		\
     73       return false;							\
     74     if (!NAME (lynx, squirt_out_relocs) (abfd, obj_datasec (abfd)))	\
     75       return false;							\
     76   }
     77 #endif
     78 
     79 #include "libaout.h"
     80 #include "aout/aout64.h"
     81 
     82 
     83 #ifdef LYNX_CORE
     84 
     85 char *lynx_core_file_failing_command ();
     86 int lynx_core_file_failing_signal ();
     87 bool lynx_core_file_matches_executable_p ();
     88 bfd_cleanup lynx_core_file_p ();
     89 
     90 #define	MY_core_file_failing_command lynx_core_file_failing_command
     91 #define	MY_core_file_failing_signal lynx_core_file_failing_signal
     92 #define	MY_core_file_matches_executable_p lynx_core_file_matches_executable_p
     93 #define	MY_core_file_p lynx_core_file_p
     94 
     95 #endif /* LYNX_CORE */
     96 
     97 
     99 #define KEEPIT udata.i
    100 
    101 extern reloc_howto_type aout_32_ext_howto_table[];
    102 extern reloc_howto_type aout_32_std_howto_table[];
    103 
    104 /* Standard reloc stuff */
    105 /* Output standard relocation information to a file in target byte order. */
    106 
    107 static void
    108 NAME(lynx,swap_std_reloc_out) (bfd *abfd,
    109 			       arelent *g,
    110 			       struct reloc_std_external *natptr)
    111 {
    112   int r_index;
    113   asymbol *sym = *(g->sym_ptr_ptr);
    114   int r_extern;
    115   unsigned int r_length;
    116   int r_pcrel;
    117   int r_baserel, r_jmptable, r_relative;
    118   asection *output_section = sym->section->output_section;
    119 
    120   PUT_WORD (abfd, g->address, natptr->r_address);
    121 
    122   r_length = bfd_log2 (bfd_get_reloc_size (g->howto));
    123   r_pcrel = (int) g->howto->pc_relative;	/* Relative to PC? */
    124   /* r_baserel, r_jmptable, r_relative???  FIXME-soon */
    125   r_baserel = 0;
    126   r_jmptable = 0;
    127   r_relative = 0;
    128 
    129   /* name was clobbered by aout_write_syms to be symbol index */
    130 
    131   /* If this relocation is relative to a symbol then set the
    132      r_index to the symbols index, and the r_extern bit.
    133 
    134      Absolute symbols can come in in two ways, either as an offset
    135      from the abs section, or as a symbol which has an abs value.
    136      check for that here
    137   */
    138 
    139   if (bfd_is_com_section (output_section)
    140       || bfd_is_abs_section (output_section)
    141       || bfd_is_und_section (output_section))
    142     {
    143       if (bfd_abs_section_ptr->symbol == sym)
    144 	{
    145 	  /* Whoops, looked like an abs symbol, but is really an offset
    146 	     from the abs section */
    147 	  r_index = 0;
    148 	  r_extern = 0;
    149 	}
    150       else
    151 	{
    152 	  /* Fill in symbol */
    153 	  r_extern = 1;
    154 	  r_index = (*g->sym_ptr_ptr)->KEEPIT;
    155 	}
    156     }
    157   else
    158     {
    159       /* Just an ordinary section */
    160       r_extern = 0;
    161       r_index = output_section->target_index;
    162     }
    163 
    164   /* now the fun stuff */
    165   if (bfd_header_big_endian (abfd))
    166     {
    167       natptr->r_index[0] = r_index >> 16;
    168       natptr->r_index[1] = r_index >> 8;
    169       natptr->r_index[2] = r_index;
    170       natptr->r_type[0] =
    171 	(r_extern ? RELOC_STD_BITS_EXTERN_BIG : 0)
    172 	| (r_pcrel ? RELOC_STD_BITS_PCREL_BIG : 0)
    173 	| (r_baserel ? RELOC_STD_BITS_BASEREL_BIG : 0)
    174 	| (r_jmptable ? RELOC_STD_BITS_JMPTABLE_BIG : 0)
    175 	| (r_relative ? RELOC_STD_BITS_RELATIVE_BIG : 0)
    176 	| (r_length << RELOC_STD_BITS_LENGTH_SH_BIG);
    177     }
    178   else
    179     {
    180       natptr->r_index[2] = r_index >> 16;
    181       natptr->r_index[1] = r_index >> 8;
    182       natptr->r_index[0] = r_index;
    183       natptr->r_type[0] =
    184 	(r_extern ? RELOC_STD_BITS_EXTERN_LITTLE : 0)
    185 	| (r_pcrel ? RELOC_STD_BITS_PCREL_LITTLE : 0)
    186 	| (r_baserel ? RELOC_STD_BITS_BASEREL_LITTLE : 0)
    187 	| (r_jmptable ? RELOC_STD_BITS_JMPTABLE_LITTLE : 0)
    188 	| (r_relative ? RELOC_STD_BITS_RELATIVE_LITTLE : 0)
    189 	| (r_length << RELOC_STD_BITS_LENGTH_SH_LITTLE);
    190     }
    191 }
    192 
    193 
    194 /* Extended stuff */
    195 /* Output extended relocation information to a file in target byte order. */
    196 
    197 static void
    198 NAME(lynx,swap_ext_reloc_out) (bfd *abfd,
    199 			       arelent *g,
    200 			       struct reloc_ext_external *natptr)
    201 {
    202   int r_index;
    203   int r_extern;
    204   unsigned int r_type;
    205   unsigned int r_addend;
    206   asymbol *sym = *(g->sym_ptr_ptr);
    207   asection *output_section = sym->section->output_section;
    208 
    209   PUT_WORD (abfd, g->address, natptr->r_address);
    210 
    211   r_type = (unsigned int) g->howto->type;
    212 
    213   r_addend = g->addend + (*(g->sym_ptr_ptr))->section->output_section->vma;
    214 
    215 
    216   /* If this relocation is relative to a symbol then set the
    217      r_index to the symbols index, and the r_extern bit.
    218 
    219      Absolute symbols can come in in two ways, either as an offset
    220      from the abs section, or as a symbol which has an abs value.
    221      check for that here
    222      */
    223 
    224   if (bfd_is_com_section (output_section)
    225       || bfd_is_abs_section (output_section)
    226       || bfd_is_und_section (output_section))
    227     {
    228       if (bfd_abs_section_ptr->symbol == sym)
    229 	{
    230 	  /* Whoops, looked like an abs symbol, but is really an offset
    231 	 from the abs section */
    232 	  r_index = 0;
    233 	  r_extern = 0;
    234 	}
    235       else
    236 	{
    237 	  r_extern = 1;
    238 	  r_index = (*g->sym_ptr_ptr)->KEEPIT;
    239 	}
    240     }
    241   else
    242     {
    243       /* Just an ordinary section */
    244       r_extern = 0;
    245       r_index = output_section->target_index;
    246     }
    247 
    248 
    249   /* now the fun stuff */
    250   if (bfd_header_big_endian (abfd))
    251     {
    252       natptr->r_index[0] = r_index >> 16;
    253       natptr->r_index[1] = r_index >> 8;
    254       natptr->r_index[2] = r_index;
    255       natptr->r_type[0] =
    256 	(r_extern ? RELOC_EXT_BITS_EXTERN_BIG : 0)
    257 	| (r_type << RELOC_EXT_BITS_TYPE_SH_BIG);
    258     }
    259   else
    260     {
    261       natptr->r_index[2] = r_index >> 16;
    262       natptr->r_index[1] = r_index >> 8;
    263       natptr->r_index[0] = r_index;
    264       natptr->r_type[0] =
    265 	(r_extern ? RELOC_EXT_BITS_EXTERN_LITTLE : 0)
    266 	| (r_type << RELOC_EXT_BITS_TYPE_SH_LITTLE);
    267     }
    268 
    269   PUT_WORD (abfd, r_addend, natptr->r_addend);
    270 }
    271 
    272 /* BFD deals internally with all things based from the section they're
    273    in. so, something in 10 bytes into a text section  with a base of
    274    50 would have a symbol (.text+10) and know .text vma was 50.
    275 
    276    Aout keeps all it's symbols based from zero, so the symbol would
    277    contain 60. This macro subs the base of each section from the value
    278    to give the true offset from the section */
    279 
    280 
    281 #define MOVE_ADDRESS(ad)						\
    282   if (r_extern)								\
    283     {									\
    284       /* undefined symbol */						\
    285       if (symbols != NULL && r_index < bfd_get_symcount (abfd))		\
    286 	cache_ptr->sym_ptr_ptr = symbols + r_index;			\
    287       else								\
    288 	cache_ptr->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;	\
    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_write (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