summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorgonzo <gonzo@FreeBSD.org>2012-02-11 00:54:57 +0000
committergonzo <gonzo@FreeBSD.org>2012-02-11 00:54:57 +0000
commitf8da975fafd830421ec1cfd6b3fb95d6847ba59d (patch)
treebbe05817d22baee008daca896bc3254b1dcdcf47
parentebc4133dca40744e7e5a2037e613bf403a16cc65 (diff)
downloadFreeBSD-src-f8da975fafd830421ec1cfd6b3fb95d6847ba59d.zip
FreeBSD-src-f8da975fafd830421ec1cfd6b3fb95d6847ba59d.tar.gz
Add handlers for TLS-related relocation entries
-rw-r--r--libexec/rtld-elf/mips/reloc.c87
-rw-r--r--libexec/rtld-elf/mips/rtld_machdep.h3
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
OpenPOWER on IntegriCloud