(root)/
binutils-2.41/
bfd/
i386lynx.c
       1  /* BFD back-end for i386 a.out binaries under LynxOS.
       2     Copyright (C) 1990-2023 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  bfd_cleanup 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  
     100  #define KEEPIT udata.i
     101  
     102  extern reloc_howto_type aout_32_ext_howto_table[];
     103  extern reloc_howto_type aout_32_std_howto_table[];
     104  
     105  /* Standard reloc stuff */
     106  /* Output standard relocation information to a file in target byte order. */
     107  
     108  static void
     109  NAME(lynx,swap_std_reloc_out) (bfd *abfd,
     110  			       arelent *g,
     111  			       struct reloc_std_external *natptr)
     112  {
     113    int r_index;
     114    asymbol *sym = *(g->sym_ptr_ptr);
     115    int r_extern;
     116    unsigned int r_length;
     117    int r_pcrel;
     118    int r_baserel, r_jmptable, r_relative;
     119    asection *output_section = sym->section->output_section;
     120  
     121    PUT_WORD (abfd, g->address, natptr->r_address);
     122  
     123    r_length = bfd_log2 (bfd_get_reloc_size (g->howto));
     124    r_pcrel = (int) g->howto->pc_relative;	/* Relative to PC? */
     125    /* r_baserel, r_jmptable, r_relative???  FIXME-soon */
     126    r_baserel = 0;
     127    r_jmptable = 0;
     128    r_relative = 0;
     129  
     130    /* name was clobbered by aout_write_syms to be symbol index */
     131  
     132    /* If this relocation is relative to a symbol then set the
     133       r_index to the symbols index, and the r_extern bit.
     134  
     135       Absolute symbols can come in in two ways, either as an offset
     136       from the abs section, or as a symbol which has an abs value.
     137       check for that here
     138    */
     139  
     140    if (bfd_is_com_section (output_section)
     141        || bfd_is_abs_section (output_section)
     142        || bfd_is_und_section (output_section))
     143      {
     144        if (bfd_abs_section_ptr->symbol == sym)
     145  	{
     146  	  /* Whoops, looked like an abs symbol, but is really an offset
     147  	     from the abs section */
     148  	  r_index = 0;
     149  	  r_extern = 0;
     150  	}
     151        else
     152  	{
     153  	  /* Fill in symbol */
     154  	  r_extern = 1;
     155  	  r_index = (*g->sym_ptr_ptr)->KEEPIT;
     156  	}
     157      }
     158    else
     159      {
     160        /* Just an ordinary section */
     161        r_extern = 0;
     162        r_index = output_section->target_index;
     163      }
     164  
     165    /* now the fun stuff */
     166    if (bfd_header_big_endian (abfd))
     167      {
     168        natptr->r_index[0] = r_index >> 16;
     169        natptr->r_index[1] = r_index >> 8;
     170        natptr->r_index[2] = r_index;
     171        natptr->r_type[0] =
     172  	(r_extern ? RELOC_STD_BITS_EXTERN_BIG : 0)
     173  	| (r_pcrel ? RELOC_STD_BITS_PCREL_BIG : 0)
     174  	| (r_baserel ? RELOC_STD_BITS_BASEREL_BIG : 0)
     175  	| (r_jmptable ? RELOC_STD_BITS_JMPTABLE_BIG : 0)
     176  	| (r_relative ? RELOC_STD_BITS_RELATIVE_BIG : 0)
     177  	| (r_length << RELOC_STD_BITS_LENGTH_SH_BIG);
     178      }
     179    else
     180      {
     181        natptr->r_index[2] = r_index >> 16;
     182        natptr->r_index[1] = r_index >> 8;
     183        natptr->r_index[0] = r_index;
     184        natptr->r_type[0] =
     185  	(r_extern ? RELOC_STD_BITS_EXTERN_LITTLE : 0)
     186  	| (r_pcrel ? RELOC_STD_BITS_PCREL_LITTLE : 0)
     187  	| (r_baserel ? RELOC_STD_BITS_BASEREL_LITTLE : 0)
     188  	| (r_jmptable ? RELOC_STD_BITS_JMPTABLE_LITTLE : 0)
     189  	| (r_relative ? RELOC_STD_BITS_RELATIVE_LITTLE : 0)
     190  	| (r_length << RELOC_STD_BITS_LENGTH_SH_LITTLE);
     191      }
     192  }
     193  
     194  
     195  /* Extended stuff */
     196  /* Output extended relocation information to a file in target byte order. */
     197  
     198  static void
     199  NAME(lynx,swap_ext_reloc_out) (bfd *abfd,
     200  			       arelent *g,
     201  			       struct reloc_ext_external *natptr)
     202  {
     203    int r_index;
     204    int r_extern;
     205    unsigned int r_type;
     206    unsigned int r_addend;
     207    asymbol *sym = *(g->sym_ptr_ptr);
     208    asection *output_section = sym->section->output_section;
     209  
     210    PUT_WORD (abfd, g->address, natptr->r_address);
     211  
     212    r_type = (unsigned int) g->howto->type;
     213  
     214    r_addend = g->addend + (*(g->sym_ptr_ptr))->section->output_section->vma;
     215  
     216  
     217    /* If this relocation is relative to a symbol then set the
     218       r_index to the symbols index, and the r_extern bit.
     219  
     220       Absolute symbols can come in in two ways, either as an offset
     221       from the abs section, or as a symbol which has an abs value.
     222       check for that here
     223       */
     224  
     225    if (bfd_is_com_section (output_section)
     226        || bfd_is_abs_section (output_section)
     227        || bfd_is_und_section (output_section))
     228      {
     229        if (bfd_abs_section_ptr->symbol == sym)
     230  	{
     231  	  /* Whoops, looked like an abs symbol, but is really an offset
     232  	 from the abs section */
     233  	  r_index = 0;
     234  	  r_extern = 0;
     235  	}
     236        else
     237  	{
     238  	  r_extern = 1;
     239  	  r_index = (*g->sym_ptr_ptr)->KEEPIT;
     240  	}
     241      }
     242    else
     243      {
     244        /* Just an ordinary section */
     245        r_extern = 0;
     246        r_index = output_section->target_index;
     247      }
     248  
     249  
     250    /* now the fun stuff */
     251    if (bfd_header_big_endian (abfd))
     252      {
     253        natptr->r_index[0] = r_index >> 16;
     254        natptr->r_index[1] = r_index >> 8;
     255        natptr->r_index[2] = r_index;
     256        natptr->r_type[0] =
     257  	(r_extern ? RELOC_EXT_BITS_EXTERN_BIG : 0)
     258  	| (r_type << RELOC_EXT_BITS_TYPE_SH_BIG);
     259      }
     260    else
     261      {
     262        natptr->r_index[2] = r_index >> 16;
     263        natptr->r_index[1] = r_index >> 8;
     264        natptr->r_index[0] = r_index;
     265        natptr->r_type[0] =
     266  	(r_extern ? RELOC_EXT_BITS_EXTERN_LITTLE : 0)
     267  	| (r_type << RELOC_EXT_BITS_TYPE_SH_LITTLE);
     268      }
     269  
     270    PUT_WORD (abfd, r_addend, natptr->r_addend);
     271  }
     272  
     273  /* BFD deals internally with all things based from the section they're
     274     in. so, something in 10 bytes into a text section  with a base of
     275     50 would have a symbol (.text+10) and know .text vma was 50.
     276  
     277     Aout keeps all it's symbols based from zero, so the symbol would
     278     contain 60. This macro subs the base of each section from the value
     279     to give the true offset from the section */
     280  
     281  
     282  #define MOVE_ADDRESS(ad)						\
     283    if (r_extern)								\
     284      {									\
     285        /* undefined symbol */						\
     286        if (symbols != NULL && r_index < bfd_get_symcount (abfd))		\
     287  	cache_ptr->sym_ptr_ptr = symbols + r_index;			\
     288        else								\
     289  	cache_ptr->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;	\
     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  	{								\
     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    unsigned 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    unsigned 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 bool
     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_and_read (abfd, reloc_size, reloc_size);
     419    if (!relocs && reloc_size != 0)
     420      {
     421        free (reloc_cache);
     422        return false;
     423      }
     424  
     425    if (each_size == RELOC_EXT_SIZE)
     426      {
     427        struct reloc_ext_external *rptr = (struct reloc_ext_external *) relocs;
     428        unsigned int counter = 0;
     429        arelent *cache_ptr = reloc_cache;
     430  
     431        for (; counter < count; counter++, rptr++, cache_ptr++)
     432  	{
     433  	  NAME(lynx,swap_ext_reloc_in) (abfd, rptr, cache_ptr, symbols,
     434  					(bfd_size_type) bfd_get_symcount (abfd));
     435  	}
     436      }
     437    else
     438      {
     439        struct reloc_std_external *rptr = (struct reloc_std_external *) relocs;
     440        unsigned int counter = 0;
     441        arelent *cache_ptr = reloc_cache;
     442  
     443        for (; counter < count; counter++, rptr++, cache_ptr++)
     444  	{
     445  	  NAME(lynx,swap_std_reloc_in) (abfd, rptr, cache_ptr, symbols,
     446  					(bfd_size_type) bfd_get_symcount (abfd));
     447  	}
     448  
     449      }
     450  
     451    bfd_release (abfd, relocs);
     452    asect->relocation = reloc_cache;
     453    asect->reloc_count = count;
     454    return true;
     455  }
     456  
     457  
     458  
     459  /* Write out a relocation section into an object file.  */
     460  
     461  static bool
     462  NAME(lynx,squirt_out_relocs) (bfd *abfd, asection *section)
     463  {
     464    arelent **generic;
     465    unsigned char *native, *natptr;
     466    size_t each_size;
     467    unsigned int count = section->reloc_count;
     468    bfd_size_type natsize;
     469  
     470    if (count == 0)
     471      return true;
     472  
     473    each_size = obj_reloc_entry_size (abfd);
     474    natsize = count;
     475    natsize *= each_size;
     476    native = (unsigned char *) bfd_zalloc (abfd, natsize);
     477    if (!native)
     478      return false;
     479  
     480    generic = section->orelocation;
     481  
     482    if (each_size == RELOC_EXT_SIZE)
     483      {
     484        for (natptr = native;
     485  	   count != 0;
     486  	   --count, natptr += each_size, ++generic)
     487  	NAME(lynx,swap_ext_reloc_out) (abfd, *generic, (struct reloc_ext_external *) natptr);
     488      }
     489    else
     490      {
     491        for (natptr = native;
     492  	   count != 0;
     493  	   --count, natptr += each_size, ++generic)
     494  	NAME(lynx,swap_std_reloc_out) (abfd, *generic, (struct reloc_std_external *) natptr);
     495      }
     496  
     497    if (bfd_bwrite (native, natsize, abfd) != natsize)
     498      {
     499        bfd_release (abfd, native);
     500        return false;
     501      }
     502    bfd_release (abfd, native);
     503  
     504    return true;
     505  }
     506  
     507  /* This is stupid.  This function should be a boolean predicate */
     508  static long
     509  NAME(lynx,canonicalize_reloc) (bfd *abfd,
     510  			       sec_ptr section,
     511  			       arelent **relptr,
     512  			       asymbol **symbols)
     513  {
     514    arelent *tblptr = section->relocation;
     515    unsigned int count;
     516  
     517    if (!(tblptr || NAME(lynx,slurp_reloc_table) (abfd, section, symbols)))
     518      return -1;
     519  
     520    if (section->flags & SEC_CONSTRUCTOR)
     521      {
     522        arelent_chain *chain = section->constructor_chain;
     523        for (count = 0; count < section->reloc_count; count++)
     524  	{
     525  	  *relptr++ = &chain->relent;
     526  	  chain = chain->next;
     527  	}
     528      }
     529    else
     530      {
     531        tblptr = section->relocation;
     532  
     533        for (count = 0; count++ < section->reloc_count;)
     534  	{
     535  	  *relptr++ = tblptr++;
     536  	}
     537      }
     538    *relptr = 0;
     539  
     540    return section->reloc_count;
     541  }
     542  
     543  #define MY_canonicalize_reloc NAME(lynx,canonicalize_reloc)
     544  
     545  #include "aout-target.h"