diff options
Diffstat (limited to 'elf')
-rw-r--r-- | elf/dl-close.c | 8 | ||||
-rw-r--r-- | elf/dl-deps.c | 6 | ||||
-rw-r--r-- | elf/dl-load.c | 11 | ||||
-rw-r--r-- | elf/dl-open.c | 17 | ||||
-rw-r--r-- | elf/dynamic-link.h | 2 | ||||
-rw-r--r-- | elf/elf.h | 19 | ||||
-rw-r--r-- | elf/noload.c | 70 | ||||
-rw-r--r-- | elf/rtld.c | 10 |
8 files changed, 129 insertions, 14 deletions
diff --git a/elf/dl-close.c b/elf/dl-close.c index ec563ed8d0..99d52d02e2 100644 --- a/elf/dl-close.c +++ b/elf/dl-close.c @@ -48,6 +48,11 @@ _dl_close (void *_map) unsigned int nrellist; 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) _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 counts on all the objects MAP depends on. */ 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 it are gone. */ diff --git a/elf/dl-deps.c b/elf/dl-deps.c index 1d3779f822..5bc048edb9 100644 --- a/elf/dl-deps.c +++ b/elf/dl-deps.c @@ -67,7 +67,7 @@ openaux (void *a) args->aux = _dl_map_object (args->map, args->name, 0, (args->map->l_type == lt_executable ? 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, 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. */ 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, (l->l_type == lt_executable ? lt_library : l->l_type), - trace_mode); + trace_mode, 0); } /* The auxiliary object is actually available. diff --git a/elf/dl-load.c b/elf/dl-load.c index 2c506b55c1..fbf82e2068 100644 --- a/elf/dl-load.c +++ b/elf/dl-load.c @@ -688,7 +688,7 @@ static #endif struct link_map * _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. */ #define ELF32_CLASS ELFCLASS32 @@ -752,6 +752,11 @@ _dl_map_object_from_fd (const char *name, int fd, char *realname, 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. */ if (__builtin_expect (_dl_debug_files, 0)) _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 * internal_function _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; 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")); } - return _dl_map_object_from_fd (name, fd, realname, loader, type); + return _dl_map_object_from_fd (name, fd, realname, loader, type, noload); } diff --git a/elf/dl-open.c b/elf/dl-open.c index 680377be0a..477ecdf62e 100644 --- a/elf/dl-open.c +++ b/elf/dl-open.c @@ -144,7 +144,17 @@ dl_open_worker (void *a) } /* 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) /* It was already open. */ return; @@ -279,6 +289,11 @@ dl_open_worker (void *a) /* 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) /* We must be the static _dl_open in libc.a. A static program that has loaded a dynamic object now has competition. */ diff --git a/elf/dynamic-link.h b/elf/dynamic-link.h index 79e17ed51c..c6fa3e1eb4 100644 --- a/elf/dynamic-link.h +++ b/elf/dynamic-link.h @@ -114,6 +114,8 @@ elf_get_dynamic_info (struct link_map *l) if (flags & DF_BIND_NOW) 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 both RUNPATH and RPATH are given, the latter is ignored. */ info[DT_RPATH] = NULL; diff --git a/elf/elf.h b/elf/elf.h index 2005bdcf63..ce04184fa6 100644 --- a/elf/elf.h +++ b/elf/elf.h @@ -622,7 +622,7 @@ typedef struct #define DT_PLTPADSZ 0x6ffffdf9 #define DT_MOVEENT 0x6ffffdfa #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 the following DT_* entry. */ #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_INITFIRST 0x00000020 /* Set RTLD_INITFIRST 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. */ diff --git a/elf/noload.c b/elf/noload.c new file mode 100644 index 0000000000..826427f4bd --- /dev/null +++ b/elf/noload.c @@ -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; +} diff --git a/elf/rtld.c b/elf/rtld.c index 1db96999ea..8276b79a71 100644 --- a/elf/rtld.c +++ b/elf/rtld.c @@ -313,7 +313,7 @@ static void map_doit (void *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 @@ -514,7 +514,7 @@ of this helper program; chances are you did not intend to run this program.\n\ else { 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_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)) { 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) /* It is no duplicate. */ ++npreloads; @@ -762,7 +762,7 @@ of this helper program; chances are you did not intend to run this program.\n\ if (p[0] != '\0') { 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) /* It is no duplicate. */ ++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)); 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) /* It is no duplicate. */ ++npreloads; |