diff options
Diffstat (limited to 'elf')
-rw-r--r-- | elf/Makefile | 8 | ||||
-rw-r--r-- | elf/dl-close.c | 3 | ||||
-rw-r--r-- | elf/dl-iteratephdr.c | 6 | ||||
-rw-r--r-- | elf/dl-object.c | 3 | ||||
-rw-r--r-- | elf/dl-support.c | 5 | ||||
-rw-r--r-- | elf/link.h | 12 | ||||
-rw-r--r-- | elf/tst-dlmodcount.c | 107 |
7 files changed, 138 insertions, 6 deletions
diff --git a/elf/Makefile b/elf/Makefile index ead590bdc1..42a2279a72 100644 --- a/elf/Makefile +++ b/elf/Makefile @@ -80,7 +80,7 @@ distribute := rtld-Rules \ reldep9.c reldep9mod1.c reldep9mod2.c reldep9mod3.c \ tst-array1.exp tst-array2.exp tst-array4.exp \ tst-array2dep.c \ - tst-execstack-mod.c \ + tst-execstack-mod.c tst-dlmodcount.c \ check-textrel.c dl-sysdep.h CFLAGS-dl-runtime.c = -fexceptions -fasynchronous-unwind-tables @@ -151,7 +151,7 @@ tests += loadtest restest1 preloadtest loadfail multiload origtest resolvfail \ restest2 next dblload dblunload reldep5 reldep6 reldep7 reldep8 \ circleload1 tst-tls3 tst-tls4 tst-tls5 tst-tls6 tst-tls7 tst-tls8 \ tst-tls10 tst-tls11 tst-tls12 tst-tls13 tst-tls14 tst-align \ - $(tests-execstack-$(have-z-execstack)) + $(tests-execstack-$(have-z-execstack)) tst-dlmodcount # reldep9 test-srcs = tst-pathopt tests-vis-yes = vismain @@ -713,4 +713,8 @@ $(objpfx)check-textrel.out: $(objpfx)check-textrel $(sort $(wildcard $(common-objpfx)*/lib*.so \ $(common-objpfx)iconvdata/*.so)) > $@ generated += check-textrel check-textrel.out + +$(objpfx)tst-dlmodcount: $(libdl) +$(objpfx)tst-dlmodcount.out: $(test-modules) + endif diff --git a/elf/dl-close.c b/elf/dl-close.c index b482e89f13..519d3d316f 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-2002, 2003 Free Software Foundation, Inc. + Copyright (C) 1996-2002, 2003, 2004 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 @@ -319,6 +319,7 @@ _dl_close (void *_map) /* Notify the debugger we are about to remove some loaded objects. */ _r_debug.r_state = RT_DELETE; _dl_debug_state (); + ++GL(dl_load_subs); #ifdef USE_TLS size_t tls_free_start; diff --git a/elf/dl-iteratephdr.c b/elf/dl-iteratephdr.c index fd45f8529f..a6df7f21e8 100644 --- a/elf/dl-iteratephdr.c +++ b/elf/dl-iteratephdr.c @@ -1,5 +1,5 @@ /* Get loaded objects program headers. - Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc. + Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Jakub Jelinek <jakub@redhat.com>, 2001. @@ -48,6 +48,8 @@ __dl_iterate_phdr (int (*callback) (struct dl_phdr_info *info, info.dlpi_name = l->l_name; info.dlpi_phdr = l->l_phdr; info.dlpi_phnum = l->l_phnum; + info.dlpi_adds = GL(dl_load_adds); + info.dlpi_subs = GL(dl_load_subs); ret = callback (&info, sizeof (struct dl_phdr_info), data); if (ret) break; @@ -84,6 +86,8 @@ dl_iterate_phdr (int (*callback) (struct dl_phdr_info *info, info.dlpi_name = ""; info.dlpi_phdr = _dl_phdr; info.dlpi_phnum = _dl_phnum; + info.dlpi_adds = GL(dl_load_adds); + info.dlpi_subs = GL(dl_load_subs); ret = (*callback) (&info, sizeof (struct dl_phdr_info), data); if (ret) return ret; diff --git a/elf/dl-object.c b/elf/dl-object.c index a33b40ab5b..52131181b3 100644 --- a/elf/dl-object.c +++ b/elf/dl-object.c @@ -1,5 +1,5 @@ /* Storage management for the chain of loaded shared objects. - Copyright (C) 1995,96,97,98,99,2000,2001,2002 Free Software Foundation, Inc. + Copyright (C) 1995-2002, 2004 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 @@ -83,6 +83,7 @@ _dl_new_object (char *realname, const char *libname, int type, else GL(dl_loaded) = new; ++GL(dl_nloaded); + ++GL(dl_load_adds); /* If we have no loader the new object acts as it. */ if (loader == NULL) diff --git a/elf/dl-support.c b/elf/dl-support.c index aa255b443b..8e5c905566 100644 --- a/elf/dl-support.c +++ b/elf/dl-support.c @@ -71,6 +71,11 @@ struct link_map *_dl_loaded; /* Number of object in the _dl_loaded list. */ unsigned int _dl_nloaded; +/* Incremented whenever something may have been added to dl_loaded. */ +unsigned long long _dl_load_adds; +/* Incremented whenever something may have been removed from dl_loaded. */ +unsigned long long _dl_load_subs; + /* Fake scope. In dynamically linked binaries this is the scope of the main application but here we don't have something like this. So create a fake scope containing nothing. */ diff --git a/elf/link.h b/elf/link.h index 7e2a8f6fee..f6d76bdf35 100644 --- a/elf/link.h +++ b/elf/link.h @@ -1,6 +1,6 @@ /* Data structure for communication from the run-time dynamic linker for loaded ELF shared objects. - Copyright (C) 1995-1999, 2000, 2001 Free Software Foundation, Inc. + Copyright (C) 1995-1999, 2000, 2001, 2004 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 @@ -100,6 +100,16 @@ struct dl_phdr_info const char *dlpi_name; const ElfW(Phdr) *dlpi_phdr; ElfW(Half) dlpi_phnum; + + /* Note: the next two members were introduced after the first + version of this structure was available. Check the SIZE + argument pass to the dl_iterate_phdr() callback to determine + whether or not they are provided. */ + + /* Incremented when a new object may have been added. */ + unsigned long long int dlpi_adds; + /* Incremented when an object may have been removed. */ + unsigned long long int dlpi_subs; }; __BEGIN_DECLS diff --git a/elf/tst-dlmodcount.c b/elf/tst-dlmodcount.c new file mode 100644 index 0000000000..b48ed0e2ae --- /dev/null +++ b/elf/tst-dlmodcount.c @@ -0,0 +1,107 @@ +/* Copyright (C) 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by David Mosberger <davidm@hpl.hp.com>, 2004. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <link.h> +#include <stdio.h> + +#define SET 0 +#define ADD 1 +#define REMOVE 2 + +#define leq(l,r) (((r) - (l)) <= ~0ULL / 2) + +static int +callback (struct dl_phdr_info *info, size_t size, void *ptr) +{ + static int last_adds = 0, last_subs = 0; + intptr_t cmd = (intptr_t) ptr; + + printf (" size = %Zu\n", size); + if (size < (offsetof (struct dl_phdr_info, dlpi_subs) + + sizeof (info->dlpi_subs))) + { + fprintf (stderr, "dl_iterate_phdr failed to pass dlpi_adds/dlpi_subs\n"); + exit (5); + } + + printf (" dlpi_adds = %Lu dlpi_subs = %Lu\n", + info->dlpi_adds, info->dlpi_subs); + + switch (cmd) + { + case SET: + break; + + case ADD: + if (leq (info->dlpi_adds, last_adds)) + { + fprintf (stderr, "dlpi_adds failed to get incremented!\n"); + exit (3); + } + break; + + case REMOVE: + if (leq (info->dlpi_subs, last_subs)) + { + fprintf (stderr, "dlpi_subs failed to get incremented!\n"); + exit (4); + } + break; + } + last_adds = info->dlpi_adds; + last_subs = info->dlpi_subs; + return -1; +} + +static void * +load (const char *path) +{ + void *handle; + + printf ("loading `%s'\n", path); + handle = dlopen (path, RTLD_LAZY); + if (!handle) + exit (1); + dl_iterate_phdr (callback, (void *)(intptr_t) ADD); + return handle; +} + +static void +unload (const char *path, void *handle) +{ + int ret; + + printf ("unloading `%s'\n", path); + if (dlclose (handle) < 0) + exit (2); + dl_iterate_phdr (callback, (void *)(intptr_t) REMOVE); +} + +int +main (int argc, char **argv) +{ + void *handle1, *handle2; + + dl_iterate_phdr (callback, (void *)(intptr_t) SET); + handle1 = load ("firstobj.so"); + handle2 = load ("globalmod1.so"); + unload ("firstobj.so", handle1); + unload ("globalmod1.so", handle2); + return 0; +} |