/* write.c - emit .o file
- Copyright (C) 1986, 87, 90, 91, 92, 93, 94, 95, 96, 97, 1998
+ Copyright (C) 1986, 87, 90, 91, 92, 93, 94, 95, 96, 97, 98, 1999
Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
static void
renumber_sections (abfd, sec, countparg)
- bfd *abfd;
+ bfd *abfd ATTRIBUTE_UNUSED;
asection *sec;
PTR countparg;
{
static void
chain_frchains_together (abfd, section, xxx)
- bfd *abfd; /* unused */
+ bfd *abfd ATTRIBUTE_UNUSED;
segT section;
- PTR xxx; /* unused */
+ PTR xxx ATTRIBUTE_UNUSED;
{
segment_info_type *info;
- fragP->fr_fix) / fragP->fr_var;
if (fragP->fr_offset < 0)
{
- as_bad (_("attempt to .org/.space backwards? (%ld)"),
- (long) fragP->fr_offset);
+ as_bad_where (fragP->fr_file, fragP->fr_line,
+ _("attempt to .org/.space backwards? (%ld)"),
+ (long) fragP->fr_offset);
}
fragP->fr_type = rs_fill;
break;
relax_and_size_seg (abfd, sec, xxx)
bfd *abfd;
asection *sec;
- PTR xxx;
+ PTR xxx ATTRIBUTE_UNUSED;
{
flagword flags;
fragS *fragp;
#ifdef DEBUG2
static void
dump_section_relocs (abfd, sec, stream_)
- bfd *abfd;
+ bfd *abfd ATTRIBUTE_UNUSED;
asection *sec;
char *stream_;
{
while (fixp)
{
symbolS *s = fixp->fx_addsy;
- if (s)
+
+ fprintf (stream, " %08lx: type %d ", (unsigned long) fixp,
+ (int) fixp->fx_r_type);
+ if (s == NULL)
+ fprintf (stream, "no sym\n");
+ else
{
- fprintf (stream, " %08x: %s(%s", fixp, S_GET_NAME (s),
- s->bsym->section->name);
- if (s->bsym->flags & BSF_SECTION_SYM)
- {
- fprintf (stream, " section sym");
- if (S_GET_VALUE (s))
- fprintf (stream, "+%x", S_GET_VALUE (s));
- }
- else
- fprintf (stream, "+%x", S_GET_VALUE (s));
- fprintf (stream, ")+%x\n", fixp->fx_offset);
+ print_symbol_value_1 (stream, s);
+ fprintf (stream, "\n");
}
- else
- fprintf (stream, " %08x: type %d no sym\n", fixp, fixp->fx_r_type);
fixp = fixp->fx_next;
}
}
static void
adjust_reloc_syms (abfd, sec, xxx)
- bfd *abfd;
+ bfd *abfd ATTRIBUTE_UNUSED;
asection *sec;
- PTR xxx;
+ PTR xxx ATTRIBUTE_UNUSED;
{
segment_info_type *seginfo = seg_info (sec);
fixS *fixp;
point. It is possible to see unresolved expression
symbols, though, since they are not in the regular symbol
table. */
- if (sym != NULL && ! sym->sy_resolved)
+ if (sym != NULL)
resolve_symbol_value (sym, 1);
- if (fixp->fx_subsy != NULL && ! fixp->fx_subsy->sy_resolved)
+ if (fixp->fx_subsy != NULL)
resolve_symbol_value (fixp->fx_subsy, 1);
/* If this symbol is equated to an undefined symbol, convert
the fixup to being against that symbol. */
- if (sym != NULL && sym->sy_value.X_op == O_symbol
+ if (sym != NULL && symbol_equated_p (sym)
&& (! S_IS_DEFINED (sym) || S_IS_COMMON (sym)))
{
- fixp->fx_offset += sym->sy_value.X_add_number;
- sym = sym->sy_value.X_add_symbol;
+ fixp->fx_offset += symbol_get_value_expression (sym)->X_add_number;
+ sym = symbol_get_value_expression (sym)->X_add_symbol;
fixp->fx_addsy = sym;
}
- if (sym != NULL && sym->sy_mri_common)
+ if (sym != NULL && symbol_mri_common_p (sym))
{
/* These symbols are handled specially in fixup_segment. */
goto done;
relocation unless TC_FORCE_RELOCATION returns 1. */
if (TC_FORCE_RELOCATION (fixp))
{
- fixp->fx_addsy->sy_used_in_reloc = 1;
+ symbol_mark_used_in_reloc (fixp->fx_addsy);
#ifdef UNDEFINED_DIFFERENCE_OK
if (fixp->fx_subsy != NULL)
- fixp->fx_subsy->sy_used_in_reloc = 1;
+ symbol_mark_used_in_reloc (fixp->fx_subsy);
#endif
}
goto done;
if (bfd_is_und_section (symsec)
|| bfd_is_com_section (symsec))
{
- fixp->fx_addsy->sy_used_in_reloc = 1;
+ symbol_mark_used_in_reloc (fixp->fx_addsy);
#ifdef UNDEFINED_DIFFERENCE_OK
/* We have the difference of an undefined symbol and some
other symbol. Make sure to mark the other symbol as used
in a relocation so that it will always be output. */
if (fixp->fx_subsy)
- fixp->fx_subsy->sy_used_in_reloc = 1;
+ symbol_mark_used_in_reloc (fixp->fx_subsy);
#endif
goto done;
}
- /* Don't try to reduce relocs which refer to .linkonce
- sections. It can lead to confusion when a debugging
- section refers to a .linkonce section. I hope this will
- always be correct. */
- if (symsec != sec)
+ /* Don't try to reduce relocs which refer to non-local symbols
+ in .linkonce sections. It can lead to confusion when a
+ debugging section refers to a .linkonce section. I hope
+ this will always be correct. */
+ if (symsec != sec && ! S_IS_LOCAL (sym))
{
boolean linkonce;
if (linkonce)
{
- fixp->fx_addsy->sy_used_in_reloc = 1;
+ symbol_mark_used_in_reloc (fixp->fx_addsy);
#ifdef UNDEFINED_DIFFERENCE_OK
if (fixp->fx_subsy != NULL)
- fixp->fx_subsy->sy_used_in_reloc = 1;
+ symbol_mark_used_in_reloc (fixp->fx_subsy);
#endif
goto done;
}
/* Since we're reducing to section symbols, don't attempt to reduce
anything that's already using one. */
- if (sym->bsym->flags & BSF_SECTION_SYM)
+ if (symbol_section_p (sym))
{
- fixp->fx_addsy->sy_used_in_reloc = 1;
+ symbol_mark_used_in_reloc (fixp->fx_addsy);
goto done;
}
the wrong area of memory. */
if (S_IS_WEAK (sym))
{
- fixp->fx_addsy->sy_used_in_reloc = 1;
+ symbol_mark_used_in_reloc (fixp->fx_addsy);
goto done;
}
#endif
#ifdef obj_fix_adjustable
if (! obj_fix_adjustable (fixp))
{
- fixp->fx_addsy->sy_used_in_reloc = 1;
+ symbol_mark_used_in_reloc (fixp->fx_addsy);
goto done;
}
#endif
#ifdef tc_fix_adjustable
if (! tc_fix_adjustable (fixp))
{
- fixp->fx_addsy->sy_used_in_reloc = 1;
+ symbol_mark_used_in_reloc (fixp->fx_addsy);
goto done;
}
#endif
the section when it calls resolve_symbol_value. */
fixp->fx_offset += S_GET_VALUE (sym);
fixp->fx_addsy = section_symbol (S_GET_SEGMENT (sym));
- fixp->fx_addsy->sy_used_in_reloc = 1;
+ symbol_mark_used_in_reloc (fixp->fx_addsy);
+#ifdef DEBUG5
+ fprintf (stderr, "\nadjusted fixup:\n");
+ print_fixup (fixp);
+#endif
done:
;
write_relocs (abfd, sec, xxx)
bfd *abfd;
asection *sec;
- PTR xxx;
+ PTR xxx ATTRIBUTE_UNUSED;
{
segment_info_type *seginfo = seg_info (sec);
int i;
symbol, then use generate the reloc against the latter symbol
rather than the former. */
sym = fixp->fx_addsy;
- while (sym->sy_value.X_op == O_symbol
+ while (symbol_equated_p (sym)
&& (! S_IS_DEFINED (sym) || S_IS_COMMON (sym)))
{
symbolS *n;
/* We must avoid looping, as that can occur with a badly
written program. */
- n = sym->sy_value.X_add_symbol;
+ n = symbol_get_value_expression (sym)->X_add_symbol;
if (n == sym)
break;
- fixp->fx_offset += sym->sy_value.X_add_number;
+ fixp->fx_offset += symbol_get_value_expression (sym)->X_add_number;
sym = n;
}
fixp->fx_addsy = sym;
symbol, then use generate the reloc against the latter symbol
rather than the former. */
sym = fixp->fx_addsy;
- while (sym->sy_value.X_op == O_symbol
+ while (symbol_equated_p (sym)
&& (! S_IS_DEFINED (sym) || S_IS_COMMON (sym)))
- sym = sym->sy_value.X_add_symbol;
+ sym = symbol_get_value_expression (sym)->X_add_symbol;
fixp->fx_addsy = sym;
reloc = tc_gen_reloc (sec, fixp);
(bfd_get_section_flags (abfd, sec)
& (flagword) ~SEC_RELOC));
+#ifdef SET_SECTION_RELOCS
+ SET_SECTION_RELOCS (sec, relocs, n);
+#endif
+
#ifdef DEBUG3
{
int i;
static void
write_contents (abfd, sec, xxx)
- bfd *abfd;
+ bfd *abfd ATTRIBUTE_UNUSED;
asection *sec;
- PTR xxx;
+ PTR xxx ATTRIBUTE_UNUSED;
{
segment_info_type *seginfo = seg_info (sec);
unsigned long offset = 0;
symp = symbol_rootP;
for (i = 0; i < nsyms; i++, symp = symbol_next (symp))
{
- asympp[i] = symp->bsym;
- symp->written = 1;
+ asympp[i] = symbol_get_bfdsym (symp);
+ symbol_mark_written (symp);
}
}
else
any alignment is meaningless, and, moreover, will look weird
if we are generating a listing. */
frag_align (had_errors () ? 0 : SUB_SEGMENT_ALIGN (now_seg),
- NOP_OPCODE, 0);
+ subseg_text_p (now_seg) ? NOP_OPCODE : 0,
+ 0);
/* frag_align will have left a new frag.
Use this last frag for an empty ".fill".
/* This is the offset from ??? to table_ptr+0 */
to_addr = table_addr - S_GET_VALUE (lie->sub);
#ifdef BFD_ASSEMBLER
- to_addr -= lie->sub->sy_frag->fr_address;
+ to_addr -= symbol_get_frag (lie->sub)->fr_address;
#endif
md_number_to_chars (lie->word_goes_here, to_addr, 2);
for (untruth = lie->next_broken_word; untruth && untruth->dispfrag == fragP; untruth = untruth->next_broken_word)
from_addr = table_addr;
to_addr = S_GET_VALUE (lie->add) + lie->addnum;
#ifdef BFD_ASSEMBLER
- to_addr += lie->add->sy_frag->fr_address;
+ to_addr += symbol_get_frag (lie->add)->fr_address;
#endif
md_create_long_jump (table_ptr, from_addr, to_addr, lie->dispfrag, lie->add);
table_ptr += md_long_jump_size;
symbolS *symp;
for (symp = symbol_rootP; symp; symp = symbol_next (symp))
- if (!symp->sy_resolved)
- resolve_symbol_value (symp, 1);
+ resolve_symbol_value (symp, 1);
}
+ resolve_local_symbol_values ();
PROGRESS (1);
int punt = 0;
const char *name;
- if (symp->sy_mri_common)
+ if (symbol_mri_common_p (symp))
{
if (S_IS_EXTERNAL (symp))
as_bad (_("%s: global symbols not supported in common sections"),
/* Do it again, because adjust_reloc_syms might introduce
more symbols. They'll probably only be section symbols,
but they'll still need to have the values computed. */
- if (! symp->sy_resolved)
- {
- if (symp->sy_value.X_op == O_constant)
- {
- /* This is the normal case; skip the call. */
- S_SET_VALUE (symp,
- (S_GET_VALUE (symp)
- + symp->sy_frag->fr_address));
- symp->sy_resolved = 1;
- }
- else
- resolve_symbol_value (symp, 1);
- }
+ resolve_symbol_value (symp, 1);
/* Skip symbols which were equated to undefined or common
symbols. */
- if (symp->sy_value.X_op == O_symbol
+ if (symbol_equated_p (symp)
&& (! S_IS_DEFINED (symp) || S_IS_COMMON (symp)))
{
symbol_remove (symp, &symbol_rootP, &symbol_lastP);
printf ("symbol `%s'\n\t@%x: value=%d flags=%x seg=%s\n",
S_GET_NAME (symp), symp,
S_GET_VALUE (symp),
- symp->bsym->flags,
- segment_name (symp->bsym->section));
+ symbol_get_bfdsym (symp)->flags,
+ segment_name (S_GET_SEGMENT (symp)));
#endif
#ifdef obj_frob_symbol
obj_frob_symbol (symp, punt);
#endif
#ifdef tc_frob_symbol
- if (! punt || symp->sy_used_in_reloc)
+ if (! punt || symbol_used_in_reloc_p (symp))
tc_frob_symbol (symp, punt);
#endif
and symbols that the frob_symbol macros told us to punt,
but we keep such symbols if they are used in relocs. */
if ((! EMIT_SECTION_SYMBOLS
- && (symp->bsym->flags & BSF_SECTION_SYM) != 0)
+ && symbol_section_p (symp))
/* Note that S_IS_EXTERN 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_LOCAL (symp) || punt)
- && ! symp->sy_used_in_reloc))
+ && ! symbol_used_in_reloc_p (symp)))
{
symbol_remove (symp, &symbol_rootP, &symbol_lastP);
/* After symbol_remove, symbol_next(symp) still returns
}
/* Make sure we really got a value for the symbol. */
- if (! symp->sy_resolved)
+ if (! symbol_resolved_p (symp))
{
as_bad (_("can't resolve value for symbol \"%s\""),
S_GET_NAME (symp));
- symp->sy_resolved = 1;
+ symbol_mark_resolved (symp);
}
/* Set the value into the BFD symbol. Up til now the value
has only been kept in the gas symbolS struct. */
- symp->bsym->value = S_GET_VALUE (symp);
+ symbol_get_bfdsym (symp)->value = S_GET_VALUE (symp);
}
}
#endif
know (!(S_GET_SEGMENT (symbolP) == absolute_section)
|| symbolP->sy_frag == &zero_address_frag);
- target +=
- S_GET_VALUE (symbolP)
- + symbolP->sy_frag->fr_address;
+ target += S_GET_VALUE (symbolP) + symbol_get_frag (symbolP)->fr_address;
/* If frag has yet to be reached on this pass,
assume it will move by STRETCH just as we did.
There should be a faster way to do this. */
- if (symbolP->sy_frag->fr_address >= was_address
- && is_dnrange (fragP, symbolP->sy_frag))
+ if (symbol_get_frag (symbolP)->fr_address >= was_address
+ && is_dnrange (fragP, symbol_get_frag (symbolP)))
{
target += stretch;
}
if (lie->added)
continue;
- offset = (lie->add->sy_frag->fr_address
+ offset = (symbol_get_frag (lie->add)->fr_address
+ S_GET_VALUE (lie->add)
+ lie->addnum
- - (lie->sub->sy_frag->fr_address
+ - (symbol_get_frag (lie->sub)->fr_address
+ S_GET_VALUE (lie->sub)));
if (offset <= -32768 || offset >= 32767)
{
for (untruth = lie->next_broken_word;
untruth && untruth->dispfrag == lie->dispfrag;
untruth = untruth->next_broken_word)
- if ((untruth->add->sy_frag == lie->add->sy_frag)
- && S_GET_VALUE (untruth->add) == S_GET_VALUE (lie->add))
+ if ((symbol_get_frag (untruth->add)
+ == symbol_get_frag (lie->add))
+ && (S_GET_VALUE (untruth->add)
+ == S_GET_VALUE (lie->add)))
{
untruth->added = 2;
untruth->use_jump = lie;
know (!(S_GET_SEGMENT (symbolP) == SEG_ABSOLUTE)
|| (symbolP->sy_frag == &zero_address_frag));
#endif
- target += S_GET_VALUE (symbolP)
- + symbolP->sy_frag->fr_address;
+ target += (S_GET_VALUE (symbolP)
+ + symbol_get_frag (symbolP)->fr_address);
} /* if we have a symbol */
know (fragP->fr_next);
/* Growth may be negative, but variable part of frag
cannot have fewer than 0 chars. That is, we can't
.org backwards. */
- as_bad (_("attempt to .org backwards ignored"));
- growth = 0;
+ as_bad_where (fragP->fr_file, fragP->fr_line,
+ _("attempt to .org backwards ignored"));
+
+ /* We've issued an error message. Change the
+ frag to avoid cascading errors. */
+ fragP->fr_type = rs_align;
+ fragP->fr_subtype = 0;
+ fragP->fr_offset = 0;
+ fragP->fr_fix = after - address;
+ growth = stretch;
}
growth -= stretch; /* This is an absolute growth factor */
if (symbolP)
{
growth = S_GET_VALUE (symbolP);
- if (symbolP->sy_frag != &zero_address_frag
+ if (symbol_get_frag (symbolP) != &zero_address_frag
|| S_IS_COMMON (symbolP)
|| ! S_IS_DEFINED (symbolP))
as_bad_where (fragP->fr_file, fragP->fr_line,
plt = fixP->fx_plt;
if (add_symbolP != NULL
- && add_symbolP->sy_mri_common)
+ && symbol_mri_common_p (add_symbolP))
{
know (add_symbolP->sy_value.X_op == O_symbol);
add_number += S_GET_VALUE (add_symbolP);
fixP->fx_offset = add_number;
- add_symbolP = fixP->fx_addsy = add_symbolP->sy_value.X_add_symbol;
+ add_symbolP = fixP->fx_addsy =
+ symbol_get_value_expression (add_symbolP)->X_add_symbol;
}
if (add_symbolP)
#if !(defined (TC_V850) && defined (OBJ_ELF))
#if !(defined (TC_M68K) && defined (OBJ_ELF))
#if !(defined (TC_ARM) && defined (OBJ_ELF))
+#if !(defined (TC_I960) && defined (OBJ_ELF))
#if !defined (TC_I386) || !(defined (OBJ_ELF) || defined (OBJ_COFF)) || defined (TE_PE)
add_number += S_GET_VALUE (add_symbolP);
#endif
#endif
#endif
+#endif
#endif
}
}
#else
fixP->fx_addsy = section_symbol (absolute_section);
#endif
- fixP->fx_addsy->sy_used_in_reloc = 1;
+ symbol_mark_used_in_reloc (fixP->fx_addsy);
++seg_reloc_count;
}
}
+ if (!fixP->fx_done)
+ {
+#ifdef MD_APPLY_FIX3
+ md_apply_fix3 (fixP, &add_number, this_segment_type);
+#else
+#ifdef BFD_ASSEMBLER
+ md_apply_fix (fixP, &add_number);
+#else
+ md_apply_fix (fixP, add_number);
+#endif
+#endif
+
+#ifndef TC_HANDLES_FX_DONE
+ /* If the tc-* files haven't been converted, assume it's handling
+ it the old way, where a null fx_addsy means that the fix has
+ been applied completely, and no further work is needed. */
+ if (fixP->fx_addsy == 0 && fixP->fx_pcrel == 0)
+ fixP->fx_done = 1;
+#endif
+ }
+
if (!fixP->fx_bit_fixP && !fixP->fx_no_overflow && size > 0)
{
if ((size_t) size < sizeof (valueT))
{
- valueT mask, hibit;
+ valueT mask;
- /* set all bits to one */
mask = 0;
- mask--;
- /* Technically, combining these produces an undefined result
- if size is sizeof (valueT), though I think these two
- half-way operations should both be defined. And the
- compiler should be able to combine them if it's valid on
- the host architecture. */
- mask <<= size * 4;
- mask <<= size * 4;
- hibit = (valueT) 1 << (size * 8 - 1);
- if (((add_number & mask) != 0
- || (fixP->fx_signed
- && (add_number & hibit) != 0))
- && ((add_number & mask) != mask
- || (add_number & hibit) == 0))
+ mask--; /* set all bits to one */
+ mask <<= size * 8 - (fixP->fx_signed ? 1 : 0);
+ if ((add_number & mask) != 0 && (add_number & mask) != mask)
{
char buf[50], buf2[50];
sprint_value (buf, fragP->fr_address + where);
#endif
} /* not a bit fix */
- if (!fixP->fx_done)
- {
-#ifdef MD_APPLY_FIX3
- md_apply_fix3 (fixP, &add_number, this_segment_type);
-#else
-#ifdef BFD_ASSEMBLER
- md_apply_fix (fixP, &add_number);
-#else
- md_apply_fix (fixP, add_number);
-#endif
-#endif
-
-#ifndef TC_HANDLES_FX_DONE
- /* If the tc-* files haven't been converted, assume it's handling
- it the old way, where a null fx_addsy means that the fix has
- been applied completely, and no further work is needed. */
- if (fixP->fx_addsy == 0 && fixP->fx_pcrel == 0)
- fixP->fx_done = 1;
-#endif
- }
#ifdef TC_VALIDATE_FIX
- skip: ;
+ skip: ATTRIBUTE_UNUSED_LABEL
+ ;
#endif
#ifdef DEBUG5
fprintf (stderr, "result:\n");
write_print_statistics (file)
FILE *file;
{
- fprintf (stderr, "fixups: %d\n", n_fixups);
+ fprintf (file, "fixups: %d\n", n_fixups);
}
/* for debugging */