/* write.c - emit .o file
Copyright 1986, 1987, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
- 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
+ 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
(! SEG_NORMAL (SEG))
#endif
+#ifndef md_register_arithmetic
+# define md_register_arithmetic 1
+#endif
+
#ifndef TC_FORCE_RELOCATION_SUB_ABS
-#define TC_FORCE_RELOCATION_SUB_ABS(FIX) 0
+#define TC_FORCE_RELOCATION_SUB_ABS(FIX, SEG) \
+ (!md_register_arithmetic && (SEG) == reg_section)
#endif
#ifndef TC_FORCE_RELOCATION_SUB_LOCAL
#ifdef DIFF_EXPR_OK
-#define TC_FORCE_RELOCATION_SUB_LOCAL(FIX) 0
+#define TC_FORCE_RELOCATION_SUB_LOCAL(FIX, SEG) \
+ (!md_register_arithmetic && (SEG) == reg_section)
#else
-#define TC_FORCE_RELOCATION_SUB_LOCAL(FIX) 1
+#define TC_FORCE_RELOCATION_SUB_LOCAL(FIX, SEG) 1
#endif
#endif
#ifndef TC_VALIDATE_FIX_SUB
#ifdef UNDEFINED_DIFFERENCE_OK
/* The PA needs this for PIC code generation. */
-#define TC_VALIDATE_FIX_SUB(FIX) 1
+#define TC_VALIDATE_FIX_SUB(FIX, SEG) \
+ (md_register_arithmetic || (SEG) != reg_section)
#else
-#define TC_VALIDATE_FIX_SUB(FIX) \
- ((FIX)->fx_r_type == BFD_RELOC_GPREL32 \
- || (FIX)->fx_r_type == BFD_RELOC_GPREL16)
+#define TC_VALIDATE_FIX_SUB(FIX, SEG) \
+ ((md_register_arithmetic || (SEG) != reg_section) \
+ && ((FIX)->fx_r_type == BFD_RELOC_GPREL32 \
+ || (FIX)->fx_r_type == BFD_RELOC_GPREL16))
#endif
#endif
n_fixups++;
- fixP = obstack_alloc (¬es, sizeof (fixS));
+ fixP = (fixS *) obstack_alloc (¬es, sizeof (fixS));
fixP->fx_frag = frag;
fixP->fx_where = where;
{
prev_frag->fr_next = frchp->frch_root;
prev_frag = frchp->frch_last;
- assert (prev_frag->fr_type != 0);
+ gas_assert (prev_frag->fr_type != 0);
if (frchp->fix_root != (fixS *) NULL)
{
if (seg_info (section)->fix_root == (fixS *) NULL)
prev_fix = frchp->fix_tail;
}
}
- assert (prev_frag->fr_type != 0);
- assert (prev_frag != &dummy);
+ gas_assert (prev_frag->fr_type != 0);
+ gas_assert (prev_frag != &dummy);
prev_frag->fr_next = 0;
return prev_frag;
}
case rs_machine_dependent:
md_convert_frag (stdoutput, sec, fragP);
- assert (fragP->fr_next == NULL
+ gas_assert (fragP->fr_next == NULL
|| ((offsetT) (fragP->fr_next->fr_address - fragP->fr_address)
== fragP->fr_fix));
size = 0;
flags = bfd_get_section_flags (abfd, sec);
+ if (size == 0 && bfd_get_section_size (sec) != 0 &&
+ (flags & SEC_HAS_CONTENTS) != 0)
+ return;
if (size > 0 && ! seginfo->bss)
flags |= SEC_HAS_CONTENTS;
flags &= ~SEC_RELOC;
x = bfd_set_section_flags (abfd, sec, flags);
- assert (x);
+ gas_assert (x);
newsize = md_section_align (sec, size);
x = bfd_set_section_size (abfd, sec, newsize);
- assert (x);
+ gas_assert (x);
/* If the size had to be rounded up, add some padding in the last
non-empty frag. */
- assert (newsize >= size);
+ gas_assert (newsize >= size);
if (size != newsize)
{
fragS *last = seginfo->frchainP->frch_last;
#endif
}
else if (sub_symbol_segment == absolute_section
- && !TC_FORCE_RELOCATION_SUB_ABS (fixP))
+ && !TC_FORCE_RELOCATION_SUB_ABS (fixP, add_symbol_segment))
{
add_number -= S_GET_VALUE (fixP->fx_subsy);
fixP->fx_offset = add_number;
fixP->fx_subsy = NULL;
}
else if (sub_symbol_segment == this_segment
- && !TC_FORCE_RELOCATION_SUB_LOCAL (fixP))
+ && !TC_FORCE_RELOCATION_SUB_LOCAL (fixP, add_symbol_segment))
{
add_number -= S_GET_VALUE (fixP->fx_subsy);
fixP->fx_offset = (add_number + fixP->fx_dot_value
fixP->fx_subsy = NULL;
fixP->fx_pcrel = 1;
}
- else if (!TC_VALIDATE_FIX_SUB (fixP))
+ else if (!TC_VALIDATE_FIX_SUB (fixP, add_symbol_segment))
{
- as_bad_where (fixP->fx_file, fixP->fx_line,
- _("can't resolve `%s' {%s section} - `%s' {%s section}"),
- fixP->fx_addsy ? S_GET_NAME (fixP->fx_addsy) : "0",
- segment_name (add_symbol_segment),
- S_GET_NAME (fixP->fx_subsy),
- segment_name (sub_symbol_segment));
+ if (!md_register_arithmetic
+ && (add_symbol_segment == reg_section
+ || sub_symbol_segment == reg_section))
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ _("register value used as expression"));
+ else
+ as_bad_where (fixP->fx_file, fixP->fx_line,
+ _("can't resolve `%s' {%s section} - `%s' {%s section}"),
+ fixP->fx_addsy ? S_GET_NAME (fixP->fx_addsy) : "0",
+ segment_name (add_symbol_segment),
+ S_GET_NAME (fixP->fx_subsy),
+ segment_name (sub_symbol_segment));
}
}
{
char *err;
bfd_reloc_status_type s;
+ asymbol *sym;
+
+ if (reloc->sym_ptr_ptr != NULL
+ && (sym = *reloc->sym_ptr_ptr) != NULL
+ && (sym->flags & BSF_KEEP) == 0
+ && ((sym->flags & BSF_SECTION_SYM) == 0
+ || (EMIT_SECTION_SYMBOLS
+ && !bfd_is_abs_section (sym->section))))
+ as_bad_where (file, line, _("redefined symbol cannot be used on reloc"));
s = bfd_install_relocation (stdoutput, reloc,
fragp->fr_literal, fragp->fr_address,
rp = &r->next;
}
- relocs = xcalloc (n, sizeof (arelent *));
+ relocs = (arelent **) xcalloc (n, sizeof (arelent *));
i = 0;
for (fixp = seginfo->fix_root; fixp != (fixS *) NULL; fixp = fixp->fx_next)
char *fill_literal;
offsetT count;
- assert (f->fr_type == rs_fill);
+ gas_assert (f->fr_type == rs_fill);
if (f->fr_fix)
{
x = bfd_set_section_contents (stdoutput, sec,
fill_literal = f->fr_literal + f->fr_fix;
fill_size = f->fr_var;
count = f->fr_offset;
- assert (count >= 0);
+ gas_assert (count >= 0);
if (fill_size && count)
{
char buf[256];
int i;
bfd_size_type amt = (bfd_size_type) nsyms * sizeof (asymbol *);
- asympp = bfd_alloc (stdoutput, amt);
+ asympp = (asymbol **) bfd_alloc (stdoutput, amt);
symp = symbol_rootP;
for (i = 0; i < nsyms; i++, symp = symbol_next (symp))
{
asympp[i] = symbol_get_bfdsym (symp);
+ if (asympp[i]->flags != BSF_SECTION_SYM
+ || !(bfd_is_const_section (asympp[i]->section)
+ && asympp[i]->section->symbol == asympp[i]))
+ asympp[i]->flags |= BSF_KEEP;
symbol_mark_written (symp);
}
}
else
asympp = 0;
result = bfd_set_symtab (stdoutput, asympp, nsyms);
- assert (result);
+ gas_assert (result);
symbol_table_frozen = 1;
}
if (lie->added == 2)
continue;
/* Patch the jump table. */
- /* This is the offset from ??? to table_ptr+0. */
- to_addr = table_addr - S_GET_VALUE (lie->sub);
-#ifdef TC_CHECK_ADJUSTED_BROKEN_DOT_WORD
- TC_CHECK_ADJUSTED_BROKEN_DOT_WORD (to_addr, lie);
-#endif
- md_number_to_chars (lie->word_goes_here, to_addr, 2);
- for (untruth = lie->next_broken_word;
+ for (untruth = (struct broken_word *) (fragP->fr_symbol);
untruth && untruth->dispfrag == fragP;
untruth = untruth->next_broken_word)
{
if (untruth->use_jump == lie)
- md_number_to_chars (untruth->word_goes_here, to_addr, 2);
+ {
+ /* This is the offset from ??? to table_ptr+0.
+ The target is the same for all users of this
+ md_long_jump, but the "sub" bases (and hence the
+ offsets) may be different. */
+ addressT to_word = table_addr - S_GET_VALUE (untruth->sub);
+#ifdef TC_CHECK_ADJUSTED_BROKEN_DOT_WORD
+ TC_CHECK_ADJUSTED_BROKEN_DOT_WORD (to_word, untruth);
+#endif
+ md_number_to_chars (untruth->word_goes_here, to_word, 2);
+ }
}
/* Install the long jump. */
if (symbol_equated_reloc_p (symp)
|| S_IS_WEAKREFR (symp))
{
- const char *name = S_GET_NAME (symp);
+ const char *sname = S_GET_NAME (symp);
+
if (S_IS_COMMON (symp)
- && !TC_FAKE_LABEL (name)
+ && !TC_FAKE_LABEL (sname)
&& !S_IS_WEAKREFR (symp)
&& (!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));
+ sname, S_GET_NAME (e->X_add_symbol));
+ }
+ if (S_GET_SEGMENT (symp) == reg_section)
+ {
+ /* Report error only if we know the symbol name. */
+ if (S_GET_NAME (symp) != reg_section->name)
+ as_bad (_("can't make global register symbol `%s'"),
+ sname);
}
symbol_remove (symp, &symbol_rootP, &symbol_lastP);
continue;
obj_adjust_symtab ();
#endif
+ /* Stop if there is an error. */
+ if (had_errors ())
+ return;
+
/* Now that all the sizes are known, and contents correct, we can
start writing to the file. */
set_symtab ();
#ifdef obj_frob_file
obj_frob_file ();
#endif
-
+#ifdef obj_coff_generate_pdata
+ obj_coff_generate_pdata ();
+#endif
bfd_map_over_sections (stdoutput, write_relocs, (char *) 0);
#ifdef tc_frob_file_after_relocs
S_GET_NAME (lie->sub),
buf);
}
- lie->added = 1;
if (fragP->fr_subtype == 0)
{
fragP->fr_subtype++;
growth += md_short_jump_size;
}
- for (untruth = lie->next_broken_word;
+
+ /* Redirect *all* words of this table with the same
+ target, lest we have to handle the case where the
+ same target but with a offset that fits on this
+ round overflows at the next relaxation round. */
+ for (untruth = (struct broken_word *) (fragP->fr_symbol);
untruth && untruth->dispfrag == lie->dispfrag;
untruth = untruth->next_broken_word)
if ((symbol_get_frag (untruth->add)
untruth->added = 2;
untruth->use_jump = lie;
}
+
+ lie->added = 1;
growth += md_long_jump_size;
}
}
}
know (fragP->fr_next);
- after = fragP->fr_next->fr_address;
+ after = fragP->fr_next->fr_address + stretch;
growth = target - after;
if (growth < 0)
{
fragP->fr_type = rs_align;
fragP->fr_subtype = 0;
fragP->fr_offset = 0;
- fragP->fr_fix = after - was_address;
- break;
+ fragP->fr_fix = after - address;
}
-
- /* This is an absolute growth factor */
- growth -= stretch;
- break;
}
+ break;
case rs_space:
growth = 0;
fprintf_vma (stderr, (bfd_vma) ((bfd_hostptr_t) fixp->fx_frag));
fprintf (stderr, " where=%ld offset=%lx addnumber=%lx",
(long) fixp->fx_where,
- (long) fixp->fx_offset, (long) fixp->fx_addnumber);
+ (unsigned long) fixp->fx_offset,
+ (unsigned long) fixp->fx_addnumber);
fprintf (stderr, "\n %s (%d)", bfd_get_reloc_code_name (fixp->fx_r_type),
fixp->fx_r_type);
if (fixp->fx_addsy)