diff options
author | Ulrich Drepper <drepper@redhat.com> | 2001-03-16 07:40:05 +0000 |
---|---|---|
committer | Ulrich Drepper <drepper@redhat.com> | 2001-03-16 07:40:05 +0000 |
commit | a986484f67346b28ff09833c1f4fd3505b52138e (patch) | |
tree | 598498dabf381610b1d7e27815917d67426bc34a /elf/dl-load.c | |
parent | 328c5f650ffcdc8f10e4ebd6f741ad0b8e6ea1c1 (diff) | |
download | glibc-a986484f67346b28ff09833c1f4fd3505b52138e.zip glibc-a986484f67346b28ff09833c1f4fd3505b52138e.tar.gz glibc-a986484f67346b28ff09833c1f4fd3505b52138e.tar.bz2 |
Update.
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.
Diffstat (limited to 'elf/dl-load.c')
-rw-r--r-- | elf/dl-load.c | 75 |
1 files changed, 63 insertions, 12 deletions
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; |