aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gas/ChangeLog13
-rw-r--r--gas/config/tc-hppa.c35
-rw-r--r--gas/write.c125
3 files changed, 117 insertions, 56 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog
index be9da74..22dd3cb 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,3 +1,16 @@
+Tue Nov 30 13:40:30 1993 Jeffrey A. Law (law@snake.cs.utah.edu)
+
+ * write.c (TC_FORCE_RELOCATION): Provide a default definition.
+ (fixup_segment): Allow the target machine to specify that a
+ relocation must be generated for a particular fixup. Remove
+ #ifndef TC_HPPA hack.
+
+ * config/tc-hppa.h (TC_FORCE_RELOCATION): Define.
+
+ * config/tc-hppa.c (md_apply_fix_1): Never change fx_addsy to
+ be NULL. Only fixup_segment is supposed to do that.
+ (hppa_force_relocation): New function.
+
Tue Nov 30 11:21:41 1993 Ian Lance Taylor (ian@tweedledumb.cygnus.com)
* Makefile.in (stabs.o): Added dependencies.
diff --git a/gas/config/tc-hppa.c b/gas/config/tc-hppa.c
index e588ca8..6ee3ac2 100644
--- a/gas/config/tc-hppa.c
+++ b/gas/config/tc-hppa.c
@@ -3102,7 +3102,6 @@ md_apply_fix_1 (fixP, val)
dis_assemble_12 (result, &w1, &w);
result = ((w1 << 2) | w);
- fixP->fx_addsy = NULL;
break;
#define stub_needed(CALLER, CALLEE) \
@@ -3129,7 +3128,6 @@ md_apply_fix_1 (fixP, val)
sign_unext ((new_val - 8) >> 2, 17, &result);
dis_assemble_17 (result, &w1, &w2, &w);
result = ((w2 << 2) | (w1 << 16) | w);
- fixP->fx_addsy = NULL;
break;
#undef too_far
@@ -6346,6 +6344,39 @@ hppa_fix_adjustable (fixp)
return 0;
}
+/* Return nonzero if the fixup in FIXP will require a relocation,
+ even it if appears that the fixup could be completely handled
+ within GAS. */
+
+int
+hppa_force_relocation (fixp)
+ fixS *fixp;
+{
+ struct hppa_fix_struct *hppa_fixp = fixp->tc_fix_data;
+
+#ifdef OBJ_SOM
+ if (fixp->fx_r_type == R_HPPA_ENTRY || fixp->fx_r_type == R_HPPA_EXIT)
+ return 1;
+#endif
+
+#define stub_needed(CALLER, CALLEE) \
+ ((CALLEE) && (CALLER) && ((CALLEE) != (CALLER)))
+
+ /* It is necessary to force PC-relative calls/jumps to have a relocation
+ entry if they're going to need either a argument relocation or long
+ call stub. FIXME. Can't we need the same for absolute calls? */
+ if (fixp->fx_pcrel
+ && (stub_needed (((obj_symbol_type *)
+ fixp->fx_addsy->bsym)->tc_data.hppa_arg_reloc,
+ hppa_fixp->fx_arg_reloc)))
+ return 1;
+
+#undef stub_needed
+
+ /* No need (yet) to force another relocations to be emitted. */
+ return 0;
+}
+
/* Now for some ELF specific code. FIXME. */
#ifdef OBJ_ELF
static symext_chainS *symext_rootP;
diff --git a/gas/write.c b/gas/write.c
index f27b5e1..9e0ba8e 100644
--- a/gas/write.c
+++ b/gas/write.c
@@ -30,6 +30,10 @@
#define NOP_OPCODE 0x00
#endif
+#ifndef TC_FORCE_RELOCATION
+#define TC_FORCE_RELOCATION(FIXP) 0
+#endif
+
#ifndef WORKING_DOT_WORD
extern CONST int md_short_jump_size;
extern CONST int md_long_jump_size;
@@ -638,9 +642,7 @@ write_relocs (abfd, sec, xxx)
if (fixp->fx_where + fixp->fx_size
> fixp->fx_frag->fr_fix + fixp->fx_frag->fr_offset)
abort ();
- /* Pass bogus address so that when bfd_perform_relocation adds
- `address' back in, it'll come up with `data', which is where
- we want it to operate. */
+
if (reloc->howto->partial_inplace == false
&& reloc->howto->pcrel_offset == true
&& reloc->howto->pc_relative == true)
@@ -648,6 +650,9 @@ write_relocs (abfd, sec, xxx)
/* bfd_perform_relocation screws this up */
reloc->addend += reloc->address;
}
+ /* Pass bogus address so that when bfd_perform_relocation adds
+ `address' back in, it'll come up with `data', which is where
+ we want it to operate. */
s = bfd_perform_relocation (stdoutput, reloc, data - reloc->address,
sec, stdoutput);
switch (s)
@@ -1288,10 +1293,6 @@ write_object_file ()
#endif /* VMS */
#else /* BFD_ASSEMBLER */
-#ifdef obj_check_file_symbols
- obj_check_file_symbols ();
-#endif
-
bfd_map_over_sections (stdoutput, adjust_reloc_syms, (char *)0);
/* Set up symbol table, and write it out. */
@@ -1329,60 +1330,58 @@ write_object_file ()
symp->bsym->flags,
segment_name (symp->bsym->section));
#endif
- if (! symp->sy_used_in_reloc)
- {
+
#ifdef obj_frob_symbol
- {
- int punt = 0;
- obj_frob_symbol (symp, punt);
- if (punt)
- goto punt_it;
- }
+ {
+ int punt = 0;
+ obj_frob_symbol (symp, punt);
+ if (punt)
+ goto punt_it;
+ }
#endif
#ifdef tc_frob_symbol
- {
- int punt = 0;
- tc_frob_symbol (symp, punt);
- if (punt)
- goto punt_it;
- }
+ {
+ int punt = 0;
+ tc_frob_symbol (symp, punt);
+ if (punt)
+ goto punt_it;
+ }
#endif
- }
/* If we don't want to keep this symbol, splice it out of the
chain now. */
- if (! symp->sy_used_in_reloc
- && S_IS_LOCAL (symp))
+ if (S_IS_LOCAL (symp))
{
- symbolS *prev, *next;
-#if defined (obj_frob_symbol) || defined (tc_frob_symbol)
punt_it:
-#endif
- prev = symbol_previous (symp);
- next = symbol_next (symp);
+ if (! symp->sy_used_in_reloc)
+ {
+ symbolS *prev, *next;
+ prev = symbol_previous (symp);
+ next = symbol_next (symp);
#ifdef DEBUG_SYMS
- verify_symbol_chain_2 (symp);
+ verify_symbol_chain_2 (symp);
#endif
- if (prev)
- {
- symbol_next (prev) = next;
- symp = prev;
- }
- else if (symp == symbol_rootP)
- symbol_rootP = next;
- else
- abort ();
- if (next)
- symbol_previous (next) = prev;
- else
- symbol_lastP = prev;
+ if (prev)
+ {
+ symbol_next (prev) = next;
+ symp = prev;
+ }
+ else if (symp == symbol_rootP)
+ symbol_rootP = next;
+ else
+ abort ();
+ if (next)
+ symbol_previous (next) = prev;
+ else
+ symbol_lastP = prev;
#ifdef DEBUG_SYMS
- if (prev)
- verify_symbol_chain_2 (prev);
- else if (next)
- verify_symbol_chain_2 (next);
+ if (prev)
+ verify_symbol_chain_2 (prev);
+ else if (next)
+ verify_symbol_chain_2 (next);
#endif
- continue;
+ continue;
+ }
}
/* Make sure we really got a value for the symbol. */
@@ -1896,7 +1895,12 @@ fixup_segment (fixP, this_segment_type)
S_GET_VALUE (sub_symbolP);
add_symbolP = NULL;
- fixP->fx_addsy = NULL;
+
+ /* 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;
}
else
{
@@ -1960,9 +1964,12 @@ fixup_segment (fixP, this_segment_type)
add_number += S_GET_VALUE (add_symbolP);
add_number -= md_pcrel_from (fixP);
pcrel = 0; /* Lie. Don't want further pcrel processing. */
-#ifndef TC_HPPA
- fixP->fx_addsy = NULL; /* No relocations please. */
-#endif
+
+ /* 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;
}
else
{
@@ -1973,7 +1980,12 @@ fixup_segment (fixP, this_segment_type)
reloc_callj (fixP);
#endif /* TC_I960 */
add_number += S_GET_VALUE (add_symbolP);
- fixP->fx_addsy = NULL;
+
+ /* 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
@@ -1991,7 +2003,12 @@ fixup_segment (fixP, this_segment_type)
* relocation.
*/
as_bad ("can't use COBR format with external label");
- fixP->fx_addsy = NULL; /* No relocations please. */
+
+ /* 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;
continue;
} /* COBR */
#endif /* TC_I960 */