tech-userlevel archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
dl_iterate_phdr support for static applications
Hi all,
attached is a patch to support dl_iterate_phdr for statically linked
applications. This has two direct use cases at the moment:
(1) TLS support (since ld.elf_so can't do it for -static)
(2) libgcc_s's exception handling
The second part is also important for dynamically linked programs, since
it removes the need for the register calls and the associated locking
mess in libgcc_s.
A small program to print the interesting (and used) fields is also
attached, it could be used in combination with readelf -l and -h to
validate the output. Note that the path field for static binaries is
only set if called with an absolute path or via PATH.
Joerg
Index: src/lib/csu/alpha/crt0.c
===================================================================
--- src/lib/csu/alpha/crt0.c
+++ src/lib/csu/alpha/crt0.c
@@ -66,10 +66,12 @@
#ifdef DYNAMIC
if (&rtld_DYNAMIC != NULL)
_rtld_setup(cleanup, obj);
#endif
+
+ _libc_init();
#ifdef MCRT0
atexit(_mcleanup);
monstartup((u_long)&_eprol, (u_long)&_etext);
#endif
Index: src/lib/csu/arm_elf/crt0.c
===================================================================
--- src/lib/csu/arm_elf/crt0.c
+++ src/lib/csu/arm_elf/crt0.c
@@ -90,10 +90,12 @@
#ifdef DYNAMIC
/* ld(1) convention: if DYNAMIC = 0 then statically linked */
if (&rtld_DYNAMIC)
_rtld_setup(cleanup, obj);
#endif /* DYNAMIC */
+
+ _libc_init();
#ifdef MCRT0
atexit(_mcleanup);
monstartup((u_long)&_eprol, (u_long)&_etext);
#endif /* MCRT0 */
Index: src/lib/csu/common/crt0-common.c
===================================================================
--- src/lib/csu/common/crt0-common.c
+++ src/lib/csu/common/crt0-common.c
@@ -48,10 +48,11 @@
extern int main(int, char **, char **);
extern void _init(void);
extern void _fini(void);
+extern void _libc_init(void);
/*
* Arrange for _DYNAMIC to be weak and undefined (and therefore to show up
* as being at address zero, unless something else defines it). That way,
* if we happen to be compiling without -static but with without any
@@ -112,10 +113,12 @@
_FATAL("Corrupt Obj_Entry pointer in GOT\n");
if (obj->version != RTLD_VERSION)
_FATAL("Dynamic linker version mismatch\n");
atexit(cleanup);
}
+
+ _libc_init();
#ifdef MCRT0
atexit(_mcleanup);
monstartup((u_long)&__eprol, (u_long)&__etext);
#endif
Index: src/lib/csu/common_elf/common.h
===================================================================
--- src/lib/csu/common_elf/common.h
+++ src/lib/csu/common_elf/common.h
@@ -69,10 +69,11 @@
char *__progname = "";
struct ps_strings *__ps_strings = 0;
extern void _init(void);
extern void _fini(void);
+extern void _libc_init(void);
#ifdef DYNAMIC
void _rtld_setup(void (*)(void), const Obj_Entry *obj);
/*
Index: src/lib/csu/hppa/crt0.c
===================================================================
--- src/lib/csu/hppa/crt0.c
+++ src/lib/csu/hppa/crt0.c
@@ -90,10 +90,12 @@
#ifdef DYNAMIC
if (&rtld_DYNAMIC != NULL)
_rtld_setup(cleanup, obj);
#endif
+
+ _libc_init();
#ifdef MCRT0
atexit(_mcleanup);
monstartup((u_long)&_eprol, (u_long)&_etext);
#endif
Index: src/lib/csu/ia64/crt0.c
===================================================================
--- src/lib/csu/ia64/crt0.c
+++ src/lib/csu/ia64/crt0.c
@@ -73,10 +73,12 @@
#ifdef DYNAMIC
if (&rtld_DYNAMIC != NULL)
_rtld_setup(cleanup, obj);
#endif
+
+ _libc_init();
#ifdef MCRT0
atexit(_mcleanup);
monstartup((u_long)&_eprol, (u_long)&_etext);
#endif
Index: src/lib/csu/m68k_elf/crt0.c
===================================================================
--- src/lib/csu/m68k_elf/crt0.c
+++ src/lib/csu/m68k_elf/crt0.c
@@ -76,10 +76,12 @@
#ifdef DYNAMIC
if (&rtld_DYNAMIC != NULL)
_rtld_setup(cleanup, obj);
#endif
+
+ _libc_init();
#ifdef MCRT0
atexit(_mcleanup);
monstartup((u_long)&_eprol, (u_long)&_etext);
#endif
Index: src/lib/csu/powerpc/crt0.c
===================================================================
--- src/lib/csu/powerpc/crt0.c
+++ src/lib/csu/powerpc/crt0.c
@@ -89,10 +89,12 @@
#ifdef DYNAMIC
if (&rtld_DYNAMIC != NULL)
_rtld_setup(cleanup, obj);
#endif
+
+ _libc_init();
#ifdef MCRT0
atexit(_mcleanup);
monstartup((u_long)&_eprol, (u_long)&_etext);
#endif
Index: src/lib/csu/powerpc64/crt0.c
===================================================================
--- src/lib/csu/powerpc64/crt0.c
+++ src/lib/csu/powerpc64/crt0.c
@@ -75,10 +75,12 @@
#ifdef DYNAMIC
if (&rtld_DYNAMIC != NULL)
_rtld_setup(cleanup, obj);
#endif
+
+ _libc_init();
#ifdef MCRT0
atexit(_mcleanup);
monstartup((u_long)&_eprol, (u_long)&_etext);
#endif
Index: src/lib/csu/sh3_elf/crt0.c
===================================================================
--- src/lib/csu/sh3_elf/crt0.c
+++ src/lib/csu/sh3_elf/crt0.c
@@ -70,10 +70,12 @@
#ifdef DYNAMIC
if (&rtld_DYNAMIC != NULL)
_rtld_setup(cleanup, obj);
#endif
+
+ _libc_init();
#ifdef MCRT0
atexit(_mcleanup);
monstartup((u_long)&_eprol, (u_long)&_etext);
#endif
Index: src/lib/csu/sparc64/crt0.c
===================================================================
--- src/lib/csu/sparc64/crt0.c
+++ src/lib/csu/sparc64/crt0.c
@@ -95,10 +95,12 @@
#ifdef DYNAMIC
if (&rtld_DYNAMIC != NULL)
_rtld_setup(cleanup, obj);
#endif
+
+ _libc_init();
#ifdef MCRT0
atexit(_mcleanup);
monstartup((u_long)&_eprol, (u_long)&_etext);
#endif
Index: src/lib/csu/sparc_elf/crt0.c
===================================================================
--- src/lib/csu/sparc_elf/crt0.c
+++ src/lib/csu/sparc_elf/crt0.c
@@ -80,10 +80,12 @@
#ifdef DYNAMIC
if (&rtld_DYNAMIC != NULL)
_rtld_setup(cleanup, obj);
#endif
+
+ _libc_init();
#ifdef MCRT0
atexit(_mcleanup);
monstartup((u_long)&_eprol, (u_long)&_etext);
#endif
Index: src/lib/csu/vax_elf/crt0.c
===================================================================
--- src/lib/csu/vax_elf/crt0.c
+++ src/lib/csu/vax_elf/crt0.c
@@ -77,10 +77,12 @@
#ifdef DYNAMIC
if (&rtld_DYNAMIC != NULL)
_rtld_setup(cleanup, obj);
#endif
+
+ _libc_init();
#ifdef MCRT0
atexit(_mcleanup);
monstartup((u_long)&_eprol, (u_long)&_etext);
#endif
Index: src/lib/libc/dlfcn/dlfcn_elf.c
===================================================================
--- src/lib/libc/dlfcn/dlfcn_elf.c
+++ src/lib/libc/dlfcn/dlfcn_elf.c
@@ -28,11 +28,15 @@
#include <sys/cdefs.h>
#if defined(LIBC_SCCS) && !defined(lint)
__RCSID("$NetBSD: dlfcn_elf.c,v 1.7 2010/10/16 10:27:07 skrll Exp $");
#endif /* LIBC_SCCS and not lint */
+#include "reentrant.h"
#include "namespace.h"
+#include <elf.h>
+#include <errno.h>
+#include <string.h>
#undef dlopen
#undef dlclose
#undef dlsym
#undef dlerror
@@ -126,13 +130,63 @@
{
return -1;
}
+static once_t dl_iterate_phdr_once = ONCE_INITIALIZER;
+static const char *dlpi_name;
+static Elf_Addr dlpi_addr;
+static const Elf_Phdr *dlpi_phdr;
+static Elf_Half dlpi_phnum;
+
+/*
+ * Declare as common symbol to allow new libc with older binaries to
+ * not trigger an undefined reference.
+ */
+extern __dso_hidden void *__auxinfo;
+
+static void
+dl_iterate_phdr_setup(void)
+{
+ const AuxInfo *aux;
+
+ if (__auxinfo == NULL)
+ return;
+
+ for (aux = __auxinfo; aux->a_type != AT_NULL; ++aux) {
+ switch (aux->a_type) {
+ case AT_BASE:
+ dlpi_addr = aux->a_v;
+ break;
+ case AT_PHDR:
+ dlpi_phdr = (void *)aux->a_v;
+ break;
+ case AT_PHNUM:
+ dlpi_phnum = aux->a_v;
+ break;
+ case AT_SUN_EXECNAME:
+ dlpi_name = (void *)aux->a_v;
+ break;
+ }
+ }
+}
+
/*ARGSUSED*/
int
dl_iterate_phdr(int (*callback)(struct dl_phdr_info *, size_t, void *),
void *data)
{
+ struct dl_phdr_info phdr_info;
+
+ if (__auxinfo == NULL)
+ return EOPNOTSUPP;
+
+ thr_once(&dl_iterate_phdr_once, dl_iterate_phdr_setup);
+
+ memset(&phdr_info, 0, sizeof(phdr_info));
+ phdr_info.dlpi_addr = dlpi_addr;
+ phdr_info.dlpi_phdr = dlpi_phdr;
+ phdr_info.dlpi_phnum = dlpi_phnum;
+ phdr_info.dlpi_name = dlpi_name;
- return 0;
+ return callback(&phdr_info, sizeof(phdr_info), data);
}
Index: src/lib/libc/misc/initfini.c
===================================================================
--- src/lib/libc/misc/initfini.c
+++ src/lib/libc/misc/initfini.c
@@ -34,22 +34,45 @@
#ifdef _LIBC
#include "namespace.h"
#endif
-void __libc_init(void) __attribute__((__constructor__, __used__));
+#include <sys/param.h>
+#include <sys/exec.h>
+#include <stdbool.h>
+
+void _libc_init(void) __attribute__((__constructor__, __used__));
void __guard_setup(void);
void __libc_thr_init(void);
void __libc_atomic_init(void);
void __libc_atexit_init(void);
void __libc_env_init(void);
-/* LINTED used */
+static bool libc_initialised;
+
+void _libc_init(void);
+
+__dso_hidden void *__auxinfo;
+struct ps_strings *__ps_strings;
+
+/*
+ * _libc_init is called twice. The first time explicitly by crt0.o
+ * (for newer versions) and the second time as indirectly via _init().
+ */
void
-__libc_init(void)
+_libc_init(void)
{
+
+ if (libc_initialised)
+ return;
+
+ libc_initialised = 1;
+
+ if (__ps_strings != NULL)
+ __auxinfo = __ps_strings->ps_argvstr +
+ __ps_strings->ps_nargvstr + __ps_strings->ps_nenvstr + 2;
/* For -fstack-protector */
__guard_setup();
/* Atomic operations */
Index: src/lib/libc/stdlib/exit.c
===================================================================
--- src/lib/libc/stdlib/exit.c
+++ src/lib/libc/stdlib/exit.c
@@ -41,17 +41,10 @@
#include <stdlib.h>
#include <unistd.h>
#ifdef _LIBC
#include "reentrant.h"
#include "atexit.h"
-#endif
-
-#ifdef _LIBC
-extern void __libc_init(void);
-#ifndef __lint
-static void (*force_ref)(void) __used = __libc_init;
-#endif
#endif
void (*__cleanup) __P((void));
/*
Index: src/sys/compat/netbsd32/netbsd32_exec_elf32.c
===================================================================
--- src/sys/compat/netbsd32/netbsd32_exec_elf32.c
+++ src/sys/compat/netbsd32/netbsd32_exec_elf32.c
@@ -113,11 +113,11 @@
{
if (itp && epp->ep_interp == NULL) {
extern const char machine32[];
(void)compat_elf_check_interp(epp, itp, machine32);
}
- epp->ep_flags |= EXEC_32;
+ epp->ep_flags |= EXEC_32 | EXEC_FORCEAUX;
epp->ep_vm_minaddr = VM_MIN_ADDRESS;
epp->ep_vm_maxaddr = USRSTACK32;
#ifdef ELF_INTERP_NON_RELOCATABLE
*pos = ELF_LINK_ADDR;
#endif
Index: src/sys/kern/exec_elf.c
===================================================================
--- src/sys/kern/exec_elf.c
+++ src/sys/kern/exec_elf.c
@@ -934,7 +934,8 @@
if ((error = ELF_MD_PROBE_FUNC(l, epp, eh, itp, pos)) != 0)
return error;
#elif defined(ELF_INTERP_NON_RELOCATABLE)
*pos = ELF_LINK_ADDR;
#endif
+ epp->ep_flags |= EXEC_FORCEAUX;
return 0;
}
#include <elf.h>
#include <link.h>
#include <stdio.h>
static int
dl_iterate_phdr_cb(struct dl_phdr_info *info, size_t len, void *cookie)
{
const Elf64_Phdr *phdr = info->dlpi_phdr;
const Elf64_Phdr *phlimit = phdr + info->dlpi_phnum;
static int first = 1;
if (!first)
puts("");
first = 0;
printf("Base: %p\nPath: %s\nHeader address: %p\n"
"Number of header entries: %u\n",
(void *)info->dlpi_addr, info->dlpi_name, info->dlpi_phdr,
(unsigned)info->dlpi_phnum);
for (; phdr < phlimit; ++phdr)
printf("%u %p\n", phdr->p_type, (void *)phdr->p_vaddr);
return 0;
}
int
main(void)
{
dl_iterate_phdr(dl_iterate_phdr_cb, NULL);
return 0;
}
Home |
Main Index |
Thread Index |
Old Index