This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
Re: [RFA] ARM OABI - pc-relative relocations
Jerome Guitton <guitton@act-europe.fr> writes:
> Ouch! That is perfectly reasonable, but I have a problem. I am
> targetting VxWorks 5.5 on ARM. WRS' tools uses RELA, with the old ABI
> definition... And I am interested in making a the GNU tools and WRS
> tools compatible.
I already have patches for this. They are not quite suitable for
inclusion, but I think only small changes would be required. Also I
am not sure they solve your problem. What I did was hack up BFD to
produce RELA relocs for ARM, and then I modified GAS so that in
RELA/arm mode it always sets the instruction addend to zero. The
linker then need not know or care about the quirky old-ABI spec for
RELA. Conveniently, this is what WRS' tools do, too.
Patch is appended. Comments? I do not know the proper way to get
USE_REL set to 0; obviously "#ifndef NOT_VXWORKS" is not the right
approach.
zw
* bfd/elfarm-nabi.c: Force USE_REL to 0.
* bfd/elf32-arm.h (elf32_arm_final_link_relocate): Do not adjust
RELA addends by howto->size.
* gas/config/tc-arm.c: If a fixup will produce a relocation in
the final object file, and RELA relocations are used for this
segment, then don't put the addend in the instruction stream;
instead correct fixP->fx_offset and/or fixP->fx_addnumber as
necessary.
===================================================================
Index: bfd/elfarm-nabi.c
--- bfd/elfarm-nabi.c 2 Sep 2003 23:49:48 -0000 1.1.3.1
+++ bfd/elfarm-nabi.c 1 Dec 2003 08:00:23 -0000 1.1.3.1.2.1
@@ -27,7 +27,12 @@
#define NUM_ELEM(a) (sizeof (a) / (sizeof (a)[0]))
#endif
+/* WRS LOCAL - force use of RELA */
+#ifndef NOT_VXWORKS
+#define USE_REL 0 /* affirmative setting to catch others */
+#else
#define USE_REL 1
+#endif
#define TARGET_LITTLE_SYM bfd_elf32_littlearm_vec
#define TARGET_LITTLE_NAME "elf32-littlearm"
===================================================================
Index: bfd/elf32-arm.h
--- bfd/elf32-arm.h 26 Nov 2003 05:09:51 -0000 1.1.3.1.2.1
+++ bfd/elf32-arm.h 1 Dec 2003 08:00:22 -0000 1.1.3.1.2.2
@@ -1458,7 +1458,12 @@ elf32_arm_final_link_relocate (howto, in
value -= (input_section->output_section->vma
+ input_section->output_offset);
value -= rel->r_offset;
+#if USE_REL
value += (signed_addend << howto->size);
+#else
+ /* RELA addends do not have to be adjusted by howto->size. */
+ value += signed_addend;
+#endif
/* Previous versions of this code also used to add in the pipeline
offset here. This is wrong because the linker is not supposed
===================================================================
Index: gas/config/tc-arm.c
--- gas/config/tc-arm.c 26 Nov 2003 05:10:06 -0000 1.1.3.1.2.1
+++ gas/config/tc-arm.c 1 Dec 2003 08:00:23 -0000 1.1.3.1.2.2
@@ -11274,7 +11274,19 @@ md_apply_fix3 (fixP, valP, seg)
as_bad_where (fixP->fx_file, fixP->fx_line,
_("out of range branch"));
- newval = (value & 0x00ffffff) | (newval & 0xff000000);
+ if (seg->use_rela_p && !fixP->fx_done)
+ {
+ /* Must unshift the value before storing it in the addend. */
+ value <<= 2;
+#ifdef OBJ_ELF
+ if (! target_oabi)
+ fixP->fx_offset = value;
+#endif
+ fixP->fx_addnumber = value;
+ newval = newval & 0xff000000;
+ }
+ else
+ newval = (value & 0x00ffffff) | (newval & 0xff000000);
md_number_to_chars (buf, newval, INSN_SIZE);
break;
@@ -11290,7 +11302,22 @@ md_apply_fix3 (fixP, valP, seg)
hbit = (value >> 1) & 1;
value = (value >> 2) & 0x00ffffff;
value = (value + (newval & 0x00ffffff)) & 0x00ffffff;
- newval = value | (newval & 0xfe000000) | (hbit << 24);
+
+ if (seg->use_rela_p && !fixP->fx_done)
+ {
+ /* Must sign-extend and unshift the value before storing
+ it in the addend. */
+ value = SEXT24 (value);
+ value = (value << 2) | hbit;
+#ifdef OBJ_ELF
+ if (! target_oabi)
+ fixP->fx_offset = value;
+#endif
+ fixP->fx_addnumber = value;
+ newval = newval & 0xfe000000;
+ }
+ else
+ newval = value | (newval & 0xfe000000) | (hbit << 24);
md_number_to_chars (buf, newval, INSN_SIZE);
}
break;
@@ -11306,7 +11333,17 @@ md_apply_fix3 (fixP, valP, seg)
if ((value & ~0xff) && ((value & ~0xff) != ~0xff))
as_bad_where (fixP->fx_file, fixP->fx_line,
_("branch out of range"));
- newval = (newval & 0xff00) | ((value & 0x1ff) >> 1);
+ if (seg->use_rela_p && !fixP->fx_done)
+ {
+#ifdef OBJ_ELF
+ if (! target_oabi)
+ fixP->fx_offset = value;
+#endif
+ fixP->fx_addnumber = value;
+ newval = newval & 0xff00;
+ }
+ else
+ newval = (newval & 0xff00) | ((value & 0x1ff) >> 1);
}
md_number_to_chars (buf, newval, THUMB_SIZE);
break;
@@ -11322,7 +11359,17 @@ md_apply_fix3 (fixP, valP, seg)
if ((value & ~0x7ff) && ((value & ~0x7ff) != ~0x7ff))
as_bad_where (fixP->fx_file, fixP->fx_line,
_("branch out of range"));
- newval = (newval & 0xf800) | ((value & 0xfff) >> 1);
+ if (seg->use_rela_p && !fixP->fx_done)
+ {
+#ifdef OBJ_ELF
+ if (! target_oabi)
+ fixP->fx_offset = value;
+#endif
+ fixP->fx_addnumber = value;
+ newval = newval & 0xf800;
+ }
+ else
+ newval = (newval & 0xf800) | ((value & 0xfff) >> 1);
}
md_number_to_chars (buf, newval, THUMB_SIZE);
break;
@@ -11347,20 +11394,36 @@ md_apply_fix3 (fixP, valP, seg)
as_bad_where (fixP->fx_file, fixP->fx_line,
_("branch with link out of range"));
- newval = (newval & 0xf800) | ((value & 0x7fffff) >> 12);
- newval2 = (newval2 & 0xf800) | ((value & 0xfff) >> 1);
if (fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX)
/* For a BLX instruction, make sure that the relocation is rounded up
to a word boundary. This follows the semantics of the instruction
which specifies that bit 1 of the target address will come from bit
1 of the base address. */
- newval2 = (newval2 + 1) & ~ 1;
+ value = (value + 1) & ~ 1;
+
+ if (seg->use_rela_p && !fixP->fx_done)
+ {
+#ifdef OBJ_ELF
+ if (! target_oabi)
+ fixP->fx_offset = value;
+#endif
+ fixP->fx_addnumber = value;
+ newval = newval & 0xf800;
+ newval2 = newval2 & 0xf800;
+ }
+ else
+ {
+ newval = (newval & 0xf800) | ((value & 0x7fffff) >> 12);
+ newval2 = (newval2 & 0xf800) | ((value & 0xfff) >> 1);
+ }
md_number_to_chars (buf, newval, THUMB_SIZE);
md_number_to_chars (buf + THUMB_SIZE, newval2, THUMB_SIZE);
}
break;
case BFD_RELOC_8:
+ if (seg->use_rela_p && !fixP->fx_done)
+ break;
if (fixP->fx_done || fixP->fx_pcrel)
md_number_to_chars (buf, value, 1);
#ifdef OBJ_ELF
@@ -11373,6 +11436,8 @@ md_apply_fix3 (fixP, valP, seg)
break;
case BFD_RELOC_16:
+ if (seg->use_rela_p && !fixP->fx_done)
+ break;
if (fixP->fx_done || fixP->fx_pcrel)
md_number_to_chars (buf, value, 2);
#ifdef OBJ_ELF
@@ -11387,12 +11452,16 @@ md_apply_fix3 (fixP, valP, seg)
#ifdef OBJ_ELF
case BFD_RELOC_ARM_GOT32:
case BFD_RELOC_ARM_GOTOFF:
+ if (seg->use_rela_p && !fixP->fx_done)
+ break;
md_number_to_chars (buf, 0, 4);
break;
#endif
case BFD_RELOC_RVA:
case BFD_RELOC_32:
+ if (seg->use_rela_p && !fixP->fx_done)
+ break;
if (fixP->fx_done || fixP->fx_pcrel)
md_number_to_chars (buf, value, 4);
#ifdef OBJ_ELF