/* write.c - emit .o file
Copyright 1986, 1987, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
- 1998, 1999, 2000, 2001, 2002, 2003, 2004
+ 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
You should have received a copy of the GNU General Public License
along with GAS; see the file COPYING. If not, write to the Free
- Software Foundation, 59 Temple Place - Suite 330, Boston, MA
- 02111-1307, USA. */
+ Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
+ 02110-1301, USA. */
/* This thing should be set up to do byteordering correctly. But... */
#define MD_PCREL_FROM_SECTION(FIX, SEC) md_pcrel_from (FIX)
#endif
+#ifndef TC_FAKE_LABEL
+#define TC_FAKE_LABEL(NAME) (strcmp ((NAME), FAKE_LABEL_NAME) == 0)
+#endif
+
/* Used to control final evaluation of expressions. */
int finalize_syms = 0;
if (fixp->fx_subsy != NULL)
resolve_symbol_value (fixp->fx_subsy);
- /* If this symbol is equated to an undefined symbol, convert
- the fixup to being against that symbol. */
+ /* If this symbol is equated to an undefined or common symbol,
+ convert the fixup to being against that symbol. */
if (symbol_equated_reloc_p (sym))
{
+ symbolS *new_sym
+ = symbol_get_value_expression (sym)->X_add_symbol;
+ const char *name = S_GET_NAME (sym);
+ if (!S_IS_COMMON (new_sym)
+ && !TC_FAKE_LABEL (name)
+ && (!S_IS_EXTERNAL (sym) || S_IS_LOCAL (sym)))
+ as_bad (_("Local symbol `%s' can't be equated to undefined symbol `%s'"),
+ name, S_GET_NAME (new_sym));
fixp->fx_offset += symbol_get_value_expression (sym)->X_add_number;
- sym = symbol_get_value_expression (sym)->X_add_symbol;
+ sym = new_sym;
fixp->fx_addsy = sym;
}
#ifdef BFD_ASSEMBLER
/* Remove the sections created by gas for its own purposes. */
{
- asection **seclist;
int i;
- seclist = &stdoutput->sections;
- while (*seclist)
- {
- if (*seclist == reg_section || *seclist == expr_section)
- {
- bfd_section_list_remove (stdoutput, seclist);
- stdoutput->section_count--;
- }
- else
- seclist = &(*seclist)->next;
- }
+ bfd_section_list_remove (stdoutput, reg_section);
+ bfd_section_list_remove (stdoutput, expr_section);
+ stdoutput->section_count -= 2;
i = 0;
bfd_map_over_sections (stdoutput, renumber_sections, &i);
}
Count the number of string-table chars we will emit.
Put this info into the headers as appropriate. */
know (zero_address_frag.fr_address == 0);
- string_byte_count = sizeof (string_byte_count);
+ string_byte_count = 4;
obj_crawl_symbol_chain (&headers);
- if (string_byte_count == sizeof (string_byte_count))
+ if (string_byte_count == 4)
string_byte_count = 0;
H_SET_STRING_SIZE (&headers, string_byte_count);
if (symbol_rootP)
{
symbolS *symp;
+ bfd_boolean skip_next_symbol = FALSE;
for (symp = symbol_rootP; symp; symp = symbol_next (symp))
{
int punt = 0;
const char *name;
+ if (skip_next_symbol)
+ {
+ /* Don't do anything besides moving the value of the
+ symbol from the GAS value-field to the BFD value-field. */
+ symbol_get_bfdsym (symp)->value = S_GET_VALUE (symp);
+ skip_next_symbol = FALSE;
+ continue;
+ }
+
if (symbol_mri_common_p (symp))
{
if (S_IS_EXTERNAL (symp))
symbols. */
if (symbol_equated_reloc_p (symp))
{
- if (S_IS_COMMON (symp))
- as_bad (_("`%s' can't be equated to common symbol"),
- S_GET_NAME (symp));
+ const char *name = S_GET_NAME (symp);
+ if (S_IS_COMMON (symp)
+ && !TC_FAKE_LABEL (name)
+ && (!S_IS_EXTERNAL (symp) || S_IS_LOCAL (symp)))
+ {
+ expressionS *e = symbol_get_value_expression (symp);
+ as_bad (_("Local symbol `%s' can't be equated to common symbol `%s'"),
+ name, S_GET_NAME (e->X_add_symbol));
+ }
symbol_remove (symp, &symbol_rootP, &symbol_lastP);
continue;
}
if (symp == abs_section_sym
|| (! EMIT_SECTION_SYMBOLS
&& symbol_section_p (symp))
- /* Note that S_IS_EXTERN and S_IS_LOCAL are not always
+ /* Note that S_IS_EXTERNAL and S_IS_LOCAL are not always
opposites. Sometimes the former checks flags and the
latter examines the name... */
- || (!S_IS_EXTERN (symp)
+ || (!S_IS_EXTERNAL (symp)
&& (punt || S_IS_LOCAL (symp))
&& ! symbol_used_in_reloc_p (symp)))
{
/* Set the value into the BFD symbol. Up til now the value
has only been kept in the gas symbolS struct. */
symbol_get_bfdsym (symp)->value = S_GET_VALUE (symp);
+
+ /* A warning construct is a warning symbol followed by the
+ symbol warned about. Don't let anything object-format or
+ target-specific muck with it; it's ready for output. */
+ if (symbol_get_bfdsym (symp)->flags & BSF_WARNING)
+ skip_next_symbol = TRUE;
}
}
into the section. Here it is assumed that the
section's VMA is zero, and can omit subtracting it
from the symbol's value to get the address offset. */
- know (S_GET_SECTION (symbolP)->vma == 0);
+#ifdef BFD_ASSEMBLER
+ know (S_GET_SEGMENT (symbolP)->vma == 0);
+#endif
target += S_GET_VALUE (symbolP) * OCTETS_PER_BYTE;
}
if (fixP->fx_addsy != NULL
&& symbol_mri_common_p (fixP->fx_addsy))
{
- know (fixP->fx_addsy->sy_value.X_op == O_symbol);
add_number += S_GET_VALUE (fixP->fx_addsy);
fixP->fx_offset = add_number;
fixP->fx_addsy