summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormarius <marius@FreeBSD.org>2011-03-06 15:20:11 +0000
committermarius <marius@FreeBSD.org>2011-03-06 15:20:11 +0000
commit2830ede5b875db3f539d9e9aa68e8dd1a0538626 (patch)
tree5ae03a572be72e3fd0d851acb0f567c8119d6b93
parent3e53ebd5768237e6c9c0763894f1dc7a4ee78ef5 (diff)
downloadFreeBSD-src-2830ede5b875db3f539d9e9aa68e8dd1a0538626.zip
FreeBSD-src-2830ede5b875db3f539d9e9aa68e8dd1a0538626.tar.gz
- With the addition of TLS support binutils started to make the addend
values for resolved symbols relative to relocbase instead of sections so detect this case and handle as appropriate, which allows using kernel modules linked with affected versions of binutils. Actually I think this is a bug in binutils but given that apparently nobody complained for nearly six years and powerpc has basically the same workaround I decided to put it in for the sparc64 kernel, too. - Fix R_SPARC_HIX22 relocations. Apparently these are hardly ever used.
-rw-r--r--libexec/rtld-elf/sparc64/reloc.c3
-rw-r--r--sys/sparc64/sparc64/elf_machdep.c12
2 files changed, 14 insertions, 1 deletions
diff --git a/libexec/rtld-elf/sparc64/reloc.c b/libexec/rtld-elf/sparc64/reloc.c
index 6249fb0..b58e3e5 100644
--- a/libexec/rtld-elf/sparc64/reloc.c
+++ b/libexec/rtld-elf/sparc64/reloc.c
@@ -355,6 +355,9 @@ reloc_nonplt_object(Obj_Entry *obj, const Elf_Rela *rela, SymCache *cache,
if (type == R_SPARC_OLO10)
value = (value & 0x3ff) + ELF64_R_TYPE_DATA(rela->r_info);
+ if (type == R_SPARC_HIX22)
+ value ^= 0xffffffffffffffff;
+
if (RELOC_PC_RELATIVE(type))
value -= (Elf_Addr)where;
diff --git a/sys/sparc64/sparc64/elf_machdep.c b/sys/sparc64/sparc64/elf_machdep.c
index a1c14ee..2e58c8c 100644
--- a/sys/sparc64/sparc64/elf_machdep.c
+++ b/sys/sparc64/sparc64/elf_machdep.c
@@ -332,7 +332,14 @@ elf_reloc(linker_file_t lf, Elf_Addr relocbase, const void *data, int type,
addr = lookup(lf, symidx, 1);
if (addr == 0)
return (-1);
- value += addr;
+ /*
+ * With the addition of TLS support binutils started to make
+ * addend values relative to relocbase instead of sections.
+ */
+ if (addr > relocbase && addr <= relocbase + value)
+ value += relocbase;
+ else
+ value += addr;
if (RELOC_BARE_SYMBOL(rtype))
value = elf_relocaddr(lf, value);
}
@@ -340,6 +347,9 @@ elf_reloc(linker_file_t lf, Elf_Addr relocbase, const void *data, int type,
if (rtype == R_SPARC_OLO10)
value = (value & 0x3ff) + ELF64_R_TYPE_DATA(rela->r_info);
+ if (rtype == R_SPARC_HIX22)
+ value ^= 0xffffffffffffffff;
+
if (RELOC_PC_RELATIVE(rtype))
value -= (Elf_Addr)where;
OpenPOWER on IntegriCloud