dis_assemble_12 (result, &w1, &w);
result = ((w1 << 2) | w);
- fixP->fx_addsy = NULL;
break;
#define stub_needed(CALLER, CALLEE) \
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
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;
#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;
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)
/* 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)
#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. */
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. */
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
{
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
{
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
* 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 */