Skip to content

Commit

Permalink
[BZ #77]
Browse files Browse the repository at this point in the history
Update.
	Add support for namespaces in the dynamic linker.
	* dlfcn/Makefile (libdl-routines): Add dlmopen.
	* dlfcn/Versions [libdl, GLIBC_2.3.4]: Add dlmopen.
	* dlfcn/dlfcn.h: Define Lmid_t, LM_ID_BASE, and LM_ID_NEWLM.
	Declare dlmopen.  Document RTLD_DI_LMID.
	* dlfcn/dlinfo.c: Handle RTLD_DI_LMID.
	* dlfcn/dlmopen.c: New file.
	* dlfcn/dlopen.c: Pass new parameter to _dl_open.
	* dlfcn/dlopenold.c: Likewise.
	* elf/dl-addr.c: Adjust for removal of GL(dl_loaded).
	* elf/dl-caller.c: Likewise.
	* elf/dl-close.c: Likewise.
	* elf/dl-conflict.c: Likewise.
	* elf/dl-debug.c: Likewise.
	* elf/dl-lookup.c: Likewise.
	* elf/dl-sym.c: Likewise.
	* elf/dl-version.c: Likewise.
	* elf/do-lookup.h: Likewise.
	* elf/rtld.c: Likewise.
	* sysdeps/unix/sysv/linux/i386/dl-librecon.h: Likewise.
	* elf/dl-depsc: Likewise.  Add new parameter to _dl_map_object.
	* elf/dl-fini.c: Call destructors in all namespaces.
	* elf/dl-iteratephdr.c: Compute total nloaded.  Adjust for removal of
	GL(dl_loaded).
	* elf/dl-libc.c: Pass new parameter to _dl_open.  Adjust for removal
	of GL(dl_loaded).
	* elf/dl-load.c (_dl_map_object_from_fd): Don't load ld.so a second
	time.  Reuse the one from the main namespace in all others.
	Pass new parameter to _dl_new_object.
	Adjust for removal of GL(dl_loaded).
	* elf/dl-object.c: Take new parameter.  Use it to initialize l_ns.
	Adjust for removal of GL(dl_loaded).
	* elf/dl-open.c (_dl_open): Take new parameter.
	Adjust for removal of GL(dl_loaded).
	* elf/dl-support.c: Replace global _dl_loaded etc variables with
	_dl_ns variable.
	* include/dlfcn.h: Adjust prototype of _dl_open.
	Define __LM_ID_CALLER.
	* include/link.h: Add l_real, l_ns, and l_direct_opencount elements.
	* sysdeps/generic/dl-tls.c: Bump TLS_STATIC_SURPLUS.  Since libc is
	using TLS we need memory appropriate to the number of namespaces.
	* sysdeps/generic/ldsodefs.h (struct rtld_global): Replace _dl_loaded,
	_dl_nloaded, _dl_global_scope, _dl_main_searchlist, and
	_dl_global_scope_alloc with _dl_ns element.  Define DL_NNS.
	Adjust prototypes of _dl_map_object and member in rtld_global_ro.
	* malloc/malloc.c: Include <dlfcn.h>.
	* malloc/arena.c (ptmalloc_init): If libc is not in primary namespace,
	never use brk.
	* elf/Makefile: Add rules to build and run tst-dlmopen1 and
	tst-dlmopen2.
	* elf/tst-dlmopen1.c: New file.
	* elf/tst-dlmopen1mod.c: New file.
	* elf/tst-dlmopen2.c: New file.

	* elf/dl-close.c: Improve reference counting by tracking direct loads.
	* elf/dl-lookup.c (add_dependency): Likewise.
	* elf/dl-open.c (dl_open_worker): Likewise.
	* elf/rtld.c (dl_main): Likewise.

2004-09-09  GOTO Masanori  <gotom@debian.or.jp>

	[BZ #77]
	* elf/dl-close.c: Count down l_opencount to check not only for
	l_reldeps, but also l_initfini.

2004-10-13  Ulrich Drepper  <drepper@redhat.com>
  • Loading branch information
Ulrich Drepper committed Oct 14, 2004
1 parent 8e9185f commit c0f62c5
Show file tree
Hide file tree
Showing 37 changed files with 1,108 additions and 490 deletions.
67 changes: 67 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
@@ -1,3 +1,70 @@
2004-10-13 Ulrich Drepper <drepper@redhat.com>

Add support for namespaces in the dynamic linker.
* dlfcn/Makefile (libdl-routines): Add dlmopen.
* dlfcn/Versions [libdl, GLIBC_2.3.4]: Add dlmopen.
* dlfcn/dlfcn.h: Define Lmid_t, LM_ID_BASE, and LM_ID_NEWLM.
Declare dlmopen. Document RTLD_DI_LMID.
* dlfcn/dlinfo.c: Handle RTLD_DI_LMID.
* dlfcn/dlmopen.c: New file.
* dlfcn/dlopen.c: Pass new parameter to _dl_open.
* dlfcn/dlopenold.c: Likewise.
* elf/dl-addr.c: Adjust for removal of GL(dl_loaded).
* elf/dl-caller.c: Likewise.
* elf/dl-close.c: Likewise.
* elf/dl-conflict.c: Likewise.
* elf/dl-debug.c: Likewise.
* elf/dl-lookup.c: Likewise.
* elf/dl-sym.c: Likewise.
* elf/dl-version.c: Likewise.
* elf/do-lookup.h: Likewise.
* elf/rtld.c: Likewise.
* sysdeps/unix/sysv/linux/i386/dl-librecon.h: Likewise.
* elf/dl-depsc: Likewise. Add new parameter to _dl_map_object.
* elf/dl-fini.c: Call destructors in all namespaces.
* elf/dl-iteratephdr.c: Compute total nloaded. Adjust for removal of
GL(dl_loaded).
* elf/dl-libc.c: Pass new parameter to _dl_open. Adjust for removal
of GL(dl_loaded).
* elf/dl-load.c (_dl_map_object_from_fd): Don't load ld.so a second
time. Reuse the one from the main namespace in all others.
Pass new parameter to _dl_new_object.
Adjust for removal of GL(dl_loaded).
* elf/dl-object.c: Take new parameter. Use it to initialize l_ns.
Adjust for removal of GL(dl_loaded).
* elf/dl-open.c (_dl_open): Take new parameter.
Adjust for removal of GL(dl_loaded).
* elf/dl-support.c: Replace global _dl_loaded etc variables with
_dl_ns variable.
* include/dlfcn.h: Adjust prototype of _dl_open.
Define __LM_ID_CALLER.
* include/link.h: Add l_real, l_ns, and l_direct_opencount elements.
* sysdeps/generic/dl-tls.c: Bump TLS_STATIC_SURPLUS. Since libc is
using TLS we need memory appropriate to the number of namespaces.
* sysdeps/generic/ldsodefs.h (struct rtld_global): Replace _dl_loaded,
_dl_nloaded, _dl_global_scope, _dl_main_searchlist, and
_dl_global_scope_alloc with _dl_ns element. Define DL_NNS.
Adjust prototypes of _dl_map_object and member in rtld_global_ro.
* malloc/malloc.c: Include <dlfcn.h>.
* malloc/arena.c (ptmalloc_init): If libc is not in primary namespace,
never use brk.
* elf/Makefile: Add rules to build and run tst-dlmopen1 and
tst-dlmopen2.
* elf/tst-dlmopen1.c: New file.
* elf/tst-dlmopen1mod.c: New file.
* elf/tst-dlmopen2.c: New file.

* elf/dl-close.c: Improve reference counting by tracking direct loads.
* elf/dl-lookup.c (add_dependency): Likewise.
* elf/dl-open.c (dl_open_worker): Likewise.
* elf/rtld.c (dl_main): Likewise.

2004-09-09 GOTO Masanori <gotom@debian.or.jp>

[BZ #77]
* elf/dl-close.c: Count down l_opencount to check not only for
l_reldeps, but also l_initfini.

2004-10-13 Ulrich Drepper <drepper@redhat.com>

* elf/dl-close.c (_dl_close): Update bug reporting instructions.
Expand Down
3 changes: 2 additions & 1 deletion dlfcn/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@
subdir := dlfcn
headers := bits/dlfcn.h dlfcn.h
extra-libs := libdl
libdl-routines := dlopen dlclose dlsym dlvsym dlerror dladdr dladdr1 dlinfo
libdl-routines := dlopen dlclose dlsym dlvsym dlerror dladdr dladdr1 dlinfo \
dlmopen
distribute := dlopenold.c glreflib1.c glreflib2.c failtestmod.c \
defaultmod1.c defaultmod2.c errmsg1mod.c modatexit.c \
modcxaatexit.c modstatic.c \
Expand Down
3 changes: 3 additions & 0 deletions dlfcn/Versions
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,7 @@ libdl {
GLIBC_2.3.3 {
dladdr1; dlinfo;
}
GLIBC_2.3.4 {
dlmopen;
}
}
17 changes: 15 additions & 2 deletions dlfcn/dlfcn.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* User functions for run-time dynamic loading.
Copyright (C) 1995-1999,2000,2001,2003 Free Software Foundation, Inc.
Copyright (C) 1995-1999,2000,2001,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
Expand Down Expand Up @@ -39,6 +39,14 @@
the run-time address of the symbol called NAME in the global scope
is returned. */
# define RTLD_DEFAULT ((void *) 0)


/* Type for namespace indeces. */
typedef long int Lmid_t;

/* Special namespace ID values. */
# define LM_ID_BASE 0 /* Initial namespace. */
# define LM_ID_NEWLM -1 /* For dlmopen: request new namespace. */
#endif


Expand All @@ -58,6 +66,9 @@ extern void *dlsym (void *__restrict __handle,
__const char *__restrict __name) __THROW;

#ifdef __USE_GNU
/* Like `dlopen', but request object to be allocated in a new namespace. */
extern void *dlmopen (Lmid_t __nsid, __const char *__file, int __mode) __THROW;

/* Find the run-time address in the shared object HANDLE refers to
of the symbol called NAME with VERSION. */
extern void *dlvsym (void *__restrict __handle,
Expand Down Expand Up @@ -114,6 +125,9 @@ extern int dlinfo (void *__restrict __handle,
/* These are the possible values for the REQUEST argument to `dlinfo'. */
enum
{
/* Treat ARG as `lmid_t *'; store namespace ID for HANDLE there. */
RTLD_DI_LMID = 1,

/* Treat ARG as `struct link_map **';
store the `struct link_map *' for HANDLE there. */
RTLD_DI_LINKMAP = 2,
Expand All @@ -130,7 +144,6 @@ enum
expand $ORIGIN in this shared object's dependency file names. */
RTLD_DI_ORIGIN = 6,

RTLD_DI_LMID = 1, /* Unsupported, defined by Solaris. */
RTLD_DI_CONFIGADDR = 3 /* Unsupported, defined by Solaris. */
};

Expand Down
5 changes: 4 additions & 1 deletion dlfcn/dlinfo.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,12 +55,15 @@ RTLD_SELF used in code not dynamically loaded"));

switch (args->request)
{
case RTLD_DI_LMID:
case RTLD_DI_CONFIGADDR:
default:
GLRO(dl_signal_error) (0, NULL, NULL, N_("unsupported dlinfo request"));
break;

case RTLD_DI_LMID:
*(Lmid_t *) args->arg = l->l_ns;
break;

case RTLD_DI_LINKMAP:
*(struct link_map **) args->arg = l;
break;
Expand Down
69 changes: 69 additions & 0 deletions dlfcn/dlmopen.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/* Load a shared object at run time.
Copyright (C) 1995,96,97,98,99,2000,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
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 <dlfcn.h>
#include <errno.h>
#include <libintl.h>
#include <stddef.h>
#include <ldsodefs.h>

struct dlmopen_args
{
/* Namespace ID. */
Lmid_t nsid;
/* The arguments for dlopen_doit. */
const char *file;
int mode;
/* The return value of dlopen_doit. */
void *new;
/* Address of the caller. */
const void *caller;
};

static void
dlmopen_doit (void *a)
{
struct dlmopen_args *args = (struct dlmopen_args *) a;

/* Non-shared code has no support for multiple namespaces. */
if (args->nsid != LM_ID_BASE)
#ifdef SHARED
/* If trying to open the link map for the main executable the namespace
must be the main one. */
if (args->file == NULL)
#endif
GLRO(dl_signal_error) (EINVAL, NULL, NULL, N_("invalid namespace"));

args->new = _dl_open (args->file ?: "", args->mode | __RTLD_DLOPEN,
args->caller, args->nsid);
}


void *
dlmopen (Lmid_t nsid, const char *file, int mode)
{
struct dlmopen_args args;
args.nsid = nsid;
args.file = file;
args.mode = mode;
args.caller = RETURN_ADDRESS (0);

return _dlerror_run (dlmopen_doit, &args) ? NULL : args.new;
}
static_link_warning (dlmopen)
13 changes: 11 additions & 2 deletions dlfcn/dlopen.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* Load a shared object at run time.
Copyright (C) 1995,96,97,98,99,2000,2003 Free Software Foundation, Inc.
Copyright (C) 1995,96,97,98,99,2000,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
Expand Down Expand Up @@ -31,13 +31,22 @@ struct dlopen_args
const void *caller;
};


/* Non-shared code has no support for multiple namespaces. */
#ifdef SHARED
# define NS __LM_ID_CALLER
#else
# define NS LM_ID_BASE
#endif


static void
dlopen_doit (void *a)
{
struct dlopen_args *args = (struct dlopen_args *) a;

args->new = _dl_open (args->file ?: "", args->mode | __RTLD_DLOPEN,
args->caller);
args->caller, args->file == NULL ? LM_ID_BASE : NS);
}


Expand Down
12 changes: 10 additions & 2 deletions dlfcn/dlopenold.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* Load a shared object at run time.
Copyright (C) 1995-1999, 2000 Free Software Foundation, Inc.
Copyright (C) 1995-1999, 2000, 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
Expand Down Expand Up @@ -37,13 +37,21 @@ struct dlopen_args
};


/* Non-shared code has no support for multiple namespaces. */
#ifdef SHARED
# define NS __LM_ID_CALLER
#else
# define NS LM_ID_BASE
#endif


static void
dlopen_doit (void *a)
{
struct dlopen_args *args = (struct dlopen_args *) a;

args->new = _dl_open (args->file ?: "", args->mode | __RTLD_DLOPEN,
args->caller);
args->caller, args->file == NULL ? LM_ID_BASE : NS);
}

extern void *__dlopen_nocheck (const char *file, int mode);
Expand Down
12 changes: 10 additions & 2 deletions elf/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ tests += loadtest restest1 preloadtest loadfail multiload origtest resolvfail \
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)) tst-dlmodcount \
tst-dlopenrpath tst-deep1
tst-dlopenrpath tst-deep1 tst-dlmopen1 tst-dlmopen2
# reldep9
test-srcs = tst-pathopt
tests-vis-yes = vismain
Expand Down Expand Up @@ -187,7 +187,8 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \
reldep8mod1 reldep8mod2 reldep8mod3 \
reldep9mod1 reldep9mod2 reldep9mod3 \
tst-alignmod $(modules-execstack-$(have-z-execstack)) \
tst-dlopenrpathmod tst-deep1mod1 tst-deep1mod2 tst-deep1mod3
tst-dlopenrpathmod tst-deep1mod1 tst-deep1mod2 tst-deep1mod3 \
tst-dlmopen1mod
ifeq (yes,$(have-initfini-array))
modules-names += tst-array2dep
endif
Expand Down Expand Up @@ -762,3 +763,10 @@ $(objpfx)tst-deep1: $(libdl) $(objpfx)tst-deep1mod1.so
$(objpfx)tst-deep1.out: $(objpfx)tst-deep1mod2.so
LDFLAGS-tst-deep1 += -rdynamic
tst-deep1mod3.so-no-z-defs = yes

$(objpfx)tst-dlmopen1mod.so: $(libdl)
$(objpfx)tst-dlmopen1: $(libdl)
$(objpfx)tst-dlmopen1.out: $(objpfx)tst-dlmopen1mod.so

$(objpfx)tst-dlmopen2: $(libdl)
$(objpfx)tst-dlmopen2.out: $(objpfx)tst-dlmopen1mod.so
41 changes: 21 additions & 20 deletions elf/dl-addr.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,26 +38,27 @@ _dl_addr (const void *address, Dl_info *info,

/* Find the highest-addressed object that ADDRESS is not below. */
match = NULL;
for (struct link_map *l = GL(dl_loaded); l; l = l->l_next)
if (addr >= l->l_map_start && addr < l->l_map_end)
{
/* We know ADDRESS lies within L if in any shared object.
Make sure it isn't past the end of L's segments. */
size_t n = l->l_phnum;
if (n > 0)
{
do
--n;
while (l->l_phdr[n].p_type != PT_LOAD);
if (addr >= (l->l_addr +
l->l_phdr[n].p_vaddr + l->l_phdr[n].p_memsz))
/* Off the end of the highest-addressed shared object. */
continue;
}

match = l;
break;
}
for (Lmid_t ns = 0; ns < DL_NNS; ++ns)
for (struct link_map *l = GL(dl_ns)[ns]._ns_loaded; l; l = l->l_next)
if (addr >= l->l_map_start && addr < l->l_map_end)
{
/* We know ADDRESS lies within L if in any shared object.
Make sure it isn't past the end of L's segments. */
size_t n = l->l_phnum;
if (n > 0)
{
do
--n;
while (l->l_phdr[n].p_type != PT_LOAD);
if (addr >= (l->l_addr +
l->l_phdr[n].p_vaddr + l->l_phdr[n].p_memsz))
/* Off the end of the highest-addressed shared object. */
continue;
}

match = l;
break;
}

int result = 0;
if (match != NULL)
Expand Down
Loading

0 comments on commit c0f62c5

Please sign in to comment.