* elf/elf.h: Add various DF_1_*, DTF_1_*, and DF_P1_* entries.
	* elf/dl-close.c (_dl_close): Don't close an object if it is marked
	with nodelete.
	* elf/dl-open.c (dl_open_worker): Pass RTLD_NOLOAD as new parameter
	to _dl_map_object.  Return immediately if no object loaded.
	Set DF_1_NODELETE bit in l_flags_1 if RTLD_NODELETE was passed.
	* elf/dynamic-link.h (elf_get_dynamic_info): Copy DT_FLAGS_1 entry
	if it exists into l_flags_1 word.
	* elf/dl-load.c (_dl_map_object_from_fd): Take no parameter and use
	it to determine whether loading is wanted or not.
	(_dl_map_object): Likewise.
	Call _dl_map_object_from_fd with new parameter.
	* sysdeps/generic/ldsodefs.h: Update prototype.
	* elf/dl-deps.c: Add new parameter to _dl_map_object calls.
	* elf/rtld.c: Likewise.
	* elf/Makefile (tests): Add noload.  Add rules to generate noload.
	* elf/noload.c: New file.
	* include/link.h (struct link_map): Add l_feature_1 and l_flags_1.
	* sysdeps/generic/bits/dlfcn.h: Define RTLD_NOLOAD and RTLD_NODELETE.
	* sysdeps/mips/bits/dlfcn.h: Likewise.
This commit is contained in:
Ulrich Drepper 2000-07-20 22:53:54 +00:00
parent 5e61ef8848
commit bf8b3e74bf
14 changed files with 179 additions and 27 deletions

View File

@ -1,5 +1,26 @@
2000-07-20 Ulrich Drepper <drepper@redhat.com> 2000-07-20 Ulrich Drepper <drepper@redhat.com>
* elf/elf.h: Add various DF_1_*, DTF_1_*, and DF_P1_* entries.
* elf/dl-close.c (_dl_close): Don't close an object if it is marked
with nodelete.
* elf/dl-open.c (dl_open_worker): Pass RTLD_NOLOAD as new parameter
to _dl_map_object. Return immediately if no object loaded.
Set DF_1_NODELETE bit in l_flags_1 if RTLD_NODELETE was passed.
* elf/dynamic-link.h (elf_get_dynamic_info): Copy DT_FLAGS_1 entry
if it exists into l_flags_1 word.
* elf/dl-load.c (_dl_map_object_from_fd): Take no parameter and use
it to determine whether loading is wanted or not.
(_dl_map_object): Likewise.
Call _dl_map_object_from_fd with new parameter.
* sysdeps/generic/ldsodefs.h: Update prototype.
* elf/dl-deps.c: Add new parameter to _dl_map_object calls.
* elf/rtld.c: Likewise.
* elf/Makefile (tests): Add noload. Add rules to generate noload.
* elf/noload.c: New file.
* include/link.h (struct link_map): Add l_feature_1 and l_flags_1.
* sysdeps/generic/bits/dlfcn.h: Define RTLD_NOLOAD and RTLD_NODELETE.
* sysdeps/mips/bits/dlfcn.h: Likewise.
* libio/Makefile (tests): Add tst_wprintf2. * libio/Makefile (tests): Add tst_wprintf2.
(tst_wprintf2-ARGS): Define. (tst_wprintf2-ARGS): Define.
* libio/tst_wprintf2.c: New file. * libio/tst_wprintf2.c: New file.

View File

@ -22,20 +22,24 @@
#endif #endif
/* The MODE argument to `dlopen' contains one of the following: */ /* The MODE argument to `dlopen' contains one of the following: */
#define RTLD_LAZY 0x001 /* Lazy function call binding. */ #define RTLD_LAZY 0x00001 /* Lazy function call binding. */
#define RTLD_NOW 0x002 /* Immediate function call binding. */ #define RTLD_NOW 0x00002 /* Immediate function call binding. */
#define RTLD_BINDING_MASK 0x3 /* Mask of binding time value. */ #define RTLD_BINDING_MASK 0x3 /* Mask of binding time value. */
#define RTLD_NOLOAD 0x00004 /* Do not load the object. */
/* If the following bit is set in the MODE argument to `dlopen', /* If the following bit is set in the MODE argument to `dlopen',
the symbols of the loaded object and its dependencies are made the symbols of the loaded object and its dependencies are made
visible as if the object were linked directly into the program. */ visible as if the object were linked directly into the program. */
#define RTLD_GLOBAL 0x100 #define RTLD_GLOBAL 0x00100
/* Unix98 demands the following flag which is the inverse to RTLD_GLOBAL. /* Unix98 demands the following flag which is the inverse to RTLD_GLOBAL.
The implementation does this by default and so we can define the The implementation does this by default and so we can define the
value to zero. */ value to zero. */
#define RTLD_LOCAL 0 #define RTLD_LOCAL 0
/* Do not delete object when closed. */
#define RTLD_NODELETE 0x01000
#ifdef __USE_GNU #ifdef __USE_GNU
/* To support profiling of shared objects it is a good idea to call /* To support profiling of shared objects it is a good idea to call
the function found using `dlsym' using the following macro since the function found using `dlsym' using the following macro since

View File

@ -48,6 +48,11 @@ _dl_close (void *_map)
unsigned int nrellist; unsigned int nrellist;
unsigned int i; unsigned int i;
/* First see whether we can remove the object at all. */
if (map->l_flags_1 & DF_1_NODELETE)
/* Nope. Do nothing. */
return;
if (map->l_opencount == 0) if (map->l_opencount == 0)
_dl_signal_error (0, map->l_name, N_("shared object not open")); _dl_signal_error (0, map->l_name, N_("shared object not open"));
@ -112,7 +117,8 @@ _dl_close (void *_map)
points to, the 0th elt being MAP itself. Decrement the reference points to, the 0th elt being MAP itself. Decrement the reference
counts on all the objects MAP depends on. */ counts on all the objects MAP depends on. */
for (i = 0; i < nsearchlist; ++i) for (i = 0; i < nsearchlist; ++i)
--list[i]->l_opencount; if (! (list[i]->l_flags_1 & DF_1_NODELETE))
--list[i]->l_opencount;
/* Check each element of the search list to see if all references to /* Check each element of the search list to see if all references to
it are gone. */ it are gone. */

View File

@ -67,7 +67,7 @@ openaux (void *a)
args->aux = _dl_map_object (args->map, args->name, 0, args->aux = _dl_map_object (args->map, args->name, 0,
(args->map->l_type == lt_executable (args->map->l_type == lt_executable
? lt_library : args->map->l_type), ? lt_library : args->map->l_type),
args->trace_mode); args->trace_mode, 0);
} }
@ -232,7 +232,7 @@ _dl_map_object_deps (struct link_map *map,
dep = _dl_map_object (l, name, 0, dep = _dl_map_object (l, name, 0,
l->l_type == lt_executable ? lt_library : l->l_type == lt_executable ? lt_library :
l->l_type, trace_mode); l->l_type, trace_mode, 0);
/* Add it in any case to the duplicate list. */ /* Add it in any case to the duplicate list. */
newp = alloca (sizeof (struct list)); newp = alloca (sizeof (struct list));
@ -316,7 +316,7 @@ _dl_map_object_deps (struct link_map *map,
args.aux = _dl_map_object (l, name, 0, args.aux = _dl_map_object (l, name, 0,
(l->l_type == lt_executable (l->l_type == lt_executable
? lt_library : l->l_type), ? lt_library : l->l_type),
trace_mode); trace_mode, 0);
} }
/* The auxiliary object is actually available. /* The auxiliary object is actually available.

View File

@ -688,7 +688,7 @@ static
#endif #endif
struct link_map * struct link_map *
_dl_map_object_from_fd (const char *name, int fd, char *realname, _dl_map_object_from_fd (const char *name, int fd, char *realname,
struct link_map *loader, int l_type) struct link_map *loader, int l_type, int noload)
{ {
/* This is the expected ELF header. */ /* This is the expected ELF header. */
#define ELF32_CLASS ELFCLASS32 #define ELF32_CLASS ELFCLASS32
@ -752,6 +752,11 @@ _dl_map_object_from_fd (const char *name, int fd, char *realname,
return l; return l;
} }
if (noload)
/* We are not supposed to load the object unless it is already
loaded. So return now. */
return NULL;
/* Print debugging message. */ /* Print debugging message. */
if (__builtin_expect (_dl_debug_files, 0)) if (__builtin_expect (_dl_debug_files, 0))
_dl_debug_message (1, "file=", name, "; generating link map\n", NULL); _dl_debug_message (1, "file=", name, "; generating link map\n", NULL);
@ -1301,7 +1306,7 @@ open_path (const char *name, size_t namelen, int preloaded,
struct link_map * struct link_map *
internal_function internal_function
_dl_map_object (struct link_map *loader, const char *name, int preloaded, _dl_map_object (struct link_map *loader, const char *name, int preloaded,
int type, int trace_mode) int type, int trace_mode, int noload)
{ {
int fd; int fd;
char *realname; char *realname;
@ -1501,5 +1506,5 @@ _dl_map_object (struct link_map *loader, const char *name, int preloaded,
_dl_signal_error (errno, name, N_("cannot open shared object file")); _dl_signal_error (errno, name, N_("cannot open shared object file"));
} }
return _dl_map_object_from_fd (name, fd, realname, loader, type); return _dl_map_object_from_fd (name, fd, realname, loader, type, noload);
} }

View File

@ -144,7 +144,17 @@ dl_open_worker (void *a)
} }
/* Load the named object. */ /* Load the named object. */
args->map = new = _dl_map_object (NULL, file, 0, lt_loaded, 0); args->map = new = _dl_map_object (NULL, file, 0, lt_loaded, 0,
mode & RTLD_NOLOAD);
/* If the pointer returned is NULL this means the RTLD_NOLOAD flag is
set and the object is not already loaded. */
if (new == NULL)
{
assert (mode & RTLD_NOLOAD);
return;
}
if (new->l_searchlist.r_list) if (new->l_searchlist.r_list)
/* It was already open. */ /* It was already open. */
return; return;
@ -279,6 +289,11 @@ dl_open_worker (void *a)
/* XXX Do we have to add something to r_dupsearchlist??? --drepper */ /* XXX Do we have to add something to r_dupsearchlist??? --drepper */
} }
/* Mark the object as not deletable if the RTLD_NODELETE flags was
passed. */
if (__builtin_expect (mode & RTLD_NODELETE, 0))
new->l_flags_1 |= DF_1_NODELETE;
if (_dl_sysdep_start == NULL) if (_dl_sysdep_start == NULL)
/* We must be the static _dl_open in libc.a. A static program that /* We must be the static _dl_open in libc.a. A static program that
has loaded a dynamic object now has competition. */ has loaded a dynamic object now has competition. */

View File

@ -114,6 +114,8 @@ elf_get_dynamic_info (struct link_map *l)
if (flags & DF_BIND_NOW) if (flags & DF_BIND_NOW)
info[DT_BIND_NOW] = info[DT_FLAGS]; info[DT_BIND_NOW] = info[DT_FLAGS];
} }
if (info[VERSYMIDX (DT_FLAGS_1)] != NULL)
l->l_flags_1 = info[VERSYMIDX (DT_FLAGS_1)]->d_un.d_val;
if (info[DT_RUNPATH] != NULL) if (info[DT_RUNPATH] != NULL)
/* If both RUNPATH and RPATH are given, the latter is ignored. */ /* If both RUNPATH and RPATH are given, the latter is ignored. */
info[DT_RPATH] = NULL; info[DT_RPATH] = NULL;

View File

@ -622,7 +622,7 @@ typedef struct
#define DT_PLTPADSZ 0x6ffffdf9 #define DT_PLTPADSZ 0x6ffffdf9
#define DT_MOVEENT 0x6ffffdfa #define DT_MOVEENT 0x6ffffdfa
#define DT_MOVESZ 0x6ffffdfb #define DT_MOVESZ 0x6ffffdfb
#define DT_FEATURE_1 0x6ffffdfc #define DT_FEATURE_1 0x6ffffdfc /* Feature selection (DTF_*). */
#define DT_POSFLAG_1 0x6ffffdfd /* Flags for DT_* entries, effecting #define DT_POSFLAG_1 0x6ffffdfd /* Flags for DT_* entries, effecting
the following DT_* entry. */ the following DT_* entry. */
#define DT_SYMINSZ 0x6ffffdfe /* Size of syminfo table (in bytes) */ #define DT_SYMINSZ 0x6ffffdfe /* Size of syminfo table (in bytes) */
@ -678,6 +678,23 @@ typedef struct
#define DF_1_LOADFLTR 0x00000010 /* Trigger filtee loading at runtime.*/ #define DF_1_LOADFLTR 0x00000010 /* Trigger filtee loading at runtime.*/
#define DF_1_INITFIRST 0x00000020 /* Set RTLD_INITFIRST for this object*/ #define DF_1_INITFIRST 0x00000020 /* Set RTLD_INITFIRST for this object*/
#define DF_1_NOOPEN 0x00000040 /* Set RTLD_NOOPEN for this object. */ #define DF_1_NOOPEN 0x00000040 /* Set RTLD_NOOPEN for this object. */
#define DF_1_ORIGIN 0x00000080 /* $ORIGIN must be handled. */
#define DF_1_DIRECT 0x00000100 /* Direct binding enabled. */
#define DF_1_TRANS 0x00000200
#define DF_1_INTERPOSE 0x00000400 /* Object is used to interpose. */
#define DF_1_NODEFLIB 0x00000800 /* Ignore default lib search path. */
#define DF_1_NODUMP 0x00001000
#define DF_1_CONFALT 0x00002000
#define DF_1_ENDFILTEE 0x00004000
/* Flags for the feature selection in DT_FEATURE_1. */
#define DTF_1_PARINIT 0x00000001
#define DTF_1_CONFEXP 0x00000002
/* Flags in the DT_POSFLAG_1 entry effecting only the next DT_* entry. */
#define DF_P1_LAZYLOAD 0x00000001 /* Lazyload following object. */
#define DF_P1_GROUPPERM 0x00000002 /* Symbols from next object are not
generally available. */
/* Version definition sections. */ /* Version definition sections. */

70
elf/noload.c Normal file
View File

@ -0,0 +1,70 @@
#include <dlfcn.h>
#include <stdio.h>
int
main (void)
{
int result = 0;
/* First try to load an object which is a dependency. This should
succeed. */
if (dlopen ("testobj1.so", RTLD_LAZY | RTLD_NOLOAD) == NULL)
{
printf ("cannot open \"testobj1.so\": %s\n", dlerror ());
result = 1;
}
else
puts ("loading \"testobj1.so\" succeeded, OK");
/* Now try loading an object which is not already loaded. */
if (dlopen ("testobj5.so", RTLD_LAZY | RTLD_NOLOAD) != NULL)
{
puts ("succeeded in loading \"testobj5.so\"");
result = 1;
}
else
{
/* Load the object and run the same test again. */
void *p;
puts ("\"testobj5.so\" wasn't loaded and RTLD_NOLOAD prevented it, OK");
p = dlopen ("testobj5.so", RTLD_LAZY);
if (p == NULL)
{
printf ("cannot open \"testobj5.so\" without RTLD_NOLOAD: %s\n",
dlerror ());
result = 1;
}
else
{
puts ("loading \"testobj5.so\" succeeded, OK");
if (dlopen ("testobj5.so", RTLD_LAZY | RTLD_NOLOAD) == NULL)
{
printf ("cannot open \"testobj5.so\": %s\n", dlerror ());
result = 1;
}
else
puts ("loading \"testobj5.so\" with RTLD_NOLOAD succeeded, OK");
if (dlclose (p) != 0)
{
printf ("cannot close \"testobj5.so\": %s\n", dlerror ());
result = 1;
}
else
puts ("closing \"testobj5.so\" succeeded, OK");
}
}
return result;
}
int
foo (int a)
{
return 42 + a;
}

View File

@ -313,7 +313,7 @@ static void
map_doit (void *a) map_doit (void *a)
{ {
struct map_args *args = (struct map_args *) a; struct map_args *args = (struct map_args *) a;
args->main_map = _dl_map_object (NULL, args->str, 0, lt_library, 0); args->main_map = _dl_map_object (NULL, args->str, 0, lt_library, 0, 0);
} }
static void static void
@ -514,7 +514,7 @@ of this helper program; chances are you did not intend to run this program.\n\
else else
{ {
HP_TIMING_NOW (start); HP_TIMING_NOW (start);
_dl_map_object (NULL, _dl_argv[0], 0, lt_library, 0); _dl_map_object (NULL, _dl_argv[0], 0, lt_library, 0, 0);
HP_TIMING_NOW (stop); HP_TIMING_NOW (stop);
HP_TIMING_DIFF (load_time, start, stop); HP_TIMING_DIFF (load_time, start, stop);
@ -694,7 +694,7 @@ of this helper program; chances are you did not intend to run this program.\n\
|| strchr (p, '/') == NULL)) || strchr (p, '/') == NULL))
{ {
struct link_map *new_map = _dl_map_object (_dl_loaded, p, 1, struct link_map *new_map = _dl_map_object (_dl_loaded, p, 1,
lt_library, 0); lt_library, 0, 0);
if (new_map->l_opencount == 1) if (new_map->l_opencount == 1)
/* It is no duplicate. */ /* It is no duplicate. */
++npreloads; ++npreloads;
@ -762,7 +762,7 @@ of this helper program; chances are you did not intend to run this program.\n\
if (p[0] != '\0') if (p[0] != '\0')
{ {
struct link_map *new_map = _dl_map_object (_dl_loaded, p, 1, struct link_map *new_map = _dl_map_object (_dl_loaded, p, 1,
lt_library, 0); lt_library, 0, 0);
if (new_map->l_opencount == 1) if (new_map->l_opencount == 1)
/* It is no duplicate. */ /* It is no duplicate. */
++npreloads; ++npreloads;
@ -773,7 +773,7 @@ of this helper program; chances are you did not intend to run this program.\n\
{ {
char *p = strndupa (problem, file_size - (problem - file)); char *p = strndupa (problem, file_size - (problem - file));
struct link_map *new_map = _dl_map_object (_dl_loaded, p, 1, struct link_map *new_map = _dl_map_object (_dl_loaded, p, 1,
lt_library, 0); lt_library, 0, 0);
if (new_map->l_opencount == 1) if (new_map->l_opencount == 1)
/* It is no duplicate. */ /* It is no duplicate. */
++npreloads; ++npreloads;

View File

@ -214,6 +214,10 @@ struct link_map
unsigned int l_reldepsmax; unsigned int l_reldepsmax;
unsigned int l_reldepsact; unsigned int l_reldepsact;
struct link_map **l_reldeps; struct link_map **l_reldeps;
/* Various flag words. */
ElfW(Word) l_feature_1;
ElfW(Word) l_flags_1;
}; };
#endif /* link.h */ #endif /* link.h */

View File

@ -22,20 +22,24 @@
#endif #endif
/* The MODE argument to `dlopen' contains one of the following: */ /* The MODE argument to `dlopen' contains one of the following: */
#define RTLD_LAZY 0x001 /* Lazy function call binding. */ #define RTLD_LAZY 0x00001 /* Lazy function call binding. */
#define RTLD_NOW 0x002 /* Immediate function call binding. */ #define RTLD_NOW 0x00002 /* Immediate function call binding. */
#define RTLD_BINDING_MASK 0x3 /* Mask of binding time value. */ #define RTLD_BINDING_MASK 0x3 /* Mask of binding time value. */
#define RTLD_NOLOAD 0x00004 /* Do not load the object. */
/* If the following bit is set in the MODE argument to `dlopen', /* If the following bit is set in the MODE argument to `dlopen',
the symbols of the loaded object and its dependencies are made the symbols of the loaded object and its dependencies are made
visible as if the object were linked directly into the program. */ visible as if the object were linked directly into the program. */
#define RTLD_GLOBAL 0x100 #define RTLD_GLOBAL 0x00100
/* Unix98 demands the following flag which is the inverse to RTLD_GLOBAL. /* Unix98 demands the following flag which is the inverse to RTLD_GLOBAL.
The implementation does this by default and so we can define the The implementation does this by default and so we can define the
value to zero. */ value to zero. */
#define RTLD_LOCAL 0 #define RTLD_LOCAL 0
/* Do not delete object when closed. */
#define RTLD_NODELETE 0x01000
#ifdef __USE_GNU #ifdef __USE_GNU
/* To support profiling of shared objects it is a good idea to call /* To support profiling of shared objects it is a good idea to call
the function found using `dlsym' using the following macro since the function found using `dlsym' using the following macro since

View File

@ -271,7 +271,7 @@ extern void _dl_receive_error (receiver_fct fct, void (*operate) (void *),
value to allow additional security checks. */ value to allow additional security checks. */
extern struct link_map *_dl_map_object (struct link_map *loader, extern struct link_map *_dl_map_object (struct link_map *loader,
const char *name, int preloaded, const char *name, int preloaded,
int type, int trace_mode) int type, int trace_mode, int noload)
internal_function; internal_function;
/* Call _dl_map_object on the dependencies of MAP, and set up /* Call _dl_map_object on the dependencies of MAP, and set up

View File

@ -22,20 +22,24 @@
#endif #endif
/* The MODE argument to `dlopen' contains one of the following: */ /* The MODE argument to `dlopen' contains one of the following: */
#define RTLD_LAZY 0x001 /* Lazy function call binding. */ #define RTLD_LAZY 0x0001 /* Lazy function call binding. */
#define RTLD_NOW 0x002 /* Immediate function call binding. */ #define RTLD_NOW 0x0002 /* Immediate function call binding. */
#define RTLD_BINDING_MASK 0x3 /* Mask of binding time value. */ #define RTLD_BINDING_MASK 0x3 /* Mask of binding time value. */
#define RTLD_NOLOAD 0x00008 /* Do not load the object. */
/* If the following bit is set in the MODE argument to `dlopen', /* If the following bit is set in the MODE argument to `dlopen',
the symbols of the loaded object and its dependencies are made the symbols of the loaded object and its dependencies are made
visible as if the object were linked directly into the program. */ visible as if the object were linked directly into the program. */
#define RTLD_GLOBAL 0x004 #define RTLD_GLOBAL 0x0004
/* Unix98 demands the following flag which is the inverse to RTLD_GLOBAL. /* Unix98 demands the following flag which is the inverse to RTLD_GLOBAL.
The implementation does this by default and so we can define the The implementation does this by default and so we can define the
value to zero. */ value to zero. */
#define RTLD_LOCAL 0 #define RTLD_LOCAL 0
/* Do not delete object when closed. */
#define RTLD_NODELETE 0x01000
#ifdef __USE_GNU #ifdef __USE_GNU
/* To support profiling of shared objects it is a good idea to call /* To support profiling of shared objects it is a good idea to call
the function found using `dlsym' using the following macro since the function found using `dlsym' using the following macro since