summaryrefslogtreecommitdiffstats
path: root/lib/libc/gen/dlfcn.c
diff options
context:
space:
mode:
authorkib <kib@FreeBSD.org>2012-02-17 10:49:29 +0000
committerkib <kib@FreeBSD.org>2012-02-17 10:49:29 +0000
commit64ade36cab6e0ed6360892f218e783983556dde1 (patch)
tree4ac15d54cf734a144a3a7707224503456d970cbc /lib/libc/gen/dlfcn.c
parent7580cb460821c765fe29dae1c2c0b108821cc895 (diff)
downloadFreeBSD-src-64ade36cab6e0ed6360892f218e783983556dde1.zip
FreeBSD-src-64ade36cab6e0ed6360892f218e783983556dde1.tar.gz
Fetch the aux vector for the static libc, and use the entries to
initialize the cache of the system information as it was done for the dynamic libc. This removes several sysctls from the static binary startup. Use the aux vector to fill the single struct dl_phdr_info describing the static binary itself, to implement dl_iterate_phdr(3) for the static binaries. [1] Based on the submission by: John Marino <draco marino st> [1] Tested by: flo (sparc64) MFC after: 2 weeks
Diffstat (limited to 'lib/libc/gen/dlfcn.c')
-rw-r--r--lib/libc/gen/dlfcn.c53
1 files changed, 51 insertions, 2 deletions
diff --git a/lib/libc/gen/dlfcn.c b/lib/libc/gen/dlfcn.c
index 7be9f87..ad24bb4 100644
--- a/lib/libc/gen/dlfcn.c
+++ b/lib/libc/gen/dlfcn.c
@@ -34,6 +34,10 @@ __FBSDID("$FreeBSD$");
#include <dlfcn.h>
#include <link.h>
#include <stddef.h>
+#include "namespace.h"
+#include <pthread.h>
+#include "un-namespace.h"
+#include "libc_private.h"
static char sorry[] = "Service unavailable";
@@ -138,13 +142,58 @@ _rtld_thread_init(void * li)
_rtld_error(sorry);
}
+static pthread_once_t dl_phdr_info_once = PTHREAD_ONCE_INIT;
+static struct dl_phdr_info phdr_info;
+
+static void
+dl_init_phdr_info(void)
+{
+ Elf_Auxinfo *auxp;
+ size_t phent;
+ unsigned int i;
+
+ phent = 0;
+ for (auxp = __elf_aux_vector; auxp->a_type != AT_NULL; auxp++) {
+ switch (auxp->a_type) {
+ case AT_BASE:
+ phdr_info.dlpi_addr = (Elf_Addr)auxp->a_un.a_ptr;
+ break;
+ case AT_EXECPATH:
+ phdr_info.dlpi_name = (const char *)auxp->a_un.a_ptr;
+ break;
+ case AT_PHDR:
+ phdr_info.dlpi_phdr =
+ (const Elf_Phdr *)auxp->a_un.a_ptr;
+ break;
+ case AT_PHENT:
+ phent = auxp->a_un.a_val;
+ break;
+ case AT_PHNUM:
+ phdr_info.dlpi_phnum = (Elf_Half)auxp->a_un.a_val;
+ break;
+ }
+ }
+ for (i = 0; i < phdr_info.dlpi_phnum; i++) {
+ if (phdr_info.dlpi_phdr[i].p_type == PT_TLS) {
+ phdr_info.dlpi_tls_modid = 1;
+ phdr_info.dlpi_tls_data =
+ (void*)phdr_info.dlpi_phdr[i].p_vaddr;
+ }
+ }
+ phdr_info.dlpi_adds = 1;
+}
+
#pragma weak dl_iterate_phdr
int
dl_iterate_phdr(int (*callback)(struct dl_phdr_info *, size_t, void *),
void *data)
{
- _rtld_error(sorry);
- return 0;
+
+ __init_elf_aux_vector();
+ if (__elf_aux_vector == NULL)
+ return (1);
+ _once(&dl_phdr_info_once, dl_init_phdr_info);
+ return (callback(&phdr_info, sizeof(phdr_info), data));
}
#pragma weak fdlopen
OpenPOWER on IntegriCloud