obj-aout.c revision 38889
1193323Sed/* a.out object file format
2193323Sed   Copyright (C) 1989, 90, 91, 92, 93, 94, 95, 1996
3193323Sed   Free Software Foundation, Inc.
4193323Sed
5193323SedThis file is part of GAS, the GNU Assembler.
6193323Sed
7193323SedGAS is free software; you can redistribute it and/or modify
8193323Sedit under the terms of the GNU General Public License as
9193323Sedpublished by the Free Software Foundation; either version 2,
10193323Sedor (at your option) any later version.
11193323Sed
12193323SedGAS is distributed in the hope that it will be useful, but
13193323SedWITHOUT ANY WARRANTY; without even the implied warranty of
14193323SedMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
15249423Sdimthe GNU General Public License for more details.
16249423Sdim
17193323SedYou should have received a copy of the GNU General Public
18251662SdimLicense along with GAS; see the file COPYING.  If not, write
19193323Sedto the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
20203954Srdivacky
21198892Srdivacky#include "as.h"
22249423Sdim#ifdef BFD_ASSEMBLER
23234353Sdim#undef NO_RELOC
24249423Sdim#include "aout/aout64.h"
25198090Srdivacky#endif
26193323Sed#include "obstack.h"
27234353Sdim
28234353Sdim#ifndef BFD_ASSEMBLER
29234353Sdim/* in: segT   out: N_TYPE bits */
30249423Sdimconst short seg_N_TYPE[] =
31193323Sed{
32193323Sed  N_ABS,
33193323Sed  N_TEXT,
34193323Sed  N_DATA,
35193323Sed  N_BSS,
36263508Sdim  N_UNDF,			/* unknown */
37198090Srdivacky  N_UNDF,			/* error */
38193323Sed  N_UNDF,			/* expression */
39193323Sed  N_UNDF,			/* debug */
40193323Sed  N_UNDF,			/* ntv */
41195098Sed  N_UNDF,			/* ptv */
42195098Sed  N_REGISTER,			/* register */
43195098Sed};
44193323Sed
45195098Sedconst segT N_TYPE_seg[N_TYPE + 2] =
46251662Sdim{				/* N_TYPE == 0x1E = 32-2 */
47263508Sdim  SEG_UNKNOWN,			/* N_UNDF == 0 */
48234353Sdim  SEG_GOOF,
49193323Sed  SEG_ABSOLUTE,			/* N_ABS == 2 */
50193323Sed  SEG_GOOF,
51218893Sdim  SEG_TEXT,			/* N_TEXT == 4 */
52218893Sdim  SEG_GOOF,
53193323Sed  SEG_DATA,			/* N_DATA == 6 */
54198090Srdivacky  SEG_GOOF,
55198892Srdivacky  SEG_BSS,			/* N_BSS == 8 */
56198892Srdivacky  SEG_GOOF,
57198892Srdivacky  SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF,
58198892Srdivacky  SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF,
59198892Srdivacky  SEG_GOOF, SEG_GOOF, SEG_GOOF, SEG_GOOF,
60198892Srdivacky  SEG_REGISTER,			/* dummy N_REGISTER for regs = 30 */
61198892Srdivacky  SEG_GOOF,
62198090Srdivacky};
63198892Srdivacky#endif
64198892Srdivacky
65198090Srdivackystatic void obj_aout_line PARAMS ((int));
66193323Sedstatic void obj_aout_weak PARAMS ((int));
67198090Srdivackystatic void obj_aout_type PARAMS ((int));
68198090Srdivacky
69193323Sedconst pseudo_typeS obj_pseudo_table[] =
70193323Sed{
71198892Srdivacky  {"line", obj_aout_line, 0},	/* source code line number */
72193323Sed  {"ln", obj_aout_line, 0},	/* coff line number that we use anyway */
73193323Sed
74193323Sed  {"weak", obj_aout_weak, 0},	/* mark symbol as weak.  */
75193323Sed
76193323Sed  {"type", obj_aout_type, 0},
77198090Srdivacky
78193323Sed  /* coff debug pseudos (ignored) */
79193323Sed  {"def", s_ignore, 0},
80198892Srdivacky  {"dim", s_ignore, 0},
81198090Srdivacky  {"endef", s_ignore, 0},
82218893Sdim  {"ident", s_ignore, 0},
83193323Sed  {"line", s_ignore, 0},
84193323Sed  {"ln", s_ignore, 0},
85193323Sed  {"scl", s_ignore, 0},
86198090Srdivacky  {"size", s_ignore, 0},
87193323Sed  {"tag", s_ignore, 0},
88193323Sed  {"val", s_ignore, 0},
89193323Sed  {"version", s_ignore, 0},
90198090Srdivacky
91218893Sdim  {"optim", s_ignore, 0},	/* For sun386i cc (?) */
92218893Sdim
93243830Sdim  /* other stuff */
94198090Srdivacky  {"ABORT", s_abort, 0},
95193323Sed
96193323Sed  {NULL}			/* end sentinel */
97218893Sdim};				/* obj_pseudo_table */
98218893Sdim
99218893Sdim
100218893Sdim#ifdef BFD_ASSEMBLER
101218893Sdim
102218893Sdimvoid
103218893Sdimobj_aout_frob_symbol (sym, punt)
104218893Sdim     symbolS *sym;
105218893Sdim     int *punt;
106218893Sdim{
107193323Sed  flagword flags;
108218893Sdim  asection *sec;
109243830Sdim  int desc, type, other;
110218893Sdim
111218893Sdim  flags = sym->bsym->flags;
112198892Srdivacky  desc = S_GET_DESC (sym);
113218893Sdim  type = S_GET_TYPE (sym);
114218893Sdim  other = S_GET_OTHER (sym);
115193323Sed  sec = sym->bsym->section;
116218893Sdim
117218893Sdim  /* Only frob simple symbols this way right now.  */
118218893Sdim  if (! (type & ~ (N_TYPE | N_EXT)))
119193323Sed    {
120193323Sed      if (type == (N_UNDF | N_EXT)
121198090Srdivacky	  && sec == &bfd_abs_section)
122198090Srdivacky	sym->bsym->section = sec = bfd_und_section_ptr;
123193323Sed
124218893Sdim      if ((type & N_TYPE) != N_INDR
125218893Sdim	  && (type & N_TYPE) != N_SETA
126203954Srdivacky	  && (type & N_TYPE) != N_SETT
127221345Sdim	  && (type & N_TYPE) != N_SETD
128243830Sdim	  && (type & N_TYPE) != N_SETB
129221345Sdim	  && type != N_WARNING
130193323Sed	  && (sec == &bfd_abs_section
131218893Sdim	      || sec == &bfd_und_section))
132193323Sed	return;
133193323Sed      if (flags & BSF_EXPORT)
134218893Sdim	type |= N_EXT;
135218893Sdim
136203954Srdivacky      switch (type & N_TYPE)
137203954Srdivacky	{
138203954Srdivacky	case N_SETA:
139203954Srdivacky	case N_SETT:
140203954Srdivacky	case N_SETD:
141223017Sdim	case N_SETB:
142218893Sdim	  /* Set the debugging flag for constructor symbols so that
143218893Sdim	     BFD leaves them alone.  */
144218893Sdim	  sym->bsym->flags |= BSF_DEBUGGING;
145263508Sdim
146218893Sdim	  /* You can't put a common symbol in a set.  The way a set
147223017Sdim	     element works is that the symbol has a definition and a
148226633Sdim	     name, and the linker adds the definition to the set of
149193323Sed	     that name.  That does not work for a common symbol,
150193323Sed	     because the linker can't tell which common symbol the
151218893Sdim	     user means.  FIXME: Using as_bad here may be
152218893Sdim	     inappropriate, since the user may want to force a
153218893Sdim	     particular type without regard to the semantics of sets;
154221345Sdim	     on the other hand, we certainly don't want anybody to be
155193323Sed	     mislead into thinking that their code will work.  */
156263508Sdim	  if (S_IS_COMMON (sym))
157193323Sed	    as_bad ("Attempt to put a common symbol into set %s",
158193323Sed		    S_GET_NAME (sym));
159218893Sdim	  /* Similarly, you can't put an undefined symbol in a set.  */
160193323Sed	  else if (! S_IS_DEFINED (sym))
161193323Sed	    as_bad ("Attempt to put an undefined symbol into set %s",
162193323Sed		    S_GET_NAME (sym));
163193323Sed
164193323Sed	  break;
165193323Sed	case N_INDR:
166193323Sed	  /* Put indirect symbols in the indirect section.  */
167193323Sed	  sym->bsym->section = bfd_ind_section_ptr;
168193323Sed	  sym->bsym->flags |= BSF_INDIRECT;
169203954Srdivacky	  if (type & N_EXT)
170218893Sdim	    {
171218893Sdim	      sym->bsym->flags |= BSF_EXPORT;
172218893Sdim	      sym->bsym->flags &=~ BSF_LOCAL;
173218893Sdim	    }
174221345Sdim	  break;
175218893Sdim	case N_WARNING:
176218893Sdim	  /* Mark warning symbols.  */
177203954Srdivacky	  sym->bsym->flags |= BSF_WARNING;
178193323Sed	  break;
179193323Sed	}
180193323Sed    }
181226633Sdim  else
182198090Srdivacky    {
183198090Srdivacky      sym->bsym->flags |= BSF_DEBUGGING;
184193323Sed    }
185193323Sed
186203954Srdivacky  S_SET_TYPE (sym, type);
187198090Srdivacky
188198090Srdivacky  /* Double check weak symbols.  */
189198090Srdivacky  if (sym->bsym->flags & BSF_WEAK)
190203954Srdivacky    {
191193323Sed      if (S_IS_COMMON (sym))
192193323Sed	as_bad ("Symbol `%s' can not be both weak and common",
193193323Sed		S_GET_NAME (sym));
194226633Sdim    }
195199481Srdivacky}
196226633Sdim
197210299Sedvoid
198226633Sdimobj_aout_frob_file ()
199193323Sed{
200203954Srdivacky  /* Relocation processing may require knowing the VMAs of the sections.
201203954Srdivacky     Since writing to a section will cause the BFD back end to compute the
202203954Srdivacky     VMAs, fake it out here....  */
203203954Srdivacky  bfd_byte b = 0;
204203954Srdivacky  boolean x = true;
205193323Sed  if (bfd_section_size (stdoutput, text_section) != 0)
206221345Sdim    {
207218893Sdim      x = bfd_set_section_contents (stdoutput, text_section, &b, (file_ptr) 0,
208193323Sed				    (bfd_size_type) 1);
209243830Sdim    }
210193323Sed  else if (bfd_section_size (stdoutput, data_section) != 0)
211203954Srdivacky    {
212203954Srdivacky      x = bfd_set_section_contents (stdoutput, data_section, &b, (file_ptr) 0,
213203954Srdivacky				    (bfd_size_type) 1);
214193323Sed    }
215193323Sed  assert (x == true);
216193323Sed}
217193323Sed
218263508Sdim#else
219221345Sdim
220193323Sed/* Relocation. */
221193323Sed
222193323Sed/*
223193323Sed *		emit_relocations()
224193323Sed *
225234353Sdim * Crawl along a fixS chain. Emit the segment's relocations.
226234353Sdim */
227234353Sdimvoid
228234353Sdimobj_emit_relocations (where, fixP, segment_address_in_file)
229234353Sdim     char **where;
230234353Sdim     fixS *fixP;		/* Fixup chain for this segment. */
231234353Sdim     relax_addressT segment_address_in_file;
232234353Sdim{
233263508Sdim  for (; fixP; fixP = fixP->fx_next)
234263508Sdim    if (fixP->fx_done == 0)
235263508Sdim      {
236263508Sdim	symbolS *sym;
237263508Sdim
238234353Sdim	sym = fixP->fx_addsy;
239234353Sdim	while (sym->sy_value.X_op == O_symbol
240234353Sdim	       && (! S_IS_DEFINED (sym) || S_IS_COMMON (sym)))
241234353Sdim	  sym = sym->sy_value.X_add_symbol;
242234353Sdim	fixP->fx_addsy = sym;
243234353Sdim
244234353Sdim	if (! sym->sy_resolved && ! S_IS_DEFINED (sym))
245243830Sdim	  {
246234353Sdim	    char *file;
247234353Sdim	    unsigned int line;
248234353Sdim
249234353Sdim	    if (expr_symbol_where (sym, &file, &line))
250263508Sdim	      as_bad_where (file, line, "unresolved relocation");
251263508Sdim	    else
252263508Sdim	      as_bad ("bad relocation: symbol `%s' not in symbol table",
253263508Sdim		      S_GET_NAME (sym));
254263508Sdim	  }
255263508Sdim
256263508Sdim	tc_aout_fix_to_chars (*where, fixP, segment_address_in_file);
257263508Sdim	*where += md_reloc_size;
258263508Sdim      }
259263508Sdim}
260263508Sdim
261263508Sdim#ifndef obj_header_append
262263508Sdim/* Aout file generation & utilities */
263263508Sdimvoid
264263508Sdimobj_header_append (where, headers)
265263508Sdim     char **where;
266263508Sdim     object_headers *headers;
267263508Sdim{
268263508Sdim  tc_headers_hook (headers);
269263508Sdim
270263508Sdim#ifdef CROSS_COMPILE
271263508Sdim  md_number_to_chars (*where, headers->header.a_info, sizeof (headers->header.a_info));
272263508Sdim  *where += sizeof (headers->header.a_info);
273263508Sdim  md_number_to_chars (*where, headers->header.a_text, sizeof (headers->header.a_text));
274263508Sdim  *where += sizeof (headers->header.a_text);
275243830Sdim  md_number_to_chars (*where, headers->header.a_data, sizeof (headers->header.a_data));
276243830Sdim  *where += sizeof (headers->header.a_data);
277193323Sed  md_number_to_chars (*where, headers->header.a_bss, sizeof (headers->header.a_bss));
278218893Sdim  *where += sizeof (headers->header.a_bss);
279218893Sdim  md_number_to_chars (*where, headers->header.a_syms, sizeof (headers->header.a_syms));
280218893Sdim  *where += sizeof (headers->header.a_syms);
281263508Sdim  md_number_to_chars (*where, headers->header.a_entry, sizeof (headers->header.a_entry));
282218893Sdim  *where += sizeof (headers->header.a_entry);
283193323Sed  md_number_to_chars (*where, headers->header.a_trsize, sizeof (headers->header.a_trsize));
284218893Sdim  *where += sizeof (headers->header.a_trsize);
285218893Sdim  md_number_to_chars (*where, headers->header.a_drsize, sizeof (headers->header.a_drsize));
286218893Sdim  *where += sizeof (headers->header.a_drsize);
287193323Sed
288221345Sdim#else /* CROSS_COMPILE */
289221345Sdim
290193323Sed  append (where, (char *) &headers->header, sizeof (headers->header));
291193323Sed#endif /* CROSS_COMPILE */
292193323Sed
293193323Sed}
294193323Sed#endif
295193323Sed
296193323Sedvoid
297193323Sedobj_symbol_to_chars (where, symbolP)
298193323Sed     char **where;
299193323Sed     symbolS *symbolP;
300193323Sed{
301198090Srdivacky  md_number_to_chars ((char *) &(S_GET_OFFSET (symbolP)), S_GET_OFFSET (symbolP), sizeof (S_GET_OFFSET (symbolP)));
302198090Srdivacky  md_number_to_chars ((char *) &(S_GET_DESC (symbolP)), S_GET_DESC (symbolP), sizeof (S_GET_DESC (symbolP)));
303193323Sed  md_number_to_chars ((char *) &(symbolP->sy_symbol.n_value), S_GET_VALUE (symbolP), sizeof (symbolP->sy_symbol.n_value));
304221345Sdim
305218893Sdim  append (where, (char *) &symbolP->sy_symbol, sizeof (obj_symbol_type));
306218893Sdim}
307193323Sed
308221345Sdimvoid
309193323Sedobj_emit_symbols (where, symbol_rootP)
310193323Sed     char **where;
311193323Sed     symbolS *symbol_rootP;
312221345Sdim{
313193323Sed  symbolS *symbolP;
314193323Sed
315193323Sed  /* Emit all symbols left in the symbol chain.  */
316193323Sed  for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next (symbolP))
317193323Sed    {
318221345Sdim      /* Used to save the offset of the name. It is used to point
319193323Sed	 to the string in memory but must be a file offset. */
320193323Sed      register char *temp;
321193323Sed
322263508Sdim      temp = S_GET_NAME (symbolP);
323263508Sdim      S_SET_OFFSET (symbolP, symbolP->sy_name_offset);
324263508Sdim
325193323Sed      /* Any symbol still undefined and is not a dbg symbol is made N_EXT. */
326193323Sed      if (!S_IS_DEBUG (symbolP) && !S_IS_DEFINED (symbolP))
327193323Sed	S_SET_EXTERNAL (symbolP);
328218893Sdim
329263508Sdim      /* Adjust the type of a weak symbol.  */
330263508Sdim      if (S_GET_WEAK (symbolP))
331263508Sdim	{
332193323Sed	  switch (S_GET_TYPE (symbolP))
333193323Sed	    {
334193323Sed	    case N_UNDF: S_SET_TYPE (symbolP, N_WEAKU); break;
335193323Sed	    case N_ABS:	 S_SET_TYPE (symbolP, N_WEAKA); break;
336198090Srdivacky	    case N_TEXT: S_SET_TYPE (symbolP, N_WEAKT); break;
337198892Srdivacky	    case N_DATA: S_SET_TYPE (symbolP, N_WEAKD); break;
338198892Srdivacky	    case N_BSS:  S_SET_TYPE (symbolP, N_WEAKB); break;
339263508Sdim	    default: as_bad ("%s: bad type for weak symbol", temp); break;
340263508Sdim	    }
341263508Sdim	}
342193323Sed
343193323Sed      obj_symbol_to_chars (where, symbolP);
344198892Srdivacky      S_SET_NAME (symbolP, temp);
345198892Srdivacky    }
346198892Srdivacky}
347263508Sdim
348263508Sdim#endif /* ! BFD_ASSEMBLER */
349198892Srdivacky
350221345Sdimstatic void
351193323Sedobj_aout_line (ignore)
352193323Sed     int ignore;
353198090Srdivacky{
354198090Srdivacky  /* Assume delimiter is part of expression.
355263508Sdim     BSD4.2 as fails with delightful bug, so we
356263508Sdim     are not being incompatible here. */
357263508Sdim  new_logical_line ((char *) NULL, (int) (get_absolute_expression ()));
358193323Sed  demand_empty_rest_of_line ();
359193323Sed}				/* obj_aout_line() */
360193323Sed
361193323Sed/* Handle .weak.  This is a GNU extension.  */
362193323Sed
363263508Sdimstatic void
364263508Sdimobj_aout_weak (ignore)
365263508Sdim     int ignore;
366263508Sdim{
367263508Sdim  char *name;
368263508Sdim  int c;
369263508Sdim  symbolS *symbolP;
370263508Sdim
371263508Sdim  do
372263508Sdim    {
373263508Sdim      name = input_line_pointer;
374263508Sdim      c = get_symbol_end ();
375263508Sdim      symbolP = symbol_find_or_make (name);
376263508Sdim      *input_line_pointer = c;
377263508Sdim      SKIP_WHITESPACE ();
378263508Sdim      S_SET_WEAK (symbolP);
379263508Sdim      if (c == ',')
380263508Sdim	{
381193323Sed	  input_line_pointer++;
382194178Sed	  SKIP_WHITESPACE ();
383193323Sed	  if (*input_line_pointer == '\n')
384193323Sed	    c = '\n';
385193323Sed	}
386193323Sed    }
387193323Sed  while (c == ',');
388193323Sed  demand_empty_rest_of_line ();
389218893Sdim}
390218893Sdim
391218893Sdim/* Handle .type.  On {Net,Open}BSD, this is used to set the n_other field,
392218893Sdim   which is then apparently used when doing dynamic linking.  Older
393193323Sed   versions ogas ignored the .type pseudo-op, so we also ignore it if
394226633Sdim   we can't parse it.  */
395218893Sdim
396193323Sedstatic void
397193323Sedobj_aout_type (ignore)
398218893Sdim     int ignore;
399218893Sdim{
400218893Sdim  char *name;
401218893Sdim  int c;
402218893Sdim  symbolS *sym;
403193323Sed
404193323Sed  name = input_line_pointer;
405193323Sed  c = get_symbol_end ();
406193323Sed  sym = symbol_find (name);
407193323Sed  *input_line_pointer = c;
408193323Sed  if (sym != NULL)
409193323Sed    {
410193323Sed      SKIP_WHITESPACE ();
411193323Sed      if (*input_line_pointer == ',')
412198090Srdivacky	{
413263508Sdim	  ++input_line_pointer;
414263508Sdim	  SKIP_WHITESPACE ();
415263508Sdim	  if (*input_line_pointer == '@')
416193323Sed	    {
417239462Sdim	      ++input_line_pointer;
418193323Sed	      if (strncmp (input_line_pointer, "object", 6) == 0)
419195098Sed		S_SET_OTHER (sym, 1);
420195098Sed	      else if (strncmp (input_line_pointer, "function", 8) == 0)
421195098Sed		S_SET_OTHER (sym, 2);
422195098Sed	    }
423195098Sed	}
424198090Srdivacky    }
425198090Srdivacky
426195098Sed  /* Ignore everything else on the line.  */
427251662Sdim  s_ignore (0);
428251662Sdim}
429251662Sdim
430251662Sdimvoid
431251662Sdimobj_read_begin_hook ()
432251662Sdim{
433198892Srdivacky}
434198892Srdivacky
435198892Srdivacky#ifndef BFD_ASSEMBLER
436198892Srdivacky
437198892Srdivackyvoid
438198892Srdivackyobj_crawl_symbol_chain (headers)
439198892Srdivacky     object_headers *headers;
440198892Srdivacky{
441198892Srdivacky  symbolS *symbolP;
442198892Srdivacky  symbolS **symbolPP;
443198892Srdivacky  int symbol_number = 0;
444198892Srdivacky
445198892Srdivacky  tc_crawl_symbol_chain (headers);
446193323Sed
447198892Srdivacky  symbolPP = &symbol_rootP;	/*->last symbol chain link. */
448193323Sed  while ((symbolP = *symbolPP) != NULL)
449198892Srdivacky    {
450198892Srdivacky      if (symbolP->sy_mri_common)
451198892Srdivacky	{
452198892Srdivacky	  if (S_IS_EXTERNAL (symbolP))
453198892Srdivacky	    as_bad ("%s: global symbols not supported in common sections",
454193323Sed		    S_GET_NAME (symbolP));
455198892Srdivacky	  *symbolPP = symbol_next (symbolP);
456193323Sed	  continue;
457193323Sed	}
458193323Sed
459193323Sed      if (flag_readonly_data_in_text && (S_GET_SEGMENT (symbolP) == SEG_DATA))
460193323Sed	{
461193323Sed	  S_SET_SEGMENT (symbolP, SEG_TEXT);
462193323Sed	}			/* if pusing data into text */
463193323Sed
464193323Sed      resolve_symbol_value (symbolP, 1);
465193323Sed
466193323Sed      /* Skip symbols which were equated to undefined or common
467193323Sed	 symbols.  */
468193323Sed      if (symbolP->sy_value.X_op == O_symbol
469193323Sed	  && (! S_IS_DEFINED (symbolP) || S_IS_COMMON (symbolP)))
470193323Sed	{
471193323Sed	  *symbolPP = symbol_next (symbolP);
472193323Sed	  continue;
473193323Sed	}
474193323Sed
475193323Sed      /* OK, here is how we decide which symbols go out into the brave
476193323Sed	 new symtab.  Symbols that do are:
477199481Srdivacky
478193323Sed	 * symbols with no name (stabd's?)
479193323Sed	 * symbols with debug info in their N_TYPE
480193323Sed
481193323Sed	 Symbols that don't are:
482193323Sed	 * symbols that are registers
483193323Sed	 * symbols with \1 as their 3rd character (numeric labels)
484221345Sdim	 * "local labels" as defined by S_LOCAL_NAME(name) if the -L
485193323Sed	 switch was passed to gas.
486203954Srdivacky
487193323Sed	 All other symbols are output.  We complain if a deleted
488193323Sed	 symbol was marked external. */
489193323Sed
490193323Sed
491193323Sed      if (!S_IS_REGISTER (symbolP)
492193323Sed	  && (!S_GET_NAME (symbolP)
493221345Sdim	      || S_IS_DEBUG (symbolP)
494226633Sdim	      || !S_IS_DEFINED (symbolP)
495193323Sed	      || S_IS_EXTERNAL (symbolP)
496193323Sed	      || (S_GET_NAME (symbolP)[0] != '\001'
497198090Srdivacky		  && (flag_keep_locals || !S_LOCAL_NAME (symbolP)))))
498198090Srdivacky	{
499198090Srdivacky	  symbolP->sy_number = symbol_number++;
500198090Srdivacky
501198090Srdivacky	  /* The + 1 after strlen account for the \0 at the
502198090Srdivacky			   end of each string */
503198090Srdivacky	  if (!S_IS_STABD (symbolP))
504198090Srdivacky	    {
505198090Srdivacky	      /* Ordinary case. */
506198090Srdivacky	      symbolP->sy_name_offset = string_byte_count;
507198090Srdivacky	      string_byte_count += strlen (S_GET_NAME (symbolP)) + 1;
508198090Srdivacky	    }
509198090Srdivacky	  else			/* .Stabd case. */
510218893Sdim	    symbolP->sy_name_offset = 0;
511203954Srdivacky	  symbolPP = &(symbol_next (symbolP));
512198090Srdivacky	}
513198090Srdivacky      else
514198090Srdivacky	{
515263508Sdim	  if (S_IS_EXTERNAL (symbolP) || !S_IS_DEFINED (symbolP))
516198090Srdivacky	    /* This warning should never get triggered any more.
517198090Srdivacky	       Well, maybe if you're doing twisted things with
518234353Sdim	       register names...  */
519226633Sdim	    {
520199481Srdivacky	      as_bad ("Local symbol %s never defined.", decode_local_label_name (S_GET_NAME (symbolP)));
521203954Srdivacky	    }			/* oops. */
522203954Srdivacky
523203954Srdivacky	  /* Unhook it from the chain */
524218893Sdim	  *symbolPP = symbol_next (symbolP);
525198090Srdivacky	}			/* if this symbol should be in the output */
526198090Srdivacky    }				/* for each symbol */
527198090Srdivacky
528198090Srdivacky  H_SET_SYMBOL_TABLE_SIZE (headers, symbol_number);
529198090Srdivacky}
530198090Srdivacky
531263508Sdim/*
532198090Srdivacky * Find strings by crawling along symbol table chain.
533234353Sdim */
534198090Srdivacky
535226633Sdimvoid
536226633Sdimobj_emit_strings (where)
537218893Sdim     char **where;
538198090Srdivacky{
539198090Srdivacky  symbolS *symbolP;
540218893Sdim
541198090Srdivacky#ifdef CROSS_COMPILE
542203954Srdivacky  /* Gotta do md_ byte-ordering stuff for string_byte_count first - KWK */
543203954Srdivacky  md_number_to_chars (*where, string_byte_count, sizeof (string_byte_count));
544198090Srdivacky  *where += sizeof (string_byte_count);
545198090Srdivacky#else /* CROSS_COMPILE */
546198090Srdivacky  append (where, (char *) &string_byte_count, (unsigned long) sizeof (string_byte_count));
547198090Srdivacky#endif /* CROSS_COMPILE */
548198090Srdivacky
549198090Srdivacky  for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next (symbolP))
550198090Srdivacky    {
551198090Srdivacky      if (S_GET_NAME (symbolP))
552198090Srdivacky	append (&next_object_file_charP, S_GET_NAME (symbolP),
553263508Sdim		(unsigned long) (strlen (S_GET_NAME (symbolP)) + 1));
554263508Sdim    }				/* walk symbol chain */
555263508Sdim}
556263508Sdim
557263508Sdim#ifndef AOUT_VERSION
558263508Sdim#define AOUT_VERSION 0
559263508Sdim#endif
560263508Sdim
561263508Sdimvoid
562263508Sdimobj_pre_write_hook (headers)
563263508Sdim     object_headers *headers;
564263508Sdim{
565263508Sdim  H_SET_DYNAMIC (headers, 0);
566198090Srdivacky  H_SET_VERSION (headers, AOUT_VERSION);
567263508Sdim  H_SET_MACHTYPE (headers, AOUT_MACHTYPE);
568263508Sdim  tc_aout_pre_write_hook (headers);
569263508Sdim}
570263508Sdim
571263508Sdimvoid
572263508SdimDEFUN_VOID (s_sect)
573263508Sdim{
574198090Srdivacky  /* Strip out the section name */
575263508Sdim  char *section_name;
576198090Srdivacky  char *section_name_end;
577198090Srdivacky  char c;
578198090Srdivacky
579198090Srdivacky  unsigned int len;
580198090Srdivacky  unsigned int exp;
581198090Srdivacky  char *save;
582198090Srdivacky
583198090Srdivacky  section_name = input_line_pointer;
584198090Srdivacky  c = get_symbol_end ();
585198090Srdivacky  section_name_end = input_line_pointer;
586198090Srdivacky
587198090Srdivacky  len = section_name_end - section_name;
588198090Srdivacky  input_line_pointer++;
589198090Srdivacky  save = input_line_pointer;
590198090Srdivacky
591198090Srdivacky  SKIP_WHITESPACE ();
592198090Srdivacky  if (c == ',')
593198090Srdivacky    {
594234353Sdim      exp = get_absolute_expression ();
595234353Sdim    }
596234353Sdim  else if (*input_line_pointer == ',')
597234353Sdim    {
598234353Sdim      input_line_pointer++;
599234353Sdim      exp = get_absolute_expression ();
600234353Sdim    }
601226633Sdim  else
602226633Sdim    {
603226633Sdim      input_line_pointer = save;
604226633Sdim      exp = 0;
605226633Sdim    }
606226633Sdim  if (exp >= 1000)
607226633Sdim    {
608199481Srdivacky      as_bad ("subsegment index too high");
609226633Sdim    }
610226633Sdim
611199481Srdivacky  if (strcmp (section_name, ".text") == 0)
612199481Srdivacky    {
613199481Srdivacky      subseg_set (SEG_TEXT, (subsegT) exp);
614199481Srdivacky    }
615199481Srdivacky
616198090Srdivacky  if (strcmp (section_name, ".data") == 0)
617198090Srdivacky    {
618198090Srdivacky      if (flag_readonly_data_in_text)
619198090Srdivacky	subseg_set (SEG_TEXT, (subsegT) exp + 1000);
620198090Srdivacky      else
621198090Srdivacky	subseg_set (SEG_DATA, (subsegT) exp);
622198090Srdivacky    }
623198090Srdivacky
624198090Srdivacky  *section_name_end = c;
625198090Srdivacky}
626198090Srdivacky
627198090Srdivacky#endif /* ! BFD_ASSEMBLER */
628203954Srdivacky
629203954Srdivacky/* end of obj-aout.c */
630203954Srdivacky