diff options
author | Eric Andersen <andersen@codepoet.org> | 2004-10-03 07:53:52 +0000 |
---|---|---|
committer | Eric Andersen <andersen@codepoet.org> | 2004-10-03 07:53:52 +0000 |
commit | 3b8039fd51c6b2e292d44794ba273aca2c88b321 (patch) | |
tree | ee2868495a5f93fa093887d6e39e8da4768c330c /utils/ldd.c | |
parent | 31cfe2300d8b9aee110ba0a7213f6befdd3ffce0 (diff) |
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.
>
Diffstat (limited to 'utils/ldd.c')
-rw-r--r-- | utils/ldd.c | 112 |
1 files changed, 109 insertions, 3 deletions
diff --git a/utils/ldd.c b/utils/ldd.c index 48022cd8b..55433b601 100644 --- a/utils/ldd.c +++ b/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; |