OSDN Git Service

This patch from Mike Frysinger, extended from an earlier patch from Peter S.
authorEric Andersen <andersen@codepoet.org>
Sun, 3 Oct 2004 07:53:52 +0000 (07:53 -0000)
committerEric Andersen <andersen@codepoet.org>
Sun, 3 Oct 2004 07:53:52 +0000 (07:53 -0000)
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.
>

Rules.mak
extra/Configs/Config.in
ldso/include/dl-elf.h
ldso/ldso/Makefile
ldso/ldso/dl-elf.c
ldso/libdl/Makefile
ldso/libdl/libdl.c
utils/Makefile
utils/dl-cache.h [new file with mode: 0644]
utils/ldconfig.c
utils/ldd.c

index 61e32bf..20fa6ed 100644 (file)
--- a/Rules.mak
+++ b/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)
index d093372..51caa36 100644 (file)
@@ -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
index f1213d1..5a6e56c 100644 (file)
@@ -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);
 
index 90f44ba..4196748 100644 (file)
@@ -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
index 019acaa..0719680 100644 (file)
@@ -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)
        {
index 3d1c2eb..2da54e0 100644 (file)
@@ -21,7 +21,7 @@
 TOPDIR=../../
 include $(TOPDIR)Rules.mak
 
-XXFLAGS=$(XWARNINGS) $(LIBRARY_CACHE)
+XXFLAGS=$(XWARNINGS)
 ifeq ($(DODEBUG),y)
 XXFLAGS+=-O0 -g3
 else
index 3992163..aa19e81 100644 (file)
@@ -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
index 52308d0..14b7876 100644 (file)
@@ -29,7 +29,7 @@ else
 TARGET_ICONV =
 endif
 
-XXFLAGS=$(LIBRARY_CACHE)
+XXFLAGS=
 ifeq ($(strip $(LDSO_LDD_SUPPORT)),y)
 XXFLAGS+= -D__LDSO_LDD_SUPPORT
 endif
diff --git a/utils/dl-cache.h b/utils/dl-cache.h
new file mode 100644 (file)
index 0000000..ba7cd3f
--- /dev/null
@@ -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
index acb78a2..e466a42 100644 (file)
@@ -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
index 48022cd..55433b6 100644 (file)
@@ -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;