summaryrefslogtreecommitdiff
path: root/libexec/ld.so
diff options
context:
space:
mode:
authorPhilip Guenther <guenther@cvs.openbsd.org>2016-05-07 19:05:25 +0000
committerPhilip Guenther <guenther@cvs.openbsd.org>2016-05-07 19:05:25 +0000
commitbe4e94637d7117375492627b79c41629c7da9bc3 (patch)
tree61a9fabcc07d38d2720bbb937e83103928286550 /libexec/ld.so
parent33d8693716b4a6d503e0ba97f94a783905b87f28 (diff)
Use a Thread Information Block in both single and multi-threaded programs.
This stores errno, the cancelation flags, and related bits for each thread and is allocated by ld.so or libc.a. This is an ABI break from 5.9-stable! Make libpthread dlopen'able by moving the cancelation wrappers into libc and doing locking and fork/errno handling via callbacks that libpthread registers when it first initializes. 'errno' *must* be declared via <errno.h> now! Clean up libpthread's symbol exports like libc. On powerpc, offset the TIB/TCB/TLS data from the register per the ELF spec. Testing by various, particularly sthen@ and patrick@ ok kettenis@
Diffstat (limited to 'libexec/ld.so')
-rw-r--r--libexec/ld.so/Makefile4
-rw-r--r--libexec/ld.so/Symbols.map4
-rw-r--r--libexec/ld.so/alpha/ldasm.S4
-rw-r--r--libexec/ld.so/alpha/syscall.h4
-rw-r--r--libexec/ld.so/amd64/ldasm.S3
-rw-r--r--libexec/ld.so/amd64/syscall.h4
-rw-r--r--libexec/ld.so/arm/ldasm.S4
-rw-r--r--libexec/ld.so/arm/syscall.h4
-rw-r--r--libexec/ld.so/hppa/ldasm.S14
-rw-r--r--libexec/ld.so/hppa/syscall.h4
-rw-r--r--libexec/ld.so/i386/ldasm.S4
-rw-r--r--libexec/ld.so/i386/syscall.h4
-rw-r--r--libexec/ld.so/library.c16
-rw-r--r--libexec/ld.so/library_mquery.c17
-rw-r--r--libexec/ld.so/loader.c22
-rw-r--r--libexec/ld.so/m88k/ldasm.S5
-rw-r--r--libexec/ld.so/m88k/syscall.h3
-rw-r--r--libexec/ld.so/mips64/ldasm.S5
-rw-r--r--libexec/ld.so/mips64/syscall.h4
-rw-r--r--libexec/ld.so/powerpc/ldasm.S3
-rw-r--r--libexec/ld.so/powerpc/syscall.h3
-rw-r--r--libexec/ld.so/resolve.h16
-rw-r--r--libexec/ld.so/sh/ldasm.S4
-rw-r--r--libexec/ld.so/sh/syscall.h4
-rw-r--r--libexec/ld.so/sparc/ldasm.S14
-rw-r--r--libexec/ld.so/sparc/syscall.h3
-rw-r--r--libexec/ld.so/sparc64/ldasm.S9
-rw-r--r--libexec/ld.so/sparc64/syscall.h3
-rw-r--r--libexec/ld.so/tib.c186
29 files changed, 343 insertions, 31 deletions
diff --git a/libexec/ld.so/Makefile b/libexec/ld.so/Makefile
index 50be47137fd..5c6da586143 100644
--- a/libexec/ld.so/Makefile
+++ b/libexec/ld.so/Makefile
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile,v 1.60 2015/08/31 02:53:57 guenther Exp $
+# $OpenBSD: Makefile,v 1.61 2016/05/07 19:05:23 guenther Exp $
SUBDIR=ldconfig ldd
MAN= ld.so.1
@@ -19,7 +19,7 @@ VPATH=${.CURDIR}/../../lib/libc/string
SRCS= ldasm.S boot.c loader.c resolve.c dlfcn.c dl_printf.c rtld_machine.c
SRCS+= path.c util.c sod.c strsep.c strtol.c dir.c library_subr.c dl_prebind.c
SRCS+= dl_realpath.c dl_uname.c dl_dirname.c strlcat.c strlen.c trace.c
-SRCS+= malloc.c reallocarray.c
+SRCS+= malloc.c reallocarray.c tib.c
.if (${MACHINE_ARCH} == "i386")
SRCS+= library_mquery.c
diff --git a/libexec/ld.so/Symbols.map b/libexec/ld.so/Symbols.map
index e167f603dfe..795caac6108 100644
--- a/libexec/ld.so/Symbols.map
+++ b/libexec/ld.so/Symbols.map
@@ -14,6 +14,10 @@
/* alias in reserved namespace for libpthread to use */
_dlctl;
+ /* TLS related bits */
+ _dl_allocate_tib;
+ _dl_free_tib;
+
/* looked up by gdb */
_dl_bind;
_dl_debug_state;
diff --git a/libexec/ld.so/alpha/ldasm.S b/libexec/ld.so/alpha/ldasm.S
index f71de97c74d..952b0c7e174 100644
--- a/libexec/ld.so/alpha/ldasm.S
+++ b/libexec/ld.so/alpha/ldasm.S
@@ -1,4 +1,4 @@
-/* $OpenBSD: ldasm.S,v 1.34 2016/03/21 22:41:28 bluhm Exp $ */
+/* $OpenBSD: ldasm.S,v 1.35 2016/05/07 19:05:23 guenther Exp $ */
/*
* Copyright (c) 2001 Niklas Hallqvist
@@ -317,6 +317,7 @@ DL_SYSCALL(sendsyslog)
DL_SYSCALL(pledge)
DL_SYSCALL(gettimeofday)
DL_SYSCALL_NOERR(issetugid)
+DL_SYSCALL_NOERR(getthrid)
DL_SYSCALL(lstat)
DL_SYSCALL(mprotect)
DL_SYSCALL(munmap)
@@ -324,6 +325,7 @@ DL_SYSCALL(open)
DL_SYSCALL(read)
DL_SYSCALL(readlink)
DL_SYSCALL2(_syscall,__syscall)
+DL_SYSCALL2_NOERR(set_tcb,__set_tcb)
DL_SYSCALL(sysctl)
DL_SYSCALL(utrace)
DL_SYSCALL(write)
diff --git a/libexec/ld.so/alpha/syscall.h b/libexec/ld.so/alpha/syscall.h
index df364c4715e..8005b3e3307 100644
--- a/libexec/ld.so/alpha/syscall.h
+++ b/libexec/ld.so/alpha/syscall.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: syscall.h,v 1.32 2016/03/21 22:41:28 bluhm Exp $ */
+/* $OpenBSD: syscall.h,v 1.33 2016/05/07 19:05:23 guenther Exp $ */
/*
* Copyright (c) 2001 Niklas Hallqvist
@@ -41,6 +41,7 @@ int _dl_close(int);
__dead
int _dl_exit(int);
int _dl_issetugid(void);
+int _dl_getthrid(void);
void * _dl_mmap(void *, size_t, int, int, int, off_t);
int _dl_mprotect(const void *, size_t, int);
int _dl_munmap(const void *, size_t);
@@ -58,6 +59,7 @@ int _dl_getcwd(char *, size_t);
int _dl_utrace(const char *, const void *, size_t);
int _dl_getentropy(char *, size_t);
int _dl_sendsyslog(const char *, size_t, int);
+void _dl_set_tcb(void *);
static inline off_t
_dl_lseek(int fildes, off_t offset, int whence)
diff --git a/libexec/ld.so/amd64/ldasm.S b/libexec/ld.so/amd64/ldasm.S
index 2dc0fe096ed..922c1b8aea2 100644
--- a/libexec/ld.so/amd64/ldasm.S
+++ b/libexec/ld.so/amd64/ldasm.S
@@ -1,4 +1,4 @@
-/* $OpenBSD: ldasm.S,v 1.23 2016/03/21 22:41:29 bluhm Exp $ */
+/* $OpenBSD: ldasm.S,v 1.24 2016/05/07 19:05:23 guenther Exp $ */
/*
* Copyright (c) 2002,2004 Dale Rahn
@@ -87,6 +87,7 @@ DL_SYSCALL(read)
DL_SYSCALL(write)
DL_SYSCALL(close)
DL_SYSCALL(issetugid)
+DL_SYSCALL(getthrid)
DL_SYSCALL(getdents)
DL_SYSCALL(mprotect)
DL_SYSCALL(munmap)
diff --git a/libexec/ld.so/amd64/syscall.h b/libexec/ld.so/amd64/syscall.h
index 26ebf6c4092..270e9bb2468 100644
--- a/libexec/ld.so/amd64/syscall.h
+++ b/libexec/ld.so/amd64/syscall.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: syscall.h,v 1.20 2016/03/21 22:41:29 bluhm Exp $ */
+/* $OpenBSD: syscall.h,v 1.21 2016/05/07 19:05:23 guenther Exp $ */
/*
* Copyright (c) 2001 Niklas Hallqvist
@@ -42,6 +42,7 @@ int _dl_close(int);
__dead
int _dl_exit(int);
int _dl_issetugid(void);
+int _dl_getthrid(void);
long _dl__syscall(quad_t, ...);
int _dl_mprotect(const void *, size_t, int);
int _dl_munmap(const void *, size_t);
@@ -58,6 +59,7 @@ int _dl_getcwd(char *, size_t);
int _dl_utrace(const char *, const void *, size_t);
int _dl_getentropy(char *, size_t);
int _dl_sendsyslog(const char *, size_t, int);
+void _dl_set_tcb(void *);
static inline off_t
_dl_lseek(int fildes, off_t offset, int whence)
diff --git a/libexec/ld.so/arm/ldasm.S b/libexec/ld.so/arm/ldasm.S
index 36f1ab62bc2..80365b9b9c8 100644
--- a/libexec/ld.so/arm/ldasm.S
+++ b/libexec/ld.so/arm/ldasm.S
@@ -1,4 +1,4 @@
-/* $OpenBSD: ldasm.S,v 1.21 2016/03/21 22:41:29 bluhm Exp $ */
+/* $OpenBSD: ldasm.S,v 1.22 2016/05/07 19:05:23 guenther Exp $ */
/*
* Copyright (c) 2004 Dale Rahn
@@ -113,6 +113,7 @@ _dl_exit:
b 1b
DL_SYSCALL(issetugid)
+DL_SYSCALL(getthrid)
DL_SYSCALL2(_syscall,__syscall)
DL_SYSCALL(munmap)
DL_SYSCALL(mprotect)
@@ -129,6 +130,7 @@ DL_SYSCALL(sendsyslog)
DL_SYSCALL(pledge)
DL_SYSCALL2(getcwd,__getcwd)
DL_SYSCALL(sysctl)
+DL_SYSCALL2(set_tcb,__set_tcb)
DL_SYSCALL(getdents)
diff --git a/libexec/ld.so/arm/syscall.h b/libexec/ld.so/arm/syscall.h
index d9ecc3b2c3a..d74a9e26c3d 100644
--- a/libexec/ld.so/arm/syscall.h
+++ b/libexec/ld.so/arm/syscall.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: syscall.h,v 1.20 2016/03/21 22:41:29 bluhm Exp $ */
+/* $OpenBSD: syscall.h,v 1.21 2016/05/07 19:05:23 guenther Exp $ */
/*
* Copyright (c) 2001 Niklas Hallqvist
@@ -42,6 +42,7 @@ int _dl_close(int);
__dead
int _dl_exit(int);
int _dl_issetugid(void);
+int _dl_getthrid(void);
long _dl__syscall(quad_t, ...);
int _dl_mprotect(const void *, size_t, int);
int _dl_munmap(const void *, size_t);
@@ -58,6 +59,7 @@ int _dl_getcwd(char *, size_t);
int _dl_utrace(const char *, const void *, size_t);
int _dl_getentropy(char *, size_t);
int _dl_sendsyslog(const char *, size_t, int);
+void _dl_set_tcb(void *);
static inline off_t
_dl_lseek(int fildes, off_t offset, int whence)
diff --git a/libexec/ld.so/hppa/ldasm.S b/libexec/ld.so/hppa/ldasm.S
index 59e5902e676..1663eb65f04 100644
--- a/libexec/ld.so/hppa/ldasm.S
+++ b/libexec/ld.so/hppa/ldasm.S
@@ -1,4 +1,4 @@
-/* $OpenBSD: ldasm.S,v 1.20 2016/03/21 22:41:29 bluhm Exp $ */
+/* $OpenBSD: ldasm.S,v 1.21 2016/05/07 19:05:23 guenther Exp $ */
/*
* Copyright (c) 2004 Michael Shalayeff
@@ -182,6 +182,12 @@ ENTRY(_dl_issetugid,0)
nop
EXIT(_dl_issetugid)
+ENTRY(_dl_getthrid,0)
+ SYSCALL(getthrid)
+ bv r0(rp)
+ nop
+EXIT(_dl_getthrid)
+
ENTRY(_dl__syscall,0)
SYSCALL(__syscall)
bv r0(rp)
@@ -278,6 +284,12 @@ ENTRY(_dl_sendsyslog,0)
nop
EXIT(_dl_sendsyslog)
+ENTRY(_dl_set_tcb,0)
+ SYSCALL(__set_tcb)
+ bv r0(rp)
+ nop
+EXIT(_dl_set_tcb)
+
ENTRY(_dl_pledge,0)
SYSCALL(pledge)
bv r0(rp)
diff --git a/libexec/ld.so/hppa/syscall.h b/libexec/ld.so/hppa/syscall.h
index 26ebf6c4092..270e9bb2468 100644
--- a/libexec/ld.so/hppa/syscall.h
+++ b/libexec/ld.so/hppa/syscall.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: syscall.h,v 1.20 2016/03/21 22:41:29 bluhm Exp $ */
+/* $OpenBSD: syscall.h,v 1.21 2016/05/07 19:05:23 guenther Exp $ */
/*
* Copyright (c) 2001 Niklas Hallqvist
@@ -42,6 +42,7 @@ int _dl_close(int);
__dead
int _dl_exit(int);
int _dl_issetugid(void);
+int _dl_getthrid(void);
long _dl__syscall(quad_t, ...);
int _dl_mprotect(const void *, size_t, int);
int _dl_munmap(const void *, size_t);
@@ -58,6 +59,7 @@ int _dl_getcwd(char *, size_t);
int _dl_utrace(const char *, const void *, size_t);
int _dl_getentropy(char *, size_t);
int _dl_sendsyslog(const char *, size_t, int);
+void _dl_set_tcb(void *);
static inline off_t
_dl_lseek(int fildes, off_t offset, int whence)
diff --git a/libexec/ld.so/i386/ldasm.S b/libexec/ld.so/i386/ldasm.S
index 86c5f0d7376..621a1c503be 100644
--- a/libexec/ld.so/i386/ldasm.S
+++ b/libexec/ld.so/i386/ldasm.S
@@ -1,4 +1,4 @@
-/* $OpenBSD: ldasm.S,v 1.25 2016/03/21 22:41:29 bluhm Exp $ */
+/* $OpenBSD: ldasm.S,v 1.26 2016/05/07 19:05:23 guenther Exp $ */
/*
* Copyright (c) 2002 Dale Rahn
@@ -109,6 +109,7 @@ _dl_exit:
DL_SYSCALL(issetugid)
+DL_SYSCALL(getthrid)
DL_SYSCALL2(_syscall,__syscall)
DL_SYSCALL(munmap)
DL_SYSCALL(mprotect)
@@ -126,6 +127,7 @@ DL_SYSCALL(pledge)
DL_SYSCALL2(getcwd,__getcwd)
DL_SYSCALL(sysctl)
DL_SYSCALL(getdents)
+DL_SYSCALL2(set_tcb,__set_tcb)
.L_cerr:
/* error: result = -errno; - handled here. */
diff --git a/libexec/ld.so/i386/syscall.h b/libexec/ld.so/i386/syscall.h
index 811c8acbdae..9b8a4bc352a 100644
--- a/libexec/ld.so/i386/syscall.h
+++ b/libexec/ld.so/i386/syscall.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: syscall.h,v 1.24 2016/03/21 22:41:29 bluhm Exp $ */
+/* $OpenBSD: syscall.h,v 1.25 2016/05/07 19:05:23 guenther Exp $ */
/*
* Copyright (c) 2001 Niklas Hallqvist
@@ -42,6 +42,7 @@ int _dl_close(int);
__dead
int _dl_exit(int);
int _dl_issetugid(void);
+int _dl_getthrid(void);
long _dl__syscall(quad_t, ...);
int _dl_mprotect(const void *, size_t, int);
int _dl_munmap(const void *, size_t);
@@ -58,6 +59,7 @@ int _dl_getcwd(char *, size_t);
int _dl_utrace(const char *, const void *, size_t);
int _dl_getentropy(char *, size_t);
int _dl_sendsyslog(const char *, size_t, int);
+void _dl_set_tcb(void *);
static inline off_t
_dl_lseek(int fildes, off_t offset, int whence)
diff --git a/libexec/ld.so/library.c b/libexec/ld.so/library.c
index 9a945b37b37..5318af38592 100644
--- a/libexec/ld.so/library.c
+++ b/libexec/ld.so/library.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: library.c,v 1.74 2016/03/20 02:29:51 guenther Exp $ */
+/* $OpenBSD: library.c,v 1.75 2016/05/07 19:05:23 guenther Exp $ */
/*
* Copyright (c) 2002 Dale Rahn
@@ -104,6 +104,7 @@ _dl_tryload_shlib(const char *libname, int type, int flags)
Elf_Dyn *dynp = NULL;
Elf_Ehdr *ehdr;
Elf_Phdr *phdp;
+ Elf_Phdr *ptls = NULL;
struct stat sb;
void *prebind_data;
@@ -164,6 +165,17 @@ _dl_tryload_shlib(const char *libname, int type, int flags)
dynp = (Elf_Dyn *)phdp->p_vaddr;
break;
case PT_TLS:
+ if (phdp->p_filesz > phdp->p_memsz) {
+ _dl_printf("%s: invalid tls data in %s.\n",
+ __progname, libname);
+ _dl_close(libfile);
+ _dl_errno = DL_CANT_LOAD_OBJ;
+ return(0);
+ }
+ if (!_dl_tib_static_done) {
+ ptls = phdp;
+ break;
+ }
_dl_printf("%s: unsupported TLS program header in %s\n",
__progname, libname);
_dl_close(libfile);
@@ -283,6 +295,8 @@ _dl_tryload_shlib(const char *libname, int type, int flags)
object->inode = sb.st_ino;
object->obj_flags |= flags;
_dl_set_sod(object->load_name, &object->sod);
+ if (ptls != NULL && ptls->p_memsz)
+ _dl_set_tls(object, ptls, libaddr, libname);
} else {
_dl_munmap((void *)libaddr, maxva - minva);
_dl_load_list_free(load_list);
diff --git a/libexec/ld.so/library_mquery.c b/libexec/ld.so/library_mquery.c
index 48151f6d4fa..870f54d7065 100644
--- a/libexec/ld.so/library_mquery.c
+++ b/libexec/ld.so/library_mquery.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: library_mquery.c,v 1.52 2016/03/20 02:29:51 guenther Exp $ */
+/* $OpenBSD: library_mquery.c,v 1.53 2016/05/07 19:05:23 guenther Exp $ */
/*
* Copyright (c) 2002 Dale Rahn
@@ -108,6 +108,7 @@ _dl_tryload_shlib(const char *libname, int type, int flags)
Elf_Phdr *phdp;
Elf_Addr load_end = 0;
Elf_Addr align = _dl_pagesz - 1, off, size;
+ Elf_Phdr *ptls = NULL;
struct stat sb;
void *prebind_data;
char hbuf[4096];
@@ -205,6 +206,17 @@ _dl_tryload_shlib(const char *libname, int type, int flags)
dynp = (Elf_Dyn *)phdp->p_vaddr;
break;
case PT_TLS:
+ if (phdp->p_filesz > phdp->p_memsz) {
+ _dl_printf("%s: invalid tls data in %s.\n",
+ __progname, libname);
+ _dl_close(libfile);
+ _dl_errno = DL_CANT_LOAD_OBJ;
+ return(0);
+ }
+ if (!_dl_tib_static_done) {
+ ptls = phdp;
+ break;
+ }
_dl_printf("%s: unsupported TLS program header in %s\n",
__progname, libname);
_dl_close(libfile);
@@ -309,6 +321,9 @@ retry:
object->inode = sb.st_ino;
object->obj_flags |= flags;
_dl_set_sod(object->load_name, &object->sod);
+ if (ptls != NULL && ptls->p_memsz)
+ _dl_set_tls(object, ptls, (Elf_Addr)lowld->start,
+ libname);
} else {
_dl_load_list_free(lowld);
}
diff --git a/libexec/ld.so/loader.c b/libexec/ld.so/loader.c
index e5e4ebebaab..609103d4c53 100644
--- a/libexec/ld.so/loader.c
+++ b/libexec/ld.so/loader.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: loader.c,v 1.158 2016/03/24 05:27:19 guenther Exp $ */
+/* $OpenBSD: loader.c,v 1.159 2016/05/07 19:05:23 guenther Exp $ */
/*
* Copyright (c) 1998 Per Fogelstrom, Opsycon AB
@@ -391,6 +391,7 @@ _dl_boot(const char **argv, char **envp, const long dyn_loff, long *dl_data)
int failed;
struct dep_node *n;
Elf_Addr minva, maxva, exe_loff;
+ Elf_Phdr *ptls = NULL;
int align;
_dl_setup_env(argv[0], envp);
@@ -480,9 +481,12 @@ _dl_boot(const char **argv, char **envp, const long dyn_loff, long *dl_data)
}
break;
case PT_TLS:
- _dl_printf("%s: unsupported TLS program header\n",
- __progname);
- _dl_exit(1);
+ if (phdp->p_filesz > phdp->p_memsz) {
+ _dl_printf("%s: invalid tls data.\n",
+ __progname);
+ _dl_exit(5);
+ }
+ ptls = phdp;
break;
}
phdp++;
@@ -492,6 +496,10 @@ _dl_boot(const char **argv, char **envp, const long dyn_loff, long *dl_data)
exe_obj->load_size = maxva - minva;
_dl_set_sod(exe_obj->load_name, &exe_obj->sod);
+ /* TLS bits in the base executable */
+ if (ptls != NULL && ptls->p_memsz)
+ _dl_set_tls(exe_obj, ptls, exe_loff, NULL);
+
n = _dl_malloc(sizeof *n);
if (n == NULL)
_dl_exit(5);
@@ -522,6 +530,9 @@ _dl_boot(const char **argv, char **envp, const long dyn_loff, long *dl_data)
dyn_obj->status |= STAT_RELOC_DONE;
_dl_set_sod(dyn_obj->load_name, &dyn_obj->sod);
+ /* calculate the offsets for static TLS allocations */
+ _dl_allocate_tls_offsets();
+
/*
* Everything should be in place now for doing the relocation
* and binding. Call _dl_rtld to do the job. Fingers crossed.
@@ -551,6 +562,9 @@ _dl_boot(const char **argv, char **envp, const long dyn_loff, long *dl_data)
_dl_loading_object = NULL;
+ /* set up the TIB for the initial thread */
+ _dl_allocate_first_tib();
+
_dl_fixup_user_env();
/*
diff --git a/libexec/ld.so/m88k/ldasm.S b/libexec/ld.so/m88k/ldasm.S
index c5ce9333855..ca2c33a854d 100644
--- a/libexec/ld.so/m88k/ldasm.S
+++ b/libexec/ld.so/m88k/ldasm.S
@@ -1,4 +1,4 @@
-/* $OpenBSD: ldasm.S,v 1.18 2016/03/21 22:41:29 bluhm Exp $ */
+/* $OpenBSD: ldasm.S,v 1.19 2016/05/07 19:05:23 guenther Exp $ */
/*
* Copyright (c) 2013 Miodrag Vallat.
@@ -173,6 +173,9 @@ ENTRY(_dl_exit)
DL_SYSCALL(issetugid)
jmp %r1
+DL_SYSCALL(getthrid)
+ jmp %r1
+
DL_SYSCALL2(_syscall,__syscall)
jmp %r1
diff --git a/libexec/ld.so/m88k/syscall.h b/libexec/ld.so/m88k/syscall.h
index f67e610c9d2..d1de184c957 100644
--- a/libexec/ld.so/m88k/syscall.h
+++ b/libexec/ld.so/m88k/syscall.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: syscall.h,v 1.16 2016/03/21 22:41:29 bluhm Exp $ */
+/* $OpenBSD: syscall.h,v 1.17 2016/05/07 19:05:23 guenther Exp $ */
/*
* Copyright (c) 2001 Niklas Hallqvist
@@ -42,6 +42,7 @@ int _dl_close(int);
__dead
int _dl_exit(int);
int _dl_issetugid(void);
+int _dl_getthrid(void);
long _dl__syscall(quad_t, ...);
int _dl_mprotect(const void *, size_t, int);
int _dl_munmap(const void *, size_t);
diff --git a/libexec/ld.so/mips64/ldasm.S b/libexec/ld.so/mips64/ldasm.S
index ec2e63e06af..a3172abfb03 100644
--- a/libexec/ld.so/mips64/ldasm.S
+++ b/libexec/ld.so/mips64/ldasm.S
@@ -1,4 +1,4 @@
-/* $OpenBSD: ldasm.S,v 1.18 2016/03/21 22:41:29 bluhm Exp $ */
+/* $OpenBSD: ldasm.S,v 1.19 2016/05/07 19:05:23 guenther Exp $ */
/*
* Copyright (c) 1998-2002 Opsycon AB, Sweden.
@@ -28,6 +28,7 @@
#include <machine/asm.h>
#include <sys/syscall.h>
+#define __cerror _dl_cerror
#include <SYS.h>
/* Stack at this stage is:
@@ -155,6 +156,7 @@ DL_SYSCALL(sendsyslog)
DL_SYSCALL(pledge)
DL_SYSCALL(gettimeofday)
DL_SYSCALL_NOERR(issetugid)
+DL_SYSCALL_NOERR(getthrid)
DL_SYSCALL(lstat)
DL_SYSCALL(mprotect)
DL_SYSCALL(munmap)
@@ -162,6 +164,7 @@ DL_SYSCALL(open)
DL_SYSCALL(read)
DL_SYSCALL(readlink)
DL_SYSCALL2(_syscall,__syscall)
+DL_SYSCALL2_NOERR(set_tcb,__set_tcb)
DL_SYSCALL(sysctl)
DL_SYSCALL(utrace)
DL_SYSCALL(write)
diff --git a/libexec/ld.so/mips64/syscall.h b/libexec/ld.so/mips64/syscall.h
index 30fe1458a98..8b85bed5124 100644
--- a/libexec/ld.so/mips64/syscall.h
+++ b/libexec/ld.so/mips64/syscall.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: syscall.h,v 1.22 2016/03/21 22:41:29 bluhm Exp $ */
+/* $OpenBSD: syscall.h,v 1.23 2016/05/07 19:05:23 guenther Exp $ */
/*
* Copyright (c) 1998-2002 Opsycon AB, Sweden.
@@ -45,12 +45,14 @@ int _dl_getcwd(char *, size_t);
ssize_t _dl_getdents(int, char *, size_t);
int _dl_gettimeofday(struct timeval *, struct timezone *);
int _dl_issetugid(void);
+int _dl_getthrid(void);
int _dl_lstat(const char *, struct stat *);
int _dl_mprotect(const void *, size_t, int);
int _dl_munmap(const void *, size_t);
int _dl_open(const char *, int);
ssize_t _dl_read(int, const char *, size_t);
ssize_t _dl_readlink(const char *, char *, size_t);
+void _dl_set_tcb(void *);
int _dl_pledge(const char *, const char **);
long _dl__syscall(quad_t, ...);
int _dl_sysctl(const int *, u_int, void *, size_t *, void *, size_t);
diff --git a/libexec/ld.so/powerpc/ldasm.S b/libexec/ld.so/powerpc/ldasm.S
index 0b2c9753d58..1ad7d009259 100644
--- a/libexec/ld.so/powerpc/ldasm.S
+++ b/libexec/ld.so/powerpc/ldasm.S
@@ -1,4 +1,4 @@
-/* $OpenBSD: ldasm.S,v 1.28 2016/03/21 22:41:29 bluhm Exp $ */
+/* $OpenBSD: ldasm.S,v 1.29 2016/05/07 19:05:23 guenther Exp $ */
/*
* Copyright (c) 1999 Dale Rahn
@@ -151,6 +151,7 @@ DL_SYSCALL(sendsyslog)
DL_SYSCALL(pledge)
DL_SYSCALL(gettimeofday)
DL_SYSCALL_NOERR(issetugid)
+DL_SYSCALL_NOERR(getthrid)
DL_SYSCALL(lstat)
DL_SYSCALL(mmap)
DL_SYSCALL(mprotect)
diff --git a/libexec/ld.so/powerpc/syscall.h b/libexec/ld.so/powerpc/syscall.h
index 24da619b6eb..42dbcfd57c2 100644
--- a/libexec/ld.so/powerpc/syscall.h
+++ b/libexec/ld.so/powerpc/syscall.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: syscall.h,v 1.40 2016/03/21 22:41:29 bluhm Exp $ */
+/* $OpenBSD: syscall.h,v 1.41 2016/05/07 19:05:23 guenther Exp $ */
/*
* Copyright (c) 1998 Per Fogelstrom, Opsycon AB
@@ -45,6 +45,7 @@ int _dl_getcwd(char *, size_t);
ssize_t _dl_getdents(int, char *, size_t);
int _dl_gettimeofday(struct timeval *, struct timezone *);
int _dl_issetugid(void);
+int _dl_getthrid(void);
int _dl_lstat(const char *, struct stat *);
void * _dl_mmap(void *, size_t, int, int, int, off_t);
int _dl_mprotect(const void *, size_t, int);
diff --git a/libexec/ld.so/resolve.h b/libexec/ld.so/resolve.h
index 8a1b2845dfb..7881b4a89a5 100644
--- a/libexec/ld.so/resolve.h
+++ b/libexec/ld.so/resolve.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: resolve.h,v 1.76 2016/03/20 02:29:51 guenther Exp $ */
+/* $OpenBSD: resolve.h,v 1.77 2016/05/07 19:05:23 guenther Exp $ */
/*
* Copyright (c) 1998 Per Fogelstrom, Opsycon AB
@@ -143,6 +143,13 @@ struct elf_object {
dev_t dev;
ino_t inode;
+ /* thread local storage info */
+ Elf_Addr tls_fsize;
+ Elf_Addr tls_msize;
+ Elf_Addr tls_align;
+ const void *tls_static_data;
+ int tls_offset;
+
/* generation number of last grpsym insert on this object */
unsigned int grpsym_gen;
@@ -245,6 +252,13 @@ void _dl_trace_setup(char **);
void _dl_trace_object_setup(elf_object_t *);
int _dl_trace_plt(const elf_object_t *, const char *);
+/* tib.c */
+void _dl_allocate_tls_offsets(void);
+void _dl_allocate_first_tib(void);
+void _dl_set_tls(elf_object_t *_object, Elf_Phdr *_ptls, Elf_Addr _libaddr,
+ const char *_libname);
+extern int _dl_tib_static_done;
+
extern elf_object_t *_dl_objects;
extern elf_object_t *_dl_last_object;
diff --git a/libexec/ld.so/sh/ldasm.S b/libexec/ld.so/sh/ldasm.S
index cafd90ea8f8..095533c726f 100644
--- a/libexec/ld.so/sh/ldasm.S
+++ b/libexec/ld.so/sh/ldasm.S
@@ -1,4 +1,4 @@
-/* $OpenBSD: ldasm.S,v 1.23 2016/03/21 22:41:29 bluhm Exp $ */
+/* $OpenBSD: ldasm.S,v 1.24 2016/05/07 19:05:23 guenther Exp $ */
/*
* Copyright (c) 2006 Dale Rahn
@@ -172,6 +172,7 @@ _dl_exit:
nop
DL_SYSCALL(issetugid)
+DL_SYSCALL(getthrid)
DL_SYSCALL2(_syscall,__syscall)
DL_SYSCALL(munmap)
DL_SYSCALL(mprotect)
@@ -194,6 +195,7 @@ DL_SYSCALL(sendsyslog)
DL_SYSCALL(pledge)
DL_SYSCALL2(getcwd,__getcwd)
DL_SYSCALL(sysctl)
+DL_SYSCALL2_NOERR(set_tcb,__set_tcb)
DL_SYSCALL(getdents)
diff --git a/libexec/ld.so/sh/syscall.h b/libexec/ld.so/sh/syscall.h
index e5069e066af..c98b8e11cec 100644
--- a/libexec/ld.so/sh/syscall.h
+++ b/libexec/ld.so/sh/syscall.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: syscall.h,v 1.18 2016/03/21 22:41:29 bluhm Exp $ */
+/* $OpenBSD: syscall.h,v 1.19 2016/05/07 19:05:23 guenther Exp $ */
/*
* Copyright (c) 2001 Niklas Hallqvist
@@ -42,6 +42,7 @@ int _dl_close(int);
__dead
int _dl_exit(int);
int _dl_issetugid(void);
+int _dl_getthrid(void);
long _dl__syscall(quad_t, ...);
int _dl_mprotect(const void *, size_t, int);
int _dl_munmap(const void *, size_t);
@@ -58,6 +59,7 @@ int _dl_getcwd(char *, size_t);
int _dl_utrace(const char *, const void *, size_t);
int _dl_getentropy(char *, size_t);
int _dl_sendsyslog(const char *, size_t, int);
+void _dl_set_tcb(void *);
static inline off_t
_dl_lseek(int fildes, off_t offset, int whence)
diff --git a/libexec/ld.so/sparc/ldasm.S b/libexec/ld.so/sparc/ldasm.S
index 3bcf14814fd..0d5788bb01c 100644
--- a/libexec/ld.so/sparc/ldasm.S
+++ b/libexec/ld.so/sparc/ldasm.S
@@ -1,4 +1,4 @@
-/* $OpenBSD: ldasm.S,v 1.30 2016/03/21 22:41:29 bluhm Exp $ */
+/* $OpenBSD: ldasm.S,v 1.31 2016/05/07 19:05:23 guenther Exp $ */
/*
* Copyright (c) 2001 Jason L. Wright (jason@thought.net)
@@ -176,6 +176,18 @@ _dl_issetugid:
.section ".text"
.align 4
+ .global _dl_getthrid
+ .type _dl_getthrid,@function
+_dl_getthrid:
+ mov SYS_getthrid | SYSCALL_G2RFLAG, %g1 ! call sys_getthrid
+ add %o7, 8, %g2 ! just return on success
+ t ST_SYSCALL ! off to wonderland
+ retl
+ sub %g0, %o0, %o0 ! error: result = -errno
+
+
+ .section ".text"
+ .align 4
.global _dl__syscall
.type _dl__syscall,@function
_dl__syscall:
diff --git a/libexec/ld.so/sparc/syscall.h b/libexec/ld.so/sparc/syscall.h
index df5293ba4ea..a1f1cff714c 100644
--- a/libexec/ld.so/sparc/syscall.h
+++ b/libexec/ld.so/sparc/syscall.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: syscall.h,v 1.25 2016/03/21 22:41:29 bluhm Exp $ */
+/* $OpenBSD: syscall.h,v 1.26 2016/05/07 19:05:23 guenther Exp $ */
/*
* Copyright (c) 2001 Niklas Hallqvist
@@ -42,6 +42,7 @@ int _dl_close(int);
__dead
int _dl_exit(int);
int _dl_issetugid(void);
+int _dl_getthrid(void);
long _dl__syscall(quad_t, ...);
int _dl_mprotect(const void *, size_t, int);
int _dl_munmap(const void *, size_t);
diff --git a/libexec/ld.so/sparc64/ldasm.S b/libexec/ld.so/sparc64/ldasm.S
index 47949f6d7c5..d0f6aa7b2c5 100644
--- a/libexec/ld.so/sparc64/ldasm.S
+++ b/libexec/ld.so/sparc64/ldasm.S
@@ -1,4 +1,4 @@
-/* $OpenBSD: ldasm.S,v 1.42 2016/03/21 22:41:29 bluhm Exp $ */
+/* $OpenBSD: ldasm.S,v 1.43 2016/05/07 19:05:23 guenther Exp $ */
/* $NetBSD: rtld_start.S,v 1.5 2001/08/14 22:17:48 eeh Exp $ */
/*
@@ -230,6 +230,13 @@ _ENTRY(_dl_issetugid)
retl
sub %g0, %o0, %o0 ! error: result = -errno
+_ENTRY(_dl_getthrid)
+ mov SYS_getthrid | SYSCALL_G2RFLAG, %g1 ! call sys_getthrid
+ add %o7, 8, %g2 ! just return on success
+ t ST_SYSCALL ! off to wonderland
+ retl
+ sub %g0, %o0, %o0 ! error: result = -errno
+
_ENTRY(_dl__syscall)
mov SYS___syscall | SYSCALL_G2RFLAG, %g1 ! call sys___syscall
add %o7, 8, %g2 ! just return on success
diff --git a/libexec/ld.so/sparc64/syscall.h b/libexec/ld.so/sparc64/syscall.h
index 0abb05b7314..6fc3aa31934 100644
--- a/libexec/ld.so/sparc64/syscall.h
+++ b/libexec/ld.so/sparc64/syscall.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: syscall.h,v 1.32 2016/03/21 22:41:29 bluhm Exp $ */
+/* $OpenBSD: syscall.h,v 1.33 2016/05/07 19:05:23 guenther Exp $ */
/*
* Copyright (c) 2001 Niklas Hallqvist
@@ -42,6 +42,7 @@ int _dl_close(int);
__dead
int _dl_exit(int);
int _dl_issetugid(void);
+int _dl_getthrid(void);
long _dl__syscall(quad_t, ...);
int _dl_mprotect(const void *, size_t, int);
int _dl_munmap(const void *, size_t);
diff --git a/libexec/ld.so/tib.c b/libexec/ld.so/tib.c
new file mode 100644
index 00000000000..ed190ea90ad
--- /dev/null
+++ b/libexec/ld.so/tib.c
@@ -0,0 +1,186 @@
+/*
+ * Copyright (c) 2016 Philip Guenther <guenther@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * Thread Information Block (TIB) and Thread Local Storage (TLS) handling
+ * (the TCB, Thread Control Block, is part of the TIB)
+ */
+
+#define _DYN_LOADER
+
+#include <sys/types.h>
+#include <sys/exec_elf.h>
+
+#include <tib.h>
+
+#include "archdep.h"
+#include "resolve.h"
+#include "util.h"
+#include "syscall.h"
+
+/* If we need the syscall, use our local syscall definition */
+#define __set_tcb(tcb) _dl_set_tcb(tcb)
+
+
+static int static_tls_size;
+
+int _dl_tib_static_done;
+
+/*
+ * Allocate a TIB for passing to __tfork for a new thread. 'extra'
+ * is the amount of space to allocate on the side of the TIB opposite
+ * of the TLS data: before the TIB for variant 1 and after the TIB
+ * for variant 2. If non-zero, tib_thread is set to point to that area.
+ */
+void *
+_dl_allocate_tib(size_t extra)
+{
+ char *base;
+ struct tib *tib;
+ char *thread = NULL;
+ struct elf_object *obj;
+
+#if TLS_VARIANT == 1
+ /* round up the extra size to align the tib after it */
+ extra = ELF_ROUND(extra, sizeof(void *));
+ base = _dl_malloc(extra + sizeof *tib + static_tls_size);
+ tib = (struct tib *)(base + extra);
+ if (extra)
+ thread = base;
+#define TLS_ADDR(tibp, offset) ((char *)(tibp) + sizeof(struct tib) + (offset))
+
+#elif TLS_VARIANT == 2
+ /* round up the tib size to align the extra area after it */
+ base = _dl_malloc(ELF_ROUND(sizeof *tib, TIB_EXTRA_ALIGN) +
+ extra + static_tls_size);
+ tib = (struct tib *)(base + static_tls_size);
+ if (extra)
+ thread = (char *)tib + ELF_ROUND(sizeof *tib, TIB_EXTRA_ALIGN);
+#define TLS_ADDR(tibp, offset) ((char *)(tibp) - (offset))
+
+#endif
+
+ for (obj = _dl_objects; obj != NULL; obj = obj->next) {
+ if (obj->tls_msize != 0) {
+ char *addr = TLS_ADDR(tib, obj->tls_offset);
+
+ _dl_memset(addr + obj->tls_fsize, 0,
+ obj->tls_msize - obj->tls_fsize);
+ if (obj->tls_static_data != NULL)
+ _dl_bcopy(obj->tls_static_data, addr,
+ obj->tls_fsize);
+ DL_DEB(("\t%s has index %u addr %p msize %u fsize %u\n",
+ obj->load_name, obj->tls_offset,
+ (void *)addr, obj->tls_msize, obj->tls_fsize));
+ }
+ }
+
+ TIB_INIT(tib, NULL, thread);
+
+ DL_DEB(("tib new=%p\n", (void *)tib));
+
+ return (tib);
+}
+
+void
+_dl_free_tib(void *tib, size_t extra)
+{
+ size_t tib_offset;
+
+#if TLS_VARIANT == 1
+ tib_offset = ELF_ROUND(extra, sizeof(void *));
+#elif TLS_VARIANT == 2
+ tib_offset = static_tls_size;
+#endif
+
+ DL_DEB(("free tib=%p\n", (void *)tib));
+ _dl_free((char *)tib - tib_offset);
+}
+
+
+/*
+ * Record what's necessary for handling TLS for an object.
+ */
+void
+_dl_set_tls(elf_object_t *object, Elf_Phdr *ptls, Elf_Addr libaddr,
+ const char *libname)
+{
+ if (ptls->p_vaddr != 0 && ptls->p_filesz != 0)
+ object->tls_static_data = (void *)(ptls->p_vaddr + libaddr);
+ object->tls_fsize = ptls->p_filesz;
+ object->tls_msize = ptls->p_memsz;
+ object->tls_align = ptls->p_align;
+
+ DL_DEB(("tls %x %x %x %x\n",
+ object->tls_static_data, object->tls_fsize, object->tls_msize,
+ object->tls_align));
+}
+
+static inline Elf_Addr
+allocate_tls_offset(Elf_Addr msize, Elf_Addr align)
+{
+ Elf_Addr offset;
+
+#if TLS_VARIANT == 1
+ /* round up to the required alignment, then allocate the space */
+ offset = ELF_ROUND(static_tls_size, align);
+ static_tls_size += msize;
+#elif TLS_VARIANT == 2
+ /*
+ * allocate the space, then round up to the alignment
+ * (these are negative offsets, so rounding up really rounds the
+ * address down)
+ */
+ static_tls_size = ELF_ROUND(static_tls_size + msize, align);
+ offset = static_tls_size;
+#else
+# error "unknown TLS_VARIANT"
+#endif
+ return offset;
+}
+
+/*
+ * Calculate the TLS offset for each object with static TLS.
+ */
+void
+_dl_allocate_tls_offsets(void)
+{
+ struct elf_object *obj;
+
+ for (obj = _dl_objects; obj != NULL; obj = obj->next) {
+ if (obj->tls_msize != 0) {
+ obj->tls_offset = allocate_tls_offset(obj->tls_msize,
+ obj->tls_align);
+ }
+ }
+
+ /* no more static TLS allocations after this */
+ _dl_tib_static_done = 1;
+}
+
+/*
+ * Allocate the TIB + TLS for the initial thread.
+ */
+void
+_dl_allocate_first_tib(void)
+{
+ struct tib *tib;
+
+ tib = _dl_allocate_tib(0);
+ tib->tib_tid = _dl_getthrid();
+
+ TCB_SET(TIB_TO_TCB(tib));
+}