summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ldso/libdl/libdl.c174
1 files changed, 96 insertions, 78 deletions
diff --git a/ldso/libdl/libdl.c b/ldso/libdl/libdl.c
index 5d7c22b85..9191f99cf 100644
--- a/ldso/libdl/libdl.c
+++ b/ldso/libdl/libdl.c
@@ -1,70 +1,82 @@
+/* vi: set sw=4 ts=4: */
/*
- * libdl.c
- *
- * Functions required for dlopen et. al.
+ * Program to load an ELF binary on a linux system, and run it
+ * after resolving ELF shared library symbols
+ *
+ * Copyright (C) 2000-2004 by Erik Andersen <andersen@codpoet.org>
+ * Copyright (c) 1994-2000 Eric Youngdale, Peter MacDonald,
+ * David Engel, Hongjiu Lu and Mitch D'Souza
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. The name of the above contributors may not be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
*/
-#include <ldso.h>
-
-/* The public interfaces */
-void *dlopen(const char *, int) __attribute__ ((__weak__, __alias__ ("_dlopen")));
-int dlclose(void *) __attribute__ ((__weak__, __alias__ ("_dlclose")));
-void *dlsym(void *, const char *) __attribute__ ((__weak__, __alias__ ("_dlsym")));
-const char *dlerror(void) __attribute__ ((__weak__, __alias__ ("_dlerror")));
-int dladdr(void *, Dl_info *) __attribute__ ((__weak__, __alias__ ("_dladdr")));
-void _dlinfo(void);
+#include <ldso.h>
#if defined (__LIBDL_SHARED__)
-/* This is a real hack. We need access to the dynamic linker, but we
-also need to make it possible to link against this library without any
-unresolved externals. We provide these weak symbols to make the link
-possible, but at run time the normal symbols are accessed. */
-static void __attribute__ ((unused)) foobar(void)
-{
- const char msg[]="libdl library not correctly linked\n";
- _dl_write(2, msg, _dl_strlen(msg));
- _dl_exit(1);
-}
-static int __attribute__ ((unused)) foobar1 = (int) foobar; /* Use as pointer */
-extern void _dl_dprintf(int, const char *, ...) __attribute__ ((__weak__, __alias__ ("foobar")));
+/* When libdl is loaded as a shared library, we need to load in
+ * and use a pile of symbols from ldso... */
+
+extern void _dl_dprintf(int, const char *, ...) __attribute__ ((__weak__));
extern char *_dl_find_hash(const char *, struct dyn_elf *, int)
- __attribute__ ((__weak__, __alias__ ("foobar")));
-extern struct elf_resolve * _dl_load_shared_library(int, struct dyn_elf **, struct elf_resolve *, char *, int)
- __attribute__ ((__weak__, __alias__ ("foobar")));
+ __attribute__ ((__weak__));
+extern struct elf_resolve * _dl_load_shared_library(int, struct dyn_elf **,
+ struct elf_resolve *, char *, int) __attribute__ ((__weak__));
extern struct elf_resolve * _dl_check_if_named_library_is_loaded(const char *, int)
- __attribute__ ((__weak__, __alias__ ("foobar")));
+ __attribute__ ((__weak__));
extern int _dl_fixup(struct dyn_elf *rpnt, int lazy)
- __attribute__ ((__weak__, __alias__ ("foobar")));
+ __attribute__ ((__weak__));
+extern struct dyn_elf *_dl_symbol_tables __attribute__ ((__weak__));
+extern struct dyn_elf *_dl_handles __attribute__ ((__weak__));
+extern struct elf_resolve *_dl_loaded_modules __attribute__ ((__weak__));
+extern struct r_debug *_dl_debug_addr __attribute__ ((__weak__));
+extern unsigned long _dl_error_number __attribute__ ((__weak__));
+extern void *(*_dl_malloc_function)(size_t) __attribute__ ((__weak__));
+#ifdef USE_CACHE
+int _dl_map_cache(void) __attribute__ ((__weak__));
+int _dl_unmap_cache(void) __attribute__ ((__weak__));
+#endif
#ifdef __mips__
extern void _dl_perform_mips_global_got_relocations(struct elf_resolve *tpnt)
- __attribute__ ((__weak__, __alias__ ("foobar")));
+ __attribute__ ((__weak__));
#endif
-#ifdef USE_CACHE
-int _dl_map_cache(void) __attribute__ ((__weak__, __alias__ ("foobar")));
-int _dl_unmap_cache(void) __attribute__ ((__weak__, __alias__ ("foobar")));
-#endif
-
-extern struct dyn_elf *_dl_symbol_tables __attribute__ ((__weak__, __alias__ ("foobar1")));
-extern struct dyn_elf *_dl_handles __attribute__ ((__weak__, __alias__ ("foobar1")));
-extern struct elf_resolve *_dl_loaded_modules __attribute__ ((__weak__, __alias__ ("foobar1")));
-extern struct r_debug *_dl_debug_addr __attribute__ ((__weak__, __alias__ ("foobar1")));
-extern unsigned long _dl_error_number __attribute__ ((__weak__, __alias__ ("foobar1")));
-extern void *(*_dl_malloc_function)(size_t) __attribute__ ((__weak__, __alias__ ("foobar1")));
#ifdef __SUPPORT_LD_DEBUG__
-extern char *_dl_debug __attribute__ ((__weak__, __alias__ ("foobar1")));
-extern char *_dl_debug_symbols __attribute__ ((__weak__, __alias__ ("foobar1")));
-extern char *_dl_debug_move __attribute__ ((__weak__, __alias__ ("foobar1")));
-extern char *_dl_debug_reloc __attribute__ ((__weak__, __alias__ ("foobar1")));
-extern char *_dl_debug_detail __attribute__ ((__weak__, __alias__ ("foobar1")));
-extern char *_dl_debug_nofixups __attribute__ ((__weak__, __alias__ ("foobar1")));
-extern char *_dl_debug_bindings __attribute__ ((__weak__, __alias__ ("foobar1")));
-extern int _dl_debug_file __attribute__ ((__weak__, __alias__ ("foobar1")));
+extern char *_dl_debug __attribute__ ((__weak__));
+extern char *_dl_debug_symbols __attribute__ ((__weak__));
+extern char *_dl_debug_move __attribute__ ((__weak__));
+extern char *_dl_debug_reloc __attribute__ ((__weak__));
+extern char *_dl_debug_detail __attribute__ ((__weak__));
+extern char *_dl_debug_nofixups __attribute__ ((__weak__));
+extern char *_dl_debug_bindings __attribute__ ((__weak__));
+extern int _dl_debug_file __attribute__ ((__weak__));
#endif
-#else /* __LIBDL_SHARED__ */
+
+#else /* __LIBDL_SHARED__ */
+
+/* When libdl is linked as a static library, we need to replace all
+ * the symbols that otherwise would have been loaded in from ldso... */
#ifdef __SUPPORT_LD_DEBUG__
char *_dl_debug = 0;
@@ -80,12 +92,12 @@ char *_dl_library_path = 0;
char *_dl_ldsopath = 0;
struct r_debug *_dl_debug_addr = NULL;
static unsigned char *_dl_malloc_addr, *_dl_mmap_zero;
+void *(*_dl_malloc_function) (size_t size);
+int _dl_fixup(struct dyn_elf *rpnt, int lazy);
#include "../ldso/dl-progname.h" /* Pull in the name of ld.so */
#include "../ldso/dl-hash.c"
#define _dl_trace_loaded_objects 0
#include "../ldso/dl-elf.c"
-void *(*_dl_malloc_function) (size_t size);
-int _dl_fixup(struct dyn_elf *rpnt, int lazy);
#endif
static int do_dlclose(void *, int need_fini);
@@ -176,7 +188,7 @@ void *_dlopen(const char *libname, int flag)
/* Try to load the specified library */
#ifdef __SUPPORT_LD_DEBUG__
- if(_dl_debug)
+ if(_dl_debug)
_dl_dprintf(_dl_debug_file, "Trying to dlopen '%s'\n", (char*)libname);
#endif
if (!(tpnt = _dl_check_if_named_library_is_loaded((char *)libname, 0)))
@@ -205,7 +217,7 @@ void *_dlopen(const char *libname, int flag)
#ifdef __SUPPORT_LD_DEBUG__
- if(_dl_debug)
+ if(_dl_debug)
_dl_dprintf(_dl_debug_file, "Looking for needed libraries\n");
#endif
@@ -217,7 +229,7 @@ void *_dlopen(const char *libname, int flag)
if (dpnt->d_tag == DT_NEEDED) {
char *name;
- lpntstr = (char*) (tcurr->loadaddr + tcurr->dynamic_info[DT_STRTAB] +
+ lpntstr = (char*) (tcurr->loadaddr + tcurr->dynamic_info[DT_STRTAB] +
dpnt->d_un.d_val);
name = _dl_get_last_path_component(lpntstr);
@@ -225,8 +237,8 @@ void *_dlopen(const char *libname, int flag)
continue;
#ifdef __SUPPORT_LD_DEBUG__
- if(_dl_debug)
- _dl_dprintf(_dl_debug_file, "Trying to load '%s', needed by '%s'\n",
+ if(_dl_debug)
+ _dl_dprintf(_dl_debug_file, "Trying to load '%s', needed by '%s'\n",
lpntstr, tcurr->libname);
#endif
@@ -258,7 +270,7 @@ void *_dlopen(const char *libname, int flag)
#endif
#ifdef __SUPPORT_LD_DEBUG__
- if(_dl_debug)
+ if(_dl_debug)
_dl_dprintf(_dl_debug_file, "Beginning dlopen relocation fixups\n");
#endif
/*
@@ -285,7 +297,7 @@ void *_dlopen(const char *libname, int flag)
}
#if 0 //def __SUPPORT_LD_DEBUG__
- if(_dl_debug)
+ if(_dl_debug)
_dlinfo();
#endif
@@ -313,7 +325,7 @@ void *_dlopen(const char *libname, int flag)
dl_elf_func = (void (*)(void)) (tpnt->loadaddr + tpnt->dynamic_info[DT_INIT]);
if (dl_elf_func && *dl_elf_func != NULL) {
#ifdef __SUPPORT_LD_DEBUG__
- if(_dl_debug)
+ if(_dl_debug)
_dl_dprintf(2, "running ctors for library %s at '%x'\n", tpnt->libname, dl_elf_func);
#endif
(*dl_elf_func) ();
@@ -324,7 +336,7 @@ void *_dlopen(const char *libname, int flag)
dl_elf_func = (void (*)(void)) (tpnt->loadaddr + tpnt->dynamic_info[DT_FINI]);
if (dl_elf_func && *dl_elf_func != NULL) {
#ifdef __SUPPORT_LD_DEBUG__
- if(_dl_debug)
+ if(_dl_debug)
_dl_dprintf(2, "setting up dtors for library %s at '%x'\n", tpnt->libname, dl_elf_func);
#endif
atexit(dl_elf_func);
@@ -340,6 +352,7 @@ oops:
do_dlclose(dyn_chain, 0);
return NULL;
}
+weak_alias(_dlopen, dlopen);
void *_dlsym(void *vhandle, const char *name)
{
@@ -394,11 +407,7 @@ void *_dlsym(void *vhandle, const char *name)
_dl_error_number = LD_NO_SYMBOL;
return ret;
}
-
-int _dlclose(void *vhandle)
-{
- return do_dlclose(vhandle, 1);
-}
+weak_alias(_dlsym, dlsym);
static int do_dlclose(void *vhandle, int need_fini)
{
@@ -432,7 +441,7 @@ static int do_dlclose(void *vhandle, int need_fini)
for (; spnt; spnt = spnt1) {
spnt1 = spnt->next;
- /* We appended the module list to the end - when we get back here,
+ /* We appended the module list to the end - when we get back here,
quit. The access counts were not adjusted to account for being here. */
if (spnt == _dl_symbol_tables)
break;
@@ -444,7 +453,7 @@ static int do_dlclose(void *vhandle, int need_fini)
*/
if (tpnt->dynamic_info[DT_FINI]) {
- dl_elf_fini = (int (*)(void)) (tpnt->loadaddr +
+ dl_elf_fini = (int (*)(void)) (tpnt->loadaddr +
tpnt->dynamic_info[DT_FINI]);
(*dl_elf_fini) ();
}
@@ -459,7 +468,7 @@ static int do_dlclose(void *vhandle, int need_fini)
for (rpnt = handle; rpnt; rpnt = rpnt1) {
rpnt1 = rpnt->next;
- /* We appended the module list to the end - when we get back here,
+ /* We appended the module list to the end - when we get back here,
quit. The access counts were not adjusted to account for being here. */
if (rpnt == _dl_symbol_tables)
break;
@@ -473,10 +482,10 @@ static int do_dlclose(void *vhandle, int need_fini)
*/
#if 0
- /* We have to do this above, before we start closing objects.
- * Otherwise when the needed symbols for _fini handling are
- * resolved a coredump would occur. Rob Ryan (robr@cmu.edu)*/
- if (tpnt->dynamic_info[DT_FINI]) {
+ /* We have to do this above, before we start closing objects.
+ * Otherwise when the needed symbols for _fini handling are
+ * resolved a coredump would occur. Rob Ryan (robr@cmu.edu)*/
+ if (tpnt->dynamic_info[DT_FINI]) {
dl_elf_fini = (int (*)(void)) (tpnt->loadaddr + tpnt->dynamic_info[DT_FINI]);
(*dl_elf_fini) ();
}
@@ -524,6 +533,12 @@ static int do_dlclose(void *vhandle, int need_fini)
return 0;
}
+int _dlclose(void *vhandle)
+{
+ return do_dlclose(vhandle, 1);
+}
+weak_alias(_dlclose, dlclose);
+
const char *_dlerror(void)
{
const char *retval;
@@ -534,6 +549,7 @@ const char *_dlerror(void)
_dl_error_number = 0;
return retval;
}
+weak_alias(_dlerror, dlerror);
/*
* Dump information to stderrr about the current loaded modules
@@ -547,8 +563,8 @@ void _dlinfo(void)
_dl_dprintf(2, "List of loaded modules\n");
/* First start with a complete list of all of the loaded files. */
- for (tpnt = _dl_loaded_modules; tpnt; tpnt = tpnt->next) {
- _dl_dprintf(2, "\t%x %x %x %s %d %s\n",
+ for (tpnt = _dl_loaded_modules; tpnt; tpnt = tpnt->next) {
+ _dl_dprintf(2, "\t%x %x %x %s %d %s\n",
(unsigned) tpnt->loadaddr, (unsigned) tpnt,
(unsigned) tpnt->symbol_scope,
type[tpnt->libtype],
@@ -564,10 +580,11 @@ void _dlinfo(void)
for (hpnt = _dl_handles; hpnt; hpnt = hpnt->next_handle) {
_dl_dprintf(2, "Modules for handle %x\n", (unsigned) hpnt);
for (rpnt = hpnt; rpnt; rpnt = rpnt->next)
- _dl_dprintf(2, "\t%x %s\n", (unsigned) rpnt->dyn,
+ _dl_dprintf(2, "\t%x %s\n", (unsigned) rpnt->dyn,
rpnt->dyn->libname);
}
}
+weak_alias(_dlinfo, dlinfo);
int _dladdr(void *__address, Dl_info * __dlip)
{
@@ -590,7 +607,7 @@ int _dladdr(void *__address, Dl_info * __dlip)
tpnt = rpnt;
#if 0
- _dl_dprintf(2, "Module \"%s\" at %x\n",
+ _dl_dprintf(2, "Module \"%s\" at %x\n",
tpnt->libname, tpnt->loadaddr);
#endif
if (tpnt->loadaddr < (ElfW(Addr)) __address
@@ -631,7 +648,7 @@ int _dladdr(void *__address, Dl_info * __dlip)
sf = 1;
}
#if 0
- _dl_dprintf(2, "Symbol \"%s\" at %x\n",
+ _dl_dprintf(2, "Symbol \"%s\" at %x\n",
strtab + symtab[si].st_name, symbol_addr);
#endif
}
@@ -646,3 +663,4 @@ int _dladdr(void *__address, Dl_info * __dlip)
return 1;
}
}
+weak_alias(_dladdr, dladdr);