소스 검색

This patch from Mike Frysinger, extended from an earlier patch from Peter S.
Mazinger implements the changes suggested by me on the uclibc list.

On Tuesday 28 September 2004 02:24 pm, Erik Andersen wrote:
> What I think should be done is
>
> *) Someone that cares about USE_CACHE should fix that option
> up to be sure it works, and give it a proper config entry
> in extra/Configs/Config.in, and rename it to something
> more appropriate such as LDSO_CACHE_SUPPORT.
>
> *) When LDSO_CACHE_SUPPORT=n, UCLIBC_RUNTIME_PREFIX /usr/X11R6/lib
> should be included in the default library search path in
> dl-elf.c, ldd, and ldconfig.
>
> *) When LDSO_CACHE_SUPPORT=y, UCLIBC_RUNTIME_PREFIX /usr/X11R6/lib
> should be excluded from the default library search path in
> dl-elf.c, ldd, and ldconfig, and those wishing to include
> X11 stuff should add that into /etc/ld.so.conf and re-run
> ldconfig.
>
> *) At present, LDSO_CONF and LDSO_CACHE use the same names
> and same structure as glibc. This precludes
> LDSO_CACHE_SUPPORT being uses in any sane fashion on a
> dial glibc and uClibc system. Just as it was necessary
> for use to use a different name for 'libuClibc' rather
> than 'libc', and 'ld-uClibc.so.0' rather than
> 'ld-linux.so.2' it seems that these configuration files
> really ought to be given different names.
>

Eric Andersen 19 년 전
부모
커밋
3b8039fd51
11개의 변경된 파일194개의 추가작업 그리고 25개의 파일을 삭제
  1. 0 1
      Rules.mak
  2. 25 0
      extra/Configs/Config.in
  3. 5 10
      ldso/include/dl-elf.h
  4. 1 1
      ldso/ldso/Makefile
  5. 5 2
      ldso/ldso/dl-elf.c
  6. 1 1
      ldso/libdl/Makefile
  7. 1 1
      ldso/libdl/libdl.c
  8. 1 1
      utils/Makefile
  9. 34 0
      utils/dl-cache.h
  10. 12 5
      utils/ldconfig.c
  11. 109 3
      utils/ldd.c

+ 0 - 1
Rules.mak

@@ -247,7 +247,6 @@ ifneq ($(DOASSERTS),y)
 endif
 
 ifeq ($(HAVE_SHARED),y)
-    LIBRARY_CACHE:=#-DUSE_CACHE
     ifeq ($(BUILD_UCLIBC_LDSO),y)
 	LDSO:=$(TOPDIR)lib/$(UCLIBC_LDSO)
 	DYNAMIC_LINKER:=$(SHARED_LIB_LOADER_PREFIX)/$(UCLIBC_LDSO)

+ 25 - 0
extra/Configs/Config.in

@@ -200,6 +200,7 @@ config FORCE_SHAREABLE_TEXT_SEGMENTS
 
 config UCLIBC_PIE_SUPPORT
 	bool "Support ET_DYN in shared library loader"
+	depends on BUILD_UCLIBC_LDSO
 	select FORCE_SHAREABLE_TEXT_SEGMENTS
 	default n
 	help
@@ -223,6 +224,30 @@ config LDSO_LDD_SUPPORT
 	  application to function.  Disabling this option will makes uClibc's
 	  shared library loader a little bit smaller.  Most people will answer Y.
 
+config LDSO_CACHE_SUPPORT
+	bool "Enable shared library loader cache"
+	depends on BUILD_UCLIBC_LDSO
+	default y
+	help
+	  Enable this to make use of /etc/ld.so.conf, the shared library loader
+	  cache configuration file to support for non-standard library paths.
+	  After updating this file, it is necessary to run 'ldconfig' to update
+	  the /etc/ld.so.cache shared library loader cache file.
+
+config LDSO_BASE_FILENAME
+	string "Shared library loader cache naming prefix"
+	depends on LDSO_CACHE_SUPPORT
+	default "ld.so"
+	help
+	  If you wish to support both uClibc and glibc on the same system, it
+	  is necessary to set this to something other than "ld.so" to avoid
+	  conflicts with glibc, which also uses "ld.so".  This prevents both
+	  libraries from using the same /etc/ld.so.cache file.  If you wish to
+	  support both uClibc and glibc on the same system then you should set
+	  this to "ld-uClibc.so".
+
+	  Most people will leave this set to the default of "ld.so".
+
 config UCLIBC_CTOR_DTOR
 	bool "Support global constructors and destructors"
 	default y

+ 5 - 10
ldso/include/dl-elf.h

@@ -5,15 +5,10 @@
 #include <elf.h>
 #include <link.h>
 
-#ifdef DEBUG
-#  define LDSO_CONF  "../util/ld.so.conf"
-#  define LDSO_CACHE "../util/ld.so.cache"
-#  define LDSO_PRELOAD "../util/ld.so.preload"
-#else
-#  define LDSO_CONF  UCLIBC_RUNTIME_PREFIX "etc/ld.so.conf"
-#  define LDSO_CACHE UCLIBC_RUNTIME_PREFIX "etc/ld.so.cache"
-#  define LDSO_PRELOAD UCLIBC_RUNTIME_PREFIX "etc/ld.so.preload"
-#endif
+#define LDSO_BASE_PATH UCLIBC_RUNTIME_PREFIX "etc/" __LDSO_BASE_FILENAME__
+#define LDSO_CONF    LDSO_BASE_PATH ".conf"
+#define LDSO_CACHE   LDSO_BASE_PATH ".cache"
+#define LDSO_PRELOAD LDSO_BASE_PATH ".preload"
 
 
 #define LIB_ANY	     -1
@@ -30,7 +25,7 @@ struct elf_resolve;
 
 
 /* Definitions and prototypes for cache stuff */
-#ifdef USE_CACHE
+#ifdef __LDSO_CACHE_SUPPORT__
 extern int _dl_map_cache(void);
 extern int _dl_unmap_cache(void);
 

+ 1 - 1
ldso/ldso/Makefile

@@ -23,7 +23,7 @@ LDSO_FULLNAME=ld-uClibc-$(MAJOR_VERSION).$(MINOR_VERSION).$(SUBLEVEL).so
 
 SSPFLAGS=$(call check_gcc,-fno-stack-protector,)
 
-XXFLAGS=$(XWARNINGS) $(LIBRARY_CACHE) $(SSPFLAGS)
+XXFLAGS=$(XWARNINGS) $(SSPFLAGS)
 ifeq ($(DODEBUG),y)
 # Not really much point in including debugging info, since gdb
 # can't really debug ldso, since gdb requires help from ldso to

+ 5 - 2
ldso/ldso/dl-elf.c

@@ -32,7 +32,7 @@
 
 #include "ldso.h"
 
-#ifdef USE_CACHE
+#ifdef __LDSO_CACHE_SUPPORT__
 
 static caddr_t _dl_cache_addr = NULL;
 static size_t _dl_cache_size = 0;
@@ -317,7 +317,7 @@ struct elf_resolve *_dl_load_shared_library(int secure, struct dyn_elf **rpnt,
 	 * ABI, so we have some flexibility here.  For now, search it before
 	 * the hard coded paths that follow (i.e before /lib and /usr/lib).
 	 */
-#ifdef USE_CACHE
+#ifdef __LDSO_CACHE_SUPPORT__
 	if (_dl_cache_addr != NULL && _dl_cache_addr != (caddr_t) - 1) {
 		int i;
 		header_t *header = (header_t *) _dl_cache_addr;
@@ -358,6 +358,9 @@ struct elf_resolve *_dl_load_shared_library(int secure, struct dyn_elf **rpnt,
 	if ((tpnt1 = search_for_named_library(libname, secure,
 					UCLIBC_RUNTIME_PREFIX "lib:"
 					UCLIBC_RUNTIME_PREFIX "usr/lib"
+#if !defined (__LDSO_CACHE_SUPPORT__)
+					":" UCLIBC_RUNTIME_PREFIX "usr/X11R6/lib"
+#endif
 					, rpnt)
 		) != NULL)
 	{

+ 1 - 1
ldso/libdl/Makefile

@@ -21,7 +21,7 @@
 TOPDIR=../../
 include $(TOPDIR)Rules.mak
 
-XXFLAGS=$(XWARNINGS) $(LIBRARY_CACHE)
+XXFLAGS=$(XWARNINGS)
 ifeq ($(DODEBUG),y)
 XXFLAGS+=-O0 -g3
 else

+ 1 - 1
ldso/libdl/libdl.c

@@ -54,7 +54,7 @@ extern struct elf_resolve *_dl_loaded_modules __attribute__ ((__weak__));
 extern struct r_debug *_dl_debug_addr __attribute__ ((__weak__));
 extern unsigned long _dl_error_number __attribute__ ((__weak__));
 extern void *(*_dl_malloc_function)(size_t) __attribute__ ((__weak__));
-#ifdef USE_CACHE
+#ifdef __LDSO_CACHE_SUPPORT__
 int _dl_map_cache(void) __attribute__ ((__weak__));
 int _dl_unmap_cache(void) __attribute__ ((__weak__));
 #endif

+ 1 - 1
utils/Makefile

@@ -29,7 +29,7 @@ else
 TARGET_ICONV =
 endif
 
-XXFLAGS=$(LIBRARY_CACHE)
+XXFLAGS=
 ifeq ($(strip $(LDSO_LDD_SUPPORT)),y)
 XXFLAGS+= -D__LDSO_LDD_SUPPORT
 endif

+ 34 - 0
utils/dl-cache.h

@@ -0,0 +1,34 @@
+#define LDSO_BASE_PATH UCLIBC_RUNTIME_PREFIX "etc/" __LDSO_BASE_FILENAME__
+#define LDSO_CONF    LDSO_BASE_PATH ".conf"
+#define LDSO_CACHE   LDSO_BASE_PATH ".cache"
+#define LDSO_PRELOAD LDSO_BASE_PATH ".preload"
+
+#define LIB_ANY	     -1
+#define LIB_DLL       0
+#define LIB_ELF       1
+#define LIB_ELF64     0x80
+#define LIB_ELF_LIBC5 2
+#define LIB_ELF_LIBC6 3
+#define LIB_ELF_LIBC0 4
+
+/* Definitions and prototypes for cache stuff */
+#ifdef __LDSO_CACHE_SUPPORT__
+
+#define LDSO_CACHE_MAGIC "ld.so-"
+#define LDSO_CACHE_MAGIC_LEN (sizeof LDSO_CACHE_MAGIC -1)
+#define LDSO_CACHE_VER "1.7.0"
+#define LDSO_CACHE_VER_LEN (sizeof LDSO_CACHE_VER -1)
+
+typedef struct {
+	char magic   [LDSO_CACHE_MAGIC_LEN];
+	char version [LDSO_CACHE_VER_LEN];
+	int nlibs;
+} header_t;
+
+typedef struct {
+	int flags;
+	int sooffset;
+	int liboffset;
+} libentry_t;
+
+#endif

+ 12 - 5
utils/ldconfig.c

@@ -503,7 +503,7 @@ void scan_dir(const char *rawname)
     {
 	if (!lp->islink)
 	    link_shlib(name, lp->name, lp->so);
-#ifdef USE_CACHE
+#ifdef __LDSO_CACHE_SUPPORT__
 	if (!nocache)
 	    cache_dolib(name, lp->so, lp->libtype);
 #endif
@@ -553,7 +553,7 @@ char *get_extpath(void)
     return res;
 }
 
-#ifdef USE_CACHE
+#ifdef __LDSO_CACHE_SUPPORT__
 typedef struct liblist
 {
     int flags;
@@ -876,6 +876,9 @@ int main(int argc, char **argv)
 	{
 	    scan_dir(UCLIBC_RUNTIME_PREFIX "lib");
 	    scan_dir(UCLIBC_RUNTIME_PREFIX "usr/lib");
+#if !defined (__LDSO_CACHE_SUPPORT__)
+	    scan_dir(UCLIBC_RUNTIME_PREFIX "usr/X11R6/lib");
+#endif
 
 	    /* I guess the defaults aren't good enough */
 	    if ((extpath = get_extpath()))
@@ -886,8 +889,12 @@ int main(int argc, char **argv)
 			if (len) 
 				while (cp[--len] == '/' && len)
 					cp[len] = 0;
-			if (strcmp(UCLIBC_RUNTIME_PREFIX "lib", cp) == 0 ||
-			    strcmp(UCLIBC_RUNTIME_PREFIX "usr/lib", cp) == 0) {
+			if (strcmp(UCLIBC_RUNTIME_PREFIX "lib", cp) == 0
+			    || strcmp(UCLIBC_RUNTIME_PREFIX "usr/lib", cp) == 0
+#if !defined (__LDSO_CACHE_SUPPORT__)
+			    || strcmp(UCLIBC_RUNTIME_PREFIX "usr/X11R6/lib", cp) == 0
+#endif
+			    ) {
 				if (verbose >= 0)
 					warnx("Path `%s' given more than once\n", cp);
 				continue;
@@ -898,7 +905,7 @@ int main(int argc, char **argv)
 	    }
 	}
 
-#ifdef USE_CACHE
+#ifdef __LDSO_CACHE_SUPPORT__
 	if (!nocache)
 	    cache_write();
 #endif

+ 109 - 3
utils/ldd.c

@@ -45,6 +45,7 @@
 #else
 #include "elf.h"
 #endif
+#include "dl-cache.h"
 
 #ifdef DMALLOC
 #include <dmalloc.h>
@@ -229,6 +230,89 @@ int check_elf_header(Elf32_Ehdr *const ehdr)
 	return 0;
 }
 
+#ifdef __LDSO_CACHE_SUPPORT__
+static caddr_t cache_addr = NULL;
+static size_t cache_size = 0;
+
+int map_cache(void)
+{
+	int fd;
+	struct stat st;
+	header_t *header;
+	libentry_t *libent;
+	int i, strtabsize;
+
+	if (cache_addr == (caddr_t) - 1)
+		return -1;
+	else if (cache_addr != NULL)
+		return 0;
+
+	if (stat(LDSO_CACHE, &st)
+			|| (fd = open(LDSO_CACHE, O_RDONLY, 0)) < 0) {
+		dprintf(2, "ldd: can't open cache '%s'\n", LDSO_CACHE);
+		cache_addr = (caddr_t) - 1;	/* so we won't try again */
+		return -1;
+	}
+
+	cache_size = st.st_size;
+	cache_addr = (caddr_t) mmap(0, cache_size, PROT_READ, MAP_SHARED, fd, 0);
+	close(fd);
+	if (cache_addr == MAP_FAILED) {
+		dprintf(2, "ldd: can't map cache '%s'\n", LDSO_CACHE);
+		return -1;
+	}
+
+	header = (header_t *) cache_addr;
+
+	if (cache_size < sizeof(header_t) ||
+			memcmp(header->magic, LDSO_CACHE_MAGIC, LDSO_CACHE_MAGIC_LEN)
+			|| memcmp(header->version, LDSO_CACHE_VER, LDSO_CACHE_VER_LEN)
+			|| cache_size <
+			(sizeof(header_t) + header->nlibs * sizeof(libentry_t))
+			|| cache_addr[cache_size - 1] != '\0')
+	{
+		dprintf(2, "ldd: cache '%s' is corrupt\n", LDSO_CACHE);
+		goto fail;
+	}
+
+	strtabsize = cache_size - sizeof(header_t) -
+		header->nlibs * sizeof(libentry_t);
+	libent = (libentry_t *) & header[1];
+
+	for (i = 0; i < header->nlibs; i++) {
+		if (libent[i].sooffset >= strtabsize ||
+				libent[i].liboffset >= strtabsize)
+		{
+			dprintf(2, "ldd: cache '%s' is corrupt\n", LDSO_CACHE);
+			goto fail;
+		}
+	}
+
+	return 0;
+
+fail:
+	munmap(cache_addr, cache_size);
+	cache_addr = (caddr_t) - 1;
+	return -1;
+}
+
+int unmap_cache(void)
+{
+	if (cache_addr == NULL || cache_addr == (caddr_t) - 1)
+		return -1;
+
+#if 1
+	munmap(cache_addr, cache_size);
+	cache_addr = NULL;
+#endif
+
+	return 0;
+}
+#else
+static inline void map_cache(void) { }
+static inline void unmap_cache(void) { }
+#endif
+
 /* This function's behavior must exactly match that
  * in uClibc/ldso/ldso/dl-elf.c */
 static void search_for_named_library(char *name, char *result, const char *path_list)
@@ -320,8 +404,23 @@ void locate_library_file(Elf32_Ehdr* ehdr, Elf32_Dyn* dynamic, int is_suid, stru
 		}
 	}
 
-#ifdef USE_CACHE
-	/* FIXME -- add code to check the Cache here */
+#ifdef __LDSO_CACHE_SUPPORT__
+	if (cache_addr != NULL && cache_addr != (caddr_t) - 1) {
+		int i;
+		header_t *header = (header_t *) cache_addr;
+		libentry_t *libent = (libentry_t *) & header[1];
+		char *strs = (char *) &libent[header->nlibs];
+
+		for (i = 0; i < header->nlibs; i++) {
+			if ((libent[i].flags == LIB_ELF ||
+			    libent[i].flags == LIB_ELF_LIBC0 ||
+			    libent[i].flags == LIB_ELF_LIBC5) &&
+			    strcmp(lib->name, strs + libent[i].sooffset) == 0) {
+				lib->path = strdup(strs + libent[i].liboffset);
+				return;
+			}
+		}
+	}
 #endif
 
 
@@ -339,7 +438,11 @@ void locate_library_file(Elf32_Ehdr* ehdr, Elf32_Dyn* dynamic, int is_suid, stru
 	/* Lastly, search the standard list of paths for the library.
 	   This list must exactly match the list in uClibc/ldso/ldso/dl-elf.c */
 	path =	UCLIBC_RUNTIME_PREFIX "lib:"
-		UCLIBC_RUNTIME_PREFIX "usr/lib";
+		UCLIBC_RUNTIME_PREFIX "usr/lib"
+#if !defined (__LDSO_CACHE_SUPPORT__)
+		":" UCLIBC_RUNTIME_PREFIX "usr/X11R6/lib"
+#endif
+		;
 	search_for_named_library(lib->name, buf, path);
 	if (*buf != '\0') {
 		lib->path = buf;
@@ -644,6 +747,8 @@ int main( int argc, char** argv)
 			printf("%s:\n", *argv);
 		}
 
+		map_cache();
+
 		if (find_dependancies(filename)!=0)
 			continue;
 
@@ -660,6 +765,7 @@ int main( int argc, char** argv)
 			}
 		}
 
+		unmap_cache();
 
 		/* Print the list */
 		got_em_all=0;