diff options
-rw-r--r-- | ChangeLog | 49 | ||||
-rw-r--r-- | Makerules | 64 | ||||
-rw-r--r-- | config.h.in | 3 | ||||
-rw-r--r-- | csu/Makefile | 13 | ||||
-rw-r--r-- | csu/abi-note.S | 6 | ||||
-rw-r--r-- | elf/Makefile | 2 | ||||
-rw-r--r-- | elf/cache.c | 62 | ||||
-rw-r--r-- | elf/dl-load.c | 75 | ||||
-rw-r--r-- | elf/dl-minimal.c | 4 | ||||
-rw-r--r-- | elf/ldconfig.c | 35 | ||||
-rw-r--r-- | elf/readlib.c | 25 | ||||
-rw-r--r-- | posix/fnmatch_loop.c | 2 | ||||
-rw-r--r-- | sysdeps/generic/dl-cache.c | 2 | ||||
-rw-r--r-- | sysdeps/generic/dl-cache.h | 2 | ||||
-rw-r--r-- | sysdeps/generic/ldconfig.h | 10 | ||||
-rw-r--r-- | sysdeps/generic/ldsodefs.h | 3 | ||||
-rw-r--r-- | sysdeps/generic/readelflib.c | 22 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/configure | 5 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/configure.in | 2 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/dl-librecon.h | 49 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/dl-osinfo.h | 2 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/i386/dl-librecon.h | 23 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/i386/readelflib.c | 19 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/ia64/readelflib.c | 19 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/init-first.c | 1 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/sparc/readelflib.c | 21 |
26 files changed, 412 insertions, 108 deletions
@@ -1,3 +1,52 @@ +2001-03-12 Jakub Jelinek <jakub@redhat.com> + + * csu/Makefile (abi-tag.h): Define OS and version separately, allow + version to be overriden from config.h. + * csu/abi-note.S: Use OS and version separately, include config.h. + * elf/dl-load.c (_dl_osversion): New. + (_dl_map_object_from_fd): Kill some warnings. + (open_verify): Check .note.ABI-tag of the library if present. + * elf/Makefile (CPPFLAGS-dl-load.c): Add -I$(csu-objpfx). + * elf/cache.c (struct cache_entry): Add osversion. + (print_entry): Print osversion. + (print_cache): Pass osversion to it. + (compare): Sort according to osversion. + (save_cache): Set osversion. + (add_to_cache): Add osversion argument. + * sysdeps/generic/ldconfig.h (add_to_cache, process_file, + process_elf_file): Add osversion argument. + * elf/readlib.c (process_file): Likewise. + * sysdeps/generic/readelflib.c (process_elf_file): Likewise. + * sysdeps/unix/sysv/linux/ia64/readelflib.c (process_elf_file, + process_elf32_file, process_elf64_file): Likewise. + * sysdeps/unix/sysv/linux/i386/readelflib.c (process_elf_file, + process_elf32_file, process_elf64_file): Likewise. + * sysdeps/unix/sysv/linux/sparc/readelflib.c (process_elf_file, + process_elf32_file, process_elf64_file): Likewise. + * elf/ldconfig.c (manual_link): Pass it. + (search_dir): Issue diagnostic if two libs with the same soname in + the same directory have different .note.ABI-tag. Record osversion in + dlib_entry and use it from there. + (struct lib_entry): Remove. + (struct dlib_entry): Add osversion. + * sysdeps/generic/dl-cache.c (_dl_load_cache_lookup): Check + osversion. + * sysdeps/generic/dl-cache.h (struct file_entry_new): Replace __unused + field with osversion. + * sysdeps/generic/ldsodefs.h (_dl_osversion): Declare. + * sysdeps/unix/sysv/linux/init-first.c: Include ldsodefs.h. + * sysdeps/unix/sysv/linux/dl-osinfo.h (DL_SYSDEP_OSCHECK): Save kernel + version in _dl_osversion. + * sysdeps/unix/sysv/linux/configure.in: Define __ABI_TAG_VERSION. + * Makerules (build-shlib-helper, build-module-helper): New. + (build-shlib, build-module-helper): Make sure .note.ABI-tag comes + early. + * config.h.in (__ABI_TAG_VERSION): Add. + * elf/dl-minimal.c (__strtoul_internal): Set endptr on return. + * sysdeps/unix/sysv/linux/i386/dl-librecon.h (EXTRA_LD_ENVVARS): + Handle LD_ASSUME_KERNEL. + * sysdeps/unix/sysv/linux/dl-librecon.h: New. + 2001-03-15 Ulrich Drepper <drepper@redhat.com> * timezone/antarctica: Update from tzdata2001a. @@ -413,29 +413,75 @@ endif lib%.so: lib%_pic.a $(+preinit) $(+postinit) $(+interp) $(build-shlib) -define build-shlib -$(LINK.o) -shared -Wl,-O1 -o $@ $(sysdep-LDFLAGS) $(config-LDFLAGS) \ +define build-shlib-helper +$(LINK.o) -shared -Wl,-O1 $(sysdep-LDFLAGS) $(config-LDFLAGS) \ $(extra-B-$(@F:lib%.so=%).so) -B$(csu-objpfx) \ $(extra-B-$(@F:lib%.so=%).so) $(load-map-file) \ -Wl,-soname=lib$(libprefix)$(@F:lib%.so=%).so$($(@F)-version) \ $(LDFLAGS.so) $(LDFLAGS-$(@F:lib%.so=%).so) \ - -L$(subst :, -L,$(rpath-link)) -Wl,-rpath-link=$(rpath-link) \ - -Wl,--whole-archive \ + -L$(subst :, -L,$(rpath-link)) -Wl,-rpath-link=$(rpath-link) +endef + +ifeq (yes,$(elf)) +# binutils only position loadable notes into the first page for binaries, +# not for shared objects +define build-shlib +$(build-shlib-helper) \ + -o $@.new $(csu-objpfx)/abi-note.o -Wl,--verbose \ + $(LDLIBS-$(@F:lib%.so=%).so) 2>&1 | \ + sed -e '/^=========/,/^=========/!d;/^=========/d' \ + -e 's/^.*\.hash[ ]*:.*$$/ .note.ABI-tag : { *(.note.ABI-tag) } &/' \ + > $@.lds; \ + rm -f $@.new; \ + $(build-shlib-helper) -o $@ -T $@.lds \ + -Wl,--whole-archive $(csu-objpfx)/abi-note.o \ + $(filter-out $(map-file) $(+preinit) $(+postinit),$^) \ + $(no-whole-archive) $(LDLIBS-$(@F:lib%.so=%).so); \ + rm -f $@.lds +endef +else +define build-shlib +$(build-shlib-helper) \ + -o $@ -Wl,--whole-archive \ $(filter-out $(map-file) $(+preinit) $(+postinit),$^) \ $(no-whole-archive) $(LDLIBS-$(@F:lib%.so=%).so) endef +endif + +define build-module-helper +$(LINK.o) -shared $(sysdep-LDFLAGS) $(config-LDFLAGS) \ + -B$(csu-objpfx) $(load-map-file) \ + $(LDFLAGS.so) $(LDFLAGS-$(@F:%.so=%).so) \ + -L$(subst :, -L,$(rpath-link)) -Wl,-rpath-link=$(rpath-link) +endef # This macro is similar to build-shlib but it does not define a soname # and it does not depend on the destination name to start with `lib'. +ifeq (yes,$(elf)) +# binutils only position loadable notes into the first page for binaries, +# not for shared objects define build-module -$(LINK.o) -shared -o $@ $(sysdep-LDFLAGS) $(config-LDFLAGS) \ - -B$(csu-objpfx) $(load-map-file) \ - $(LDFLAGS.so) $(LDFLAGS-$(@F:%.so=%).so) \ - -L$(subst :, -L,$(rpath-link)) -Wl,-rpath-link=$(rpath-link) \ - -Wl,--whole-archive \ +$(build-module-helper) \ + -o $@.new $(csu-objpfx)/abi-note.o -Wl,--verbose \ + $(LDLIBS-$(@F:lib%.so=%).so) 2>&1 | \ + sed -e '/^=========/,/^=========/!d;/^=========/d' \ + -e 's/^.*\.hash[ ]*:.*$$/ .note.ABI-tag : { *(.note.ABI-tag) } &/' \ + > $@.lds; \ + rm -f $@.new; \ + $(build-module-helper) -o $@ -T $@.lds \ + -Wl,--whole-archive $(csu-objpfx)/abi-note.o \ + $(filter-out $(map-file) $(+preinit) $(+postinit),$^) \ + $(no-whole-archive) $(LDLIBS-$(@F:lib%.so=%).so); \ + rm -f $@.lds +endef +else +define build-module +$(build-module-helper) \ + -o $@ -Wl,--whole-archive \ $(filter-out $(map-file) $(+preinit) $(+postinit),$^) \ $(no-whole-archive) $(LDLIBS-$(@F:%.so=%).so) endef +endif # Don't try to use -lc when making libc.so itself. # Also omits crti.o and crtn.o, which we do not want diff --git a/config.h.in b/config.h.in index b6223d7..14e1550 100644 --- a/config.h.in +++ b/config.h.in @@ -93,6 +93,9 @@ /* Linux specific: minimum supported kernel version. */ #undef __LINUX_KERNEL_VERSION +/* Override abi-tags ABI version if necessary. */ +#undef __ABI_TAG_VERSION + /* An extension in gcc 2.96 and up allows the subtraction of two local labels. */ #undef HAVE_SUBTRACT_LOCAL_LABELS diff --git a/csu/Makefile b/csu/Makefile index ad59404..838e141 100644 --- a/csu/Makefile +++ b/csu/Makefile @@ -168,12 +168,17 @@ $(objpfx)abi-tag.h: $(..)abi-tags $(make-target-directory) rm -f $@.new sed -e 's/#.*$$//' -e '/^[ ]*$$/d' $< | \ - while read conf tag; do \ + while read conf tagos tagver; do \ test `expr '$(config-machine)-$(config-vendor)-$(config-os)' \ : "$$conf"` != 0 || continue; \ - echo "$$tag" | \ - sed -e 's/[^0-9xXa-fA-F]/ /g' -e 's/ *$$//' \ - -e 's/ /,/g' -e 's/^ */#define ABI_TAG /' > $@.new; \ + ( echo "$$tagos" | \ + sed -e 's/[^0-9xXa-fA-F ]//' \ + -e 's/^/#define __ABI_TAG_OS /'; \ + echo "#ifndef __ABI_TAG_VERSION"; \ + echo "$$tagver" | \ + sed -e 's/[^0-9xXa-fA-F]/ /g' -e 's/ *$$//' \ + -e 's/ /,/g' -e 's/^/# define __ABI_TAG_VERSION /'; \ + echo "#endif" ) > $@.new; \ done if test -r $@.new; then mv -f $@.new $@; \ else echo >&2 'This configuration not matched in $<'; exit 1; fi diff --git a/csu/abi-note.S b/csu/abi-note.S index 6050883..3ad3a47 100644 --- a/csu/abi-note.S +++ b/csu/abi-note.S @@ -1,5 +1,5 @@ /* Special .init and .fini section support. - Copyright (C) 1997 Free Software Foundation, Inc. + Copyright (C) 1997, 2001 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it @@ -54,6 +54,7 @@ offset length contents identify the earliest release of that OS that supports this ABI. See abi-tags (top level) for details. */ +#include <config.h> #include <abi-tag.h> /* OS-specific ABI tag value */ /* The linker (GNU ld 2.8 and later) recognizes an allocated section whose @@ -67,5 +68,6 @@ offset length contents .long 1 /* note type */ 0: .asciz "GNU" /* vendor name */ 1: .align 4 -2: .long ABI_TAG /* note data: the ABI tag */ +2: .long __ABI_TAG_OS /* note data: the ABI tag */ + .long __ABI_TAG_VERSION 3: .align 4 /* pad out section */ diff --git a/elf/Makefile b/elf/Makefile index a4f0a10..dff36c9 100644 --- a/elf/Makefile +++ b/elf/Makefile @@ -188,7 +188,7 @@ $(objpfx)trusted-dirs.st: Makefile $(..)Makeconfig | $(AWK) -f gen-trusted-dirs.awk > ${@:st=T}; $(move-if-change) ${@:st=T} ${@:st=h} touch $@ -CPPFLAGS-dl-load.c = -I$(objpfx). +CPPFLAGS-dl-load.c = -I$(objpfx). -I$(csu-objpfx). ifeq (yes,$(build-shared)) $(inst_slibdir)/$(rtld-version-installed-name): $(objpfx)ld.so $(+force) diff --git a/elf/cache.c b/elf/cache.c index 378ce8f..19237bb 100644 --- a/elf/cache.c +++ b/elf/cache.c @@ -39,6 +39,7 @@ struct cache_entry char *lib; /* Library name. */ char *path; /* Path to find library. */ int flags; /* Flags to indicate kind of library. */ + unsigned int osversion; /* Required OS version. */ uint64_t hwcap; /* Important hardware capabilities. */ int bits_hwcap; /* Number of bits set in hwcap. */ struct cache_entry *next; /* Next entry in list. */ @@ -52,7 +53,8 @@ static const char *flag_descr[] = /* Print a single entry. */ static void -print_entry (const char *lib, int flag, uint64_t hwcap, const char *key) +print_entry (const char *lib, int flag, unsigned int osversion, + uint64_t hwcap, const char *key) { printf ("\t%s (", lib); switch (flag & FLAG_TYPE_MASK) @@ -61,7 +63,7 @@ print_entry (const char *lib, int flag, uint64_t hwcap, const char *key) case FLAG_ELF: case FLAG_ELF_LIBC5: case FLAG_ELF_LIBC6: - fputs (flag_descr [flag & FLAG_TYPE_MASK], stdout); + fputs (flag_descr[flag & FLAG_TYPE_MASK], stdout); break; default: fputs ("unknown", stdout); @@ -85,6 +87,23 @@ print_entry (const char *lib, int flag, uint64_t hwcap, const char *key) } if (hwcap != 0) printf (", hwcap: 0x%" PRIx64, hwcap); + if (osversion != 0) + { + static const char *const abi_tag_os[] = + { + [0] = "Linux", + [1] = "Hurd", + [2] = "Solaris", + [3] = "Unknown OS" + }; + unsigned int os = osversion >> 24; + + printf (", OS ABI: %s %d.%d.%d", + abi_tag_os[os > 3 ? 3 : os], + (osversion >> 16) & 0xff, + (osversion >> 8) & 0xff, + osversion & 0xff); + } printf (") => %s\n", key); } @@ -139,7 +158,8 @@ print_cache (const char *cache_name) else { size_t offset = ALIGN_CACHE (sizeof (struct cache_file) - + cache->nlibs * sizeof (struct file_entry)); + + (cache->nlibs + * sizeof (struct file_entry))); /* This is where the strings start. */ cache_data = (const char *) &cache->libs[cache->nlibs]; @@ -150,9 +170,10 @@ print_cache (const char *cache_name) cache_new = (struct cache_file_new *) ((void *)cache + offset); - if (!memcmp (cache_new->magic, CACHEMAGIC_NEW, sizeof CACHEMAGIC_NEW - 1) - && !memcmp (cache_new->version, CACHE_VERSION, - sizeof CACHE_VERSION - 1)) + if (memcmp (cache_new->magic, CACHEMAGIC_NEW, + sizeof CACHEMAGIC_NEW - 1) == 0 + && memcmp (cache_new->version, CACHE_VERSION, + sizeof CACHE_VERSION - 1) == 0) { cache_data = (const char *) cache_new; format = 1; @@ -167,17 +188,19 @@ print_cache (const char *cache_name) /* Print everything. */ for (i = 0; i < cache->nlibs; i++) print_entry (cache_data + cache->libs[i].key, - cache->libs[i].flags, 0, + cache->libs[i].flags, 0, 0, cache_data + cache->libs[i].value); } else if (format == 1) { - printf (_("%d libs found in cache `%s'\n"), cache_new->nlibs, cache_name); + printf (_("%d libs found in cache `%s'\n"), + cache_new->nlibs, cache_name); /* Print everything. */ for (i = 0; i < cache_new->nlibs; i++) print_entry (cache_data + cache_new->libs[i].key, cache_new->libs[i].flags, + cache_new->libs[i].osversion, cache_new->libs[i].hwcap, cache_data + cache_new->libs[i].value); } @@ -217,6 +240,10 @@ int compare (const struct cache_entry *e1, const struct cache_entry *e2) return 1; else if (e2->hwcap < e1->hwcap) return -1; + if (e2->osversion > e1->osversion) + return 1; + if (e2->osversion < e1->osversion) + return -1; } return res; } @@ -280,12 +307,15 @@ save_cache (const char *cache_name) /* And the list of all entries in the new format. */ file_entries_new_size = sizeof (struct cache_file_new) + cache_entry_count * sizeof (struct file_entry_new); - file_entries_new = (struct cache_file_new *) xmalloc (file_entries_new_size); + file_entries_new = + (struct cache_file_new *) xmalloc (file_entries_new_size); /* Fill in the header. */ memset (file_entries_new, 0, sizeof (struct cache_file_new)); - memcpy (file_entries_new->magic, CACHEMAGIC_NEW, sizeof CACHEMAGIC_NEW - 1); - memcpy (file_entries_new->version, CACHE_VERSION, sizeof CACHE_VERSION - 1); + memcpy (file_entries_new->magic, CACHEMAGIC_NEW, + sizeof CACHEMAGIC_NEW - 1); + memcpy (file_entries_new->version, CACHE_VERSION, + sizeof CACHE_VERSION - 1); file_entries_new->nlibs = cache_entry_count; file_entries_new->len_strings = total_strlen; @@ -319,9 +349,9 @@ save_cache (const char *cache_name) always begins at the beginning of the the new cache struct. */ file_entries_new->libs[idx_new].flags = entry->flags; + file_entries_new->libs[idx_new].osversion = entry->osversion; file_entries_new->libs[idx_new].hwcap = entry->hwcap; file_entries_new->libs[idx_new].key = str_offset; - file_entries_new->libs[idx_new].__unused = 0; } len = strlen (entry->lib); str = stpcpy (str, entry->lib); @@ -363,7 +393,8 @@ save_cache (const char *cache_name) /* Write contents. */ if (opt_format != 2) { - if (write (fd, file_entries, file_entries_size) != (ssize_t)file_entries_size) + if (write (fd, file_entries, file_entries_size) + != (ssize_t)file_entries_size) error (EXIT_FAILURE, errno, _("Writing of cache data failed")); } if (opt_format != 0) @@ -371,7 +402,7 @@ save_cache (const char *cache_name) /* Align cache. */ if (opt_format != 2) { - char zero [pad]; + char zero[pad]; if (write (fd, zero, pad) != (ssize_t)pad) error (EXIT_FAILURE, errno, _("Writing of cache data failed")); } @@ -414,7 +445,7 @@ save_cache (const char *cache_name) /* Add one library to the cache. */ void add_to_cache (const char *path, const char *lib, int flags, - uint64_t hwcap) + unsigned int osversion, uint64_t hwcap) { struct cache_entry *new_entry, *ptr, *prev; char *full_path; @@ -430,6 +461,7 @@ add_to_cache (const char *path, const char *lib, int flags, new_entry->lib = xstrdup (lib); new_entry->path = full_path; new_entry->flags = flags; + new_entry->osversion = osversion; new_entry->hwcap = hwcap; new_entry->bits_hwcap = 0; diff --git a/elf/dl-load.c b/elf/dl-load.c index 6e4c972..0a5603f 100644 --- a/elf/dl-load.c +++ b/elf/dl-load.c @@ -30,6 +30,8 @@ #include <sys/stat.h> #include <sys/types.h> #include "dynamic-link.h" +#include <abi-tag.h> +#include <dl-osinfo.h> #include <dl-dst.h> @@ -111,6 +113,8 @@ struct filebuf size_t _dl_pagesize; +unsigned int _dl_osversion; + int _dl_clktck; extern const char *_dl_platform; @@ -1061,12 +1065,12 @@ _dl_map_object_from_fd (const char *name, int fd, struct filebuf *fbp, if (__builtin_expect (_dl_debug_mask & DL_DEBUG_FILES, 0)) _dl_debug_printf (" dynamic: 0x%0*lx base: 0x%0*lx size: 0x%0*Zx\n" " entry: 0x%0*lx phdr: 0x%0*lx phnum: %*u\n\n", - sizeof (void *) * 2, (unsigned long int) l->l_ld, - sizeof (void *) * 2, (unsigned long int) l->l_addr, - sizeof (void *) * 2, maplength, - sizeof (void *) * 2, (unsigned long int) l->l_entry, - sizeof (void *) * 2, (unsigned long int) l->l_phdr, - sizeof (void *) * 2, l->l_phnum); + (int) sizeof (void *) * 2, (unsigned long int) l->l_ld, + (int) sizeof (void *) * 2, (unsigned long int) l->l_addr, + (int) sizeof (void *) * 2, maplength, + (int) sizeof (void *) * 2, (unsigned long int) l->l_entry, + (int) sizeof (void *) * 2, (unsigned long int) l->l_phdr, + (int) sizeof (void *) * 2, l->l_phnum); elf_get_dynamic_info (l); @@ -1213,6 +1217,10 @@ open_verify (const char *name, struct filebuf *fbp) [EI_OSABI] = ELFOSABI_SYSV, [EI_ABIVERSION] = 0 }; + static const struct { + ElfW(Word) vendorlen, datalen, type; + char vendor [4]; + } expected_note = { 4, 16, 1, "GNU" }; int fd; /* Open the file. We always open files read-only. */ @@ -1220,6 +1228,10 @@ open_verify (const char *name, struct filebuf *fbp) if (fd != -1) { ElfW(Ehdr) *ehdr; + ElfW(Phdr) *phdr, *ph; + ElfW(Word) *abi_note, abi_note_buf[8]; + unsigned int osversion; + size_t maplength; /* We successfully openened the file. Now verify it is a file we can use. */ @@ -1287,12 +1299,7 @@ open_verify (const char *name, struct filebuf *fbp) lose (0, fd, name, NULL, NULL, N_("ELF file version does not match current one")); if (! __builtin_expect (elf_machine_matches_host (ehdr), 1)) - { - close_and_out: - __close (fd); - __set_errno (ENOENT); - fd = -1; - } + goto close_and_out; else if (__builtin_expect (ehdr->e_phentsize, sizeof (ElfW(Phdr))) != sizeof (ElfW(Phdr))) lose (0, fd, name, NULL, NULL, @@ -1301,6 +1308,50 @@ open_verify (const char *name, struct filebuf *fbp) && __builtin_expect (ehdr->e_type, ET_EXEC) != ET_EXEC) lose (0, fd, name, NULL, NULL, N_("only ET_DYN and ET_EXEC can be loaded")); + + maplength = ehdr->e_phnum * sizeof (ElfW(Phdr)); + if (ehdr->e_phoff + maplength <= fbp->len) + phdr = (void *) (fbp->buf + ehdr->e_phoff); + else + { + phdr = alloca (maplength); + __lseek (fd, SEEK_SET, ehdr->e_phoff); + if (__libc_read (fd, (void *) phdr, maplength) != maplength) + lose (errno, fd, name, NULL, NULL, N_("cannot read file data")); + } + + /* Check .note.ABI-tag if present. */ + for (ph = phdr; ph < &phdr[ehdr->e_phnum]; ++ph) + if (ph->p_type == PT_NOTE && ph->p_filesz == 32 && ph->p_align >= 4) + { + if (ph->p_offset + 32 <= fbp->len) + abi_note = (void *) (fbp->buf + ph->p_offset); + else + { + __lseek (fd, SEEK_SET, ph->p_offset); + if (__libc_read (fd, (void *) abi_note_buf, 32) != 32) + lose (errno, fd, name, NULL, NULL, + N_("cannot read file data")); + abi_note = abi_note_buf; + } + + if (memcmp (abi_note, &expected_note, sizeof (expected_note))) + continue; + + osversion = (abi_note [5] & 0xff) * 65536 + + (abi_note [6] & 0xff) * 256 + + (abi_note [7] & 0xff); + if (abi_note [4] != __ABI_TAG_OS + || (_dl_osversion && _dl_osversion < osversion)) + { + close_and_out: + __close (fd); + __set_errno (ENOENT); + fd = -1; + } + + break; + } } return fd; diff --git a/elf/dl-minimal.c b/elf/dl-minimal.c index 5184c11..8922edc 100644 --- a/elf/dl-minimal.c +++ b/elf/dl-minimal.c @@ -252,6 +252,8 @@ __strtoul_internal (const char *nptr, char **endptr, int base, int group) || (result == ULONG_MAX / 10 && digval > ULONG_MAX % 10)) { errno = ERANGE; + if (endptr != NULL) + *endptr = (char *) nptr; return ULONG_MAX; } result *= base; @@ -259,5 +261,7 @@ __strtoul_internal (const char *nptr, char **endptr, int base, int group) ++nptr; } + if (endptr != NULL) + *endptr = (char *) nptr; return result * sign; } diff --git a/elf/ldconfig.c b/elf/ldconfig.c index 4c00bce..d3c5355 100644 --- a/elf/ldconfig.c +++ b/elf/ldconfig.c @@ -48,19 +48,11 @@ #define PACKAGE _libc_intl_domainname -struct lib_entry - { - int flags; - uint64_t hwcap; - char *lib; - char *path; - }; - static const struct { const char *name; int flag; -} lib_types [] = +} lib_types[] = { {"libc4", FLAG_LIBC4}, {"libc5", FLAG_ELF_LIBC5}, @@ -316,7 +308,7 @@ add_dir (const char *line) *equal_sign = '\0'; ++equal_sign; entry->flag = FLAG_ANY; - for (i = 0; i < sizeof (lib_types) / sizeof (lib_types [0]); ++i) + for (i = 0; i < sizeof (lib_types) / sizeof (lib_types[0]); ++i) if (strcmp (equal_sign, lib_types[i].name) == 0) { entry->flag = lib_types[i].flag; @@ -334,7 +326,7 @@ add_dir (const char *line) i = strlen (entry->path) - 1; while (entry->path[i] == '/' && i > 0) { - entry->path [i] = '\0'; + entry->path[i] = '\0'; --i; } @@ -460,6 +452,7 @@ manual_link (char *library) char *soname; struct stat64 stat_buf; int flag; + unsigned int osversion; /* Prepare arguments for create_links call. Split library name in directory and filename first. Since path is allocated, we've got @@ -524,7 +517,8 @@ manual_link (char *library) free (path); return; } - if (process_file (real_library, library, libname, &flag, &soname, 0)) + if (process_file (real_library, library, libname, &flag, &osversion, + &soname, 0)) { error (0, 0, _("No link created since soname could not be found for %s"), library); @@ -568,6 +562,7 @@ struct dlib_entry char *soname; int flag; int is_link; + unsigned int osversion; struct dlib_entry *next; }; @@ -585,6 +580,7 @@ search_dir (const struct dir_entry *entry) struct stat64 stat_buf; int is_link; uint64_t hwcap = path_hwcap (entry->path); + unsigned int osversion; file_name_len = PATH_MAX; file_name = alloca (file_name_len); @@ -700,7 +696,7 @@ search_dir (const struct dir_entry *entry) real_name = real_file_name; if (process_file (real_name, file_name, direntry->d_name, &flag, - &soname, is_link)) + &osversion, &soname, is_link)) { if (real_name != real_file_name) free (real_name); @@ -762,6 +758,11 @@ search_dir (const struct dir_entry *entry) error (0, 0, _("libraries %s and %s in directory %s have same soname but different type."), dlib_ptr->name, direntry->d_name, entry->path); } + /* OS version should be the same - sanity check. */ + if (dlib_ptr->osversion != osversion) + error (0, 0, _("libraries %s and %s in directory %s have same\n" + "soname but different minimal supported OS version."), + dlib_ptr->name, direntry->d_name, entry->path); free (dlib_ptr->name); dlib_ptr->name = xstrdup (direntry->d_name); dlib_ptr->is_link = is_link; @@ -778,6 +779,7 @@ search_dir (const struct dir_entry *entry) dlib_ptr = (struct dlib_entry *)xmalloc (sizeof (struct dlib_entry)); dlib_ptr->name = xstrdup (direntry->d_name); dlib_ptr->flag = flag; + dlib_ptr->osversion = osversion; dlib_ptr->soname = soname; dlib_ptr->is_link = is_link; /* Add at head of list. */ @@ -797,7 +799,8 @@ search_dir (const struct dir_entry *entry) create_links (dir_name, entry->path, dlib_ptr->name, dlib_ptr->soname); if (opt_build_cache) - add_to_cache (entry->path, dlib_ptr->soname, dlib_ptr->flag, hwcap); + add_to_cache (entry->path, dlib_ptr->soname, dlib_ptr->flag, + dlib_ptr->osversion, hwcap); } /* Free all resources. */ @@ -909,7 +912,7 @@ main (int argc, char **argv) { int i; for (i = remaining; i < argc; ++i) - add_dir (argv [i]); + add_dir (argv[i]); } if (opt_chroot) @@ -990,7 +993,7 @@ main (int argc, char **argv) int i; for (i = remaining; i < argc; ++i) - manual_link (argv [i]); + manual_link (argv[i]); exit (0); } diff --git a/elf/readlib.c b/elf/readlib.c index 746c78f..2886c5d 100644 --- a/elf/readlib.c +++ b/elf/readlib.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1999, 2000 Free Software Foundation, Inc. +/* Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Andreas Jaeger <aj@suse.de>, 1999 and Jakub Jelinek <jakub@redhat.com>, 1999. @@ -48,18 +48,18 @@ struct known_names int flag; }; -static struct known_names interpreters [] = +static struct known_names interpreters[] = { - {"/lib/" LD_SO, FLAG_ELF_LIBC6}, + { "/lib/" LD_SO, FLAG_ELF_LIBC6 }, #ifdef SYSDEP_KNOWN_INTERPRETER_NAMES SYSDEP_KNOWN_INTERPRETER_NAMES #endif }; -static struct known_names known_libs [] = +static struct known_names known_libs[] = { - {LIBC_SO, FLAG_ELF_LIBC6}, - {LIBM_SO, FLAG_ELF_LIBC6}, + { LIBC_SO, FLAG_ELF_LIBC6 }, + { LIBM_SO, FLAG_ELF_LIBC6 }, #ifdef SYSDEP_KNOWN_LIBRARY_NAMES SYSDEP_KNOWN_LIBRARY_NAMES #endif @@ -70,13 +70,13 @@ static struct known_names known_libs [] = /* Returns 0 if everything is ok, != 0 in case of error. */ int process_file (const char *real_file_name, const char *file_name, - const char *lib, int *flag, char **soname, int is_link) + const char *lib, int *flag, unsigned int *osversion, + char **soname, int is_link) { FILE *file; struct stat64 statbuf; void *file_contents; int ret; - ElfW(Ehdr) *elf_header; struct exec *aout_header; @@ -142,10 +142,7 @@ process_file (const char *real_file_name, const char *file_name, } elf_header = (ElfW(Ehdr) *) file_contents; - if (elf_header->e_ident [EI_MAG0] != ELFMAG0 - || elf_header->e_ident [EI_MAG1] != ELFMAG1 - || elf_header->e_ident [EI_MAG2] != ELFMAG2 - || elf_header->e_ident [EI_MAG3] != ELFMAG3) + if (memcmp (elf_header->e_ident, ELFMAG, SELFMAG) != 0) { /* The file is neither ELF nor aout. Check if it's a linker script, like libc.so - otherwise complain. */ @@ -161,8 +158,8 @@ process_file (const char *real_file_name, const char *file_name, goto done; } - if (process_elf_file (file_name, lib, flag, soname, file_contents, - statbuf.st_size)) + if (process_elf_file (file_name, lib, flag, osversion, soname, + file_contents, statbuf.st_size)) ret = 1; done: diff --git a/posix/fnmatch_loop.c b/posix/fnmatch_loop.c index 9400734..20ae0e3 100644 --- a/posix/fnmatch_loop.c +++ b/posix/fnmatch_loop.c @@ -1182,5 +1182,7 @@ EXT (INT opt, const CHAR *pattern, const CHAR *string, const CHAR *string_end, #undef MEMPCPY #undef MEMCHR #undef STRCOLL +#undef STRLEN +#undef STRCAT #undef L #undef BTOWC diff --git a/sysdeps/generic/dl-cache.c b/sysdeps/generic/dl-cache.c index 5e16f28..65135d4 100644 --- a/sysdeps/generic/dl-cache.c +++ b/sysdeps/generic/dl-cache.c @@ -228,6 +228,8 @@ _dl_load_cache_lookup (const char *name) /* Only accept hwcap if it's for the right platform. */ #define HWCAP_CHECK \ + if (_dl_osversion && cache_new->libs[middle].osversion > _dl_osversion) \ + continue; \ if (_DL_PLATFORMS_COUNT && platform != -1 \ && (cache_new->libs[middle].hwcap & _DL_HWCAP_PLATFORM) != 0 \ && (cache_new->libs[middle].hwcap & _DL_HWCAP_PLATFORM) != platform) \ diff --git a/sysdeps/generic/dl-cache.h b/sysdeps/generic/dl-cache.h index 2d02dcf..7938fc0 100644 --- a/sysdeps/generic/dl-cache.h +++ b/sysdeps/generic/dl-cache.h @@ -76,7 +76,7 @@ struct file_entry_new { int32_t flags; /* This is 1 for an ELF library. */ uint32_t key, value; /* String table indices. */ - uint32_t __unused; /* Align next field always on 8 byte boundary. */ + uint32_t osversion; /* Required OS version. */ uint64_t hwcap; /* Hwcap entry. */ }; diff --git a/sysdeps/generic/ldconfig.h b/sysdeps/generic/ldconfig.h index aaad06d..0575f48 100644 --- a/sysdeps/generic/ldconfig.h +++ b/sysdeps/generic/ldconfig.h @@ -39,17 +39,17 @@ extern void init_cache (void); extern void save_cache (const char *cache_name); extern void add_to_cache (const char *path, const char *lib, int flags, - uint64_t hwcap); + unsigned int osversion, uint64_t hwcap); /* Declared in readlib.c. */ extern int process_file (const char *real_file_name, const char *file_name, - const char *lib, int *flag, char **soname, - int is_link); + const char *lib, int *flag, unsigned int *osversion, + char **soname, int is_link); /* Declared in readelflib.c. */ extern int process_elf_file (const char *file_name, const char *lib, int *flag, - char **soname, void *file_contents, - size_t file_length); + unsigned int *osversion, char **soname, + void *file_contents, size_t file_length); /* Declared in chroot_canon.c. */ extern char *chroot_canon (const char *chroot, const char *name); diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h index 0575eaf..bcdcf7d 100644 --- a/sysdeps/generic/ldsodefs.h +++ b/sysdeps/generic/ldsodefs.h @@ -173,6 +173,9 @@ extern char **_dl_argv; /* Cached value of `getpagesize ()'. */ extern size_t _dl_pagesize; +/* OS version. */ +extern unsigned int _dl_osversion; + /* File descriptor referring to the zero-fill device. */ extern int _dl_zerofd; diff --git a/sysdeps/generic/readelflib.c b/sysdeps/generic/readelflib.c index 2797c28..5354526 100644 --- a/sysdeps/generic/readelflib.c +++ b/sysdeps/generic/readelflib.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1999, 2000 Free Software Foundation, Inc. +/* Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Andreas Jaeger <aj@suse.de>, 1999 and Jakub Jelinek <jakub@redhat.com>, 1999. @@ -41,7 +41,8 @@ do \ /* Returns 0 if everything is ok, != 0 in case of error. */ int process_elf_file (const char *file_name, const char *lib, int *flag, - char **soname, void *file_contents, size_t file_length) + unsigned int *osversion, char **soname, void *file_contents, + size_t file_length) { int i; unsigned int j; @@ -56,6 +57,7 @@ process_elf_file (const char *file_name, const char *lib, int *flag, char *dynamic_strings; elf_header = (ElfW(Ehdr) *) file_contents; + *osversion = 0; if (elf_header->e_ident [EI_CLASS] != ElfW (CLASS)) { @@ -110,6 +112,7 @@ process_elf_file (const char *file_name, const char *lib, int *flag, dynamic_addr = segment->p_offset; dynamic_size = segment->p_filesz; break; + case PT_INTERP: program_interpreter = (char *) (file_contents + segment->p_offset); check_ptr (program_interpreter); @@ -123,6 +126,21 @@ process_elf_file (const char *file_name, const char *lib, int *flag, break; } break; + + case PT_NOTE: + if (!*osversion && segment->p_filesz == 32 && segment->p_align >= 4) + { + ElfW(Word) *abi_note = (ElfW(Word) *) (file_contents + + segment->p_offset); + if (abi_note [0] == 4 && abi_note [1] == 16 && abi_note [2] == 1 + && memcmp (abi_note + 3, "GNU", 4) == 0) + *osversion = (abi_note [4] << 24) | + ((abi_note [5] & 0xff) << 16) | + ((abi_note [6] & 0xff) << 8) | + (abi_note [7] & 0xff); + } + break; + default: break; } diff --git a/sysdeps/unix/sysv/linux/configure b/sysdeps/unix/sysv/linux/configure index e6d4a7d..fc5297d 100644 --- a/sysdeps/unix/sysv/linux/configure +++ b/sysdeps/unix/sysv/linux/configure @@ -87,6 +87,7 @@ if test -n "$minimum_kernel"; then echo $ac_n "checking for kernel header at least $minimum_kernel""... $ac_c" 1>&6 echo "configure:89: checking for kernel header at least $minimum_kernel" >&5 decnum=`echo "$minimum_kernel.0.0.0" | sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\).*/(\1 * 65536 + \2 * 256 + \3)/'`; + abinum=`echo "$minimum_kernel.0.0.0" | sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\).*/\1,\2,\3/'`; cat > conftest.$ac_ext <<EOF #line 92 "configure" #include "confdefs.h" @@ -111,6 +112,10 @@ rm -f conftest* #define __LINUX_KERNEL_VERSION $decnum EOF + cat >> confdefs.h <<EOF +#define __ABI_TAG_VERSION $abinum +EOF + else { echo "configure: error: *** The available kernel headers are older than the requested *** compatible kernel version" 1>&2; exit 1; } diff --git a/sysdeps/unix/sysv/linux/configure.in b/sysdeps/unix/sysv/linux/configure.in index 7d538e8..afe7982 100644 --- a/sysdeps/unix/sysv/linux/configure.in +++ b/sysdeps/unix/sysv/linux/configure.in @@ -74,6 +74,7 @@ if test -n "$minimum_kernel"; then AC_MSG_CHECKING(for kernel header at least $minimum_kernel) changequote(,)dnl decnum=`echo "$minimum_kernel.0.0.0" | sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\).*/(\1 * 65536 + \2 * 256 + \3)/'`; + abinum=`echo "$minimum_kernel.0.0.0" | sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\).*/\1,\2,\3/'`; changequote([,])dnl AC_EGREP_CPP([eat flaming death], [#include <linux/version.h> #if LINUX_VERSION_CODE < $decnum @@ -82,6 +83,7 @@ eat flaming death AC_MSG_RESULT($libc_minimum_kernel) if test "$libc_minimum_kernel" = ok; then AC_DEFINE_UNQUOTED(__LINUX_KERNEL_VERSION, $decnum) + AC_DEFINE_UNQUOTED(__ABI_TAG_VERSION, $abinum) else AC_MSG_ERROR([*** The available kernel headers are older than the requested *** compatible kernel version]) diff --git a/sysdeps/unix/sysv/linux/dl-librecon.h b/sysdeps/unix/sysv/linux/dl-librecon.h new file mode 100644 index 0000000..843e874 --- /dev/null +++ b/sysdeps/unix/sysv/linux/dl-librecon.h @@ -0,0 +1,49 @@ +/* Optional code to distinguish library flavours. + Copyright (C) 2001 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek <jakub@redhat.com>, 2001. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _DL_LIBRECON_H +#define _DL_LIBRECON_H 1 + +/* Recognizing extra environment variables. */ +#define EXTRA_LD_ENVVARS \ + case 13: \ + if (memcmp (&envline[3], "ASSUME_KERNEL", 13) == 0) \ + { \ + unsigned long int i, j, osversion = 0; \ + char *p = &envline[17], *q; \ + \ + for (i = 0; i < 3; i++, p = q + 1) \ + { \ + j = __strtoul_internal (p, &q, 0, 0); \ + if (j >= 255 || p == q || (i < 2 && *q && *q != '.')) \ + { \ + osversion = 0; \ + break; \ + } \ + osversion |= j << (16 - 8 * i); \ + if (!*q) \ + break; \ + } \ + if (osversion) \ + _dl_osversion = osversion; \ + break; \ + } + +#endif /* dl-librecon.h */ diff --git a/sysdeps/unix/sysv/linux/dl-osinfo.h b/sysdeps/unix/sysv/linux/dl-osinfo.h index a56f8e6..e9bacf4 100644 --- a/sysdeps/unix/sysv/linux/dl-osinfo.h +++ b/sysdeps/unix/sysv/linux/dl-osinfo.h @@ -102,5 +102,7 @@ dl_fatal (const char *str) if (version < __LINUX_KERNEL_VERSION) \ /* Not sufficent. */ \ FATAL ("FATAL: kernel too old\n"); \ + \ + _dl_osversion = version; \ } \ } while (0) diff --git a/sysdeps/unix/sysv/linux/i386/dl-librecon.h b/sysdeps/unix/sysv/linux/i386/dl-librecon.h index 7d486c5..26311b3 100644 --- a/sysdeps/unix/sysv/linux/i386/dl-librecon.h +++ b/sysdeps/unix/sysv/linux/i386/dl-librecon.h @@ -48,6 +48,29 @@ /* Recognizing extra environment variables. */ #define EXTRA_LD_ENVVARS \ + case 13: \ + if (memcmp (&envline[3], "ASSUME_KERNEL", 13) == 0) \ + { \ + unsigned long int i, j, osversion = 0; \ + char *p = &envline[17], *q; \ + \ + for (i = 0; i < 3; i++, p = q + 1) \ + { \ + j = __strtoul_internal (p, &q, 0, 0); \ + if (j >= 255 || p == q || (i < 2 && *q && *q != '.')) \ + { \ + osversion = 0; \ + break; \ + } \ + osversion |= j << (16 - 8 * i); \ + if (!*q) \ + break; \ + } \ + if (osversion) \ + _dl_osversion = osversion; \ + break; \ + } \ + \ case 15: \ if (memcmp (&envline[3], "LIBRARY_VERSION", 15) == 0) \ { \ diff --git a/sysdeps/unix/sysv/linux/i386/readelflib.c b/sysdeps/unix/sysv/linux/i386/readelflib.c index f8868bb..cc219d2 100644 --- a/sysdeps/unix/sysv/linux/i386/readelflib.c +++ b/sysdeps/unix/sysv/linux/i386/readelflib.c @@ -20,23 +20,24 @@ int process_elf32_file (const char *file_name, const char *lib, int *flag, - char **soname, void *file_contents, - size_t file_length); + unsigned int *osversion, char **soname, + void *file_contents, size_t file_length); int process_elf64_file (const char *file_name, const char *lib, int *flag, - char **soname, void *file_contents, - size_t file_length); + unsigned int *osversion, char **soname, + void *file_contents, size_t file_length); /* Returns 0 if everything is ok, != 0 in case of error. */ int process_elf_file (const char *file_name, const char *lib, int *flag, - char **soname, void *file_contents, size_t file_length) + unsigned int *osversion, char **soname, void *file_contents, + size_t file_length) { ElfW(Ehdr) *elf_header = (ElfW(Ehdr) *) file_contents; int ret; if (elf_header->e_ident [EI_CLASS] == ELFCLASS32) - return process_elf32_file (file_name, lib, flag, soname, file_contents, - file_length); + return process_elf32_file (file_name, lib, flag, osversion, soname, + file_contents, file_length); else { switch (elf_header->e_machine) @@ -50,8 +51,8 @@ process_elf_file (const char *file_name, const char *lib, int *flag, return 1; } - ret = process_elf64_file (file_name, lib, flag, soname, file_contents, - file_length); + ret = process_elf64_file (file_name, lib, flag, osversion, soname, + file_contents, file_length); /* IA64/X86-64 64bit libraries are always libc.so.6+. */ if (!ret) switch (elf_header->e_machine) diff --git a/sysdeps/unix/sysv/linux/ia64/readelflib.c b/sysdeps/unix/sysv/linux/ia64/readelflib.c index 29a402b..efc699f 100644 --- a/sysdeps/unix/sysv/linux/ia64/readelflib.c +++ b/sysdeps/unix/sysv/linux/ia64/readelflib.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2000 Free Software Foundation, Inc. +/* Copyright (C) 2000, 2001 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -18,25 +18,28 @@ int process_elf32_file (const char *file_name, const char *lib, int *flag, - char **soname, void *file_contents, size_t file_length); + unsigned int *osversion, char **soname, + void *file_contents, size_t file_length); int process_elf64_file (const char *file_name, const char *lib, int *flag, - char **soname, void *file_contents, size_t file_length); + unsigned int *osversion, char **soname, + void *file_contents, size_t file_length); /* Returns 0 if everything is ok, != 0 in case of error. */ int process_elf_file (const char *file_name, const char *lib, int *flag, - char **soname, void *file_contents, size_t file_length) + unsigned int *osversion, char **soname, + void *file_contents, size_t file_length) { ElfW(Ehdr) *elf_header = (ElfW(Ehdr) *) file_contents; int ret; if (elf_header->e_ident [EI_CLASS] == ELFCLASS32) - return process_elf32_file (file_name, lib, flag, soname, file_contents, - file_length); + return process_elf32_file (file_name, lib, flag, osversion, soname, + file_contents, file_length); else { - ret = process_elf64_file (file_name, lib, flag, soname, file_contents, - file_length); + ret = process_elf64_file (file_name, lib, flag, osversion, soname, + file_contents, file_length); /* Intel 64bit libraries are always libc.so.6+. */ if (!ret) *flag = FLAG_IA64_LIB64|FLAG_ELF_LIBC6; diff --git a/sysdeps/unix/sysv/linux/init-first.c b/sysdeps/unix/sysv/linux/init-first.c index 512a696..017878a 100644 --- a/sysdeps/unix/sysv/linux/init-first.c +++ b/sysdeps/unix/sysv/linux/init-first.c @@ -29,6 +29,7 @@ #include <libc-internal.h> #ifndef SHARED +# include <ldsodefs.h> # include "dl-osinfo.h" #endif diff --git a/sysdeps/unix/sysv/linux/sparc/readelflib.c b/sysdeps/unix/sysv/linux/sparc/readelflib.c index f500627..f8d383e 100644 --- a/sysdeps/unix/sysv/linux/sparc/readelflib.c +++ b/sysdeps/unix/sysv/linux/sparc/readelflib.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1999 Free Software Foundation, Inc. +/* Copyright (C) 1999, 2001 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Andreas Jaeger <aj@suse.de>, 1999 and Jakub Jelinek <jakub@redhat.com>, 1999. @@ -20,27 +20,28 @@ int process_elf32_file (const char *file_name, const char *lib, int *flag, - char **soname, void *file_contents, - size_t file_length); + unsigned int *osversion, char **soname, + void *file_contents, size_t file_length); int process_elf64_file (const char *file_name, const char *lib, int *flag, - char **soname, void *file_contents, - size_t file_length); + unsigned int *osversion, char **soname, + void *file_contents, size_t file_length); /* Returns 0 if everything is ok, != 0 in case of error. */ int process_elf_file (const char *file_name, const char *lib, int *flag, - char **soname, void *file_contents, size_t file_length) + unsigned int *osversion, char **soname, void *file_contents, + size_t file_length) { ElfW(Ehdr) *elf_header = (ElfW(Ehdr) *) file_contents; int ret; if (elf_header->e_ident [EI_CLASS] == ELFCLASS32) - return process_elf32_file (file_name, lib, flag, soname, file_contents, - file_length); + return process_elf32_file (file_name, lib, flag, osversion, soname, + file_contents, file_length); else { - ret = process_elf64_file (file_name, lib, flag, soname, file_contents, - file_length); + ret = process_elf64_file (file_name, lib, flag, osversion, soname, + file_contents, file_length); /* Sparc 64bit libraries are always libc.so.6+. */ if (!ret) *flag = FLAG_SPARC_LIB64|FLAG_ELF_LIBC6; |