summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorguenther <guenther@openbsd.org>2016-09-06 18:49:34 +0000
committerguenther <guenther@openbsd.org>2016-09-06 18:49:34 +0000
commit767451c3a44b994962ea42880d2a1460de78ea94 (patch)
tree738c67377e0ace17954939f9e451f7813ce0ae0a
parentRemove branch prediction hints from conditional branch instructions. These (diff)
downloadwireguard-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.c39
-rw-r--r--lib/libc/dlfcn/init.c13
-rw-r--r--lib/libc/dlfcn/init.h26
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 */