summaryrefslogtreecommitdiffstats
path: root/libexec/rtld-elf/mips/reloc.c
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 /libexec/rtld-elf/mips/reloc.c
parentebc4133dca40744e7e5a2037e613bf403a16cc65 (diff)
downloadFreeBSD-src-f8da975fafd830421ec1cfd6b3fb95d6847ba59d.zip
FreeBSD-src-f8da975fafd830421ec1cfd6b3fb95d6847ba59d.tar.gz
Add handlers for TLS-related relocation entries
Diffstat (limited to 'libexec/rtld-elf/mips/reloc.c')
-rw-r--r--libexec/rtld-elf/mips/reloc.c87
1 files changed, 85 insertions, 2 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);
}
OpenPOWER on IntegriCloud