diff options
Diffstat (limited to 'elf')
-rw-r--r-- | elf/Makefile | 30 | ||||
-rw-r--r-- | elf/dl-close.c | 13 | ||||
-rw-r--r-- | elf/dl-open.c | 42 | ||||
-rw-r--r-- | elf/loadtest.c | 114 | ||||
-rw-r--r-- | elf/testobj1.c | 11 | ||||
-rw-r--r-- | elf/testobj2.c | 11 | ||||
-rw-r--r-- | elf/testobj3.c | 11 |
7 files changed, 223 insertions, 9 deletions
diff --git a/elf/Makefile b/elf/Makefile index 81aa217..e029fba 100644 --- a/elf/Makefile +++ b/elf/Makefile @@ -1,4 +1,4 @@ -# Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc. +# Copyright (C) 1995, 1996, 1997, 1998, 1999 Free Software Foundation, Inc. # This file is part of the GNU C Library. # The GNU C Library is free software; you can redistribute it and/or @@ -75,6 +75,8 @@ others += ldconfig install-rootsbin += ldconfig endif +tests = loadtest + include ../Rules @@ -200,6 +202,32 @@ else $(objpfx)sprof: $(objpfx)libdl.a endif +# This macro is similar to build-shlib but it does not define a soname +# and it does not depend on the destination name to start with `lib'. +define build-module +$(LINK.o) -shared -o $@ $(sysdep-LDFLAGS) $(config-LDFLAGS) \ + -B$(csu-objpfx) $(load-map-file) \ + $(LDFLAGS.so) $(LDFLAGS-$(@F:%.so=%).so) \ + -L$(subst :, -L,$(rpath-link)) -Wl,-rpath-link=$(rpath-link) \ + -Wl,--whole-archive -Wl,-soname,$(@F) \ + $(filter-out $(map-file) $(+preinit) $(+postinit),$^) \ + $(no-whole-archive) $(LDLIBS-$(@F:%.so=%).so) +endef + +modules-names = testobj1 testobj2 testobj3 +test-modules = $(addprefix $(objpfx),$(addsuffix .so,$(modules-names))) + +$(objpfx)testobj2.so: $(objpfx)testobj1.so +LDLIBS-testobj2.so = $(objpfx)testobj1.so + +$(test-modules): $(objpfx)%.so: %.c + $(build-module) + +$(objpfx)loadtest: $(objpfx)libdl.so +LDFLAGS-loadtest = -rdynamic + +$(objpfx)loadtest.out: $(test-modules) + # muwahaha LDFLAGS-dl.so = -Wl,-dynamic-linker,$(slibdir)/$(rtld-installed-name) diff --git a/elf/dl-close.c b/elf/dl-close.c index 0fbeecc..6a68651 100644 --- a/elf/dl-close.c +++ b/elf/dl-close.c @@ -1,5 +1,5 @@ /* Close a shared object opened by `_dl_open'. - Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc. + Copyright (C) 1996, 1997, 1998, 1999 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -108,12 +108,11 @@ _dl_close (struct link_map *map) do --cnt; while (_dl_main_searchlist->r_list[cnt] != imap); - while (cnt < _dl_main_searchlist->r_nlist) - { - _dl_main_searchlist->r_list[0] - = _dl_main_searchlist->r_list[1]; - ++cnt; - } + + while (++cnt < _dl_main_searchlist->r_nlist) + _dl_main_searchlist->r_list[cnt - 1] + = _dl_main_searchlist->r_list[cnt]; + --_dl_main_searchlist->r_nlist; if (_dl_main_searchlist->r_nlist == _dl_initial_searchlist.r_nlist) diff --git a/elf/dl-open.c b/elf/dl-open.c index 8cf1084..3db2b0e 100644 --- a/elf/dl-open.c +++ b/elf/dl-open.c @@ -1,5 +1,5 @@ /* Load a shared object at runtime, relocate it, and run its initializer. - Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc. + Copyright (C) 1996, 1997, 1998, 1999 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -42,6 +42,11 @@ extern char **__libc_argv; extern char **__environ; +/* Undefine the following for debugging. */ +/* #define SCOPE_DEBUG 1 */ +#ifdef SCOPE_DEBUG +static void show_scope (struct link_map *new); +#endif /* During the program run we must not modify the global data of loaded shared object simultanously in two threads. Therefore we @@ -86,6 +91,10 @@ dl_open_worker (void *a) /* So far, so good. Now check the versions. */ (void) _dl_check_all_versions (new, 0); +#ifdef SCOPE_DEBUG + show_scope (new); +#endif + /* Relocate the objects loaded. We do this in reverse order so that copy relocs of earlier objects overwrite the data written by later objects. */ @@ -195,3 +204,34 @@ _dl_open (const char *file, int mode) return args.map; } + + +#ifdef SCOPE_DEBUG +#include <unistd.h> + +static void +show_scope (struct link_map *new) +{ + int scope_cnt; + + for (scope_cnt = 0; new->l_scope[scope_cnt] != NULL; ++scope_cnt) + { + char numbuf[2]; + unsigned int cnt; + + numbuf[0] = '0' + scope_cnt; + numbuf[1] = '\0'; + _dl_sysdep_message ("scope ", numbuf, ":", NULL); + + for (cnt = 0; cnt < new->l_scope[scope_cnt]->r_nlist; ++cnt) + if (*new->l_scope[scope_cnt]->r_list[cnt]->l_name) + _dl_sysdep_message (" ", + new->l_scope[scope_cnt]->r_list[cnt]->l_name, + NULL); + else + _dl_sysdep_message (" <main>", NULL); + + _dl_sysdep_message ("\n", NULL); + } +} +#endif diff --git a/elf/loadtest.c b/elf/loadtest.c new file mode 100644 index 0000000..209f420 --- /dev/null +++ b/elf/loadtest.c @@ -0,0 +1,114 @@ +#include <assert.h> +#include <dlfcn.h> +#include <errno.h> +#include <error.h> +#include <stdio.h> +#include <stdlib.h> + + +/* How many load/unload operations do we do. */ +#define TEST_ROUNDS 100 + + +static struct +{ + /* Name of the module. */ + const char *name; + /* The handle. */ + void *handle; +} testobjs[] = +{ + { "testobj1.so", NULL }, + { "testobj2.so", NULL }, + { "testobj3.so", NULL }, +}; +#define NOBJS (sizeof (testobjs) / sizeof (testobjs[0])) + + +static const struct +{ + /* Name of a function to call. */ + const char *fname; + /* Index in status and handle array. */ + int index; + /* Options while loading the module. */ + int options; +} tests[] = +{ + { "obj1func2", 0, RTLD_LAZY }, + { "obj1func1", 0, RTLD_LAZY | RTLD_GLOBAL }, + { "obj1func1", 0, RTLD_NOW, }, + { "obj1func2", 0, RTLD_NOW | RTLD_GLOBAL }, + { "obj2func2", 1, RTLD_LAZY }, + { "obj2func1", 1, RTLD_LAZY | RTLD_GLOBAL, }, + { "obj2func1", 1, RTLD_NOW, }, + { "obj2func2", 1, RTLD_NOW | RTLD_GLOBAL }, + { "obj3func2", 2, RTLD_LAZY }, + { "obj3func1", 2, RTLD_LAZY | RTLD_GLOBAL }, + { "obj3func1", 2, RTLD_NOW }, + { "obj3func2", 2, RTLD_NOW | RTLD_GLOBAL }, +}; +#define NTESTS (sizeof (tests) / sizeof (tests[0])) + + +int +main (void) +{ + int count = TEST_ROUNDS; + + /* Just a seed. */ + srandom (TEST_ROUNDS); + + while (count--) + { + int nr = random () % NTESTS; + int index = tests[nr].index; + + printf ("%4d: %4d: ", count + 1, nr); + fflush (stdout); + + if (testobjs[index].handle == NULL) + { + int (*fct) (int); + + /* Load the object. */ + testobjs[index].handle = dlopen (testobjs[index].name, + tests[nr].options); + if (testobjs[index].handle == NULL) + error (EXIT_FAILURE, 0, "cannot load `%s': %s", + testobjs[index].name, dlerror ()); + + /* Test the function call. */ + fct = dlsym (testobjs[index].handle, tests[nr].fname); + if (fct == NULL) + error (EXIT_FAILURE, 0, + "cannot get function `%s' from shared object `%s': %s", + tests[nr].fname, testobjs[index].name, dlerror ()); + + fct (10); + + printf ("successfully loaded `%s'\n", testobjs[index].name); + } + else + { + dlclose (testobjs[index].handle); + testobjs[index].handle = NULL; + + printf ("successfully unloaded `%s'\n", testobjs[index].name); + } + } + + /* Unload all loaded modules. */ + for (count = 0; count < NOBJS; ++count) + if (testobjs[count].handle != NULL) + dlclose (testobjs[count].handle); + + return 0; +} + + +int +foo (int a) +{ + return a - 1; +} diff --git a/elf/testobj1.c b/elf/testobj1.c new file mode 100644 index 0000000..9f64d67 --- /dev/null +++ b/elf/testobj1.c @@ -0,0 +1,11 @@ +int +obj1func1 (int a __attribute__ ((unused))) +{ + return 42; +} + +int +obj1func2 (int a) +{ + return foo (a) + 10; +} diff --git a/elf/testobj2.c b/elf/testobj2.c new file mode 100644 index 0000000..5c89d33 --- /dev/null +++ b/elf/testobj2.c @@ -0,0 +1,11 @@ +int +obj2func1 (int a __attribute__ ((unused))) +{ + return 43; +} + +int +obj2func2 (int a) +{ + return obj1func1 (a) + 10; +} diff --git a/elf/testobj3.c b/elf/testobj3.c new file mode 100644 index 0000000..8e3d886 --- /dev/null +++ b/elf/testobj3.c @@ -0,0 +1,11 @@ +int +obj3func1 (int a __attribute__ ((unused))) +{ + return 44; +} + +int +obj3func2 (int a) +{ + return foo (a) + 42; +} |