diff options
Diffstat (limited to 'elf')
-rw-r--r-- | elf/Makefile | 16 | ||||
-rw-r--r-- | elf/dl-error.c | 2 | ||||
-rw-r--r-- | elf/dl-load.c | 115 |
3 files changed, 84 insertions, 49 deletions
diff --git a/elf/Makefile b/elf/Makefile index f8dc9d0ef2..fb85b85e3c 100644 --- a/elf/Makefile +++ b/elf/Makefile @@ -30,7 +30,7 @@ dl-routines = $(addprefix dl-,load cache lookup object reloc deps \ runtime error init fini debug misc \ version profile) # But they are absent from the shared libc, because that code is in ld.so. -elide-routines.so = $(dl-routines) dl-support enbl-secure +elide-routines.os = $(dl-routines) dl-support enbl-secure # ld.so uses those routines, plus some special stuff for being the program # interpreter and operating independent of libc. @@ -54,8 +54,8 @@ all: # Make this the default target; it will be defined in Rules. include ../Makeconfig ifeq (yes,$(build-shared)) -extra-objs = $(rtld-routines:=.so) soinit.so sofini.so eval.so -generated = librtld.so dl-allobjs.so trusted-dirs.h rtldtbl.h +extra-objs = $(rtld-routines:=.os) soinit.os sofini.os eval.os +generated = librtld.os dl-allobjs.os trusted-dirs.h rtldtbl.h install-others = $(inst_slibdir)/$(rtld-installed-name) install-bin = ldd endif @@ -85,11 +85,11 @@ endif # Command to link into a larger single relocatable object. reloc-link = $(LINK.o) -nostdlib -nostartfiles -r -o $@ -$(objpfx)dl-allobjs.so: $(rtld-routines:%=$(objpfx)%.so) +$(objpfx)dl-allobjs.os: $(rtld-routines:%=$(objpfx)%.os) $(reloc-link) $^ # Link together the dynamic linker into a single relocatable object. -$(objpfx)librtld.so: $(objpfx)dl-allobjs.so $(common-objpfx)libc_pic.a +$(objpfx)librtld.os: $(objpfx)dl-allobjs.os $(common-objpfx)libc_pic.a $(reloc-link) '-Wl,-(' $^ -lgcc '-Wl,-)' # Do we need a linker script? @@ -107,7 +107,7 @@ $(objpfx)rtld-ldscript: $(rtld-ldscript-in) $(rtld-parms) -e 's#@@rtld-entry@@#$(rtld-entry)#' \ -e 's#@@rtld-base@@#$(rtld-base)#' $< >$@ -$(objpfx)ld.so: $(objpfx)librtld.so $(objpfx)rtld-ldscript +$(objpfx)ld.so: $(objpfx)librtld.os $(objpfx)rtld-ldscript $(rtld-link) -Wl,-soname=$(rtld-installed-name) define rtld-link @@ -116,7 +116,7 @@ $(LINK.o) -nostdlib -nostartfiles -shared -o $@ \ $(filter-out $(objpfx)rtld-ldscript,$^) endef else -$(objpfx)ld.so: $(objpfx)librtld.so +$(objpfx)ld.so: $(objpfx)librtld.os $(rtld-link) -Wl,-soname=$(rtld-installed-name) define rtld-link @@ -186,4 +186,4 @@ endif # muwahaha LDFLAGS-dl.so = -Wl,-dynamic-linker,$(slibdir)/$(rtld-installed-name) -$(objpfx)libdl.so: $(objpfx)eval.so +$(objpfx)libdl.so: $(objpfx)eval.os diff --git a/elf/dl-error.c b/elf/dl-error.c index 7ee803ad9b..72af85985d 100644 --- a/elf/dl-error.c +++ b/elf/dl-error.c @@ -75,7 +75,7 @@ _dl_signal_error (int errcode, /* Lossage while resolving the program's own symbols is always fatal. */ extern char **_dl_argv; /* Set in rtld.c at startup. */ _dl_sysdep_fatal (_dl_argv[0] ?: "<program name unknown>", - ": error in loading shared libraries", + ": error in loading shared libraries: ", objname ?: "", objname ? ": " : "", errstring, errcode ? ": " : "", errcode ? strerror (errcode) : "", "\n", NULL); diff --git a/elf/dl-load.c b/elf/dl-load.c index f0af29292a..ce3bd9fb94 100644 --- a/elf/dl-load.c +++ b/elf/dl-load.c @@ -94,6 +94,11 @@ size_t _dl_pagesize; extern const char *_dl_platform; extern size_t _dl_platformlen; +/* This is a fake list to store the RPATH information for static + binaries. */ +static struct r_search_path_elem **fake_path_list; + + /* Local version of `strdup' function. */ static inline char * local_strdup (const char *s) @@ -308,6 +313,12 @@ decompose_rpath (const char *rpath, size_t additional_room) void _dl_init_paths (void) { + static const char *trusted_dirs[] = + { +#include "trusted-dirs.h" + NULL + }; + struct r_search_path_elem **pelem; /* We have in `search_path' the information about the RPATH of the @@ -333,53 +344,72 @@ _dl_init_paths (void) nllp = 0; l = _dl_loaded; - if (l && l->l_type != lt_loaded && l->l_info[DT_RPATH]) + if (l != NULL) { - /* Allocate room for the search path and fill in information from - RPATH. */ - l->l_rpath_dirs = - decompose_rpath ((const char *) (l->l_addr - + l->l_info[DT_STRTAB]->d_un.d_ptr - + l->l_info[DT_RPATH]->d_un.d_val), - nllp); + if (l->l_type != lt_loaded && l->l_info[DT_RPATH]) + { + /* Allocate room for the search path and fill in information + from RPATH. */ + l->l_rpath_dirs = + decompose_rpath ((const char *) + (l->l_addr + l->l_info[DT_STRTAB]->d_un.d_ptr + + l->l_info[DT_RPATH]->d_un.d_val), + nllp); + } + else + { + /* If we have no LD_LIBRARY_PATH and no RPATH we must tell + this somehow to prevent we look this up again and again. */ + if (nllp == 0) + l->l_rpath_dirs = (struct r_search_path_elem **) -1l; + else + { + l->l_rpath_dirs = (struct r_search_path_elem **) + malloc ((nllp + 1) * sizeof (*l->l_rpath_dirs)); + if (l->l_rpath_dirs == NULL) + _dl_signal_error (ENOMEM, NULL, + "cannot create cache for search path"); + l->l_rpath_dirs[0] = NULL; + } + } + + /* We don't need to search the list of fake entries which is searched + when no dynamic objects were loaded at this time. */ + fake_path_list = NULL; + + if (nllp > 0) + { + char *copy = strdupa (llp); + + /* Decompose the LD_LIBRARY_PATH and fill in the result. + First search for the next place to enter elements. */ + struct r_search_path_elem **result = l->l_rpath_dirs; + while (*result != NULL) + ++result; + + /* We need to take care that the LD_LIBRARY_PATH environment + variable can contain a semicolon. */ + (void) fillin_rpath (copy, result, ":;", + __libc_enable_secure ? trusted_dirs : NULL); + } } else { - /* If we have no LD_LIBRARY_PATH and no RPATH we must tell this - somehow to prevent we look this up again and again. */ + /* This is a statically linked program but we still have to + take care for the LD_LIBRARY_PATH environment variable. We + use a fake link_map entry. This will only contain the + l_rpath_dirs information. */ + if (nllp == 0) - l->l_rpath_dirs = (struct r_search_path_elem **) -1l; + fake_path_list = NULL; else { - l->l_rpath_dirs = - (struct r_search_path_elem **) malloc ((nllp + 1) - * sizeof (*l->l_rpath_dirs)); - if (l->l_rpath_dirs == NULL) - _dl_signal_error (ENOMEM, NULL, - "cannot create cache for search path"); - l->l_rpath_dirs[0] = NULL; - } - } + fake_path_list = (struct r_search_path_elem **) + malloc ((nllp + 1) * sizeof (struct r_search_path_elem *)); - if (nllp > 0) - { - static const char *trusted_dirs[] = - { -#include "trusted-dirs.h" - NULL - }; - char *copy = strdupa (llp); - - /* Decompose the LD_LIBRARY_PATH and fill in the result. - First search for the next place to enter elements. */ - struct r_search_path_elem **result = l->l_rpath_dirs; - while (*result != NULL) - ++result; - - /* We need to take care that the LD_LIBRARY_PATH environement - variable can contain a semicolon. */ - (void) fillin_rpath (copy, result, ":;", - __libc_enable_secure ? trusted_dirs : NULL); + (void) fillin_rpath (local_strdup (llp), fake_path_list, ":;", + __libc_enable_secure ? trusted_dirs : NULL); + } } /* Now set up the rest of the rtld_search_dirs. */ @@ -871,7 +901,7 @@ _dl_map_object (struct link_map *loader, const char *name, int type, /* Look for this name among those already loaded. */ for (l = _dl_loaded; l; l = l->l_next) - if (_dl_name_match_p (name, l) || + if (l->l_opencount > 0 && _dl_name_match_p (name, l) || /* If the requested name matches the soname of a loaded object, use that object. */ (l->l_info[DT_SONAME] && @@ -923,6 +953,11 @@ _dl_map_object (struct link_map *loader, const char *name, int type, && l->l_rpath_dirs != (struct r_search_path_elem **) -1l) fd = open_path (name, namelen, l->l_rpath_dirs, &realname); + /* This is used if a static binary uses dynamic loading and there + is a LD_LIBRARY_PATH given. */ + if (fd == -1 && fake_path_list != NULL) + fd = open_path (name, namelen, fake_path_list, &realname); + if (fd == -1) { /* Check the list of libraries in the file /etc/ld.so.cache, |