(root)/
binutils-2.41/
gas/
config/
obj-aout.c
       1  /* a.out object file format
       2     Copyright (C) 1989-2023 Free Software Foundation, Inc.
       3  
       4     This file is part of GAS, the GNU Assembler.
       5  
       6     GAS is free software; you can redistribute it and/or modify
       7     it under the terms of the GNU General Public License as
       8     published by the Free Software Foundation; either version 3,
       9     or (at your option) any later version.
      10  
      11     GAS is distributed in the hope that it will be useful, but
      12     WITHOUT ANY WARRANTY; without even the implied warranty of
      13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
      14     the GNU General Public License for more details.
      15  
      16     You should have received a copy of the GNU General Public License
      17     along with GAS; see the file COPYING.  If not, write to the Free
      18     Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
      19     02110-1301, USA.  */
      20  
      21  #define OBJ_HEADER "obj-aout.h"
      22  
      23  #include "as.h"
      24  #undef NO_RELOC
      25  #include "aout/aout64.h"
      26  
      27  void
      28  obj_aout_frob_symbol (symbolS *sym, int *punt ATTRIBUTE_UNUSED)
      29  {
      30    flagword flags;
      31    asection *sec;
      32    int type;
      33  
      34    flags = symbol_get_bfdsym (sym)->flags;
      35    type = aout_symbol (symbol_get_bfdsym (sym))->type;
      36    sec = S_GET_SEGMENT (sym);
      37  
      38    /* Only frob simple symbols this way right now.  */
      39    if (! (type & ~ (N_TYPE | N_EXT)))
      40      {
      41        if (type == (N_UNDF | N_EXT)
      42  	  && sec == bfd_abs_section_ptr)
      43  	{
      44  	  sec = bfd_und_section_ptr;
      45  	  S_SET_SEGMENT (sym, sec);
      46  	}
      47  
      48        if ((type & N_TYPE) != N_INDR
      49  	  && (type & N_TYPE) != N_SETA
      50  	  && (type & N_TYPE) != N_SETT
      51  	  && (type & N_TYPE) != N_SETD
      52  	  && (type & N_TYPE) != N_SETB
      53  	  && type != N_WARNING
      54  	  && (sec == bfd_abs_section_ptr
      55  	      || sec == bfd_und_section_ptr))
      56  	return;
      57        if (flags & BSF_EXPORT)
      58  	type |= N_EXT;
      59  
      60        switch (type & N_TYPE)
      61  	{
      62  	case N_SETA:
      63  	case N_SETT:
      64  	case N_SETD:
      65  	case N_SETB:
      66  	  /* Set the debugging flag for constructor symbols so that
      67  	     BFD leaves them alone.  */
      68  	  symbol_get_bfdsym (sym)->flags |= BSF_DEBUGGING;
      69  
      70  	  /* You can't put a common symbol in a set.  The way a set
      71  	     element works is that the symbol has a definition and a
      72  	     name, and the linker adds the definition to the set of
      73  	     that name.  That does not work for a common symbol,
      74  	     because the linker can't tell which common symbol the
      75  	     user means.  FIXME: Using as_bad here may be
      76  	     inappropriate, since the user may want to force a
      77  	     particular type without regard to the semantics of sets;
      78  	     on the other hand, we certainly don't want anybody to be
      79  	     mislead into thinking that their code will work.  */
      80  	  if (S_IS_COMMON (sym))
      81  	    as_bad (_("Attempt to put a common symbol into set %s"),
      82  		    S_GET_NAME (sym));
      83  	  /* Similarly, you can't put an undefined symbol in a set.  */
      84  	  else if (! S_IS_DEFINED (sym))
      85  	    as_bad (_("Attempt to put an undefined symbol into set %s"),
      86  		    S_GET_NAME (sym));
      87  
      88  	  break;
      89  	case N_INDR:
      90  	  /* Put indirect symbols in the indirect section.  */
      91  	  S_SET_SEGMENT (sym, bfd_ind_section_ptr);
      92  	  symbol_get_bfdsym (sym)->flags |= BSF_INDIRECT;
      93  	  if (type & N_EXT)
      94  	    {
      95  	      symbol_get_bfdsym (sym)->flags |= BSF_EXPORT;
      96  	      symbol_get_bfdsym (sym)->flags &=~ BSF_LOCAL;
      97  	    }
      98  	  break;
      99  	case N_WARNING:
     100  	  /* Mark warning symbols.  */
     101  	  symbol_get_bfdsym (sym)->flags |= BSF_WARNING;
     102  	  break;
     103  	}
     104      }
     105    else
     106      symbol_get_bfdsym (sym)->flags |= BSF_DEBUGGING;
     107  
     108    aout_symbol (symbol_get_bfdsym (sym))->type = type;
     109  
     110    /* Double check weak symbols.  */
     111    if (S_IS_WEAK (sym) && S_IS_COMMON (sym))
     112      as_bad (_("Symbol `%s' can not be both weak and common"),
     113  	    S_GET_NAME (sym));
     114  }
     115  
     116  /* Relocation processing may require knowing the VMAs of the sections.
     117     Writing to a section will cause the BFD back end to compute the
     118     VMAs.  This function also ensures that file size is large enough
     119     to cover a_text and a_data should text or data be the last section
     120     in the file.  */
     121  
     122  void
     123  obj_aout_frob_file_before_fix (void)
     124  {
     125    asection *sec;
     126    bfd_vma *sizep = NULL;
     127    if ((sec = data_section)->size != 0)
     128      sizep = &exec_hdr (stdoutput)->a_data;
     129    else if ((sec = text_section)->size != 0)
     130      sizep = &exec_hdr (stdoutput)->a_text;
     131    if (sizep)
     132      {
     133        bfd_size_type size = sec->size;
     134        bfd_byte b = 0;
     135  
     136        gas_assert (bfd_set_section_contents (stdoutput, sec, &b, size - 1, 1));
     137  
     138        /* We don't know the aligned size until after VMAs and sizes are
     139  	 set on the bfd_set_section_contents call.  If that size is
     140  	 larger than the section then write again to ensure the file
     141  	 contents extend to cover the aligned size.  */
     142        if (*sizep > size)
     143  	{
     144  	  file_ptr pos = sec->filepos + *sizep;
     145  
     146  	  gas_assert (bfd_seek (stdoutput, pos - 1, SEEK_SET) == 0
     147  		      && bfd_bwrite (&b, 1, stdoutput) == 1);
     148  	}
     149      }
     150  }
     151  
     152  static void
     153  obj_aout_line (int ignore ATTRIBUTE_UNUSED)
     154  {
     155    /* Assume delimiter is part of expression.
     156       BSD4.2 as fails with delightful bug, so we
     157       are not being incompatible here.  */
     158    new_logical_line ((char *) NULL, (int) (get_absolute_expression ()));
     159    demand_empty_rest_of_line ();
     160  }
     161  
     162  /* Handle .weak.  This is a GNU extension.  */
     163  
     164  static void
     165  obj_aout_weak (int ignore ATTRIBUTE_UNUSED)
     166  {
     167    char *name;
     168    int c;
     169    symbolS *symbolP;
     170  
     171    do
     172      {
     173        c = get_symbol_name (&name);
     174        symbolP = symbol_find_or_make (name);
     175        (void) restore_line_pointer (c);
     176        SKIP_WHITESPACE ();
     177        S_SET_WEAK (symbolP);
     178        if (c == ',')
     179  	{
     180  	  input_line_pointer++;
     181  	  SKIP_WHITESPACE ();
     182  	  if (*input_line_pointer == '\n')
     183  	    c = '\n';
     184  	}
     185      }
     186    while (c == ',');
     187    demand_empty_rest_of_line ();
     188  }
     189  
     190  /* Handle .type.  On {Net,Open}BSD, this is used to set the n_other field,
     191     which is then apparently used when doing dynamic linking.  Older
     192     versions of gas ignored the .type pseudo-op, so we also ignore it if
     193     we can't parse it.  */
     194  
     195  static void
     196  obj_aout_type (int ignore ATTRIBUTE_UNUSED)
     197  {
     198    char *name;
     199    int c;
     200    symbolS *sym;
     201  
     202    c = get_symbol_name (&name);
     203    sym = symbol_find_or_make (name);
     204    (void) restore_line_pointer (c);
     205    SKIP_WHITESPACE ();
     206    if (*input_line_pointer == ',')
     207      {
     208        ++input_line_pointer;
     209        SKIP_WHITESPACE ();
     210        if (*input_line_pointer == '@')
     211  	{
     212  	  ++input_line_pointer;
     213  	  if (startswith (input_line_pointer, "object"))
     214  	    S_SET_OTHER (sym, 1);
     215  	  else if (startswith (input_line_pointer, "function"))
     216  	    S_SET_OTHER (sym, 2);
     217  	}
     218      }
     219  
     220    /* Ignore everything else on the line.  */
     221    s_ignore (0);
     222  }
     223  
     224  /* Support for an AOUT emulation.  */
     225  
     226  static void
     227  aout_pop_insert (void)
     228  {
     229    pop_insert (aout_pseudo_table);
     230  }
     231  
     232  static int
     233  obj_aout_s_get_other (symbolS *sym)
     234  {
     235    return aout_symbol (symbol_get_bfdsym (sym))->other;
     236  }
     237  
     238  static void
     239  obj_aout_s_set_other (symbolS *sym, int o)
     240  {
     241    aout_symbol (symbol_get_bfdsym (sym))->other = o;
     242  }
     243  
     244  static int
     245  obj_aout_sec_sym_ok_for_reloc (asection *sec ATTRIBUTE_UNUSED)
     246  {
     247    return obj_sec_sym_ok_for_reloc (sec);
     248  }
     249  
     250  static void
     251  obj_aout_process_stab (segT seg ATTRIBUTE_UNUSED,
     252  		       int w,
     253  		       const char *s,
     254  		       int t,
     255  		       int o,
     256  		       int d)
     257  {
     258    aout_process_stab (w, s, t, o, d);
     259  }
     260  
     261  static int
     262  obj_aout_s_get_desc (symbolS *sym)
     263  {
     264    return aout_symbol (symbol_get_bfdsym (sym))->desc;
     265  }
     266  
     267  static void
     268  obj_aout_s_set_desc (symbolS *sym, int d)
     269  {
     270    aout_symbol (symbol_get_bfdsym (sym))->desc = d;
     271  }
     272  
     273  static int
     274  obj_aout_s_get_type (symbolS *sym)
     275  {
     276    return aout_symbol (symbol_get_bfdsym (sym))->type;
     277  }
     278  
     279  static void
     280  obj_aout_s_set_type (symbolS *sym, int t)
     281  {
     282    aout_symbol (symbol_get_bfdsym (sym))->type = t;
     283  }
     284  
     285  static int
     286  obj_aout_separate_stab_sections (void)
     287  {
     288    return 0;
     289  }
     290  
     291  /* When changed, make sure these table entries match the single-format
     292     definitions in obj-aout.h.  */
     293  
     294  const struct format_ops aout_format_ops =
     295  {
     296    bfd_target_aout_flavour,
     297    1,	/* dfl_leading_underscore.  */
     298    0,	/* emit_section_symbols.  */
     299    0,	/* begin.  */
     300    0,	/* end.  */
     301    0,	/* app_file.  */
     302    obj_aout_frob_symbol,
     303    0,	/* frob_file.  */
     304    0,	/* frob_file_before_adjust.  */
     305    obj_aout_frob_file_before_fix,
     306    0,	/* frob_file_after_relocs.  */
     307    0,	/* s_get_size.  */
     308    0,	/* s_set_size.  */
     309    0,	/* s_get_align.  */
     310    0,	/* s_set_align.  */
     311    obj_aout_s_get_other,
     312    obj_aout_s_set_other,
     313    obj_aout_s_get_desc,
     314    obj_aout_s_set_desc,
     315    obj_aout_s_get_type,
     316    obj_aout_s_set_type,
     317    0,	/* copy_symbol_attributes.  */
     318    0,	/* generate_asm_lineno.  */
     319    obj_aout_process_stab,
     320    obj_aout_separate_stab_sections,
     321    0,	/* init_stab_section.  */
     322    obj_aout_sec_sym_ok_for_reloc,
     323    aout_pop_insert,
     324    0,	/* ecoff_set_ext.  */
     325    0,	/* read_begin_hook.  */
     326    0,	/* symbol_new_hook.  */
     327    0,	/* symbol_clone_hook.  */
     328    0	/* adjust_symtab.  */
     329  };
     330  
     331  const pseudo_typeS aout_pseudo_table[] =
     332  {
     333    {"line", obj_aout_line, 0},	/* Source code line number.  */
     334    {"ln", obj_aout_line, 0},	/* COFF line number that we use anyway.  */
     335  
     336    {"weak", obj_aout_weak, 0},	/* Mark symbol as weak.  */
     337  
     338    {"type", obj_aout_type, 0},
     339  
     340    /* coff debug pseudos (ignored) */
     341    {"def", s_ignore, 0},
     342    {"dim", s_ignore, 0},
     343    {"endef", s_ignore, 0},
     344    {"ident", s_ignore, 0},
     345    {"line", s_ignore, 0},
     346    {"ln", s_ignore, 0},
     347    {"scl", s_ignore, 0},
     348    {"size", s_ignore, 0},
     349    {"tag", s_ignore, 0},
     350    {"val", s_ignore, 0},
     351    {"version", s_ignore, 0},
     352  
     353    {"optim", s_ignore, 0},	/* For sun386i cc (?).  */
     354  
     355    /* other stuff */
     356    {"ABORT", s_abort, 0},
     357  
     358    {NULL, NULL, 0}
     359  };