summaryrefslogtreecommitdiff
path: root/gas/write.c
diff options
context:
space:
mode:
authorAlan Modra <amodra@bigpond.net.au>2002-09-05 00:01:18 +0000
committerAlan Modra <amodra@bigpond.net.au>2002-09-05 00:01:18 +0000
commita1b21dcdfbd5658dd57ccdecfd95319ec28e6551 (patch)
tree35994cf39ce1f17aa2f18969fe31c3781b146843 /gas/write.c
parentfef4effd994bbc0e0fb17657b9647a16f7957d35 (diff)
downloadbinutils-redhat-a1b21dcdfbd5658dd57ccdecfd95319ec28e6551.tar.gz
gas reloc rewrite.
Diffstat (limited to 'gas/write.c')
-rw-r--r--gas/write.c580
1 files changed, 227 insertions, 353 deletions
diff --git a/gas/write.c b/gas/write.c
index 3f609d3ead..17c323209f 100644
--- a/gas/write.c
+++ b/gas/write.c
@@ -33,19 +33,62 @@
#endif
#ifndef TC_FORCE_RELOCATION
-#define TC_FORCE_RELOCATION(FIX) 0
+#define TC_FORCE_RELOCATION(FIX) \
+ (S_FORCE_RELOC ((FIX)->fx_addsy))
#endif
-#ifndef TC_FORCE_RELOCATION_SECTION
-#define TC_FORCE_RELOCATION_SECTION(FIX, SEG) TC_FORCE_RELOCATION (FIX)
+#ifndef TC_FORCE_RELOCATION_ABS
+#define TC_FORCE_RELOCATION_ABS(FIX) \
+ (TC_FORCE_RELOCATION (FIX))
+#endif
+
+#ifndef TC_FORCE_RELOCATION_LOCAL
+#define TC_FORCE_RELOCATION_LOCAL(FIX) \
+ (!(FIX)->fx_pcrel \
+ || (FIX)->fx_plt \
+ || TC_FORCE_RELOCATION (FIX))
+#endif
+
+#ifndef TC_FORCE_RELOCATION_SUB_SAME
+#define TC_FORCE_RELOCATION_SUB_SAME(FIX, SEG) \
+ (! SEG_NORMAL (SEG))
+#endif
+
+#ifndef TC_FORCE_RELOCATION_SUB_ABS
+#define TC_FORCE_RELOCATION_SUB_ABS(FIX) \
+ (S_FORCE_RELOC ((FIX)->fx_subsy))
+#endif
+
+#ifndef TC_FORCE_RELOCATION_SUB_LOCAL
+#ifdef DIFF_EXPR_OK
+#define TC_FORCE_RELOCATION_SUB_LOCAL(FIX) \
+ (S_FORCE_RELOC ((FIX)->fx_subsy))
+#else
+#define TC_FORCE_RELOCATION_SUB_LOCAL(FIX) 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
+#else
+#ifdef BFD_ASSEMBLER
+#define TC_VALIDATE_FIX_SUB(FIX) \
+ ((FIX)->fx_r_type == BFD_RELOC_GPREL32 \
+ || (FIX)->fx_r_type == BFD_RELOC_GPREL16)
+#else
+#define TC_VALIDATE_FIX_SUB(FIX) 0
+#endif
+#endif
#endif
#ifndef TC_LINKRELAX_FIXUP
#define TC_LINKRELAX_FIXUP(SEG) 1
#endif
-#ifndef TC_FIX_ADJUSTABLE
-#define TC_FIX_ADJUSTABLE(FIX) 1
+#ifndef MD_APPLY_SYM_VALUE
+#define MD_APPLY_SYM_VALUE(FIX) 1
#endif
#ifndef TC_FINALIZE_SYMS_BEFORE_SIZE_SEG
@@ -65,6 +108,9 @@ extern const int md_long_jump_size;
int finalize_syms = 0;
int symbol_table_frozen;
+
+symbolS *abs_section_sym;
+
void print_fixup PARAMS ((fixS *));
#ifdef BFD_ASSEMBLER
@@ -125,6 +171,7 @@ static fragS *chain_frchains_together_1 PARAMS ((segT, struct frchain *));
static void chain_frchains_together PARAMS ((bfd *, segT, PTR));
static void cvt_frag_to_fill PARAMS ((segT, fragS *));
static void adjust_reloc_syms PARAMS ((bfd *, asection *, PTR));
+static void fix_segment PARAMS ((bfd *, asection *, PTR));
static void write_relocs PARAMS ((bfd *, asection *, PTR));
static void write_contents PARAMS ((bfd *, asection *, PTR));
static void set_symtab PARAMS ((void));
@@ -775,41 +822,32 @@ adjust_reloc_syms (abfd, sec, xxx)
continue;
}
+ /* If the symbol is undefined, common, weak, or global (ELF
+ shared libs), we can't replace it with the section symbol. */
+ if (S_FORCE_RELOC (fixp->fx_addsy))
+ continue;
+
+ /* Is there some other (target cpu dependent) reason we can't adjust
+ this one? (E.g. relocations involving function addresses on
+ the PA. */
+#ifdef tc_fix_adjustable
+ if (! tc_fix_adjustable (fixp))
+ continue;
+#endif
+
+ /* Since we're reducing to section symbols, don't attempt to reduce
+ anything that's already using one. */
+ if (symbol_section_p (sym))
+ continue;
+
symsec = S_GET_SEGMENT (sym);
if (symsec == NULL)
abort ();
if (bfd_is_abs_section (symsec))
{
- /* The fixup_segment routine will not use this symbol in a
- relocation unless TC_FORCE_RELOCATION returns 1. */
- if (TC_FORCE_RELOCATION (fixp))
- {
- symbol_mark_used_in_reloc (fixp->fx_addsy);
-#ifdef UNDEFINED_DIFFERENCE_OK
- if (fixp->fx_subsy != NULL)
- symbol_mark_used_in_reloc (fixp->fx_subsy);
-#endif
- }
- continue;
- }
-
- /* If it's one of these sections, assume the symbol is
- definitely going to be output. The code in
- md_estimate_size_before_relax in tc-mips.c uses this test
- as well, so if you change this code you should look at that
- code. */
- if (bfd_is_und_section (symsec)
- || bfd_is_com_section (symsec))
- {
- 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)
- symbol_mark_used_in_reloc (fixp->fx_subsy);
-#endif
+ /* The fixup_segment routine normally will not use this
+ symbol in a relocation. */
continue;
}
@@ -819,117 +857,51 @@ adjust_reloc_syms (abfd, sec, xxx)
this will always be correct. */
if (symsec != sec && ! S_IS_LOCAL (sym))
{
- boolean linkonce;
-
- linkonce = false;
-#ifdef BFD_ASSEMBLER
- if ((bfd_get_section_flags (stdoutput, symsec) & SEC_LINK_ONCE)
- != 0)
- linkonce = true;
-#endif
-#ifdef OBJ_ELF
- /* The GNU toolchain uses an extension for ELF: a section
- beginning with the magic string .gnu.linkonce is a
- linkonce section. */
- if (strncmp (segment_name (symsec), ".gnu.linkonce",
- sizeof ".gnu.linkonce" - 1) == 0)
- linkonce = true;
-#endif
-
- if (linkonce)
- {
- symbol_mark_used_in_reloc (fixp->fx_addsy);
-#ifdef UNDEFINED_DIFFERENCE_OK
- if (fixp->fx_subsy != NULL)
- symbol_mark_used_in_reloc (fixp->fx_subsy);
-#endif
- continue;
- }
- }
-
- /* Since we're reducing to section symbols, don't attempt to reduce
- anything that's already using one. */
- if (symbol_section_p (sym))
- {
- symbol_mark_used_in_reloc (fixp->fx_addsy);
- continue;
- }
-
-#ifdef BFD_ASSEMBLER
- /* We can never adjust a reloc against a weak symbol. If we
- did, and the weak symbol was overridden by a real symbol
- somewhere else, then our relocation would be pointing at
- the wrong area of memory. */
- if (S_IS_WEAK (sym))
- {
- symbol_mark_used_in_reloc (fixp->fx_addsy);
- continue;
+ if ((symsec->flags & SEC_LINK_ONCE) != 0
+ || (IS_ELF
+ /* The GNU toolchain uses an extension for ELF: a
+ section beginning with the magic string
+ .gnu.linkonce is a linkonce section. */
+ && strncmp (segment_name (symsec), ".gnu.linkonce",
+ sizeof ".gnu.linkonce" - 1) == 0))
+ continue;
}
/* Never adjust a reloc against local symbol in a merge section
with non-zero addend. */
if ((symsec->flags & SEC_MERGE) != 0 && fixp->fx_offset != 0)
- {
- symbol_mark_used_in_reloc (fixp->fx_addsy);
- continue;
- }
+ continue;
/* Never adjust a reloc against TLS local symbol. */
if ((symsec->flags & SEC_THREAD_LOCAL) != 0)
- {
- symbol_mark_used_in_reloc (fixp->fx_addsy);
- continue;
- }
-#endif
-
- /* Is there some other reason we can't adjust this one? (E.g.,
- call/bal links in i960-bout symbols.) */
-#ifdef obj_fix_adjustable
- if (! obj_fix_adjustable (fixp))
- {
- symbol_mark_used_in_reloc (fixp->fx_addsy);
- continue;
- }
-#endif
-
- /* Is there some other (target cpu dependent) reason we can't adjust
- this one? (E.g. relocations involving function addresses on
- the PA. */
-#ifdef tc_fix_adjustable
- if (! tc_fix_adjustable (fixp))
- {
- symbol_mark_used_in_reloc (fixp->fx_addsy);
- continue;
- }
-#endif
-
- /* If the section symbol isn't going to be output, the relocs
- at least should still work. If not, figure out what to do
- when we run into that case.
+ continue;
- We refetch the segment when calling section_symbol, rather
+ /* We refetch the segment when calling section_symbol, rather
than using symsec, because S_GET_VALUE may wind up changing
the section when it calls resolve_symbol_value. */
fixp->fx_offset += S_GET_VALUE (sym);
fixp->fx_addsy = section_symbol (S_GET_SEGMENT (sym));
- symbol_mark_used_in_reloc (fixp->fx_addsy);
#ifdef DEBUG5
fprintf (stderr, "\nadjusted fixup:\n");
print_fixup (fixp);
#endif
}
- else
- {
- /* There was no symbol required by this relocation. However,
- BFD doesn't really handle relocations without symbols well.
- So fake up a local symbol in the absolute section. */
- fixp->fx_addsy = section_symbol (absolute_section);
- }
dump_section_relocs (abfd, sec, stderr);
}
static void
+fix_segment (abfd, sec, xxx)
+ bfd *abfd ATTRIBUTE_UNUSED;
+ asection *sec;
+ PTR xxx ATTRIBUTE_UNUSED;
+{
+ segment_info_type *seginfo = seg_info (sec);
+
+ fixup_segment (seginfo->fix_root, sec);
+}
+
+static void
write_relocs (abfd, sec, xxx)
bfd *abfd;
asection *sec;
@@ -947,8 +919,6 @@ write_relocs (abfd, sec, xxx)
if (seginfo == NULL)
return;
- fixup_segment (seginfo->fix_root, sec);
-
n = 0;
for (fixp = seginfo->fix_root; fixp; fixp = fixp->fx_next)
n++;
@@ -1926,6 +1896,15 @@ write_object_file ()
bfd_map_over_sections (stdoutput, adjust_reloc_syms, (char *) 0);
+#ifdef tc_frob_file_before_fix
+ tc_frob_file_before_fix ();
+#endif
+#ifdef obj_frob_file_before_fix
+ obj_frob_file_before_fix ();
+#endif
+
+ bfd_map_over_sections (stdoutput, fix_segment, (char *) 0);
+
/* Set up symbol table, and write it out. */
if (symbol_rootP)
{
@@ -1995,13 +1974,14 @@ write_object_file ()
want section symbols. Otherwise, we skip local symbols
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
- && symbol_section_p (symp))
+ if (symp == abs_section_sym
+ || (! EMIT_SECTION_SYMBOLS
+ && 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)
+ && (punt || S_IS_LOCAL (symp))
&& ! symbol_used_in_reloc_p (symp)))
{
symbol_remove (symp, &symbol_rootP, &symbol_lastP);
@@ -2109,7 +2089,7 @@ relax_frag (segment, fragP, stretch)
#endif
know (sym_frag != NULL);
#endif
- know (!(S_GET_SEGMENT (symbolP) == absolute_section)
+ know (S_GET_SEGMENT (symbolP) != absolute_section
|| sym_frag == &zero_address_frag);
target += S_GET_VALUE (symbolP);
@@ -2555,10 +2535,6 @@ relax_segment (segment_frag_root, segment)
#if defined (BFD_ASSEMBLER) || (!defined (BFD) && !defined (OBJ_VMS))
-#ifndef TC_RELOC_RTSYM_LOC_FIXUP
-#define TC_RELOC_RTSYM_LOC_FIXUP(X) (1)
-#endif
-
/* fixup_segment()
Go through all the fixS's in a segment and see which ones can be
@@ -2576,13 +2552,19 @@ fixup_segment (fixP, this_segment)
segT this_segment;
{
long seg_reloc_count = 0;
- symbolS *add_symbolP;
- symbolS *sub_symbolP;
valueT add_number;
- int pcrel, plt;
fragS *fragP;
segT add_symbol_segment = absolute_section;
+ if (fixP != NULL && abs_section_sym == NULL)
+ {
+#ifndef BFD_ASSEMBLER
+ abs_section_sym = &abs_symbol;
+#else
+ abs_section_sym = section_symbol (absolute_section);
+#endif
+ }
+
/* If the linker is doing the relaxing, we must not do any fixups.
Well, strictly speaking that's not true -- we could do any that
@@ -2592,7 +2574,21 @@ fixup_segment (fixP, this_segment)
if (linkrelax && TC_LINKRELAX_FIXUP (this_segment))
{
for (; fixP; fixP = fixP->fx_next)
- seg_reloc_count++;
+ if (!fixP->fx_done)
+ {
+ if (fixP->fx_addsy == NULL)
+ {
+ /* There was no symbol required by this relocation.
+ However, BFD doesn't really handle relocations
+ without symbols well. So fake up a local symbol in
+ the absolute section. */
+ fixP->fx_addsy = abs_section_sym;
+ }
+ symbol_mark_used_in_reloc (fixP->fx_addsy);
+ if (fixP->fx_subsy != NULL)
+ symbol_mark_used_in_reloc (fixP->fx_subsy);
+ seg_reloc_count++;
+ }
TC_ADJUST_RELOC_COUNT (fixP, seg_reloc_count);
return seg_reloc_count;
}
@@ -2606,267 +2602,145 @@ fixup_segment (fixP, this_segment)
fragP = fixP->fx_frag;
know (fragP);
- add_symbolP = fixP->fx_addsy;
#ifdef TC_VALIDATE_FIX
TC_VALIDATE_FIX (fixP, this_segment, skip);
#endif
- sub_symbolP = fixP->fx_subsy;
add_number = fixP->fx_offset;
- pcrel = fixP->fx_pcrel;
- plt = fixP->fx_plt;
- if (add_symbolP != NULL
- && symbol_mri_common_p (add_symbolP))
+ if (fixP->fx_addsy != NULL
+ && symbol_mri_common_p (fixP->fx_addsy))
{
- know (add_symbolP->sy_value.X_op == O_symbol);
- add_number += S_GET_VALUE (add_symbolP);
+ know (fixP->fx_addsy->sy_value.X_op == O_symbol);
+ add_number += S_GET_VALUE (fixP->fx_addsy);
fixP->fx_offset = add_number;
- add_symbolP = fixP->fx_addsy =
- symbol_get_value_expression (add_symbolP)->X_add_symbol;
+ fixP->fx_addsy
+ = symbol_get_value_expression (fixP->fx_addsy)->X_add_symbol;
}
- if (add_symbolP)
- add_symbol_segment = S_GET_SEGMENT (add_symbolP);
+ if (fixP->fx_addsy != NULL)
+ add_symbol_segment = S_GET_SEGMENT (fixP->fx_addsy);
- if (sub_symbolP)
+ if (fixP->fx_subsy != NULL)
{
- resolve_symbol_value (sub_symbolP);
- if (add_symbolP == NULL || add_symbol_segment == absolute_section)
+ segT sub_symbol_segment;
+ resolve_symbol_value (fixP->fx_subsy);
+ sub_symbol_segment = S_GET_SEGMENT (fixP->fx_subsy);
+ if (fixP->fx_addsy != NULL
+ && sub_symbol_segment == add_symbol_segment
+ && !TC_FORCE_RELOCATION_SUB_SAME (fixP, add_symbol_segment))
{
- if (add_symbolP != NULL)
- {
- add_number += S_GET_VALUE (add_symbolP);
- add_symbolP = NULL;
- fixP->fx_addsy = NULL;
- }
-
- /* It's just -sym. */
- if (S_GET_SEGMENT (sub_symbolP) == absolute_section)
- {
- add_number -= S_GET_VALUE (sub_symbolP);
- fixP->fx_subsy = NULL;
- }
- else if (pcrel
- && S_GET_SEGMENT (sub_symbolP) == this_segment)
- {
- /* Should try converting to a constant. */
- goto bad_sub_reloc;
- }
- else
- bad_sub_reloc:
- as_bad_where (fixP->fx_file, fixP->fx_line,
- _("negative of non-absolute symbol `%s'"),
- S_GET_NAME (sub_symbolP));
- }
- else if (S_GET_SEGMENT (sub_symbolP) == add_symbol_segment
- && SEG_NORMAL (add_symbol_segment))
- {
- /* Difference of 2 symbols from same segment.
- Can't make difference of 2 undefineds: 'value' means
- something different for N_UNDF. */
-#ifdef TC_I960
- /* Makes no sense to use the difference of 2 arbitrary symbols
- as the target of a call instruction. */
- if (fixP->fx_tcbit)
- as_bad_where (fixP->fx_file, fixP->fx_line,
- _("callj to difference of two symbols"));
-#endif /* TC_I960 */
- add_number += (S_GET_VALUE (add_symbolP)
- - S_GET_VALUE (sub_symbolP));
+ add_number += S_GET_VALUE (fixP->fx_addsy);
+ add_number -= S_GET_VALUE (fixP->fx_subsy);
+ fixP->fx_offset = add_number;
+ /* If the back-end code has selected a pc-relative
+ reloc, adjust the value to be pc-relative. */
if (1
#ifdef TC_M68K
/* See the comment below about 68k weirdness. */
&& 0
#endif
- && pcrel)
- add_number -= MD_PCREL_FROM_SECTION (fixP, this_segment);
-
- add_symbolP = NULL;
- pcrel = 0; /* No further pcrel processing. */
-
- /* Let the target machine make the final determination
- as to whether or not a relocation will be needed to
- handle this fixup. */
- if (!TC_FORCE_RELOCATION_SECTION (fixP, this_segment))
- {
- fixP->fx_pcrel = 0;
- fixP->fx_addsy = NULL;
- fixP->fx_subsy = NULL;
- }
+ && fixP->fx_pcrel)
+ add_number -= MD_PCREL_FROM_SECTION (fixP, this_segment);
+ fixP->fx_addsy = NULL;
+ fixP->fx_subsy = NULL;
+ fixP->fx_pcrel = 0;
}
- else
+ else if (sub_symbol_segment == absolute_section
+ && !TC_FORCE_RELOCATION_SUB_ABS (fixP))
{
- /* Different segments in subtraction. */
- know (!(S_IS_EXTERNAL (sub_symbolP)
- && (S_GET_SEGMENT (sub_symbolP) == absolute_section)));
-
- if ((S_GET_SEGMENT (sub_symbolP) == absolute_section))
- add_number -= S_GET_VALUE (sub_symbolP);
+ 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))
+ {
+ add_number -= S_GET_VALUE (fixP->fx_subsy);
+ fixP->fx_offset = add_number;
-#ifdef DIFF_EXPR_OK
- else if (S_GET_SEGMENT (sub_symbolP) == this_segment)
- {
- /* Make it pc-relative. */
- if (0
+ /* Make it pc-relative. If the back-end code has not
+ selected a pc-relative reloc, cancel the adjustment
+ we do later on all pc-relative relocs. */
+ if (0
#ifdef TC_M68K
- /* Do this for m68k even if it's already described
- as pc-relative. On the m68k, an operand of
- "pc@(foo-.-2)" should address "foo" in a
- pc-relative mode. */
- || 1
-#endif
- || !pcrel)
- {
- add_number += MD_PCREL_FROM_SECTION (fixP,
- this_segment);
- pcrel = 1;
- fixP->fx_pcrel = 1;
- }
-
- add_number -= S_GET_VALUE (sub_symbolP);
- sub_symbolP = 0;
- fixP->fx_subsy = 0;
- }
-#endif
-#ifdef UNDEFINED_DIFFERENCE_OK
- /* The PA needs this for PIC code generation. We basically
- don't want to do anything if we have the difference of two
- symbols at this point. */
- else if (1)
- {
- /* Leave it alone. */
- }
-#endif
-#ifdef BFD_ASSEMBLER
- else if (fixP->fx_r_type == BFD_RELOC_GPREL32
- || fixP->fx_r_type == BFD_RELOC_GPREL16)
- {
- /* Leave it alone. */
- }
-#endif
- else
- {
- char buf[50];
- sprint_value (buf, fragP->fr_address + fixP->fx_where);
- as_bad_where (fixP->fx_file, fixP->fx_line,
- _("subtraction of two symbols in different sections `%s' {%s section} - `%s' {%s section} at file address %s"),
- S_GET_NAME (add_symbolP),
- segment_name (S_GET_SEGMENT (add_symbolP)),
- S_GET_NAME (sub_symbolP),
- segment_name (S_GET_SEGMENT (sub_symbolP)),
- buf);
- }
+ /* Do this for m68k even if it's already described
+ as pc-relative. On the m68k, an operand of
+ "pc@(foo-.-2)" should address "foo" in a
+ pc-relative mode. */
+ || 1
+#endif
+ || !fixP->fx_pcrel)
+ add_number += MD_PCREL_FROM_SECTION (fixP, this_segment);
+ fixP->fx_subsy = NULL;
+ fixP->fx_pcrel = 1;
+ }
+ else if (!TC_VALIDATE_FIX_SUB (fixP))
+ {
+ 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 (add_symbolP)
+ if (fixP->fx_addsy)
{
- if (add_symbol_segment == this_segment && pcrel && !plt
- && TC_RELOC_RTSYM_LOC_FIXUP (fixP))
+ if (add_symbol_segment == this_segment
+ && !TC_FORCE_RELOCATION_LOCAL (fixP))
{
/* This fixup was made when the symbol's segment was
SEG_UNKNOWN, but it is now in the local segment.
So we know how to do the address without relocation. */
-#ifdef TC_I960
- /* reloc_callj() may replace a 'call' with a 'calls' or a
- 'bal', in which cases it modifies *fixP as appropriate.
- In the case of a 'calls', no further work is required,
- and *fixP has been set up to make the rest of the code
- below a no-op. */
- reloc_callj (fixP);
-#endif /* TC_I960 */
-
- add_number += S_GET_VALUE (add_symbolP);
- add_number -= MD_PCREL_FROM_SECTION (fixP, this_segment);
- /* Lie. Don't want further pcrel processing. */
- pcrel = 0;
-
- /* Let the target machine make the final determination
- as to whether or not a relocation will be needed to
- handle this fixup. */
- if (!TC_FORCE_RELOCATION (fixP))
- {
- fixP->fx_pcrel = 0;
- fixP->fx_addsy = NULL;
- }
+ add_number += S_GET_VALUE (fixP->fx_addsy);
+ fixP->fx_offset = add_number;
+ if (fixP->fx_pcrel)
+ add_number -= MD_PCREL_FROM_SECTION (fixP, this_segment);
+ fixP->fx_addsy = NULL;
+ fixP->fx_pcrel = 0;
}
- else
+ else if (add_symbol_segment == absolute_section
+ && !TC_FORCE_RELOCATION_ABS (fixP))
{
- if (add_symbol_segment == absolute_section
- && ! pcrel)
- {
-#ifdef TC_I960
- /* See comment about reloc_callj() above. */
- reloc_callj (fixP);
-#endif /* TC_I960 */
- add_number += S_GET_VALUE (add_symbolP);
-
- /* Let the target machine make the final determination
- as to whether or not a relocation will be needed to
- handle this fixup. */
-
- if (!TC_FORCE_RELOCATION (fixP))
- {
- fixP->fx_addsy = NULL;
- add_symbolP = NULL;
- }
- }
- else if (add_symbol_segment == undefined_section
+ add_number += S_GET_VALUE (fixP->fx_addsy);
+ fixP->fx_offset = add_number;
+ fixP->fx_addsy = NULL;
+ }
+ else if (add_symbol_segment != undefined_section
#ifdef BFD_ASSEMBLER
- || bfd_is_com_section (add_symbol_segment)
+ && ! bfd_is_com_section (add_symbol_segment)
#endif
- )
- {
-#ifdef TC_I960
- if ((int) fixP->fx_bit_fixP == 13)
- {
- /* This is a COBR instruction. They have only a
- 13-bit displacement and are only to be used
- for local branches: flag as error, don't generate
- relocation. */
- as_bad_where (fixP->fx_file, fixP->fx_line,
- _("can't use COBR format with external label"));
- fixP->fx_addsy = NULL;
- fixP->fx_done = 1;
- continue;
- } /* COBR. */
-#endif /* TC_I960 */
-
-#ifdef OBJ_COFF
-#ifdef TE_I386AIX
- if (S_IS_COMMON (add_symbolP))
- add_number += S_GET_VALUE (add_symbolP);
-#endif /* TE_I386AIX */
-#endif /* OBJ_COFF */
- ++seg_reloc_count;
- }
- else
- {
- seg_reloc_count++;
- if (TC_FIX_ADJUSTABLE (fixP))
- add_number += S_GET_VALUE (add_symbolP);
- }
- }
+ && MD_APPLY_SYM_VALUE (fixP))
+ add_number += S_GET_VALUE (fixP->fx_addsy);
}
- if (pcrel)
+ if (fixP->fx_pcrel)
{
add_number -= MD_PCREL_FROM_SECTION (fixP, this_segment);
- if (add_symbolP == 0)
+ if (!fixP->fx_done && fixP->fx_addsy == NULL)
{
-#ifndef BFD_ASSEMBLER
- fixP->fx_addsy = &abs_symbol;
-#else
- fixP->fx_addsy = section_symbol (absolute_section);
-#endif
- symbol_mark_used_in_reloc (fixP->fx_addsy);
- ++seg_reloc_count;
+ /* There was no symbol required by this relocation.
+ However, BFD doesn't really handle relocations
+ without symbols well. So fake up a local symbol in
+ the absolute section. */
+ fixP->fx_addsy = abs_section_sym;
}
}
if (!fixP->fx_done)
md_apply_fix3 (fixP, &add_number, this_segment);
+ if (!fixP->fx_done)
+ {
+ ++seg_reloc_count;
+ if (fixP->fx_addsy == NULL)
+ fixP->fx_addsy = abs_section_sym;
+ symbol_mark_used_in_reloc (fixP->fx_addsy);
+ if (fixP->fx_subsy != NULL)
+ symbol_mark_used_in_reloc (fixP->fx_subsy);
+ }
+
if (!fixP->fx_bit_fixP && !fixP->fx_no_overflow && fixP->fx_size != 0)
{
if (fixP->fx_size < sizeof (valueT))