sh-linux patch for 32-bit relative relocation
kaz Kojima
kkojima@rr.iij4u.or.jp
Mon Sep 10 21:06:00 GMT 2001
Hello,
Here is a patch for sh-linux to handle the substraction of two
symbols in different sections correctly. This is essentially same
with the old patch
http://sources.redhat.com/ml/binutils/2001-01/msg00071.html
which had a possible ABI problem in non linux targets, but is now
organized as a linux specific patch which doesn't affect non linux
targets. Formally the change for gas/tc-sh.c affects all sh targets,
but the effect of this change is ignored by non linux targets since
src_mask of HOWTO (R_SH_REL32,... is set to 0 in such targets.
I think that almost all sh-linux developpers are using this patch
successfully and enough test is done. Without this, we can't get
working shared libraries for stdc++, X and many other packages.
Regards,
kaz
--
2001-09-11 Kaz Kojima <kkojima@rr.iij4u.or.jp>
* bfd/elf32-sh-lin.c (LINUX_ABI): Defined.
* bfd/elf32-sh.c (sh_elf_howto_table): Don't mask source
R_SH_REL32 relocation in linux case.
(sh_elf_relocate_section): Use in-place value in computing
addend for R_SH_REL32 relocation in linux case.
Index: bfd/elf32-sh-lin.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-sh-lin.c,v
retrieving revision 1.1
diff -u -r1.1 elf32-sh-lin.c
--- elf32-sh-lin.c 2000/09/07 04:23:43 1.1
+++ elf32-sh-lin.c 2001/08/22 01:26:50
@@ -25,5 +25,6 @@
#define ELF_MACHINE_CODE EM_SH
#define ELF_MAXPAGESIZE 0x10000
#define elf_symbol_leading_char 0
+#define LINUX_ABI 1
#include "elf32-sh.c"
Index: bfd/elf32-sh.c
===================================================================
RCS file: /cvs/src/src/bfd/elf32-sh.c,v
retrieving revision 1.29
diff -u -r1.29 elf32-sh.c
--- elf32-sh.c 2001/05/23 16:38:36 1.29
+++ elf32-sh.c 2001/08/22 01:27:09
@@ -112,6 +112,7 @@
false), /* pcrel_offset */
/* 32 bit PC relative relocation. */
+#if defined(LINUX_ABI)
HOWTO (R_SH_REL32, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
@@ -121,10 +122,25 @@
complain_overflow_signed, /* complain_on_overflow */
sh_elf_ignore_reloc, /* special_function */
"R_SH_REL32", /* name */
+ true, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ true), /* pcrel_offset */
+#else
+ HOWTO (R_SH_REL32, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ true, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ sh_elf_ignore_reloc, /* special_function */
+ "R_SH_REL32", /* name */
false, /* partial_inplace */
0, /* src_mask */
0xffffffff, /* dst_mask */
true), /* pcrel_offset */
+#endif
/* 8 bit PC relative branch divided by 2. */
HOWTO (R_SH_DIR8WPN, /* type */
@@ -3048,7 +3064,11 @@
section symbol winds up in the output section. */
sym = local_syms + r_symndx;
if (ELF_ST_TYPE (sym->st_info) == STT_SECTION)
- goto final_link_relocate;
+ {
+ r = _bfd_relocate_contents (howto, input_bfd, relocation,
+ contents + rel->r_offset);
+ goto relocation_done;
+ }
continue;
}
@@ -3251,9 +3271,15 @@
else if (r_type == R_SH_REL32)
{
BFD_ASSERT (h != NULL && h->dynindx != -1);
+#if defined(LINUX_ABI)
+ addend = bfd_get_32 (input_bfd,
+ (bfd_byte *) contents + rel->r_offset);
+#else
+ addend = rel->r_addend;
+#endif
relocate = false;
outrel.r_info = ELF32_R_INFO (h->dynindx, R_SH_REL32);
- outrel.r_addend = rel->r_addend;
+ outrel.r_addend = addend;
}
else
{
@@ -3266,14 +3292,25 @@
{
relocate = true;
outrel.r_info = ELF32_R_INFO (0, R_SH_RELATIVE);
+#if defined(LINUX_ABI)
+ outrel.r_addend = 0;
+#else
outrel.r_addend = relocation + rel->r_addend;
+#endif
}
else
{
BFD_ASSERT (h->dynindx != -1);
+#if defined(LINUX_ABI)
+ addend = bfd_get_32 (input_bfd,
+ ((bfd_byte *) contents
+ + rel->r_offset));
+#else
+ addend = rel->r_addend;
+#endif
relocate = false;
outrel.r_info = ELF32_R_INFO (h->dynindx, R_SH_DIR32);
- outrel.r_addend = relocation + rel->r_addend;
+ outrel.r_addend = relocation + addend;
}
}
@@ -3371,7 +3408,11 @@
+ sgot->output_offset
+ off);
outrel.r_info = ELF32_R_INFO (0, R_SH_RELATIVE);
+#if defined(LINUX_ABI)
+ outrel.r_addend = 0;
+#else
outrel.r_addend = relocation;
+#endif
bfd_elf32_swap_reloca_out (output_bfd, &outrel,
(((Elf32_External_Rela *)
srelgot->contents)
@@ -3471,6 +3512,7 @@
}
}
+ relocation_done:
if (r != bfd_reloc_ok)
{
switch (r)
@@ -4237,9 +4279,13 @@
&& (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR))
{
rel.r_info = ELF32_R_INFO (0, R_SH_RELATIVE);
+#if defined(LINUX_ABI)
+ rel.r_addend = 0;
+#else
rel.r_addend = (h->root.u.def.value
+ h->root.u.def.section->output_section->vma
+ h->root.u.def.section->output_offset);
+#endif
}
else
{
Index: tc-sh.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-sh.c,v
retrieving revision 1.40
diff -u -r1.40 tc-sh.c
--- tc-sh.c 2001/07/03 15:22:19 1.40
+++ tc-sh.c 2001/09/11 00:39:37
@@ -2834,6 +2834,11 @@
&& fixP->fx_addsy != NULL
&& S_IS_WEAK (fixP->fx_addsy))
val -= S_GET_VALUE (fixP->fx_addsy);
+
+ if (OUTPUT_FLAVOR == bfd_target_elf_flavour
+ && fixP->fx_r_type == BFD_RELOC_32_PCREL
+ && fixP->fx_addsy != NULL)
+ val += fixP->fx_where + fixP->fx_frag->fr_address;
#endif
#ifndef BFD_ASSEMBLER
More information about the Binutils
mailing list