From 25b31a949680f1f6ad0965a8f514815e7c9ff7fb Mon Sep 17 00:00:00 2001 From: Marius Strobl Date: Sun, 6 Mar 2011 15:20:11 +0000 Subject: [PATCH] - 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. --- libexec/rtld-elf/sparc64/reloc.c | 3 +++ sys/sparc64/sparc64/elf_machdep.c | 12 +++++++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/libexec/rtld-elf/sparc64/reloc.c b/libexec/rtld-elf/sparc64/reloc.c index 6249fb0ce649..b58e3e5fb8ff 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 a1c14ee2623c..2e58c8c3ed83 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;