obj-aout.c revision 33965
133965Sjdp/* a.out object file format
233965Sjdp   Copyright (C) 1989, 90, 91, 92, 93, 94, 95, 1996
333965Sjdp   Free Software Foundation, Inc.
433965Sjdp
533965SjdpThis file is part of GAS, the GNU Assembler.
633965Sjdp
733965SjdpGAS is free software; you can redistribute it and/or modify
833965Sjdpit under the terms of the GNU General Public License as
933965Sjdppublished by the Free Software Foundation; either version 2,
1033965Sjdpor (at your option) any later version.
1133965Sjdp
1233965SjdpGAS is distributed in the hope that it will be useful, but
1333965SjdpWITHOUT ANY WARRANTY; without even the implied warranty of
1433965SjdpMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
1533965Sjdpthe GNU General Public License for more details.
1633965Sjdp
1733965SjdpYou should have received a copy of the GNU General Public
1833965SjdpLicense along with GAS; see the file COPYING.  If not, write
1933965Sjdpto the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
2033965Sjdp
2133965Sjdp#include "as.h"
2233965Sjdp#ifdef BFD_ASSEMBLER
2333965Sjdp#undef NO_RELOC
2433965Sjdp#include "aout/aout64.h"
2533965Sjdp#endif
2633965Sjdp#include "obstack.h"
2733965Sjdp
2833965Sjdp#ifndef BFD_ASSEMBLER
2933965Sjdp/* in: segT   out: N_TYPE bits */
3033965Sjdpconst short seg_N_TYPE[] =
3133965Sjdp{
3233965Sjdp  N_ABS,
3333965Sjdp  N_TEXT,
3433965Sjdp  N_DATA,
3533965Sjdp  N_BSS,
3633965Sjdp  N_UNDF,			/* unknown */
3733965Sjdp  N_UNDF,			/* error */
3833965Sjdp  N_UNDF,			/* expression */
3933965Sjdp  N_UNDF,			/* debug */
4033965Sjdp  N_UNDF,			/* ntv */
4133965Sjdp  N_UNDF,			/* ptv */
4233965Sjdp  N_REGISTER,			/* register */
4333965Sjdp};
4433965Sjdp
4533965Sjdpconst segT N_TYPE_seg[N_TYPE + 2] =
4633965Sjdp{				/* N_TYPE == 0x1E = 32-2 */
4733965Sjdp  SEG_UNKNOWN,			/* N_UNDF == 0 */
4833965Sjdp  SEG_GOOF,
4933965Sjdp  SEG_ABSOLUTE,			/* N_ABS == 2 */
5033965Sjdp  SEG_GOOF,
5133965Sjdp  SEG_TEXT,			/* N_TEXT == 4 */
5233965Sjdp  SEG_GOOF,
5333965Sjdp  SEG_DATA,			/* N_DATA == 6 */
5433965Sjdp  SEG_GOOF,
5533965Sjdp  SEG_BSS,			/* N_BSS == 8 */
5633965Sjdp  SEG_GOOF,
5733965Sjdp  SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF,
5833965Sjdp  SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF,
5933965Sjdp  SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF,
6033965Sjdp  SEG_REGISTER,			/* dummy N_REGISTER for regs = 30 */
6133965Sjdp  SEG_GOOF,
6233965Sjdp};
6333965Sjdp#endif
6433965Sjdp
6533965Sjdpstatic void obj_aout_line PARAMS ((int));
6633965Sjdpstatic void obj_aout_weak PARAMS ((int));
6733965Sjdpstatic void obj_aout_type PARAMS ((int));
6833965Sjdp
6933965Sjdpconst pseudo_typeS obj_pseudo_table[] =
7033965Sjdp{
7133965Sjdp  {"line", obj_aout_line, 0},	/* source code line number */
7233965Sjdp  {"ln", obj_aout_line, 0},	/* coff line number that we use anyway */
7333965Sjdp
7433965Sjdp  {"weak", obj_aout_weak, 0},	/* mark symbol as weak.  */
7533965Sjdp
7633965Sjdp  {"type", obj_aout_type, 0},
7733965Sjdp
7833965Sjdp  /* coff debug pseudos (ignored) */
7933965Sjdp  {"def", s_ignore, 0},
8033965Sjdp  {"dim", s_ignore, 0},
8133965Sjdp  {"endef", s_ignore, 0},
8233965Sjdp  {"ident", s_ignore, 0},
8333965Sjdp  {"line", s_ignore, 0},
8433965Sjdp  {"ln", s_ignore, 0},
8533965Sjdp  {"scl", s_ignore, 0},
8633965Sjdp  {"size", s_ignore, 0},
8733965Sjdp  {"tag", s_ignore, 0},
8833965Sjdp  {"val", s_ignore, 0},
8933965Sjdp  {"version", s_ignore, 0},
9033965Sjdp
9133965Sjdp  {"optim", s_ignore, 0},	/* For sun386i cc (?) */
9233965Sjdp
9333965Sjdp  /* other stuff */
9433965Sjdp  {"ABORT", s_abort, 0},
9533965Sjdp
9633965Sjdp  {NULL}			/* end sentinel */
9733965Sjdp};				/* obj_pseudo_table */
9833965Sjdp
9933965Sjdp
10033965Sjdp#ifdef BFD_ASSEMBLER
10133965Sjdp
10233965Sjdpvoid
10333965Sjdpobj_aout_frob_symbol (sym, punt)
10433965Sjdp     symbolS *sym;
10533965Sjdp     int *punt;
10633965Sjdp{
10733965Sjdp  flagword flags;
10833965Sjdp  asection *sec;
10933965Sjdp  int desc, type, other;
11033965Sjdp
11133965Sjdp  flags = sym->bsym->flags;
11233965Sjdp  desc = S_GET_DESC (sym);
11333965Sjdp  type = S_GET_TYPE (sym);
11433965Sjdp  other = S_GET_OTHER (sym);
11533965Sjdp  sec = sym->bsym->section;
11633965Sjdp
11733965Sjdp  /* Only frob simple symbols this way right now.  */
11833965Sjdp  if (! (type & ~ (N_TYPE | N_EXT)))
11933965Sjdp    {
12033965Sjdp      if (type == (N_UNDF | N_EXT)
12133965Sjdp	  && sec == &bfd_abs_section)
12233965Sjdp	sym->bsym->section = sec = bfd_und_section_ptr;
12333965Sjdp
12433965Sjdp      if ((type & N_TYPE) != N_INDR
12533965Sjdp	  && (type & N_TYPE) != N_SETA
12633965Sjdp	  && (type & N_TYPE) != N_SETT
12733965Sjdp	  && (type & N_TYPE) != N_SETD
12833965Sjdp	  && (type & N_TYPE) != N_SETB
12933965Sjdp	  && type != N_WARNING
13033965Sjdp	  && (sec == &bfd_abs_section
13133965Sjdp	      || sec == &bfd_und_section))
13233965Sjdp	return;
13333965Sjdp      if (flags & BSF_EXPORT)
13433965Sjdp	type |= N_EXT;
13533965Sjdp
13633965Sjdp      switch (type & N_TYPE)
13733965Sjdp	{
13833965Sjdp	case N_SETA:
13933965Sjdp	case N_SETT:
14033965Sjdp	case N_SETD:
14133965Sjdp	case N_SETB:
14233965Sjdp	  /* Set the debugging flag for constructor symbols so that
14333965Sjdp	     BFD leaves them alone.  */
14433965Sjdp	  sym->bsym->flags |= BSF_DEBUGGING;
14533965Sjdp
14633965Sjdp	  /* You can't put a common symbol in a set.  The way a set
14733965Sjdp	     element works is that the symbol has a definition and a
14833965Sjdp	     name, and the linker adds the definition to the set of
14933965Sjdp	     that name.  That does not work for a common symbol,
15033965Sjdp	     because the linker can't tell which common symbol the
15133965Sjdp	     user means.  FIXME: Using as_bad here may be
15233965Sjdp	     inappropriate, since the user may want to force a
15333965Sjdp	     particular type without regard to the semantics of sets;
15433965Sjdp	     on the other hand, we certainly don't want anybody to be
15533965Sjdp	     mislead into thinking that their code will work.  */
15633965Sjdp	  if (S_IS_COMMON (sym))
15733965Sjdp	    as_bad ("Attempt to put a common symbol into set %s",
15833965Sjdp		    S_GET_NAME (sym));
15933965Sjdp	  /* Similarly, you can't put an undefined symbol in a set.  */
16033965Sjdp	  else if (! S_IS_DEFINED (sym))
16133965Sjdp	    as_bad ("Attempt to put an undefined symbol into set %s",
16233965Sjdp		    S_GET_NAME (sym));
16333965Sjdp
16433965Sjdp	  break;
16533965Sjdp	case N_INDR:
16633965Sjdp	  /* Put indirect symbols in the indirect section.  */
16733965Sjdp	  sym->bsym->section = bfd_ind_section_ptr;
16833965Sjdp	  sym->bsym->flags |= BSF_INDIRECT;
16933965Sjdp	  if (type & N_EXT)
17033965Sjdp	    {
17133965Sjdp	      sym->bsym->flags |= BSF_EXPORT;
17233965Sjdp	      sym->bsym->flags &=~ BSF_LOCAL;
17333965Sjdp	    }
17433965Sjdp	  break;
17533965Sjdp	case N_WARNING:
17633965Sjdp	  /* Mark warning symbols.  */
17733965Sjdp	  sym->bsym->flags |= BSF_WARNING;
17833965Sjdp	  break;
17933965Sjdp	}
18033965Sjdp    }
18133965Sjdp  else
18233965Sjdp    {
18333965Sjdp      sym->bsym->flags |= BSF_DEBUGGING;
18433965Sjdp    }
18533965Sjdp
18633965Sjdp  S_SET_TYPE (sym, type);
18733965Sjdp
18833965Sjdp  /* Double check weak symbols.  */
18933965Sjdp  if (sym->bsym->flags & BSF_WEAK)
19033965Sjdp    {
19133965Sjdp      if (S_IS_COMMON (sym))
19233965Sjdp	as_bad ("Symbol `%s' can not be both weak and common",
19333965Sjdp		S_GET_NAME (sym));
19433965Sjdp    }
19533965Sjdp}
19633965Sjdp
19733965Sjdpvoid
19833965Sjdpobj_aout_frob_file ()
19933965Sjdp{
20033965Sjdp  /* Relocation processing may require knowing the VMAs of the sections.
20133965Sjdp     Since writing to a section will cause the BFD back end to compute the
20233965Sjdp     VMAs, fake it out here....  */
20333965Sjdp  bfd_byte b = 0;
20433965Sjdp  boolean x = true;
20533965Sjdp  if (bfd_section_size (stdoutput, text_section) != 0)
20633965Sjdp    {
20733965Sjdp      x = bfd_set_section_contents (stdoutput, text_section, &b, (file_ptr) 0,
20833965Sjdp				    (bfd_size_type) 1);
20933965Sjdp    }
21033965Sjdp  else if (bfd_section_size (stdoutput, data_section) != 0)
21133965Sjdp    {
21233965Sjdp      x = bfd_set_section_contents (stdoutput, data_section, &b, (file_ptr) 0,
21333965Sjdp				    (bfd_size_type) 1);
21433965Sjdp    }
21533965Sjdp  assert (x == true);
21633965Sjdp}
21733965Sjdp
21833965Sjdp#else
21933965Sjdp
22033965Sjdp/* Relocation. */
22133965Sjdp
22233965Sjdp/*
22333965Sjdp *		emit_relocations()
22433965Sjdp *
22533965Sjdp * Crawl along a fixS chain. Emit the segment's relocations.
22633965Sjdp */
22733965Sjdpvoid
22833965Sjdpobj_emit_relocations (where, fixP, segment_address_in_file)
22933965Sjdp     char **where;
23033965Sjdp     fixS *fixP;		/* Fixup chain for this segment. */
23133965Sjdp     relax_addressT segment_address_in_file;
23233965Sjdp{
23333965Sjdp  for (; fixP; fixP = fixP->fx_next)
23433965Sjdp    if (fixP->fx_done == 0)
23533965Sjdp      {
23633965Sjdp	symbolS *sym;
23733965Sjdp
23833965Sjdp	sym = fixP->fx_addsy;
23933965Sjdp	while (sym->sy_value.X_op == O_symbol
24033965Sjdp	       && (! S_IS_DEFINED (sym) || S_IS_COMMON (sym)))
24133965Sjdp	  sym = sym->sy_value.X_add_symbol;
24233965Sjdp	fixP->fx_addsy = sym;
24333965Sjdp
24433965Sjdp	if (! sym->sy_resolved && ! S_IS_DEFINED (sym))
24533965Sjdp	  {
24633965Sjdp	    char *file;
24733965Sjdp	    unsigned int line;
24833965Sjdp
24933965Sjdp	    if (expr_symbol_where (sym, &file, &line))
25033965Sjdp	      as_bad_where (file, line, "unresolved relocation");
25133965Sjdp	    else
25233965Sjdp	      as_bad ("bad relocation: symbol `%s' not in symbol table",
25333965Sjdp		      S_GET_NAME (sym));
25433965Sjdp	  }
25533965Sjdp
25633965Sjdp	tc_aout_fix_to_chars (*where, fixP, segment_address_in_file);
25733965Sjdp	*where += md_reloc_size;
25833965Sjdp      }
25933965Sjdp}
26033965Sjdp
26133965Sjdp#ifndef obj_header_append
26233965Sjdp/* Aout file generation & utilities */
26333965Sjdpvoid
26433965Sjdpobj_header_append (where, headers)
26533965Sjdp     char **where;
26633965Sjdp     object_headers *headers;
26733965Sjdp{
26833965Sjdp  tc_headers_hook (headers);
26933965Sjdp
27033965Sjdp#ifdef CROSS_COMPILE
27133965Sjdp  md_number_to_chars (*where, headers->header.a_info, sizeof (headers->header.a_info));
27233965Sjdp  *where += sizeof (headers->header.a_info);
27333965Sjdp  md_number_to_chars (*where, headers->header.a_text, sizeof (headers->header.a_text));
27433965Sjdp  *where += sizeof (headers->header.a_text);
27533965Sjdp  md_number_to_chars (*where, headers->header.a_data, sizeof (headers->header.a_data));
27633965Sjdp  *where += sizeof (headers->header.a_data);
27733965Sjdp  md_number_to_chars (*where, headers->header.a_bss, sizeof (headers->header.a_bss));
27833965Sjdp  *where += sizeof (headers->header.a_bss);
27933965Sjdp  md_number_to_chars (*where, headers->header.a_syms, sizeof (headers->header.a_syms));
28033965Sjdp  *where += sizeof (headers->header.a_syms);
28133965Sjdp  md_number_to_chars (*where, headers->header.a_entry, sizeof (headers->header.a_entry));
28233965Sjdp  *where += sizeof (headers->header.a_entry);
28333965Sjdp  md_number_to_chars (*where, headers->header.a_trsize, sizeof (headers->header.a_trsize));
28433965Sjdp  *where += sizeof (headers->header.a_trsize);
28533965Sjdp  md_number_to_chars (*where, headers->header.a_drsize, sizeof (headers->header.a_drsize));
28633965Sjdp  *where += sizeof (headers->header.a_drsize);
28733965Sjdp
28833965Sjdp#else /* CROSS_COMPILE */
28933965Sjdp
29033965Sjdp  append (where, (char *) &headers->header, sizeof (headers->header));
29133965Sjdp#endif /* CROSS_COMPILE */
29233965Sjdp
29333965Sjdp}
29433965Sjdp#endif
29533965Sjdp
29633965Sjdpvoid
29733965Sjdpobj_symbol_to_chars (where, symbolP)
29833965Sjdp     char **where;
29933965Sjdp     symbolS *symbolP;
30033965Sjdp{
30133965Sjdp  md_number_to_chars ((char *) &(S_GET_OFFSET (symbolP)), S_GET_OFFSET (symbolP), sizeof (S_GET_OFFSET (symbolP)));
30233965Sjdp  md_number_to_chars ((char *) &(S_GET_DESC (symbolP)), S_GET_DESC (symbolP), sizeof (S_GET_DESC (symbolP)));
30333965Sjdp  md_number_to_chars ((char *) &(symbolP->sy_symbol.n_value), S_GET_VALUE (symbolP), sizeof (symbolP->sy_symbol.n_value));
30433965Sjdp
30533965Sjdp  append (where, (char *) &symbolP->sy_symbol, sizeof (obj_symbol_type));
30633965Sjdp}
30733965Sjdp
30833965Sjdpvoid
30933965Sjdpobj_emit_symbols (where, symbol_rootP)
31033965Sjdp     char **where;
31133965Sjdp     symbolS *symbol_rootP;
31233965Sjdp{
31333965Sjdp  symbolS *symbolP;
31433965Sjdp
31533965Sjdp  /* Emit all symbols left in the symbol chain.  */
31633965Sjdp  for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next (symbolP))
31733965Sjdp    {
31833965Sjdp      /* Used to save the offset of the name. It is used to point
31933965Sjdp	 to the string in memory but must be a file offset. */
32033965Sjdp      register char *temp;
32133965Sjdp
32233965Sjdp      temp = S_GET_NAME (symbolP);
32333965Sjdp      S_SET_OFFSET (symbolP, symbolP->sy_name_offset);
32433965Sjdp
32533965Sjdp      /* Any symbol still undefined and is not a dbg symbol is made N_EXT. */
32633965Sjdp      if (!S_IS_DEBUG (symbolP) && !S_IS_DEFINED (symbolP))
32733965Sjdp	S_SET_EXTERNAL (symbolP);
32833965Sjdp
32933965Sjdp      /* Adjust the type of a weak symbol.  */
33033965Sjdp      if (S_GET_WEAK (symbolP))
33133965Sjdp	{
33233965Sjdp	  switch (S_GET_TYPE (symbolP))
33333965Sjdp	    {
33433965Sjdp	    case N_UNDF: S_SET_TYPE (symbolP, N_WEAKU); break;
33533965Sjdp	    case N_ABS:	 S_SET_TYPE (symbolP, N_WEAKA); break;
33633965Sjdp	    case N_TEXT: S_SET_TYPE (symbolP, N_WEAKT); break;
33733965Sjdp	    case N_DATA: S_SET_TYPE (symbolP, N_WEAKD); break;
33833965Sjdp	    case N_BSS:  S_SET_TYPE (symbolP, N_WEAKB); break;
33933965Sjdp	    default: as_bad ("%s: bad type for weak symbol", temp); break;
34033965Sjdp	    }
34133965Sjdp	}
34233965Sjdp
34333965Sjdp      obj_symbol_to_chars (where, symbolP);
34433965Sjdp      S_SET_NAME (symbolP, temp);
34533965Sjdp    }
34633965Sjdp}
34733965Sjdp
34833965Sjdp#endif /* ! BFD_ASSEMBLER */
34933965Sjdp
35033965Sjdpstatic void
35133965Sjdpobj_aout_line (ignore)
35233965Sjdp     int ignore;
35333965Sjdp{
35433965Sjdp  /* Assume delimiter is part of expression.
35533965Sjdp     BSD4.2 as fails with delightful bug, so we
35633965Sjdp     are not being incompatible here. */
35733965Sjdp  new_logical_line ((char *) NULL, (int) (get_absolute_expression ()));
35833965Sjdp  demand_empty_rest_of_line ();
35933965Sjdp}				/* obj_aout_line() */
36033965Sjdp
36133965Sjdp/* Handle .weak.  This is a GNU extension.  */
36233965Sjdp
36333965Sjdpstatic void
36433965Sjdpobj_aout_weak (ignore)
36533965Sjdp     int ignore;
36633965Sjdp{
36733965Sjdp  char *name;
36833965Sjdp  int c;
36933965Sjdp  symbolS *symbolP;
37033965Sjdp
37133965Sjdp  do
37233965Sjdp    {
37333965Sjdp      name = input_line_pointer;
37433965Sjdp      c = get_symbol_end ();
37533965Sjdp      symbolP = symbol_find_or_make (name);
37633965Sjdp      *input_line_pointer = c;
37733965Sjdp      SKIP_WHITESPACE ();
37833965Sjdp      S_SET_WEAK (symbolP);
37933965Sjdp      if (c == ',')
38033965Sjdp	{
38133965Sjdp	  input_line_pointer++;
38233965Sjdp	  SKIP_WHITESPACE ();
38333965Sjdp	  if (*input_line_pointer == '\n')
38433965Sjdp	    c = '\n';
38533965Sjdp	}
38633965Sjdp    }
38733965Sjdp  while (c == ',');
38833965Sjdp  demand_empty_rest_of_line ();
38933965Sjdp}
39033965Sjdp
39133965Sjdp/* Handle .type.  On {Net,Open}BSD, this is used to set the n_other field,
39233965Sjdp   which is then apparently used when doing dynamic linking.  Older
39333965Sjdp   versions ogas ignored the .type pseudo-op, so we also ignore it if
39433965Sjdp   we can't parse it.  */
39533965Sjdp
39633965Sjdpstatic void
39733965Sjdpobj_aout_type (ignore)
39833965Sjdp     int ignore;
39933965Sjdp{
40033965Sjdp  char *name;
40133965Sjdp  int c;
40233965Sjdp  symbolS *sym;
40333965Sjdp
40433965Sjdp  name = input_line_pointer;
40533965Sjdp  c = get_symbol_end ();
40633965Sjdp  sym = symbol_find (name);
40733965Sjdp  *input_line_pointer = c;
40833965Sjdp  if (sym != NULL)
40933965Sjdp    {
41033965Sjdp      SKIP_WHITESPACE ();
41133965Sjdp      if (*input_line_pointer == ',')
41233965Sjdp	{
41333965Sjdp	  ++input_line_pointer;
41433965Sjdp	  SKIP_WHITESPACE ();
41533965Sjdp	  if (*input_line_pointer == '@')
41633965Sjdp	    {
41733965Sjdp	      ++input_line_pointer;
41833965Sjdp	      if (strncmp (input_line_pointer, "object", 6) == 0)
41933965Sjdp		S_SET_OTHER (sym, 1);
42033965Sjdp	      else if (strncmp (input_line_pointer, "function", 8) == 0)
42133965Sjdp		S_SET_OTHER (sym, 2);
42233965Sjdp	    }
42333965Sjdp	}
42433965Sjdp    }
42533965Sjdp
42633965Sjdp  /* Ignore everything else on the line.  */
42733965Sjdp  s_ignore (0);
42833965Sjdp}
42933965Sjdp
43033965Sjdpvoid
43133965Sjdpobj_read_begin_hook ()
43233965Sjdp{
43333965Sjdp}
43433965Sjdp
43533965Sjdp#ifndef BFD_ASSEMBLER
43633965Sjdp
43733965Sjdpvoid
43833965Sjdpobj_crawl_symbol_chain (headers)
43933965Sjdp     object_headers *headers;
44033965Sjdp{
44133965Sjdp  symbolS *symbolP;
44233965Sjdp  symbolS **symbolPP;
44333965Sjdp  int symbol_number = 0;
44433965Sjdp
44533965Sjdp  tc_crawl_symbol_chain (headers);
44633965Sjdp
44733965Sjdp  symbolPP = &symbol_rootP;	/*->last symbol chain link. */
44833965Sjdp  while ((symbolP = *symbolPP) != NULL)
44933965Sjdp    {
45033965Sjdp      if (symbolP->sy_mri_common)
45133965Sjdp	{
45233965Sjdp	  if (S_IS_EXTERNAL (symbolP))
45333965Sjdp	    as_bad ("%s: global symbols not supported in common sections",
45433965Sjdp		    S_GET_NAME (symbolP));
45533965Sjdp	  *symbolPP = symbol_next (symbolP);
45633965Sjdp	  continue;
45733965Sjdp	}
45833965Sjdp
45933965Sjdp      if (flag_readonly_data_in_text && (S_GET_SEGMENT (symbolP) == SEG_DATA))
46033965Sjdp	{
46133965Sjdp	  S_SET_SEGMENT (symbolP, SEG_TEXT);
46233965Sjdp	}			/* if pusing data into text */
46333965Sjdp
46433965Sjdp      resolve_symbol_value (symbolP);
46533965Sjdp
46633965Sjdp      /* Skip symbols which were equated to undefined or common
46733965Sjdp	 symbols.  */
46833965Sjdp      if (symbolP->sy_value.X_op == O_symbol
46933965Sjdp	  && (! S_IS_DEFINED (symbolP) || S_IS_COMMON (symbolP)))
47033965Sjdp	{
47133965Sjdp	  *symbolPP = symbol_next (symbolP);
47233965Sjdp	  continue;
47333965Sjdp	}
47433965Sjdp
47533965Sjdp      /* OK, here is how we decide which symbols go out into the brave
47633965Sjdp	 new symtab.  Symbols that do are:
47733965Sjdp
47833965Sjdp	 * symbols with no name (stabd's?)
47933965Sjdp	 * symbols with debug info in their N_TYPE
48033965Sjdp
48133965Sjdp	 Symbols that don't are:
48233965Sjdp	 * symbols that are registers
48333965Sjdp	 * symbols with \1 as their 3rd character (numeric labels)
48433965Sjdp	 * "local labels" as defined by S_LOCAL_NAME(name) if the -L
48533965Sjdp	 switch was passed to gas.
48633965Sjdp
48733965Sjdp	 All other symbols are output.  We complain if a deleted
48833965Sjdp	 symbol was marked external. */
48933965Sjdp
49033965Sjdp
49133965Sjdp      if (!S_IS_REGISTER (symbolP)
49233965Sjdp	  && (!S_GET_NAME (symbolP)
49333965Sjdp	      || S_IS_DEBUG (symbolP)
49433965Sjdp	      || !S_IS_DEFINED (symbolP)
49533965Sjdp	      || S_IS_EXTERNAL (symbolP)
49633965Sjdp	      || (S_GET_NAME (symbolP)[0] != '\001'
49733965Sjdp		  && (flag_keep_locals || !S_LOCAL_NAME (symbolP)))))
49833965Sjdp	{
49933965Sjdp	  symbolP->sy_number = symbol_number++;
50033965Sjdp
50133965Sjdp	  /* The + 1 after strlen account for the \0 at the
50233965Sjdp			   end of each string */
50333965Sjdp	  if (!S_IS_STABD (symbolP))
50433965Sjdp	    {
50533965Sjdp	      /* Ordinary case. */
50633965Sjdp	      symbolP->sy_name_offset = string_byte_count;
50733965Sjdp	      string_byte_count += strlen (S_GET_NAME (symbolP)) + 1;
50833965Sjdp	    }
50933965Sjdp	  else			/* .Stabd case. */
51033965Sjdp	    symbolP->sy_name_offset = 0;
51133965Sjdp	  symbolPP = &(symbol_next (symbolP));
51233965Sjdp	}
51333965Sjdp      else
51433965Sjdp	{
51533965Sjdp	  if (S_IS_EXTERNAL (symbolP) || !S_IS_DEFINED (symbolP))
51633965Sjdp	    /* This warning should never get triggered any more.
51733965Sjdp	       Well, maybe if you're doing twisted things with
51833965Sjdp	       register names...  */
51933965Sjdp	    {
52033965Sjdp	      as_bad ("Local symbol %s never defined.", decode_local_label_name (S_GET_NAME (symbolP)));
52133965Sjdp	    }			/* oops. */
52233965Sjdp
52333965Sjdp	  /* Unhook it from the chain */
52433965Sjdp	  *symbolPP = symbol_next (symbolP);
52533965Sjdp	}			/* if this symbol should be in the output */
52633965Sjdp    }				/* for each symbol */
52733965Sjdp
52833965Sjdp  H_SET_SYMBOL_TABLE_SIZE (headers, symbol_number);
52933965Sjdp}
53033965Sjdp
53133965Sjdp/*
53233965Sjdp * Find strings by crawling along symbol table chain.
53333965Sjdp */
53433965Sjdp
53533965Sjdpvoid
53633965Sjdpobj_emit_strings (where)
53733965Sjdp     char **where;
53833965Sjdp{
53933965Sjdp  symbolS *symbolP;
54033965Sjdp
54133965Sjdp#ifdef CROSS_COMPILE
54233965Sjdp  /* Gotta do md_ byte-ordering stuff for string_byte_count first - KWK */
54333965Sjdp  md_number_to_chars (*where, string_byte_count, sizeof (string_byte_count));
54433965Sjdp  *where += sizeof (string_byte_count);
54533965Sjdp#else /* CROSS_COMPILE */
54633965Sjdp  append (where, (char *) &string_byte_count, (unsigned long) sizeof (string_byte_count));
54733965Sjdp#endif /* CROSS_COMPILE */
54833965Sjdp
54933965Sjdp  for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next (symbolP))
55033965Sjdp    {
55133965Sjdp      if (S_GET_NAME (symbolP))
55233965Sjdp	append (&next_object_file_charP, S_GET_NAME (symbolP),
55333965Sjdp		(unsigned long) (strlen (S_GET_NAME (symbolP)) + 1));
55433965Sjdp    }				/* walk symbol chain */
55533965Sjdp}
55633965Sjdp
55733965Sjdp#ifndef AOUT_VERSION
55833965Sjdp#define AOUT_VERSION 0
55933965Sjdp#endif
56033965Sjdp
56133965Sjdpvoid
56233965Sjdpobj_pre_write_hook (headers)
56333965Sjdp     object_headers *headers;
56433965Sjdp{
56533965Sjdp  H_SET_DYNAMIC (headers, 0);
56633965Sjdp  H_SET_VERSION (headers, AOUT_VERSION);
56733965Sjdp  H_SET_MACHTYPE (headers, AOUT_MACHTYPE);
56833965Sjdp  tc_aout_pre_write_hook (headers);
56933965Sjdp}
57033965Sjdp
57133965Sjdpvoid
57233965SjdpDEFUN_VOID (s_sect)
57333965Sjdp{
57433965Sjdp  /* Strip out the section name */
57533965Sjdp  char *section_name;
57633965Sjdp  char *section_name_end;
57733965Sjdp  char c;
57833965Sjdp
57933965Sjdp  unsigned int len;
58033965Sjdp  unsigned int exp;
58133965Sjdp  char *save;
58233965Sjdp
58333965Sjdp  section_name = input_line_pointer;
58433965Sjdp  c = get_symbol_end ();
58533965Sjdp  section_name_end = input_line_pointer;
58633965Sjdp
58733965Sjdp  len = section_name_end - section_name;
58833965Sjdp  input_line_pointer++;
58933965Sjdp  save = input_line_pointer;
59033965Sjdp
59133965Sjdp  SKIP_WHITESPACE ();
59233965Sjdp  if (c == ',')
59333965Sjdp    {
59433965Sjdp      exp = get_absolute_expression ();
59533965Sjdp    }
59633965Sjdp  else if (*input_line_pointer == ',')
59733965Sjdp    {
59833965Sjdp      input_line_pointer++;
59933965Sjdp      exp = get_absolute_expression ();
60033965Sjdp    }
60133965Sjdp  else
60233965Sjdp    {
60333965Sjdp      input_line_pointer = save;
60433965Sjdp      exp = 0;
60533965Sjdp    }
60633965Sjdp  if (exp >= 1000)
60733965Sjdp    {
60833965Sjdp      as_bad ("subsegment index too high");
60933965Sjdp    }
61033965Sjdp
61133965Sjdp  if (strcmp (section_name, ".text") == 0)
61233965Sjdp    {
61333965Sjdp      subseg_set (SEG_TEXT, (subsegT) exp);
61433965Sjdp    }
61533965Sjdp
61633965Sjdp  if (strcmp (section_name, ".data") == 0)
61733965Sjdp    {
61833965Sjdp      if (flag_readonly_data_in_text)
61933965Sjdp	subseg_set (SEG_TEXT, (subsegT) exp + 1000);
62033965Sjdp      else
62133965Sjdp	subseg_set (SEG_DATA, (subsegT) exp);
62233965Sjdp    }
62333965Sjdp
62433965Sjdp  *section_name_end = c;
62533965Sjdp}
62633965Sjdp
62733965Sjdp#endif /* ! BFD_ASSEMBLER */
62833965Sjdp
62933965Sjdp/* end of obj-aout.c */
630