diff options
author | 2016-09-06 18:49:34 +0000 | |
---|---|---|
committer | 2016-09-06 18:49:34 +0000 | |
commit | 767451c3a44b994962ea42880d2a1460de78ea94 (patch) | |
tree | 738c67377e0ace17954939f9e451f7813ce0ae0a | |
parent | Remove branch prediction hints from conditional branch instructions. These (diff) | |
download | wireguard-openbsd-767451c3a44b994962ea42880d2a1460de78ea94.tar.xz wireguard-openbsd-767451c3a44b994962ea42880d2a1460de78ea94.zip |
Implement dl_iterate_phdr() for static PIE executables using info extracted
from the aux vector.
ok patrick@ kettenis@
-rw-r--r-- | lib/libc/dlfcn/dlfcn_stubs.c | 39 | ||||
-rw-r--r-- | lib/libc/dlfcn/init.c | 13 | ||||
-rw-r--r-- | lib/libc/dlfcn/init.h | 26 |
3 files changed, 74 insertions, 4 deletions
diff --git a/lib/libc/dlfcn/dlfcn_stubs.c b/lib/libc/dlfcn/dlfcn_stubs.c index 59b8e1fd1c9..e04a2aa0706 100644 --- a/lib/libc/dlfcn/dlfcn_stubs.c +++ b/lib/libc/dlfcn/dlfcn_stubs.c @@ -1,4 +1,4 @@ -/* $OpenBSD: dlfcn_stubs.c,v 1.13 2015/11/01 03:00:01 guenther Exp $ */ +/* $OpenBSD: dlfcn_stubs.c,v 1.14 2016/09/06 18:49:34 guenther Exp $ */ /* * Copyright (c) 1998 Per Fogelstrom, Opsycon AB @@ -26,7 +26,11 @@ * */ +#include <sys/types.h> #include <stddef.h> +#include <link.h> + +#include "init.h" /* * All functions here are just stubs that will be overridden @@ -45,7 +49,6 @@ char *dlerror(void) __attribute__((weak)); struct dl_info; int dladdr(const void *addr, struct dl_info *info) __attribute__((weak)); -struct dl_phdr_info; int dl_iterate_phdr(int (*callback)(struct dl_phdr_info *, size_t, void *), void *date) __attribute__((weak)); #include <stdio.h> @@ -87,6 +90,11 @@ int dl_iterate_phdr(int (*callback)(struct dl_phdr_info *, size_t, void *), void *data) { +#ifndef PIC + if (_static_phdr_info.dlpi_phdr != NULL) + return callback(&_static_phdr_info, sizeof(_static_phdr_info), + data); +#endif /* !PIC */ return -1; } @@ -96,3 +104,30 @@ dladdr(const void *addr, struct dl_info *info) printf("Wrong dl symbols!\n"); return -1; } + +/* Thread Local Storage argument structure */ +typedef struct { + unsigned long int ti_module; + unsigned long int ti_offset; +} tls_index; + +void *__tls_get_addr(tls_index *) __attribute__((weak)); +#ifdef __i386 +void *___tls_get_addr(tls_index *) __attribute__((weak, __regparm__(1))); +#endif + +#if defined(__amd64) || defined(__i386) || defined(__sparc64) +void * +__tls_get_addr(tls_index *ti) +{ + return NULL; +} + +#ifdef __i386 +__attribute__((__regparm__(1))) void * +___tls_get_addr(tls_index *ti) +{ + return NULL; +} +#endif /* __i386 */ +#endif /* arch with TLS support enabled */ diff --git a/lib/libc/dlfcn/init.c b/lib/libc/dlfcn/init.c index 3147f9ba7f1..c791c88610e 100644 --- a/lib/libc/dlfcn/init.c +++ b/lib/libc/dlfcn/init.c @@ -1,4 +1,4 @@ -/* $OpenBSD: init.c,v 1.4 2016/05/07 19:05:22 guenther Exp $ */ +/* $OpenBSD: init.c,v 1.5 2016/09/06 18:49:34 guenther Exp $ */ /* * Copyright (c) 2014,2015 Philip Guenther <guenther@openbsd.org> * @@ -19,7 +19,6 @@ #define _DYN_LOADER #include <sys/types.h> -#include <sys/exec_elf.h> #include <sys/syscall.h> #ifndef PIC @@ -28,10 +27,13 @@ #include <tib.h> #include <limits.h> /* NAME_MAX */ +#include <link.h> #include <stdlib.h> /* atexit */ #include <string.h> #include <unistd.h> +#include "init.h" + /* XXX should be in an include file shared with csu */ char ***_csu_finish(char **_argv, char **_envp, void (*_cleanup)(void)); @@ -47,6 +49,8 @@ char *__progname __attribute__((weak)) = NULL; #ifndef PIC +struct dl_phdr_info _static_phdr_info = { .dlpi_name = "a.out" }; + static inline void early_static_init(char **_argv, char **_envp); static inline void setup_static_tib(Elf_Phdr *_phdr, int _phnum); #endif /* PIC */ @@ -79,11 +83,16 @@ _csu_finish(char **argv, char **envp, void (*cleanup)(void)) _pagesize = aux->au_v; break; #ifndef PIC + case AUX_base: + _static_phdr_info.dlpi_addr = aux->au_v; + break; case AUX_phdr: phdr = (void *)aux->au_v; + _static_phdr_info.dlpi_phdr = phdr; break; case AUX_phnum: phnum = aux->au_v; + _static_phdr_info.dlpi_phnum = phnum; break; #endif /* !PIC */ } diff --git a/lib/libc/dlfcn/init.h b/lib/libc/dlfcn/init.h new file mode 100644 index 00000000000..770c17ff632 --- /dev/null +++ b/lib/libc/dlfcn/init.h @@ -0,0 +1,26 @@ +/* $OpenBSD: init.h,v 1.1 2016/09/06 18:49:34 guenther Exp $ */ +/* + * 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. + */ + +#ifndef INIT_H +#define INIT_H + +__BEGIN_HIDDEN_DECLS +/* shared between dl_iterate_phdr() and _csu_finish() in static builds */ +extern struct dl_phdr_info _static_phdr_info; +__END_HIDDEN_DECLS + +#endif /* !INIT_H */ |