From 9a1c9b72d02b2bd0fdd0f9b0adf1d9fbd91f8b26 Mon Sep 17 00:00:00 2001 From: gonzo Date: Sat, 11 Feb 2012 00:54:57 +0000 Subject: [PATCH 123/175] Add handlers for TLS-related relocation entries git-svn-id: http://svn.freebsd.org/base/head@231491 ccf9f872-aa2e-dd11-9fc8-001c23d0bc1f (cherry picked from commit a35646998e192365831c1b69c79b8a2ad5756af7) Signed-off-by: Xin Li --- libexec/rtld-elf/mips/reloc.c | 87 +++++++++++++++++++++++++++++++++- libexec/rtld-elf/mips/rtld_machdep.h | 3 +- 2 files changed, 87 insertions(+), 3 deletions(-) diff --git a/libexec/rtld-elf/mips/reloc.c b/libexec/rtld-elf/mips/reloc.c index 732562d..7b520c9 100644 --- a/libexec/rtld-elf/mips/reloc.c +++ b/libexec/rtld-elf/mips/reloc.c @@ -446,6 +446,89 @@ reloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld, RtldLockState *lockstate) break; } +#ifdef __mips_n64 + case R_TYPE(TLS_DTPMOD64): +#else + case R_TYPE(TLS_DTPMOD32): +#endif + { + + const size_t rlen = sizeof(Elf_Addr); + Elf_Addr old = load_ptr(where, rlen); + Elf_Addr val = old; + + def = find_symdef(r_symndx, obj, &defobj, false, NULL, + lockstate); + if (def == NULL) + return -1; + + val += (Elf_Addr)defobj->tlsindex; + + store_ptr(where, val, rlen); + dbg("DTPMOD %s in %s %p --> %p in %s", + obj->strtab + obj->symtab[r_symndx].st_name, + obj->path, (void *)old, (void*)val, defobj->path); + break; + } + +#ifdef __mips_n64 + case R_TYPE(TLS_DTPREL64): +#else + case R_TYPE(TLS_DTPREL32): +#endif + { + const size_t rlen = sizeof(Elf_Addr); + Elf_Addr old = load_ptr(where, rlen); + Elf_Addr val = old; + + def = find_symdef(r_symndx, obj, &defobj, false, NULL, + lockstate); + if (def == NULL) + return -1; + + if (!defobj->tls_done && allocate_tls_offset(obj)) + return -1; + + val += (Elf_Addr)def->st_value - TLS_DTP_OFFSET; + store_ptr(where, val, rlen); + + dbg("DTPREL %s in %s %p --> %p in %s", + obj->strtab + obj->symtab[r_symndx].st_name, + obj->path, (void*)old, (void *)val, defobj->path); + break; + } + +#ifdef __mips_n64 + case R_TYPE(TLS_TPREL64): +#else + case R_TYPE(TLS_TPREL32): +#endif + { + const size_t rlen = sizeof(Elf_Addr); + Elf_Addr old = load_ptr(where, rlen); + Elf_Addr val = old; + + def = find_symdef(r_symndx, obj, &defobj, false, NULL, + lockstate); + + if (def == NULL) + return -1; + + if (!defobj->tls_done && allocate_tls_offset(obj)) + return -1; + + val += (Elf_Addr)(def->st_value + defobj->tlsoffset + - TLS_TP_OFFSET - TLS_TCB_SIZE); + store_ptr(where, val, rlen); + + dbg("TPREL %s in %s %p --> %p in %s", + obj->strtab + obj->symtab[r_symndx].st_name, + obj->path, (void*)old, (void *)val, defobj->path); + break; + } + + + default: dbg("sym = %lu, type = %lu, offset = %p, " "contents = %p, symbol = %s", @@ -554,7 +637,7 @@ __tls_get_addr(tls_index* ti) sysarch(MIPS_GET_TLS, &tls); p = tls_get_addr_common((Elf_Addr**)((Elf_Addr)tls - TLS_TP_OFFSET - - TLS_TCB_SIZE), ti->ti_module, ti->ti_offset); + - TLS_TCB_SIZE), ti->ti_module, ti->ti_offset + TLS_DTP_OFFSET); - return (p + TLS_DTV_OFFSET); + return (p); } diff --git a/libexec/rtld-elf/mips/rtld_machdep.h b/libexec/rtld-elf/mips/rtld_machdep.h index 14fdf44..b7cdc00 100644 --- a/libexec/rtld-elf/mips/rtld_machdep.h +++ b/libexec/rtld-elf/mips/rtld_machdep.h @@ -53,7 +53,8 @@ Elf_Addr reloc_jmpslot(Elf_Addr *where, Elf_Addr target, */ #define TLS_TP_OFFSET 0x7000 -#define TLS_DTV_OFFSET 0x8000 +#define TLS_DTP_OFFSET 0x8000 + #ifdef __mips_n64 #define TLS_TCB_SIZE 16 #else -- 1.7.9.4