summaryrefslogtreecommitdiff
path: root/lib/libc/dlfcn/init.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libc/dlfcn/init.c')
-rw-r--r--lib/libc/dlfcn/init.c107
1 files changed, 107 insertions, 0 deletions
diff --git a/lib/libc/dlfcn/init.c b/lib/libc/dlfcn/init.c
new file mode 100644
index 00000000000..b12b7104fe9
--- /dev/null
+++ b/lib/libc/dlfcn/init.c
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2014,2015 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.
+ */
+
+
+#define _DYN_LOADER
+
+#include <sys/types.h>
+#include <sys/exec_elf.h>
+
+#include <limits.h> /* NAME_MAX */
+#include <stdlib.h> /* atexit */
+#include <string.h>
+#include <unistd.h> /* _pagesize */
+#include "kbind.h"
+
+/* XXX should be in an include file shared with csu */
+char ***_csu_finish(char **_argv, char **_envp, void (*_cleanup)(void));
+
+/* provide definition for this */
+int _pagesize = 0;
+
+/*
+ * In dynamicly linked binaries environ and __progname are overriden by
+ * the definitions in ld.so.
+ */
+char **environ __attribute__((weak)) = NULL;
+char *__progname __attribute__((weak)) = NULL;
+
+
+#ifndef PIC
+static inline void early_static_init(char **_argv, char **_envp);
+#endif /* PIC */
+
+
+/*
+ * extract useful bits from the auxiliary vector and either
+ * a) register ld.so's cleanup in dynamic links, or
+ * b) init __progname, environ, and the TIB in static links.
+ */
+char ***
+_csu_finish(char **argv, char **envp, void (*cleanup)(void))
+{
+ AuxInfo *aux;
+
+#ifndef PIC
+ /* static libc in a static link? */
+ if (cleanup == NULL)
+ early_static_init(argv, envp);
+#endif /* !PIC */
+
+ /* Extract useful bits from the auxiliary vector */
+ while (*envp++ != NULL)
+ ;
+ for (aux = (void *)envp; aux->au_id != AUX_null; aux++) {
+ switch (aux->au_id) {
+ case AUX_pagesz:
+ _pagesize = aux->au_v;
+ break;
+ }
+ }
+
+ if (cleanup != NULL)
+ atexit(cleanup);
+
+ return &environ;
+}
+
+#ifndef PIC
+/*
+ * static libc in a static link? Then disable kbind and set up
+ * __progname and environ
+ */
+static inline void
+early_static_init(char **argv, char **envp)
+{
+ static char progname_storage[NAME_MAX+1] = "";
+
+ MD_DISABLE_KBIND;
+
+ environ = envp;
+
+ /* set up __progname */
+ if (*argv != NULL) { /* NULL ptr if argc = 0 */
+ const char *p = strrchr(*argv, '/');
+
+ if (p == NULL)
+ p = *argv;
+ else
+ p++;
+ strlcpy(progname_storage, p, sizeof(progname_storage));
+ }
+ __progname = progname_storage;
+}
+#endif /* !PIC */