1
0
mirror of https://sourceware.org/git/glibc.git synced 2025-07-30 22:43:12 +03:00
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>
This commit is contained in:
Ulrich Drepper
2004-10-14 02:08:23 +00:00
parent 8e9185fb1c
commit c0f62c5678
37 changed files with 1101 additions and 483 deletions

View File

@ -72,6 +72,8 @@ struct dl_open_args
/* This is the caller if _dl_open(). */
const void *caller_dl_open;
struct link_map *map;
/* Namespace ID. */
Lmid_t nsid;
};
@ -101,15 +103,17 @@ add_to_global (struct link_map *new)
in an realloc() call. Therefore we allocate a completely new
array the first time we have to add something to the locale scope. */
if (GL(dl_global_scope_alloc) == 0)
if (GL(dl_ns)[new->l_ns]._ns_global_scope_alloc == 0)
{
/* This is the first dynamic object given global scope. */
GL(dl_global_scope_alloc) = GL(dl_main_searchlist)->r_nlist + to_add + 8;
GL(dl_ns)[new->l_ns]._ns_global_scope_alloc
= GL(dl_ns)[new->l_ns]._ns_main_searchlist->r_nlist + to_add + 8;
new_global = (struct link_map **)
malloc (GL(dl_global_scope_alloc) * sizeof (struct link_map *));
malloc (GL(dl_ns)[new->l_ns]._ns_global_scope_alloc
* sizeof (struct link_map *));
if (new_global == NULL)
{
GL(dl_global_scope_alloc) = 0;
GL(dl_ns)[new->l_ns]._ns_global_scope_alloc = 0;
nomem:
GLRO(dl_signal_error) (ENOMEM, new->l_libname->name, NULL,
N_("cannot extend global scope"));
@ -117,25 +121,26 @@ add_to_global (struct link_map *new)
}
/* Copy over the old entries. */
memcpy (new_global, GL(dl_main_searchlist)->r_list,
(GL(dl_main_searchlist)->r_nlist * sizeof (struct link_map *)));
GL(dl_main_searchlist)->r_list = new_global;
GL(dl_ns)[new->l_ns]._ns_main_searchlist->r_list
= memcpy (new_global,
GL(dl_ns)[new->l_ns]._ns_main_searchlist->r_list,
(GL(dl_ns)[new->l_ns]._ns_main_searchlist->r_nlist
* sizeof (struct link_map *)));
}
else if (GL(dl_main_searchlist)->r_nlist + to_add
> GL(dl_global_scope_alloc))
else if (GL(dl_ns)[new->l_ns]._ns_main_searchlist->r_nlist + to_add
> GL(dl_ns)[new->l_ns]._ns_global_scope_alloc)
{
/* We have to extend the existing array of link maps in the
main map. */
new_global = (struct link_map **)
realloc (GL(dl_main_searchlist)->r_list,
((GL(dl_global_scope_alloc) + to_add + 8)
realloc (GL(dl_ns)[new->l_ns]._ns_main_searchlist->r_list,
((GL(dl_ns)[new->l_ns]._ns_global_scope_alloc + to_add + 8)
* sizeof (struct link_map *)));
if (new_global == NULL)
goto nomem;
GL(dl_global_scope_alloc) += to_add + 8;
GL(dl_main_searchlist)->r_list = new_global;
GL(dl_ns)[new->l_ns]._ns_global_scope_alloc += to_add + 8;
GL(dl_ns)[new->l_ns]._ns_main_searchlist->r_list = new_global;
}
/* Now add the new entries. */
@ -146,9 +151,9 @@ add_to_global (struct link_map *new)
if (map->l_global == 0)
{
map->l_global = 1;
GL(dl_main_searchlist)->r_list[GL(dl_main_searchlist)->r_nlist]
GL(dl_ns)[new->l_ns]._ns_main_searchlist->r_list[GL(dl_ns)[new->l_ns]._ns_main_searchlist->r_nlist]
= map;
++GL(dl_main_searchlist)->r_nlist;
++GL(dl_ns)[new->l_ns]._ns_main_searchlist->r_nlist;
}
}
@ -175,28 +180,34 @@ dl_open_worker (void *a)
GLRO(dl_signal_error) (0, "dlopen", NULL, N_("invalid caller"));
/* Determine the caller's map if necessary. This is needed in case
we have a DST or when the file name has no path in which case we
need to look along the RUNPATH/RPATH of the caller. */
we have a DST, when we don't know the namespace ID we have to put
the new object in, or when the file name has no path in which
case we need to look along the RUNPATH/RPATH of the caller. */
const char *dst = strchr (file, '$');
if (dst != NULL || strchr (file, '/') == NULL)
if (dst != NULL || args->nsid == __LM_ID_CALLER
|| strchr (file, '/') == NULL)
{
const void *caller_dlopen = args->caller_dlopen;
/* We have to find out from which object the caller is calling. */
call_map = NULL;
for (l = GL(dl_loaded); l; l = l->l_next)
if (caller_dlopen >= (const void *) l->l_map_start
&& caller_dlopen < (const void *) l->l_map_end)
{
/* There must be exactly one DSO for the range of the virtual
memory. Otherwise something is really broken. */
call_map = l;
break;
}
/* We have to find out from which object the caller is calling.
By default we assume this is the main application. */
call_map = GL(dl_ns)[LM_ID_BASE]._ns_loaded;
if (call_map == NULL)
/* In this case we assume this is the main application. */
call_map = GL(dl_loaded);
for (Lmid_t ns = 0; ns < DL_NNS; ++ns)
for (l = GL(dl_ns)[ns]._ns_loaded; l != NULL; l = l->l_next)
if (caller_dlopen >= (const void *) l->l_map_start
&& caller_dlopen < (const void *) l->l_map_end)
{
/* There must be exactly one DSO for the range of the virtual
memory. Otherwise something is really broken. */
assert (ns == l->l_ns);
call_map = l;
goto found_caller;
}
found_caller:
if (args->nsid == __LM_ID_CALLER)
args->nsid = call_map->l_ns;
}
/* Maybe we have to expand a DST. */
@ -238,7 +249,7 @@ dl_open_worker (void *a)
/* Load the named object. */
args->map = new = GLRO(dl_map_object) (call_map, file, 0, lt_loaded, 0,
mode | __RTLD_CALLMAP);
mode | __RTLD_CALLMAP, args->nsid);
/* If the pointer returned is NULL this means the RTLD_NOLOAD flag is
set and the object is not already loaded. */
@ -252,21 +263,30 @@ dl_open_worker (void *a)
/* This happens only if we load a DSO for 'sprof'. */
return;
/* This object is directly loaded. */
++new->l_direct_opencount;
/* It was already open. */
if (__builtin_expect (new->l_searchlist.r_list != NULL, 0))
{
/* Let the user know about the opencount. */
if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_FILES, 0))
GLRO(dl_debug_printf) ("opening file=%s; opencount == %u\n\n",
new->l_name, new->l_opencount);
GLRO(dl_debug_printf) ("opening file=%s [%lu]; opencount=%u\n\n",
new->l_name, new->l_ns, new->l_opencount);
/* If the user requested the object to be in the global namespace
but it is not so far, add it now. */
if ((mode & RTLD_GLOBAL) && new->l_global == 0)
(void) add_to_global (new);
/* Increment just the reference counter of the object. */
++new->l_opencount;
if (new->l_direct_opencount == 1)
/* This is the only direct reference. Increment all the
dependencies' reference counter. */
for (i = 0; i < new->l_searchlist.r_nlist; ++i)
++new->l_searchlist.r_list[i]->l_opencount;
else
/* Increment just the reference counter of the object. */
++new->l_opencount;
return;
}
@ -277,8 +297,9 @@ dl_open_worker (void *a)
/* So far, so good. Now check the versions. */
for (i = 0; i < new->l_searchlist.r_nlist; ++i)
if (new->l_searchlist.r_list[i]->l_versions == NULL)
(void) GLRO(dl_check_map_versions) (new->l_searchlist.r_list[i], 0, 0);
if (new->l_searchlist.r_list[i]->l_real->l_versions == NULL)
(void) GLRO(dl_check_map_versions) (new->l_searchlist.r_list[i]->l_real,
0, 0);
#ifdef SCOPE_DEBUG
show_scope (new);
@ -295,7 +316,7 @@ dl_open_worker (void *a)
l = l->l_next;
while (1)
{
if (! l->l_relocated)
if (! l->l_real->l_relocated)
{
#ifdef SHARED
if (GLRO(dl_profile) != NULL)
@ -349,7 +370,7 @@ dl_open_worker (void *a)
loaded object to the scope. */
for (i = 0; i < new->l_searchlist.r_nlist; ++i)
if (++new->l_searchlist.r_list[i]->l_opencount > 1
&& new->l_searchlist.r_list[i]->l_type == lt_loaded)
&& new->l_real->l_searchlist.r_list[i]->l_type == lt_loaded)
{
struct link_map *imap = new->l_searchlist.r_list[i];
struct r_scope_elem **runp = imap->l_scope;
@ -503,14 +524,14 @@ cannot create TLS data structures"));
/* Let the user know about the opencount. */
if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_FILES, 0))
GLRO(dl_debug_printf) ("opening file=%s; opencount == %u\n\n",
new->l_name, new->l_opencount);
GLRO(dl_debug_printf) ("opening file=%s [%lu]; opencount=%u\n\n",
new->l_name, new->l_ns, new->l_opencount);
}
void *
internal_function
_dl_open (const char *file, int mode, const void *caller_dlopen)
_dl_open (const char *file, int mode, const void *caller_dlopen, Lmid_t nsid)
{
struct dl_open_args args;
const char *objname;
@ -525,11 +546,29 @@ _dl_open (const char *file, int mode, const void *caller_dlopen)
/* Make sure we are alone. */
__rtld_lock_lock_recursive (GL(dl_load_lock));
if (nsid == LM_ID_NEWLM)
{
/* Find a new namespace. */
for (nsid = 1; nsid < DL_NNS; ++nsid)
if (GL(dl_ns)[nsid]._ns_loaded == NULL)
break;
if (nsid == DL_NNS)
{
/* No more namespace available. */
__rtld_lock_unlock_recursive (GL(dl_load_lock));
GLRO(dl_signal_error) (EINVAL, file, NULL, N_("\
no more namespaces available for dlmopen()"));
}
}
args.file = file;
args.mode = mode;
args.caller_dlopen = caller_dlopen;
args.caller_dl_open = RETURN_ADDRESS (0);
args.map = NULL;
args.nsid = nsid;
errcode = GLRO(dl_catch_error) (&objname, &errstring, dl_open_worker, &args);
#ifndef MAP_COPY