I find that it is currently too hard to get pc-relative relocations
right in a cgen-generated gas. E.g. look at testsuite/ld-elf/merge* .
When the bfd_reloc_code_real_type of a fragment is selected, it is not
known if the fragment is pc-relative or not.
You could define tc_gen_reloc to your own function that parses the
expression to find out if it is pc-relative and do the right thing then,
but that would require a lot of duplicated code for each target,
and defeat the purpose of having gas_cgen_tc_gen_reloc.
With the appended patch, tc-.h only has to do
#define GAS_CGEN_PCREL_R_TYPE(R_TYPE) gas_cgen_pcrel_r_type(R_TYPE)
to handle the vanilla pc-relative relocations.
If a few pc-relative relocations need different handling, that should
also be easily accomplished with a wrapper function.
2011-08-06 Joern Rennecke
* cgen.c (gas_cgen_pcrel_r_type): New function.
(gas_cgen_tc_gen_reloc): Check for GAS_CGEN_PCREL_R_TYPE.
* cgen.h (gas_cgen_pcrel_r_type): Declare.
Index: cgen.c
===
--- cgen.c (revision 2024)
+++ cgen.c (revision 2025)
@@ -1018,6 +1018,32 @@ gas_cgen_md_apply_fix (fixP, valP, seg)
fixP->fx_addnumber = value;
}
+bfd_reloc_code_real_type
+gas_cgen_pcrel_r_type (bfd_reloc_code_real_type r)
+{
+ switch (r)
+{
+case BFD_RELOC_8:
+ r = BFD_RELOC_8_PCREL;
+ break;
+case BFD_RELOC_16:
+ r = BFD_RELOC_16_PCREL;
+ break;
+case BFD_RELOC_24:
+ r = BFD_RELOC_24_PCREL;
+ break;
+case BFD_RELOC_32:
+ r = BFD_RELOC_32_PCREL;
+ break;
+case BFD_RELOC_64:
+ r = BFD_RELOC_64_PCREL;
+ break;
+default:
+ break;
+}
+ return r;
+}
+
/* Translate internal representation of relocation info to BFD target format.
FIXME: To what extent can we get all relevant targets to use this? */
@@ -1027,10 +1053,16 @@ gas_cgen_tc_gen_reloc (section, fixP)
asection * section ATTRIBUTE_UNUSED;
fixS * fixP;
{
+ bfd_reloc_code_real_type r_type = fixP->fx_r_type;
arelent *reloc;
+
reloc = (arelent *) xmalloc (sizeof (arelent));
- reloc->howto = bfd_reloc_type_lookup (stdoutput, fixP->fx_r_type);
+#ifdef GAS_CGEN_PCREL_R_TYPE
+ if (fixP->fx_pcrel)
+r_type = GAS_CGEN_PCREL_R_TYPE (r_type);
+#endif
+ reloc->howto = bfd_reloc_type_lookup (stdoutput, r_type);
if (reloc->howto == (reloc_howto_type *) NULL)
{
as_bad_where (fixP->fx_file, fixP->fx_line,
Index: cgen.h
===
--- cgen.h (revision 2024)
+++ cgen.h (revision 2025)
@@ -80,6 +80,8 @@ extern fixS * gas_cgen_record_fixup_exp
int, const CGEN_OPERAND *, int,
expressionS *);
+extern bfd_reloc_code_real_type gas_cgen_pcrel_r_type
(bfd_reloc_code_real_type);
+
/* md_apply_fix handler */
extern void gas_cgen_md_apply_fix (fixS *, valueT *, segT);
___
bug-binutils mailing list
bug-binutils@gnu.org
https://lists.gnu.org/mailman/listinfo/bug-binutils