/* a.out object file format
- Copyright (C) 1989, 1990, 1991 Free Software Foundation, Inc.
+ Copyright (C) 1989, 1990, 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include "as.h"
-#include "aout/stab_gnu.h"
+#ifdef BFD_ASSEMBLER
+#undef NO_RELOC
+#include "aout/aout64.h"
+#endif
#include "obstack.h"
#ifndef BFD_ASSEMBLER
N_DATA,
N_BSS,
N_UNDF, /* unknown */
- N_UNDF, /* absent */
- N_UNDF, /* pass1 */
N_UNDF, /* error */
- N_UNDF, /* bignum/flonum */
- N_UNDF, /* difference */
+ N_UNDF, /* expression */
N_UNDF, /* debug */
N_UNDF, /* ntv */
N_UNDF, /* ptv */
};
#endif
-static void obj_aout_stab PARAMS ((int what));
-static void obj_aout_line PARAMS ((void));
-static void obj_aout_desc PARAMS ((void));
+static void obj_aout_line PARAMS ((int));
+static void obj_aout_weak PARAMS ((int));
const pseudo_typeS obj_pseudo_table[] =
{
- /* stabs debug info */
{"line", obj_aout_line, 0}, /* source code line number */
{"ln", obj_aout_line, 0}, /* coff line number that we use anyway */
- {"desc", obj_aout_desc, 0}, /* desc */
- {"stabd", obj_aout_stab, 'd'},/* stabs */
- {"stabn", obj_aout_stab, 'n'},/* stabs */
- {"stabs", obj_aout_stab, 's'},/* stabs */
+
+ {"weak", obj_aout_weak, 0}, /* mark symbol as weak. */
/* coff debug pseudos (ignored) */
{"def", s_ignore, 0},
{"val", s_ignore, 0},
{"version", s_ignore, 0},
- /* stabs-in-coff (?) debug pseudos (ignored) */
{"optim", s_ignore, 0}, /* For sun386i cc (?) */
/* other stuff */
asection *sec;
int desc, type, other;
- /* Is this part format-dependent? */
- if (sym->sy_forward)
- {
- S_SET_VALUE (sym,
- S_GET_VALUE (sym)
- + S_GET_VALUE (sym->sy_forward)
- + sym->sy_forward->sy_frag->fr_address
- );
- sym->sy_forward = 0;
- }
-
flags = sym->bsym->flags;
desc = S_GET_DESC (sym);
type = S_GET_TYPE (sym);
sec = sym->bsym->section;
/* Only frob simple symbols this way right now. */
- if (! (type & ~0x1f))
+ if (! (type & ~ (N_TYPE | N_EXT)))
{
- if (sec == &bfd_abs_section
- || sec == &bfd_und_section)
+ if (type == (N_UNDF | N_EXT)
+ && sec == &bfd_abs_section)
+ sym->bsym->section = sec = bfd_und_section_ptr;
+
+ if ((type & N_TYPE) != N_INDR
+ && (type & N_TYPE) != N_SETA
+ && (type & N_TYPE) != N_SETT
+ && (type & N_TYPE) != N_SETD
+ && (type & N_TYPE) != N_SETB
+ && type != N_WARNING
+ && (sec == &bfd_abs_section
+ || sec == &bfd_und_section))
return;
if (flags & BSF_EXPORT)
- type |= 1;
+ type |= N_EXT;
+
+ switch (type & N_TYPE)
+ {
+ case N_SETA:
+ case N_SETT:
+ case N_SETD:
+ case N_SETB:
+ /* Set the debugging flag for constructor symbols so that
+ BFD leaves them alone. */
+ sym->bsym->flags |= BSF_DEBUGGING;
+
+ /* You can't put a common symbol in a set. The way a set
+ element works is that the symbol has a definition and a
+ name, and the linker adds the definition to the set of
+ that name. That does not work for a common symbol,
+ because the linker can't tell which common symbol the
+ user means. FIXME: Using as_bad here may be
+ inappropriate, since the user may want to force a
+ particular type without regard to the semantics of sets;
+ on the other hand, we certainly don't want anybody to be
+ mislead into thinking that their code will work. */
+ if (S_IS_COMMON (sym))
+ as_bad ("Attempt to put a common symbol into set %s",
+ S_GET_NAME (sym));
+ /* Similarly, you can't put an undefined symbol in a set. */
+ else if (! S_IS_DEFINED (sym))
+ as_bad ("Attempt to put an undefined symbol into set %s",
+ S_GET_NAME (sym));
+
+ break;
+ case N_INDR:
+ /* Put indirect symbols in the indirect section. */
+ sym->bsym->section = bfd_ind_section_ptr;
+ sym->bsym->flags |= BSF_INDIRECT;
+ if (type & N_EXT)
+ {
+ sym->bsym->flags |= BSF_EXPORT;
+ sym->bsym->flags &=~ BSF_LOCAL;
+ }
+ break;
+ case N_WARNING:
+ /* Mark warning symbols. */
+ sym->bsym->flags |= BSF_WARNING;
+ break;
+ }
}
else
{
}
S_SET_TYPE (sym, type);
+
+ /* Double check weak symbols. */
+ if (sym->bsym->flags & BSF_WEAK)
+ {
+ if (S_IS_COMMON (sym))
+ as_bad ("Symbol `%s' can not be both weak and common",
+ S_GET_NAME (sym));
+ }
+}
+
+void
+obj_aout_frob_file ()
+{
+ /* Relocation processing may require knowing the VMAs of the sections.
+ Since writing to a section will cause the BFD back end to compute the
+ VMAs, fake it out here.... */
+ bfd_byte b = 0;
+ boolean x = true;
+ if (bfd_section_size (stdoutput, text_section) != 0)
+ {
+ x = bfd_set_section_contents (stdoutput, text_section, &b, (file_ptr) 0,
+ (bfd_size_type) 1);
+ }
+ else if (bfd_section_size (stdoutput, data_section) != 0)
+ {
+ x = bfd_set_section_contents (stdoutput, data_section, &b, (file_ptr) 0,
+ (bfd_size_type) 1);
+ }
+ assert (x == true);
}
#else
relax_addressT segment_address_in_file;
{
for (; fixP; fixP = fixP->fx_next)
- if (fixP->fx_addsy != NULL)
+ if (fixP->fx_done == 0)
{
tc_aout_fix_to_chars (*where, fixP, segment_address_in_file);
*where += md_reloc_size;
if (!S_IS_DEBUG (symbolP) && !S_IS_DEFINED (symbolP))
S_SET_EXTERNAL (symbolP);
+ /* Adjust the type of a weak symbol. */
+ if (S_GET_WEAK (symbolP))
+ {
+ switch (S_GET_TYPE (symbolP))
+ {
+ case N_UNDF: S_SET_TYPE (symbolP, N_WEAKU); break;
+ case N_ABS: S_SET_TYPE (symbolP, N_WEAKA); break;
+ case N_TEXT: S_SET_TYPE (symbolP, N_WEAKT); break;
+ case N_DATA: S_SET_TYPE (symbolP, N_WEAKD); break;
+ case N_BSS: S_SET_TYPE (symbolP, N_WEAKB); break;
+ default: as_bad ("%s: bad type for weak symbol", temp); break;
+ }
+ }
+
obj_symbol_to_chars (where, symbolP);
S_SET_NAME (symbolP, temp);
}
#endif /* ! BFD_ASSEMBLER */
static void
-obj_aout_line ()
+obj_aout_line (ignore)
+ int ignore;
{
/* Assume delimiter is part of expression.
BSD4.2 as fails with delightful bug, so we
demand_empty_rest_of_line ();
} /* obj_aout_line() */
-/*
- * stab()
- *
- * Handle .stabX directives, which used to be open-coded.
- * So much creeping featurism overloaded the semantics that we decided
- * to put all .stabX thinking in one place. Here.
- *
- * We try to make any .stabX directive legal. Other people's AS will often
- * do assembly-time consistency checks: eg assigning meaning to n_type bits
- * and "protecting" you from setting them to certain values. (They also zero
- * certain bits before emitting symbols. Tut tut.)
- *
- * If an expression is not absolute we either gripe or use the relocation
- * information. Other people's assemblers silently forget information they
- * don't need and invent information they need that you didn't supply.
- *
- * .stabX directives always make a symbol table entry. It may be junk if
- * the rest of your .stabX directive is malformed.
- */
+/* Handle .weak. This is a GNU extension. */
+
static void
-obj_aout_stab (what)
- int what;
+obj_aout_weak (ignore)
+ int ignore;
{
- extern int listing;
-
- register symbolS *symbolP = 0;
- register char *string;
- int saved_type = 0;
- int length;
- int goof; /* TRUE if we have aborted. */
- long longint;
-
- /*
- * Enter with input_line_pointer pointing past .stabX and any following
- * whitespace.
- */
- goof = 0; /* JF who forgot this?? */
- if (what == 's')
- {
- string = demand_copy_C_string (&length);
- SKIP_WHITESPACE ();
- if (*input_line_pointer == ',')
- input_line_pointer++;
- else
- {
- as_bad ("I need a comma after symbol's name");
- goof = 1;
- }
- }
- else
- string = "";
-
- /*
- * Input_line_pointer->after ','. String->symbol name.
- */
- if (!goof)
- {
- symbolP = symbol_new (string, undefined_section, 0, (struct frag *) 0);
- switch (what)
- {
- case 'd':
- S_SET_NAME (symbolP, NULL); /* .stabd feature. */
- S_SET_VALUE (symbolP, (char*) obstack_next_free (&frags) - frag_now->fr_literal);
- symbolP->sy_frag = frag_now;
- break;
-
- case 'n':
- symbolP->sy_frag = &zero_address_frag;
- break;
-
- case 's':
- symbolP->sy_frag = &zero_address_frag;
- break;
-
- default:
- BAD_CASE (what);
- break;
- }
-
- if (get_absolute_expression_and_terminator (&longint) == ',')
- {
- saved_type = longint;
- S_SET_TYPE (symbolP, saved_type);
- }
- else
- {
- as_bad ("I want a comma after the n_type expression");
- goof = 1;
- input_line_pointer--; /* Backup over a non-',' char. */
- }
- }
-
- if (!goof)
- {
- if (get_absolute_expression_and_terminator (&longint) == ',')
- S_SET_OTHER (symbolP, longint);
- else
- {
- as_bad ("I want a comma after the n_other expression");
- goof = 1;
- input_line_pointer--; /* Backup over a non-',' char. */
- }
- }
-
- if (!goof)
- {
- S_SET_DESC (symbolP, get_absolute_expression ());
- if (what == 's' || what == 'n')
- {
- if (*input_line_pointer != ',')
- {
- as_bad ("I want a comma after the n_desc expression");
- goof = 1;
- }
- else
- {
- input_line_pointer++;
- }
- }
- }
+ char *name;
+ int c;
+ symbolS *symbolP;
- if ((!goof) && (what == 's' || what == 'n'))
- {
- pseudo_set (symbolP);
- S_SET_TYPE (symbolP, saved_type);
- }
-#ifndef NO_LISTING
- if (listing && !goof)
+ do
{
- if (S_GET_TYPE (symbolP) == N_SLINE)
- {
- listing_source_line (S_GET_DESC (symbolP));
- }
- else if (S_GET_TYPE (symbolP) == N_SO || S_GET_TYPE (symbolP) == N_SOL)
+ name = input_line_pointer;
+ c = get_symbol_end ();
+ symbolP = symbol_find_or_make (name);
+ *input_line_pointer = c;
+ SKIP_WHITESPACE ();
+ S_SET_WEAK (symbolP);
+ if (c == ',')
{
- listing_source_file (string);
+ input_line_pointer++;
+ SKIP_WHITESPACE ();
+ if (*input_line_pointer == '\n')
+ c = '\n';
}
}
-#endif
-
- if (goof)
- ignore_rest_of_line ();
- else
- demand_empty_rest_of_line ();
-} /* obj_aout_stab() */
-
-static void
-obj_aout_desc ()
-{
- register char *name;
- register char c;
- register char *p;
- register symbolS *symbolP;
- register int temp;
-
- /*
- * Frob invented at RMS' request. Set the n_desc of a symbol.
- */
- name = input_line_pointer;
- c = get_symbol_end ();
- p = input_line_pointer;
- *p = c;
- SKIP_WHITESPACE ();
- if (*input_line_pointer != ',')
- {
- *p = 0;
- as_bad ("Expected comma after name \"%s\"", name);
- *p = c;
- ignore_rest_of_line ();
- }
- else
- {
- input_line_pointer++;
- temp = get_absolute_expression ();
- *p = 0;
- symbolP = symbol_find_or_make (name);
- *p = c;
- S_SET_DESC (symbolP, temp);
- }
+ while (c == ',');
demand_empty_rest_of_line ();
-} /* obj_aout_desc() */
+}
void
obj_read_begin_hook ()
{
- return;
-} /* obj_read_begin_hook() */
+}
#ifndef BFD_ASSEMBLER
symbolS **symbolPP;
int symbol_number = 0;
- /* JF deal with forward references first... */
- for (symbolP = symbol_rootP; symbolP; symbolP = symbol_next (symbolP))
- {
- if (symbolP->sy_forward)
- {
- S_SET_VALUE (symbolP, S_GET_VALUE (symbolP)
- + S_GET_VALUE (symbolP->sy_forward)
- + symbolP->sy_forward->sy_frag->fr_address);
-
- symbolP->sy_forward = 0;
- } /* if it has a forward reference */
- } /* walk the symbol chain */
-
tc_crawl_symbol_chain (headers);
symbolPP = &symbol_rootP; /*->last symbol chain link. */
while ((symbolP = *symbolPP) != NULL)
{
- if (flagseen['R'] && (S_GET_SEGMENT (symbolP) == SEG_DATA))
+ if (flag_readonly_data_in_text && (S_GET_SEGMENT (symbolP) == SEG_DATA))
{
S_SET_SEGMENT (symbolP, SEG_TEXT);
} /* if pusing data into text */
- S_SET_VALUE (symbolP, S_GET_VALUE (symbolP) + symbolP->sy_frag->fr_address);
+ resolve_symbol_value (symbolP);
/* OK, here is how we decide which symbols go out into the brave
new symtab. Symbols that do are:
if (!S_IS_REGISTER (symbolP)
&& (!S_GET_NAME (symbolP)
|| S_IS_DEBUG (symbolP)
-#ifdef TC_I960
- /* FIXME-SOON this ifdef seems highly dubious to me. xoxorich. */
|| !S_IS_DEFINED (symbolP)
|| S_IS_EXTERNAL (symbolP)
-#endif /* TC_I960 */
- || (S_GET_NAME (symbolP)[0] != '\001' && (flagseen['L'] || !S_LOCAL_NAME (symbolP)))))
+ || (S_GET_NAME (symbolP)[0] != '\001'
+ && (flag_keep_locals || !S_LOCAL_NAME (symbolP)))))
{
symbolP->sy_number = symbol_number++;
else
{
if (S_IS_EXTERNAL (symbolP) || !S_IS_DEFINED (symbolP))
+ /* This warning should never get triggered any more.
+ Well, maybe if you're doing twisted things with
+ register names... */
{
as_bad ("Local symbol %s never defined.", decode_local_label_name (S_GET_NAME (symbolP)));
} /* oops. */
} /* for each symbol */
H_SET_SYMBOL_TABLE_SIZE (headers, symbol_number);
-
- return;
-} /* obj_crawl_symbol_chain() */
+}
/*
* Find strings by crawling along symbol table chain.
append (&next_object_file_charP, S_GET_NAME (symbolP),
(unsigned long) (strlen (S_GET_NAME (symbolP)) + 1));
} /* walk symbol chain */
-
- return;
-} /* obj_emit_strings() */
+}
#ifndef AOUT_VERSION
#define AOUT_VERSION 0
H_SET_VERSION (headers, AOUT_VERSION);
H_SET_MACHTYPE (headers, AOUT_MACHTYPE);
tc_aout_pre_write_hook (headers);
- return;
-} /* obj_pre_write_hook() */
+}
void
DEFUN_VOID (s_sect)
if (strcmp (section_name, ".text") == 0)
{
- subseg_new (SEG_TEXT, (subsegT) exp);
+ subseg_set (SEG_TEXT, (subsegT) exp);
}
if (strcmp (section_name, ".data") == 0)
{
- if (flagseen['R'])
- subseg_new (SEG_TEXT, (subsegT) exp + 1000);
+ if (flag_readonly_data_in_text)
+ subseg_set (SEG_TEXT, (subsegT) exp + 1000);
else
- subseg_new (SEG_DATA, (subsegT) exp);
+ subseg_set (SEG_DATA, (subsegT) exp);
}
*section_name_end = c;