From 266180eb985e14fa9f77cfd3b41e9211e9986162 Mon Sep 17 00:00:00 2001 From: Roland McGrath Date: Mon, 10 Jun 1996 10:18:47 +0000 Subject: Mon Jun 10 06:14:03 1996 Roland McGrath * sysdeps/mach/hurd/dl-sysdep.c (__open): Define this instead of open. (__close, __mmap): Likewise define with __ names now. Mon Jun 10 05:13:18 1996 Roland McGrath * elf/dl-support.c: New file. * elf/Makefile (CFLAGS-dl-support.c): New variable. (routines, elide-routines.so): Add dl-support. * elf/dl-minimal.c (_dl_pagesize): Remove common defn. * elf/dl-load.c (_dl_pagesize): Define it here. (_dl_map_object_from_fd): Initialize it if zero. * elf/link.h (_dl_pagesize): Remove const. Sun Jun 9 04:04:26 1996 Roland McGrath * elf/Makefile (routines): Add dl-symbol. * elf/dl-lookup.c (_dl_symbol_value): Moved to ... * elf/dl-symbol.c: New file. * elf/elf.h (Elf32_Xword, Elf32_Sxword): New types. (Elf32_Section, Elf64_Section): New types, 16 bits. (Elf32_Sym, Elf64_Sym): Use it. * elf/dl-deps.c (_dl_open): Moved to ... * elf/dl-open.c: New file. * Makefile (routines): Add dl-open. * elf/Makefile (dl-routines): New variable. (routines): Add $(dl-routines). (elide-routines.so): New variable, set to $(dl-routines). (libdl-inhibit-o): Variable removed; build all flavors of -ldl. (rtld-routines): All but rtld, dl-sysdep, and dl-minimal moved to $(dl-routines). * elf/dl-lookup.c (_dl_lookup_symbol): Remove magic symbol grokage. * elf/dladdr.c: Use ELFW(ST_BIND) in place of ELF32_ST_BIND. * elf/dl-load.c (open_path): Use __ names for open and close. Avoid using strdup. (_dl_map_object): Likewise. (_dl_map_object_from_fd): Use __ names for mmap, munmap, and mprotect. * elf/dl-minimal.c (malloc): Likewise. * elf/dl-reloc.c (_dl_relocate_object): Likewise. * elf/dl-minimal.c (_dl_pagesize): New variable. (malloc): Use that instead of a static variable. * elf/dl-reloc.c (_dl_relocate_object): Use _dl_pagesize instead of calling getpagesize. * elf/dl-load.c (_dl_map_object_from_fd): Likewise. * elf/link.h: Declare _dl_pagesize. * elf/rtld.c (dl_r_debug): Renamed to _dl_r_debug. * elf/link.h (struct link_map): Use Half for l_phnum instead of Word. * elf/rtld.c (dl_main): Use Half for phdr count arg. (_dl_sysdep_start): Update prototype of DL_MAIN function ptr arg. * elf/dl-load.c (_dl_map_object_from_fd): Use explicit Elf32_Word to extract 4-byte magic number, not ElfW(Word). Match EI_CLASS against native wordsize, either 32 or 64. * elf/elf.h (Elf64_Byte, Elf64_Section): Typedefs removed. In C a char is always a byte, no need for a typedef. Section indices are 16-bit quantities in elf64, which already have a typedef Elf64_Half. Remove partial -lelf implementation. There is now a separately-distributed `libelf' package that implements it. * elf/dl-lookup.c: Don't #include any more. (_dl_elf_hash): New function, moved from libelf.h:elf_hash. (_dl_lookup_symbol): Use it instead of elf_hash. * elf/libelf.h: File removed. * elf/elf_hash.c: File removed. * elf/Makefile (headers): Remove libelf.h. (extra-libs): Remove libelf. (libelf-routines): Variable removed. * elf/Makefile (libdl.so): Remove commands from this target. The implicit rule commands are correct, this explicit rule just serves to add some dependencies. * elf/dl-lookup.c (_dl_lookup_symbol): Use ELFW(ST_TYPE) in place of ELF32_ST_TYPE. Likewise ST_BIND. * elf/do-rel.h (elf_dynamic_do_rel): Likewise R_SYM. * elf/link.h (ElfW): New macro for wordsize-independent ElfXX_* type naming. (ELFW): New macro, likewise for ELFXX_* macro naming. (_ElfW, _ElfW_1): New macros, subroutines of ElfW and ELF. Sat Jun 8 20:52:38 1996 Roland McGrath * elf/link.h, elf/do-rel.h, elf/dynamic-link.h, elf/dl-deps.c, elf/dl-init.c, elf/dl-load.c, elf/dl-lookup.c, elf/dl-reloc.c, elf/dl-runtime.c, elf/dladdr.c, elf/dlclose.c, elf/dlsym.c, elf/linux-compat.c, elf/rtld.c: Change all uses of `Elf32_XXX' to `ElfW(XXX)' for wordsize-independence. Sat Jun 8 20:50:42 1996 Richard Henderson * elf/elf.h: Move Elf64_* types in parity with Elf32 counterparts. (Elf64_auxv_t): New type. (EM_ALPHA, R_ALPHA_*): New macros for elf64-alpha format. --- ChangeLog | 108 ++++++++++++++++ elf/Makefile | 36 +++--- elf/dl-deps.c | 27 +--- elf/dl-init.c | 2 +- elf/dl-load.c | 133 ++++++++++++-------- elf/dl-lookup.c | 103 +++++++-------- elf/dl-minimal.c | 17 ++- elf/dl-open.c | 45 +++++++ elf/dl-reloc.c | 28 ++--- elf/dl-runtime.c | 24 ++-- elf/dl-support.c | 51 ++++++++ elf/dl-symbol.c | 33 +++++ elf/dladdr.c | 8 +- elf/dlclose.c | 6 +- elf/dlsym.c | 4 +- elf/do-rel.h | 24 ++-- elf/dynamic-link.h | 6 +- elf/elf.h | 242 ++++++++++++++++++++++++------------ elf/elf_hash.c | 4 - elf/libelf.h | 283 ------------------------------------------ elf/link.h | 47 ++++--- elf/linux-compat.c | 4 +- elf/rtld.c | 42 +++---- sysdeps/mach/hurd/dl-sysdep.c | 12 +- 24 files changed, 667 insertions(+), 622 deletions(-) create mode 100644 elf/dl-open.c create mode 100644 elf/dl-support.c create mode 100644 elf/dl-symbol.c delete mode 100644 elf/elf_hash.c delete mode 100644 elf/libelf.h diff --git a/ChangeLog b/ChangeLog index 295384bc0b..16f8c5b832 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,111 @@ +Mon Jun 10 06:14:03 1996 Roland McGrath + + * sysdeps/mach/hurd/dl-sysdep.c (__open): Define this instead of open. + (__close, __mmap): Likewise define with __ names now. + +Mon Jun 10 05:13:18 1996 Roland McGrath + + * elf/dl-support.c: New file. + * elf/Makefile (CFLAGS-dl-support.c): New variable. + (routines, elide-routines.so): Add dl-support. + + * elf/dl-minimal.c (_dl_pagesize): Remove common defn. + * elf/dl-load.c (_dl_pagesize): Define it here. + (_dl_map_object_from_fd): Initialize it if zero. + * elf/link.h (_dl_pagesize): Remove const. + +Sun Jun 9 04:04:26 1996 Roland McGrath + + * elf/Makefile (routines): Add dl-symbol. + * elf/dl-lookup.c (_dl_symbol_value): Moved to ... + * elf/dl-symbol.c: New file. + + * elf/elf.h (Elf32_Xword, Elf32_Sxword): New types. + (Elf32_Section, Elf64_Section): New types, 16 bits. + (Elf32_Sym, Elf64_Sym): Use it. + + * elf/dl-deps.c (_dl_open): Moved to ... + * elf/dl-open.c: New file. + * Makefile (routines): Add dl-open. + + * elf/Makefile (dl-routines): New variable. + (routines): Add $(dl-routines). + (elide-routines.so): New variable, set to $(dl-routines). + (libdl-inhibit-o): Variable removed; build all flavors of -ldl. + (rtld-routines): All but rtld, dl-sysdep, and dl-minimal moved to + $(dl-routines). + + * elf/dl-lookup.c (_dl_lookup_symbol): Remove magic symbol grokage. + + * elf/dladdr.c: Use ELFW(ST_BIND) in place of ELF32_ST_BIND. + + * elf/dl-load.c (open_path): Use __ names for open and close. Avoid + using strdup. + (_dl_map_object): Likewise. + (_dl_map_object_from_fd): Use __ names for mmap, munmap, and mprotect. + * elf/dl-minimal.c (malloc): Likewise. + * elf/dl-reloc.c (_dl_relocate_object): Likewise. + + * elf/dl-minimal.c (_dl_pagesize): New variable. + (malloc): Use that instead of a static variable. + * elf/dl-reloc.c (_dl_relocate_object): Use _dl_pagesize instead of + calling getpagesize. + * elf/dl-load.c (_dl_map_object_from_fd): Likewise. + * elf/link.h: Declare _dl_pagesize. + + * elf/rtld.c (dl_r_debug): Renamed to _dl_r_debug. + + * elf/link.h (struct link_map): Use Half for l_phnum instead of Word. + * elf/rtld.c (dl_main): Use Half for phdr count arg. + (_dl_sysdep_start): Update prototype of DL_MAIN function ptr arg. + + * elf/dl-load.c (_dl_map_object_from_fd): Use explicit Elf32_Word to + extract 4-byte magic number, not ElfW(Word). Match EI_CLASS against + native wordsize, either 32 or 64. + + * elf/elf.h (Elf64_Byte, Elf64_Section): Typedefs removed. In C a + char is always a byte, no need for a typedef. Section indices are + 16-bit quantities in elf64, which already have a typedef Elf64_Half. + + Remove partial -lelf implementation. There is now a + separately-distributed `libelf' package that implements it. + * elf/dl-lookup.c: Don't #include any more. + (_dl_elf_hash): New function, moved from + libelf.h:elf_hash. + (_dl_lookup_symbol): Use it instead of elf_hash. + * elf/libelf.h: File removed. + * elf/elf_hash.c: File removed. + * elf/Makefile (headers): Remove libelf.h. + (extra-libs): Remove libelf. + (libelf-routines): Variable removed. + + * elf/Makefile (libdl.so): Remove commands from this target. The + implicit rule commands are correct, this explicit rule just serves to + add some dependencies. + + * elf/dl-lookup.c (_dl_lookup_symbol): Use ELFW(ST_TYPE) in place of + ELF32_ST_TYPE. Likewise ST_BIND. + * elf/do-rel.h (elf_dynamic_do_rel): Likewise R_SYM. + + * elf/link.h (ElfW): New macro for wordsize-independent ElfXX_* type + naming. + (ELFW): New macro, likewise for ELFXX_* macro naming. + (_ElfW, _ElfW_1): New macros, subroutines of ElfW and ELF. + +Sat Jun 8 20:52:38 1996 Roland McGrath + + * elf/link.h, elf/do-rel.h, elf/dynamic-link.h, elf/dl-deps.c, + elf/dl-init.c, elf/dl-load.c, elf/dl-lookup.c, elf/dl-reloc.c, + elf/dl-runtime.c, elf/dladdr.c, elf/dlclose.c, elf/dlsym.c, + elf/linux-compat.c, elf/rtld.c: Change all uses of `Elf32_XXX' to + `ElfW(XXX)' for wordsize-independence. + +Sat Jun 8 20:50:42 1996 Richard Henderson + + * elf/elf.h: Move Elf64_* types in parity with Elf32 counterparts. + (Elf64_auxv_t): New type. + (EM_ALPHA, R_ALPHA_*): New macros for elf64-alpha format. + Mon Jun 10 02:22:24 1996 Roland McGrath * sysdeps/unix/sysv/linux/configure.in: New file, start with configure. diff --git a/elf/Makefile b/elf/Makefile index b144e903e6..34be12e769 100644 --- a/elf/Makefile +++ b/elf/Makefile @@ -20,18 +20,25 @@ subdir := elf -headers := elf.h libelf.h link.h dlfcn.h -routines := init-first +headers = elf.h link.h dlfcn.h +routines = init-first $(dl-routines) dl-open dl-symbol dl-support + +# The core dynamic linking functions are in libc for the static and +# profiled libraries. +dl-routines = $(addprefix dl-,load lookup object reloc deps \ + runtime error init fini) +# But they are absent from the shared libc, because that code is in ld.so. +elide-routines.so = $(dl-routines) dl-support + +# ld.so uses those routines, plus some special stuff for being the program +# interpreter and operating independent of libc. +rtld-routines := rtld $(dl-routines) dl-sysdep dl-minimal +distribute = $(rtld-routines:=.c) dynamic-link.h do-rel.h dl-machine.h \ + soinit.c sofini.c ldd.sh.in linux-compat.c -extra-libs = libelf libdl -libelf-routines := elf_hash +extra-libs = libdl libdl-routines := dlopen dlclose dlsym dlerror dladdr -libdl-inhibit-o = $(filter-out .so,$(object-suffixes)) # Build only shared. -rtld-routines := rtld $(addprefix dl-,minimal load lookup object reloc \ - deps runtime sysdep error init fini) -distribute = $(rtld-routines:=.c) dynamic-link.h do-rel.h dl-machine.h \ - soinit.c sofini.c ldd.sh.in linux-compat.c all: # Make this the default target; it will be defined in Rules. @@ -43,7 +50,7 @@ generated = librtld.so dl-allobjs.so install-others = $(slibdir)/$(rtld-installed-name) install-bin = ldd -# Make sure these things is built in the `make lib' pass so it can be used +# Make sure these things are built in the `make lib' pass so they can be used # to run programs during the `make others' pass. lib-noranlib: $(objpfx)ld.so $(addprefix $(objpfx),$(extra-objs)) @@ -81,16 +88,17 @@ $(LINK.o) -nostdlib -nostartfiles -shared -o $@ \ -Wl,-rpath=$(default-rpath) $^ endef +# The dl code in the static libc needs a default library path. +CFLAGS-dl-support.c = -D'DEFAULT_RPATH="$(default-rpath)"' + # The Linux-compatible dynamic linker shared object is just the same # with one object file of compatibility initialization code added. $(objpfx)ld-linux.so.1: $(objpfx)linux-compat.so +# Specify the dependencies of libdl.so; its commands come from the generic +# rule to build a shared library. $(objpfx)libdl.so: $(objpfx)libdl_pic.a $(common-objpfx)libc.so $(objpfx)ld.so - $(patsubst %/,cd %;,$(objpfx)) \ - $(LINK.o) -shared -o $(@:$(objpfx)%=%) \ - $(LDFLAGS.so) $(LDFLAGS-dl.so) \ - -Wl,--whole-archive $(^:$(objpfx)%=%) $(no-whole-archive) $(slibdir)/$(rtld-installed-name): $(objpfx)ld.so; $(do-install-program) $(slibdir)/ld-linux.so.1: $(objpfx)ld-linux.so.1; $(do-install-program) diff --git a/elf/dl-deps.c b/elf/dl-deps.c index 92403d4110..7e3b259362 100644 --- a/elf/dl-deps.c +++ b/elf/dl-deps.c @@ -56,7 +56,7 @@ _dl_map_object_deps (struct link_map *map) { const char *strtab = ((void *) l->l_addr + l->l_info[DT_STRTAB]->d_un.d_ptr); - const Elf32_Dyn *d; + const ElfW(Dyn) *d; for (d = l->l_ld; d->d_tag != DT_NULL; ++d) if (d->d_tag == DT_NEEDED) { @@ -97,28 +97,3 @@ _dl_map_object_deps (struct link_map *map) scanp->map->l_reserved = 0; } } - - -struct link_map * -_dl_open (struct link_map *parent, const char *file, int mode) -{ - struct link_map *new, *l; - Elf32_Addr init; - - /* Load the named object. */ - new = _dl_map_object (parent, file); - - /* Load that object's dependencies. */ - _dl_map_object_deps (new); - - /* Relocate the objects loaded. */ - for (l = new; l; l = l->l_next) - if (! l->l_relocated) - _dl_relocate_object (l, (mode & RTLD_BINDING_MASK) == RTLD_LAZY); - - /* Run the initializer functions of new objects. */ - while (init = _dl_init_next (new)) - (*(void (*) (void)) init) (); - - return new; -} diff --git a/elf/dl-init.c b/elf/dl-init.c index ee99ce3dec..66ef83e28b 100644 --- a/elf/dl-init.c +++ b/elf/dl-init.c @@ -24,7 +24,7 @@ Cambridge, MA 02139, USA. */ /* Run initializers for MAP and its dependencies, in inverse dependency order (that is, leaf nodes first). */ -Elf32_Addr +ElfW(Addr) _dl_init_next (struct link_map *map) { unsigned int i; diff --git a/elf/dl-load.c b/elf/dl-load.c index 8103c7af2a..c6acc8c222 100644 --- a/elf/dl-load.c +++ b/elf/dl-load.c @@ -60,6 +60,7 @@ Cambridge, MA 02139, USA. */ #define STRING(x) #x int _dl_zerofd = -1; +size_t _dl_pagesize; /* Try to open NAME in one of the directories in DIRPATH. @@ -82,31 +83,48 @@ open_path (const char *name, size_t namelen, return -1; } - buf = alloca (strlen (dirpath) + 1 + namelen); + buf = __alloca (strlen (dirpath) + 1 + namelen); do { + size_t buflen; + dirpath = p; p = strpbrk (dirpath, ":;"); if (p == NULL) p = strchr (dirpath, '\0'); if (p == dirpath) - /* Two adjacent colons, or a colon at the beginning or the end of - the path means to search the current directory. */ - (void) memcpy (buf, name, namelen); + { + /* Two adjacent colons, or a colon at the beginning or the end of + the path means to search the current directory. */ + (void) memcpy (buf, name, namelen); + buflen = namelen; + } else { /* Construct the pathname to try. */ (void) memcpy (buf, dirpath, p - dirpath); buf[p - dirpath] = '/'; (void) memcpy (&buf[(p - dirpath) + 1], name, namelen); + buflen = p - dirpath + 1 + namelen; } - fd = open (buf, O_RDONLY); + fd = __open (buf, O_RDONLY); if (fd != -1) { - *realname = strdup (buf); - return fd; + *realname = malloc (buflen); + if (*realname) + { + memcpy (*realname, buf, buflen); + return fd; + } + else + { + /* No memory for the name, we certainly won't be able + to load and link it. */ + __close (fd); + return -1; + } } if (errno != ENOENT && errno != EACCES) /* The file exists and is readable, but something went wrong. */ @@ -117,7 +135,6 @@ open_path (const char *name, size_t namelen, return -1; } - /* Map in the shared object file NAME. */ struct link_map * @@ -163,9 +180,19 @@ _dl_map_object (struct link_map *loader, const char *name) } else { - fd = open (name, O_RDONLY); + fd = __open (name, O_RDONLY); if (fd != -1) - realname = strdup (name); + { + size_t len = strlen (name) + 1; + realname = malloc (len); + if (realname) + memcpy (realname, name, len); + else + { + __close (fd); + fd = -1; + } + } } if (fd == -1) @@ -182,25 +209,24 @@ struct link_map * _dl_map_object_from_fd (const char *name, int fd, char *realname) { struct link_map *l = NULL; - const size_t pagesize = getpagesize (); void *file_mapping = NULL; size_t mapping_size = 0; #define LOSE(s) lose (0, (s)) void lose (int code, const char *msg) { - (void) close (fd); + (void) __close (fd); if (file_mapping) - munmap (file_mapping, mapping_size); + __munmap (file_mapping, mapping_size); _dl_signal_error (code, l ? l->l_name : name, msg); } - inline caddr_t map_segment (Elf32_Addr mapstart, size_t len, + inline caddr_t map_segment (ElfW(Addr) mapstart, size_t len, int prot, int fixed, off_t offset) { - caddr_t mapat = mmap ((caddr_t) mapstart, len, prot, - fixed|MAP_COPY|MAP_FILE, - fd, offset); + caddr_t mapat = __mmap ((caddr_t) mapstart, len, prot, + fixed|MAP_COPY|MAP_FILE, + fd, offset); if (mapat == (caddr_t) -1) lose (errno, "failed to map segment from shared object"); return mapat; @@ -213,11 +239,11 @@ _dl_map_object_from_fd (const char *name, int fd, char *realname) { void *result; if (file_mapping) - munmap (file_mapping, mapping_size); - mapping_size = (location + size + 1 + pagesize - 1); - mapping_size &= ~(pagesize - 1); - result = mmap (file_mapping, mapping_size, PROT_READ, - MAP_COPY|MAP_FILE, fd, 0); + __munmap (file_mapping, mapping_size); + mapping_size = (location + size + 1 + _dl_pagesize - 1); + mapping_size &= ~(_dl_pagesize - 1); + result = __mmap (file_mapping, mapping_size, PROT_READ, + MAP_COPY|MAP_FILE, fd, 0); if (result == (void *) -1) lose (errno, "cannot map file data"); file_mapping = result; @@ -225,9 +251,9 @@ _dl_map_object_from_fd (const char *name, int fd, char *realname) return file_mapping + location; } - const Elf32_Ehdr *header; - const Elf32_Phdr *phdr; - const Elf32_Phdr *ph; + const ElfW(Ehdr) *header; + const ElfW(Phdr) *phdr; + const ElfW(Phdr) *ph; int type; /* Look again to see if the real name matched another already loaded. */ @@ -236,12 +262,15 @@ _dl_map_object_from_fd (const char *name, int fd, char *realname) { /* The object is already loaded. Just bump its reference count and return it. */ - close (fd); + __close (fd); free (realname); ++l->l_opencount; return l; } + if (_dl_pagesize == 0) + _dl_pagesize = __getpagesize (); + /* Map in the first page to read the header. */ header = map (0, sizeof *header); @@ -260,8 +289,10 @@ _dl_map_object_from_fd (const char *name, int fd, char *realname) #endif ) LOSE ("invalid ELF header"); - if (header->e_ident[EI_CLASS] != ELFCLASS32) - LOSE ("ELF file class not 32-bit"); +#define ELF32_CLASS ELFCLASS32 +#define ELF64_CLASS ELFCLASS64 + if (header->e_ident[EI_CLASS] != ELFW(CLASS)) + LOSE ("ELF file class not " STRING(__ELF_WORDSIZE) "-bit"); if (header->e_ident[EI_DATA] != byteorder) LOSE ("ELF file data encoding not " byteorder_name); if (header->e_ident[EI_VERSION] != EV_CURRENT) @@ -270,7 +301,7 @@ _dl_map_object_from_fd (const char *name, int fd, char *realname) LOSE ("ELF file version not " STRING(EV_CURRENT)); if (! elf_machine_matches_host (header->e_machine)) LOSE ("ELF file machine architecture not " ELF_MACHINE_NAME); - if (header->e_phentsize != sizeof (Elf32_Phdr)) + if (header->e_phentsize != sizeof (ElfW(Phdr))) LOSE ("ELF file's phentsize not the expected size"); /* Enter the new object in the list of loaded objects. */ @@ -289,13 +320,13 @@ _dl_map_object_from_fd (const char *name, int fd, char *realname) l->l_entry = header->e_entry; type = header->e_type; l->l_phnum = header->e_phnum; - phdr = map (header->e_phoff, l->l_phnum * sizeof (Elf32_Phdr)); + phdr = map (header->e_phoff, l->l_phnum * sizeof (ElfW(Phdr))); { /* Scan the program header table, collecting its load commands. */ struct loadcmd { - Elf32_Addr mapstart, mapend, dataend, allocend; + ElfW(Addr) mapstart, mapend, dataend, allocend; off_t mapoff; int prot; } loadcmds[l->l_phnum], *c; @@ -320,15 +351,15 @@ _dl_map_object_from_fd (const char *name, int fd, char *realname) case PT_LOAD: /* A load command tells us to map in part of the file. We record the load commands and process them all later. */ - if (ph->p_align % pagesize != 0) + if (ph->p_align % _dl_pagesize != 0) LOSE ("ELF load command alignment not page-aligned"); if ((ph->p_vaddr - ph->p_offset) % ph->p_align) LOSE ("ELF load command address/offset not properly aligned"); { struct loadcmd *c = &loadcmds[nloadcmds++]; c->mapstart = ph->p_vaddr & ~(ph->p_align - 1); - c->mapend = ((ph->p_vaddr + ph->p_filesz + pagesize - 1) - & ~(pagesize - 1)); + c->mapend = ((ph->p_vaddr + ph->p_filesz + _dl_pagesize - 1) + & ~(_dl_pagesize - 1)); c->dataend = ph->p_vaddr + ph->p_filesz; c->allocend = ph->p_vaddr + ph->p_memsz; c->mapoff = ph->p_offset & ~(ph->p_align - 1); @@ -344,7 +375,7 @@ _dl_map_object_from_fd (const char *name, int fd, char *realname) } /* We are done reading the file's headers now. Unmap them. */ - munmap (file_mapping, mapping_size); + __munmap (file_mapping, mapping_size); /* Now process the load commands and map segments into memory. */ c = loadcmds; @@ -362,16 +393,16 @@ _dl_map_object_from_fd (const char *name, int fd, char *realname) mapat = map_segment (c->mapstart, loadcmds[nloadcmds - 1].allocend - c->mapstart, c->prot, 0, c->mapoff); - l->l_addr = (Elf32_Addr) mapat - c->mapstart; + l->l_addr = (ElfW(Addr)) mapat - c->mapstart; /* Change protection on the excess portion to disallow all access; the portions we do not remap later will be inaccessible as if unallocated. Then jump into the normal segment-mapping loop to handle the portion of the segment past the end of the file mapping. */ - mprotect (mapat + c->mapend, - loadcmds[nloadcmds - 1].allocend - c->mapend, - 0); + __mprotect (mapat + c->mapend, + loadcmds[nloadcmds - 1].allocend - c->mapend, + 0); goto postmap; } @@ -387,11 +418,11 @@ _dl_map_object_from_fd (const char *name, int fd, char *realname) { /* Extra zero pages should appear at the end of this segment, after the data mapped from the file. */ - Elf32_Addr zero, zeroend, zeropage; + ElfW(Addr) zero, zeroend, zeropage; zero = l->l_addr + c->dataend; zeroend = l->l_addr + c->allocend; - zeropage = (zero + pagesize - 1) & ~(pagesize - 1); + zeropage = (zero + _dl_pagesize - 1) & ~(_dl_pagesize - 1); if (zeroend < zeropage) /* All the extra data is in the last page of the segment. @@ -404,23 +435,23 @@ _dl_map_object_from_fd (const char *name, int fd, char *realname) if ((c->prot & PROT_WRITE) == 0) { /* Dag nab it. */ - if (mprotect ((caddr_t) (zero & ~(pagesize - 1)), - pagesize, c->prot|PROT_WRITE) < 0) + if (__mprotect ((caddr_t) (zero & ~(_dl_pagesize - 1)), + _dl_pagesize, c->prot|PROT_WRITE) < 0) lose (errno, "cannot change memory protections"); } memset ((void *) zero, 0, zeropage - zero); if ((c->prot & PROT_WRITE) == 0) - mprotect ((caddr_t) (zero & ~(pagesize - 1)), - pagesize, c->prot); + __mprotect ((caddr_t) (zero & ~(_dl_pagesize - 1)), + _dl_pagesize, c->prot); } if (zeroend > zeropage) { /* Map the remaining zero pages in from the zero fill FD. */ caddr_t mapat; - mapat = mmap ((caddr_t) zeropage, zeroend - zeropage, c->prot, - MAP_ANON|MAP_PRIVATE|MAP_FIXED, - _dl_zerofd, 0); + mapat = __mmap ((caddr_t) zeropage, zeroend - zeropage, + c->prot, MAP_ANON|MAP_PRIVATE|MAP_FIXED, + _dl_zerofd, 0); if (mapat == (caddr_t) -1) lose (errno, "cannot map zero-fill pages"); } @@ -441,11 +472,11 @@ _dl_map_object_from_fd (const char *name, int fd, char *realname) LOSE ("object file has no dynamic section"); } else - (Elf32_Addr) l->l_ld += l->l_addr; + (ElfW(Addr)) l->l_ld += l->l_addr; if (l->l_phdr == 0) - l->l_phdr = (void *) ((const Elf32_Ehdr *) l->l_addr)->e_phoff; - (Elf32_Addr) l->l_phdr += l->l_addr; + l->l_phdr = (void *) ((const ElfW(Ehdr) *) l->l_addr)->e_phoff; + (ElfW(Addr)) l->l_phdr += l->l_addr; elf_get_dynamic_info (l->l_ld, l->l_info); if (l->l_info[DT_HASH]) diff --git a/elf/dl-lookup.c b/elf/dl-lookup.c index 104963987b..0674253041 100644 --- a/elf/dl-lookup.c +++ b/elf/dl-lookup.c @@ -18,27 +18,48 @@ not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include -#include #include #include + +/* This is the hashing function specified by the ELF ABI. */ +static inline unsigned +_dl_elf_hash (const char *name) +{ + unsigned long int hash = 0; + while (*name != '\0') + { + unsigned long int hi; + hash = (hash << 4) + *name++; + hi = hash & 0xf0000000; + if (hi != 0) + { + hash ^= hi >> 24; + /* The ELF ABI says `hash &= ~hi', but this is equivalent + in this case and on some machines one insn instead of two. */ + hash ^= hi; + } + } + return hash; +} + /* Search loaded objects' symbol tables for a definition of the symbol UNDEF_NAME. The chosen value can't be RELOC_ADDR. If NOPLT is nonzero, then a PLT entry cannot satisfy the reference; some different binding must be found. */ -Elf32_Addr -_dl_lookup_symbol (const char *undef_name, const Elf32_Sym **ref, +ElfW(Addr) +_dl_lookup_symbol (const char *undef_name, const ElfW(Sym) **ref, struct link_map *symbol_scope[2], const char *reference_name, - Elf32_Addr reloc_addr, + ElfW(Addr) reloc_addr, int noplt) { - unsigned long int hash = elf_hash (undef_name); + const unsigned long int hash = _dl_elf_hash (undef_name); struct { - Elf32_Addr a; - const Elf32_Sym *s; + ElfW(Addr) a; + const ElfW(Sym) *s; } weak_value = { 0, NULL }; size_t i; struct link_map **scope, *map; @@ -48,9 +69,9 @@ _dl_lookup_symbol (const char *undef_name, const Elf32_Sym **ref, if (*scope) for (i = 0; i < (*scope)->l_nsearchlist; ++i) { - const Elf32_Sym *symtab; + const ElfW(Sym) *symtab; const char *strtab; - Elf32_Word symidx; + ElfW(Word) symidx; map = (*scope)->l_searchlist[i]; @@ -63,7 +84,7 @@ _dl_lookup_symbol (const char *undef_name, const Elf32_Sym **ref, symidx != STN_UNDEF; symidx = map->l_chain[symidx]) { - const Elf32_Sym *sym = &symtab[symidx]; + const ElfW(Sym) *sym = &symtab[symidx]; if (sym->st_value == 0 || /* No value. */ /* Cannot resolve to the location being filled in. */ @@ -71,7 +92,7 @@ _dl_lookup_symbol (const char *undef_name, const Elf32_Sym **ref, (noplt && sym->st_shndx == SHN_UNDEF)) /* Reject PLT. */ continue; - switch (ELF32_ST_TYPE (sym->st_info)) + switch (ELFW(ST_TYPE) (sym->st_info)) { case STT_NOTYPE: case STT_FUNC: @@ -86,7 +107,7 @@ _dl_lookup_symbol (const char *undef_name, const Elf32_Sym **ref, /* Not the symbol we are looking for. */ continue; - switch (ELF32_ST_BIND (sym->st_info)) + switch (ELFW(ST_BIND) (sym->st_info)) { case STB_GLOBAL: /* Global definition. Just what we need. */ @@ -108,41 +129,15 @@ _dl_lookup_symbol (const char *undef_name, const Elf32_Sym **ref, } } - if (weak_value.s == NULL && ELF32_ST_BIND ((*ref)->st_info) != STB_WEAK) + if (weak_value.s == NULL && ELFW(ST_BIND) ((*ref)->st_info) != STB_WEAK) { - /* The symbol was not defined by any object in scope. To allow - access to dynamic linker functionality without using -ldl and - thereby brining the dynamic linker's symbols into scope, we - recognize a few magical symbol names and resolve them to the - addresses of functions inside the dynamic linker. */ - - struct magic - { - unsigned long int hash; - const char *name; - Elf32_Addr value; - }; - static struct magic magic[] = - { - { 0xd6a2a5e, "_GNU_libc_dl_open", (Elf32_Addr) &_dl_open }, -/* { 0x69ef845, "_GNU_libc_dl_close", (Elf32_Addr) &_dl_close },*/ - { 0xae4d63c, "_GNU_libc_dl_symbol", (Elf32_Addr) &_dl_symbol_value }, - { 0, NULL, 0 } - }; - struct magic *m; - - for (m = magic; m->hash; ++m) - if (hash == m->hash && !strcmp (undef_name, m->name)) - return m->value; - - { - const char msg[] = "undefined symbol: "; - char buf[sizeof msg + strlen (undef_name)]; - memcpy (buf, msg, sizeof msg - 1); - memcpy (&buf[sizeof msg - 1], undef_name, - sizeof buf - sizeof msg + 1); - _dl_signal_error (0, reference_name, buf); - } + /* We could find no value for a strong reference. */ + const char msg[] = "undefined symbol: "; + char buf[sizeof msg + strlen (undef_name)]; + memcpy (buf, msg, sizeof msg - 1); + memcpy (&buf[sizeof msg - 1], undef_name, + sizeof buf - sizeof msg + 1); + _dl_signal_error (0, reference_name, buf); } *ref = weak_value.s; @@ -155,23 +150,11 @@ _dl_lookup_symbol (const char *undef_name, const Elf32_Sym **ref, void _dl_setup_hash (struct link_map *map) { - Elf32_Word *hash = (void *) map->l_addr + map->l_info[DT_HASH]->d_un.d_ptr; - Elf32_Word nchain; + ElfW(Word) *hash = (void *) map->l_addr + map->l_info[DT_HASH]->d_un.d_ptr; + ElfW(Word) nchain; map->l_nbuckets = *hash++; nchain = *hash++; map->l_buckets = hash; hash += map->l_nbuckets; map->l_chain = hash; } - -/* Look up symbol NAME in MAP's scope and return its run-time address. */ - -Elf32_Addr -_dl_symbol_value (struct link_map *map, const char *name) -{ - Elf32_Addr loadbase; - const Elf32_Sym *ref = NULL; - struct link_map *scope[2] = { map, NULL }; - loadbase = _dl_lookup_symbol (name, &ref, scope, map->l_name, 0, 0); - return loadbase + ref->st_value; -} diff --git a/elf/dl-minimal.c b/elf/dl-minimal.c index c61b51532b..bf19fee6c4 100644 --- a/elf/dl-minimal.c +++ b/elf/dl-minimal.c @@ -34,10 +34,9 @@ void * malloc (size_t n) { extern int _dl_zerofd; - static size_t pagesize; - if (pagesize == 0) - pagesize = __getpagesize (); + if (_dl_pagesize == 0) + _dl_pagesize = __getpagesize (); if (_dl_zerofd == -1) _dl_zerofd = _dl_sysdep_open_zero_fill (); @@ -47,8 +46,8 @@ malloc (size_t n) /* Consume any unused space in the last page of our data segment. */ extern int _end; alloc_ptr = &_end; - alloc_end = (void *) 0 + (((alloc_ptr - (void *) 0) + pagesize - 1) - & ~(pagesize - 1)); + alloc_end = (void *) 0 + (((alloc_ptr - (void *) 0) + _dl_pagesize - 1) + & ~(_dl_pagesize - 1)); } /* Make sure the allocation pointer is ideally aligned. */ @@ -59,13 +58,13 @@ malloc (size_t n) { /* Insufficient space left; allocate another page. */ caddr_t page; - assert (n <= pagesize); - page = mmap (0, pagesize, PROT_READ|PROT_WRITE, - MAP_ANON|MAP_PRIVATE, _dl_zerofd, 0); + assert (n <= _dl_pagesize); + page = __mmap (0, _dl_pagesize, PROT_READ|PROT_WRITE, + MAP_ANON|MAP_PRIVATE, _dl_zerofd, 0); assert (page != (caddr_t) -1); if (page != alloc_end) alloc_ptr = page; - alloc_end = page + pagesize; + alloc_end = page + _dl_pagesize; } alloc_last_block = (void *) alloc_ptr; diff --git a/elf/dl-open.c b/elf/dl-open.c new file mode 100644 index 0000000000..221abbd35e --- /dev/null +++ b/elf/dl-open.c @@ -0,0 +1,45 @@ +/* Load a shared object at runtime, relocate it, and run its initializer. +Copyright (C) 1996 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 +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., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include +#include + +struct link_map * +_dl_open (struct link_map *parent, const char *file, int mode) +{ + struct link_map *new, *l; + ElfW(Addr) init; + + /* Load the named object. */ + new = _dl_map_object (parent, file); + + /* Load that object's dependencies. */ + _dl_map_object_deps (new); + + /* Relocate the objects loaded. */ + for (l = new; l; l = l->l_next) + if (! l->l_relocated) + _dl_relocate_object (l, (mode & RTLD_BINDING_MASK) == RTLD_LAZY); + + /* Run the initializer functions of new objects. */ + while (init = _dl_init_next (new)) + (*(void (*) (void)) init) (); + + return new; +} diff --git a/elf/dl-reloc.c b/elf/dl-reloc.c index bfa0174444..5da8575da5 100644 --- a/elf/dl-reloc.c +++ b/elf/dl-reloc.c @@ -28,8 +28,6 @@ Cambridge, MA 02139, USA. */ void _dl_relocate_object (struct link_map *l, int lazy) { - const size_t pagesize = getpagesize (); - if (l->l_relocated) return; @@ -37,17 +35,17 @@ _dl_relocate_object (struct link_map *l, int lazy) { /* Bletch. We must make read-only segments writable long enough to relocate them. */ - const Elf32_Phdr *ph; + const ElfW(Phdr) *ph; for (ph = l->l_phdr; ph < &l->l_phdr[l->l_phnum]; ++ph) if (ph->p_type == PT_LOAD && (ph->p_flags & PF_W) == 0) { caddr_t mapstart = ((caddr_t) l->l_addr + - (ph->p_vaddr & ~(pagesize - 1))); + (ph->p_vaddr & ~(_dl_pagesize - 1))); caddr_t mapend = ((caddr_t) l->l_addr + - ((ph->p_vaddr + ph->p_memsz + pagesize - 1) - & ~(pagesize - 1))); - if (mprotect (mapstart, mapend - mapstart, - PROT_READ|PROT_WRITE) < 0) + ((ph->p_vaddr + ph->p_memsz + _dl_pagesize - 1) + & ~(_dl_pagesize - 1))); + if (__mprotect (mapstart, mapend - mapstart, + PROT_READ|PROT_WRITE) < 0) _dl_signal_error (errno, l->l_name, "cannot make segment writable for relocation"); } @@ -59,8 +57,8 @@ _dl_relocate_object (struct link_map *l, int lazy) const char *strtab = ((void *) l->l_addr + l->l_info[DT_STRTAB]->d_un.d_ptr); - Elf32_Addr resolve (const Elf32_Sym **ref, - Elf32_Addr reloc_addr, int noplt) + ElfW(Addr) resolve (const ElfW(Sym) **ref, + ElfW(Addr) reloc_addr, int noplt) { return _dl_lookup_symbol (strtab + (*ref)->st_name, ref, scope, l->l_name, reloc_addr, noplt); @@ -97,21 +95,21 @@ _dl_relocate_object (struct link_map *l, int lazy) if (l->l_info[DT_TEXTREL]) { /* Undo the protection change we made before relocating. */ - const Elf32_Phdr *ph; + const ElfW(Phdr) *ph; for (ph = l->l_phdr; ph < &l->l_phdr[l->l_phnum]; ++ph) if (ph->p_type == PT_LOAD && (ph->p_flags & PF_W) == 0) { caddr_t mapstart = ((caddr_t) l->l_addr + - (ph->p_vaddr & ~(pagesize - 1))); + (ph->p_vaddr & ~(_dl_pagesize - 1))); caddr_t mapend = ((caddr_t) l->l_addr + - ((ph->p_vaddr + ph->p_memsz + pagesize - 1) - & ~(pagesize - 1))); + ((ph->p_vaddr + ph->p_memsz + _dl_pagesize - 1) + & ~(_dl_pagesize - 1))); int prot = 0; if (ph->p_flags & PF_R) prot |= PROT_READ; if (ph->p_flags & PF_X) prot |= PROT_EXEC; - if (mprotect (mapstart, mapend - mapstart, prot) < 0) + if (__mprotect (mapstart, mapend - mapstart, prot) < 0) _dl_signal_error (errno, l->l_name, "can't restore segment prot after reloc"); } diff --git a/elf/dl-runtime.c b/elf/dl-runtime.c index dce34f8a89..c306543155 100644 --- a/elf/dl-runtime.c +++ b/elf/dl-runtime.c @@ -24,9 +24,9 @@ Cambridge, MA 02139, USA. */ #define elf_machine_rel 1 #define elf_machine_rela 2 #if elf_machine_relplt == elf_machine_rel -#define PLTREL Elf32_Rel +#define PLTREL ElfW(Rel) #elif elf_machine_relplt == elf_machine_rela -#define PLTREL Elf32_Rela +#define PLTREL ElfW(Rela) #else #error "dl-machine.h bug: elf_machine_relplt not rel or rela" #endif @@ -37,11 +37,11 @@ Cambridge, MA 02139, USA. */ in the trampoline code will be a local PC-relative call. Tell the compiler not to worry that the function appears not to be called. */ -static Elf32_Addr fixup ( +static ElfW(Addr) fixup ( #ifdef ELF_MACHINE_RUNTIME_FIXUP_ARGS ELF_MACHINE_RUNTIME_FIXUP_ARGS, #endif - struct link_map *l, Elf32_Word reloc_offset) + struct link_map *l, ElfW(Word) reloc_offset) __attribute__ ((unused)); /* This function is called through a special trampoline from the PLT the @@ -51,15 +51,15 @@ static Elf32_Addr fixup ( to that address. Future calls will bounce directly from the PLT to the function. */ -static Elf32_Addr +static ElfW(Addr) fixup ( #ifdef ELF_MACHINE_RUNTIME_FIXUP_ARGS ELF_MACHINE_RUNTIME_FIXUP_ARGS, #endif - struct link_map *l, Elf32_Word reloc_offset) + struct link_map *l, ElfW(Word) reloc_offset) { - const Elf32_Sym *const symtab - = (const Elf32_Sym *) (l->l_addr + l->l_info[DT_SYMTAB]->d_un.d_ptr); + const ElfW(Sym) *const symtab + = (const ElfW(Sym) *) (l->l_addr + l->l_info[DT_SYMTAB]->d_un.d_ptr); const char *strtab = (const char *) (l->l_addr + l->l_info[DT_STRTAB]->d_un.d_ptr); @@ -67,8 +67,8 @@ fixup ( = (const void *) (l->l_addr + l->l_info[DT_JMPREL]->d_un.d_ptr + reloc_offset); - Elf32_Addr resolve (const Elf32_Sym **ref, - Elf32_Addr reloc_addr, int noplt) + ElfW(Addr) resolve (const ElfW(Sym) **ref, + ElfW(Addr) reloc_addr, int noplt) { struct link_map *scope[2] = { _dl_loaded, NULL }; return _dl_lookup_symbol (strtab + (*ref)->st_name, ref, @@ -76,9 +76,9 @@ fixup ( } /* Perform the specified relocation. */ - elf_machine_relplt (l, reloc, &symtab[ELF32_R_SYM (reloc->r_info)], resolve); + elf_machine_relplt (l, reloc, &symtab[ELFW(R_SYM) (reloc->r_info)], resolve); - return *(Elf32_Addr *) (l->l_addr + reloc->r_offset); + return *(ElfW(Addr) *) (l->l_addr + reloc->r_offset); } diff --git a/elf/dl-support.c b/elf/dl-support.c new file mode 100644 index 0000000000..b85d470770 --- /dev/null +++ b/elf/dl-support.c @@ -0,0 +1,51 @@ +/* Support for dynamic linking code in static libc. +Copyright (C) 1996 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 +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., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include +#include +#include + +/* This file defines some things that for the dynamic linker are defined in + rtld.c and dl-sysdep.c in ways appropriate to bootstrap dynamic linking. */ + +int _dl_secure; /* Always honor LD_LIBRARY_PATH. */ + +extern char *__progname; +char **_dl_argv = &__progname; /* This is checked for some error messages. */ + +/* This defines the default search path for libraries. + For the dynamic linker it is set by -rpath when linking. */ +const char *_dl_rpath = DEFAULT_RPATH; + +/* This is the only dl-sysdep.c function that is actually needed at run-time + by _dl_map_object. */ + +int +_dl_sysdep_open_zero_fill (void) +{ + return __open ("/dev/zero", O_RDONLY); +} + +/* This should never be called. */ +void +_dl_sysdep_fatal (void) +{ + assert (! "_dl_sysdep_fatal called"); +} + diff --git a/elf/dl-symbol.c b/elf/dl-symbol.c new file mode 100644 index 0000000000..7977e69ab6 --- /dev/null +++ b/elf/dl-symbol.c @@ -0,0 +1,33 @@ +/* Look up a symbol's run-time value in the scope of a loaded object. +Copyright (C) 1995, 1996 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 +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., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include +#include + +/* Look up symbol NAME in MAP's scope and return its run-time address. */ + +ElfW(Addr) +_dl_symbol_value (struct link_map *map, const char *name) +{ + ElfW(Addr) loadbase; + const ElfW(Sym) *ref = NULL; + struct link_map *scope[2] = { map, NULL }; + loadbase = _dl_lookup_symbol (name, &ref, scope, map->l_name, 0, 0); + return loadbase + ref->st_value; +} diff --git a/elf/dladdr.c b/elf/dladdr.c index 87283e2586..fa78d8fc02 100644 --- a/elf/dladdr.c +++ b/elf/dladdr.c @@ -25,9 +25,9 @@ Cambridge, MA 02139, USA. */ int dladdr (void *address, Dl_info *info) { - const Elf32_Addr addr = (Elf32_Addr) address; + const ElfW(Addr) addr = (ElfW(Addr)) address; struct link_map *l, *match; - const Elf32_Sym *symtab, *matchsym; + const ElfW(Sym) *symtab, *matchsym; const char *strtab; /* Find the highest-addressed object that ADDRESS is not below. */ @@ -64,8 +64,8 @@ dladdr (void *address, Dl_info *info) for (matchsym = NULL; (void *) symtab < (void *) strtab; ++symtab) if (addr >= match->l_addr + symtab->st_value && !matchsym || matchsym->st_value < symtab->st_value && - ELF32_ST_BIND (symtab->st_info) == STB_GLOBAL || - ELF32_ST_BIND (symtab->st_info) == STB_WEAK) + ELFW(ST_BIND) (symtab->st_info) == STB_GLOBAL || + ELFW(ST_BIND) (symtab->st_info) == STB_WEAK) matchsym = symtab; if (matchsym) diff --git a/elf/dlclose.c b/elf/dlclose.c index fbb3ca6fe2..0d2689e01c 100644 --- a/elf/dlclose.c +++ b/elf/dlclose.c @@ -65,7 +65,7 @@ dlclose (void *handle) { /* That was the last reference, and this was a dlopen-loaded object. We can unmap it. */ - const Elf32_Phdr *ph; + const ElfW(Phdr) *ph; if (map->l_info[DT_FINI]) /* Call its termination function. */ @@ -76,8 +76,8 @@ dlclose (void *handle) for (ph = map->l_phdr; ph < &map->l_phdr[map->l_phnum]; ++ph) if (ph->p_type == PT_LOAD) { - Elf32_Addr mapstart = ph->p_vaddr & ~(ph->p_align - 1); - Elf32_Addr mapend = ((ph->p_vaddr + ph->p_memsz + ElfW(Addr) mapstart = ph->p_vaddr & ~(ph->p_align - 1); + ElfW(Addr) mapend = ((ph->p_vaddr + ph->p_memsz + ph->p_align - 1) & ~(ph->p_align - 1)); munmap ((caddr_t) mapstart, mapend - mapstart); diff --git a/elf/dlsym.c b/elf/dlsym.c index f874af780a..7677f2741f 100644 --- a/elf/dlsym.c +++ b/elf/dlsym.c @@ -27,8 +27,8 @@ void * dlsym (void *handle, const char *name) { struct link_map *map = handle; - Elf32_Addr loadbase; - const Elf32_Sym *ref = NULL; + ElfW(Addr) loadbase; + const ElfW(Sym) *ref = NULL; void doit (void) { struct link_map *scope[2] = { map, NULL }; diff --git a/elf/do-rel.h b/elf/do-rel.h index 438613a32d..ebf2e84a64 100644 --- a/elf/do-rel.h +++ b/elf/do-rel.h @@ -21,9 +21,9 @@ Cambridge, MA 02139, USA. */ `elf_dynamic_do_rel' and `elf_dynamic_do_rela'. */ #ifdef DO_RELA -#define elf_dynamic_do_rel elf_dynamic_do_rela -#define Elf32_Rel Elf32_Rela -#define elf_machine_rel elf_machine_rela +#define elf_dynamic_do_rel elf_dynamic_do_rela +#define Rel Rela +#define elf_machine_rel elf_machine_rela #endif @@ -37,15 +37,15 @@ Cambridge, MA 02139, USA. */ static inline void elf_dynamic_do_rel (struct link_map *map, int reltag, int sztag, - Elf32_Addr (*resolve) (const Elf32_Sym **symbol, - Elf32_Addr reloc_addr, int noplt), + ElfW(Addr) (*resolve) (const ElfW(Sym) **symbol, + ElfW(Addr) reloc_addr, int noplt), int lazy) { - const Elf32_Sym *const symtab - = (const Elf32_Sym *) (map->l_addr + map->l_info[DT_SYMTAB]->d_un.d_ptr); - const Elf32_Rel *r - = (const Elf32_Rel *) (map->l_addr + map->l_info[reltag]->d_un.d_ptr); - const Elf32_Rel *end = &r[map->l_info[sztag]->d_un.d_val / sizeof *r]; + const ElfW(Sym) *const symtab + = (const ElfW(Sym) *) (map->l_addr + map->l_info[DT_SYMTAB]->d_un.d_ptr); + const ElfW(Rel) *r + = (const ElfW(Rel) *) (map->l_addr + map->l_info[reltag]->d_un.d_ptr); + const ElfW(Rel) *end = &r[map->l_info[sztag]->d_un.d_val / sizeof *r]; if (lazy) /* Doing lazy PLT relocations; they need very little info. */ @@ -53,9 +53,9 @@ elf_dynamic_do_rel (struct link_map *map, elf_machine_lazy_rel (map, r); else for (; r < end; ++r) - elf_machine_rel (map, r, &symtab[ELF32_R_SYM (r->r_info)], resolve); + elf_machine_rel (map, r, &symtab[ELFW(R_SYM) (r->r_info)], resolve); } #undef elf_dynamic_do_rel -#undef Elf32_Rel +#undef Rel #undef elf_machine_rel diff --git a/elf/dynamic-link.h b/elf/dynamic-link.h index 38236bae2c..b69cb3fd43 100644 --- a/elf/dynamic-link.h +++ b/elf/dynamic-link.h @@ -25,7 +25,7 @@ Cambridge, MA 02139, USA. */ /* Read the dynamic section at DYN and fill in INFO with indices DT_*. */ static inline void -elf_get_dynamic_info (Elf32_Dyn *dyn, Elf32_Dyn *info[DT_NUM + DT_PROCNUM]) +elf_get_dynamic_info (ElfW(Dyn) *dyn, ElfW(Dyn) *info[DT_NUM + DT_PROCNUM]) { unsigned int i; @@ -48,9 +48,9 @@ elf_get_dynamic_info (Elf32_Dyn *dyn, Elf32_Dyn *info[DT_NUM + DT_PROCNUM]) } if (info[DT_RELA]) - assert (info[DT_RELAENT]->d_un.d_val == sizeof (Elf32_Rela)); + assert (info[DT_RELAENT]->d_un.d_val == sizeof (ElfW(Rela))); if (info[DT_REL]) - assert (info[DT_RELENT]->d_un.d_val == sizeof (Elf32_Rel)); + assert (info[DT_RELENT]->d_un.d_val == sizeof (ElfW(Rel))); if (info[DT_PLTREL]) assert (info[DT_PLTREL]->d_un.d_val == DT_REL || info[DT_PLTREL]->d_un.d_val == DT_RELA); diff --git a/elf/elf.h b/elf/elf.h index ec81f0b820..f6d023d207 100644 --- a/elf/elf.h +++ b/elf/elf.h @@ -23,16 +23,37 @@ Cambridge, MA 02139, USA. */ #define _ELF_H 1 -/* Standard ELF types. +/* Standard ELF types. Using __attribute__ mode ensures that GCC + will choose the right number of bits for these types. */ - Using __attribute__ mode ensures that gcc will choose the right for - these types. */ +/* Type for a 16-bit quantity. */ +typedef unsigned int Elf32_Half __attribute__ ((mode (HI))); +typedef unsigned int Elf64_Half __attribute__ ((mode (HI))); + +/* Types for signed and unsigned 32-bit quantities. */ +typedef unsigned int Elf32_Word __attribute__ ((mode (SI))); +typedef int Elf32_Sword __attribute__ ((mode (SI))); +typedef unsigned int Elf64_Word __attribute__ ((mode (SI))); +typedef int Elf64_Sword __attribute__ ((mode (SI))); + +/* Types for signed and unsigned 64-bit quantities. */ +typedef unsigned int Elf32_Xword __attribute__ ((mode (DI))); +typedef int Elf32_Sxword __attribute__ ((mode (DI))); +typedef unsigned int Elf64_Xword __attribute__ ((mode (DI))); +typedef int Elf64_Sxword __attribute__ ((mode (DI))); +/* Type of addresses. */ typedef unsigned int Elf32_Addr __attribute__ ((mode (SI))); -typedef unsigned int Elf32_Half __attribute__ ((mode (HI))); +typedef unsigned int Elf64_Addr __attribute__ ((mode (DI))); + +/* Type of file offsets. */ typedef unsigned int Elf32_Off __attribute__ ((mode (SI))); -typedef int Elf32_Sword __attribute__ ((mode (SI))); -typedef unsigned int Elf32_Word __attribute__ ((mode (SI))); +typedef unsigned int Elf64_Off __attribute__ ((mode (DI))); + +/* Type for section indices, which are 16-bit quantities. */ +typedef unsigned int Elf32_Section __attribute__ ((mode (HI))); +typedef unsigned int Elf64_Section __attribute__ ((mode (HI))); + /* The ELF file header. This appears at the start of every ELF file. */ @@ -56,6 +77,24 @@ typedef struct Elf32_Half e_shstrndx; /* Section header string table index */ } Elf32_Ehdr; +typedef struct +{ + unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */ + Elf64_Half e_type; /* Object file type */ + Elf64_Half e_machine; /* Architecture */ + Elf64_Word e_version; /* Object file version */ + Elf64_Addr e_entry; /* Entry point virtual address */ + Elf64_Off e_phoff; /* Program header table file offset */ + Elf64_Off e_shoff; /* Section header table file offset */ + Elf64_Word e_flags; /* Processor-specific flags */ + Elf64_Half e_ehsize; /* ELF header size in bytes */ + Elf64_Half e_phentsize; /* Program header table entry size */ + Elf64_Half e_phnum; /* Program header table entry count */ + Elf64_Half e_shentsize; /* Section header table entry size */ + Elf64_Half e_shnum; /* Section header table entry count */ + Elf64_Half e_shstrndx; /* Section header string table index */ +} Elf64_Ehdr; + /* Fields in the e_ident array. The EI_* macros are indices into the array. The macros under each EI_* macro are the values the byte may have. */ @@ -125,6 +164,8 @@ typedef struct pick large random numbers (0x8523, 0xa7f2, etc.) to minimize the chances of collision with official or non-GNU unofficial values. */ +#define EM_ALPHA 0x9026 + /* Legal values for e_version (version). */ #define EV_NONE 0 /* Invalid ELF version */ @@ -146,6 +187,20 @@ typedef struct Elf32_Word sh_entsize; /* Entry size if section holds table */ } Elf32_Shdr; +typedef struct +{ + Elf64_Word sh_name; /* Section name (string tbl index) */ + Elf64_Word sh_type; /* Section type */ + Elf64_Xword sh_flags; /* Section flags */ + Elf64_Addr sh_addr; /* Section virtual addr at execution */ + Elf64_Off sh_offset; /* Section file offset */ + Elf64_Xword sh_size; /* Section size in bytes */ + Elf64_Word sh_link; /* Link to another section */ + Elf64_Word sh_info; /* Additional section information */ + Elf64_Xword sh_addralign; /* Section alignment */ + Elf64_Xword sh_entsize; /* Entry size if section holds table */ +} Elf64_Shdr; + /* Special section indices. */ #define SHN_UNDEF 0 /* Undefined section */ @@ -192,9 +247,19 @@ typedef struct Elf32_Word st_size; /* Symbol size */ unsigned char st_info; /* Symbol type and binding */ unsigned char st_other; /* No defined meaning, 0 */ - Elf32_Half st_shndx; /* Section index */ + Elf32_Section st_shndx; /* Section index */ } Elf32_Sym; +typedef struct +{ + Elf64_Word st_name; /* Symbol name (string tbl index) */ + unsigned char st_info; /* Symbol type and binding */ + unsigned char st_other; /* No defined meaning, 0 */ + Elf64_Section st_shndx; /* Section index */ + Elf64_Addr st_value; /* Symbol value */ + Elf64_Xword st_size; /* Symbol size */ +} Elf64_Sym; + /* Special section index. */ #define SHN_UNDEF 0 /* No section, undefined symbol. */ @@ -205,6 +270,11 @@ typedef struct #define ELF32_ST_TYPE(val) ((val) & 0xf) #define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf)) +/* Both Elf32_Sym and Elf64_Sym use the same one-byte st_info field. */ +#define ELF64_ST_BIND(val) ELF32_ST_BIND (val) +#define ELF64_ST_TYPE(val) ELF32_ST_TYPE (val) +#define ELF64_ST_INFO(bind, type) ELF32_ST_INFO ((bind), (type)) + /* Legal values for ST_BIND subfield of st_info (symbol binding). */ #define STB_LOCAL 0 /* Local symbol */ @@ -241,6 +311,17 @@ typedef struct Elf32_Word r_info; /* Relocation type and symbol index */ } Elf32_Rel; +/* I have seen two different definitions of the Elf64_Rel and + Elf64_Rela structures, so we'll leave them out until Novell (or + whoever) gets their act together. */ +/* The following, at least, is used on Sparc v9, MIPS, and Alpha. */ + +typedef struct +{ + Elf64_Addr r_offset; /* Address */ + Elf64_Xword r_info; /* Relocation type and symbol index */ +} Elf64_Rel; + /* Relocation table entry with addend (in section of type SHT_RELA). */ typedef struct @@ -250,6 +331,13 @@ typedef struct Elf32_Sword r_addend; /* Addend */ } Elf32_Rela; +typedef struct +{ + Elf64_Addr r_offset; /* Address */ + Elf64_Xword r_info; /* Relocation type and symbol index */ + Elf64_Sxword r_addend; /* Addend */ +} Elf64_Rela; + /* How to extract and insert information held in the r_info field. */ #define ELF32_R_SYM(val) ((val) >> 8) @@ -262,7 +350,8 @@ typedef struct /* Program segment header. */ -typedef struct { +typedef struct +{ Elf32_Word p_type; /* Segment type */ Elf32_Off p_offset; /* Segment file offset */ Elf32_Addr p_vaddr; /* Segment virtual address */ @@ -273,6 +362,18 @@ typedef struct { Elf32_Word p_align; /* Segment alignment */ } Elf32_Phdr; +typedef struct +{ + Elf64_Word p_type; /* Segment type */ + Elf64_Word p_flags; /* Segment flags */ + Elf64_Off p_offset; /* Segment file offset */ + Elf64_Addr p_vaddr; /* Segment virtual address */ + Elf64_Addr p_paddr; /* Segment physical address */ + Elf64_Xword p_filesz; /* Segment size in file */ + Elf64_Xword p_memsz; /* Segment size in memory */ + Elf64_Xword p_align; /* Segment alignment */ +} Elf64_Phdr; + /* Legal values for p_type (segment type). */ #define PT_NULL 0 /* Program header table entry unused */ @@ -316,6 +417,16 @@ typedef struct } d_un; } Elf32_Dyn; +typedef struct +{ + Elf64_Sxword d_tag; /* Dynamic entry type */ + union + { + Elf64_Xword d_val; /* Integer value */ + Elf64_Addr d_ptr; /* Address value */ + } d_un; +} Elf64_Dyn; + /* Legal values for d_tag (dynamic entry type). */ #define DT_NULL 0 /* Marks end of dynamic section */ @@ -347,76 +458,6 @@ typedef struct #define DT_HIPROC 0x7fffffff /* End of processor-specific */ #define DT_PROCNUM DT_MIPS_NUM /* Most used by any processor */ -/* Standard 64 bit ELF types. */ - -typedef unsigned int Elf64_Addr __attribute__ ((mode (DI))); -typedef unsigned int Elf64_Half __attribute__ ((mode (HI))); -typedef unsigned int Elf64_Off __attribute__ ((mode (DI))); -typedef int Elf64_Sword __attribute__ ((mode (SI))); -typedef int Elf64_Sxword __attribute__ ((mode (DI))); -typedef unsigned int Elf64_Word __attribute__ ((mode (SI))); -typedef unsigned int Elf64_Xword __attribute__ ((mode (DI))); -typedef unsigned int Elf64_Byte __attribute__ ((mode (QI))); -typedef unsigned int Elf64_Section __attribute__ ((mode (HI))); - -/* 64 bit ELF file header. */ - -typedef struct -{ - unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */ - Elf64_Half e_type; /* Object file type */ - Elf64_Half e_machine; /* Architecture */ - Elf64_Word e_version; /* Object file version */ - Elf64_Addr e_entry; /* Entry point virtual address */ - Elf64_Off e_phoff; /* Program header table file offset */ - Elf64_Off e_shoff; /* Section header table file offset */ - Elf64_Word e_flags; /* Processor-specific flags */ - Elf64_Half e_ehsize; /* ELF header size in bytes */ - Elf64_Half e_phentsize; /* Program header table entry size */ - Elf64_Half e_phnum; /* Program header table entry count */ - Elf64_Half e_shentsize; /* Section header table entry size */ - Elf64_Half e_shnum; /* Section header table entry count */ - Elf64_Half e_shstrndx; /* Section header string table index */ -} Elf64_Ehdr; - -/* 64 bit section header. */ - -typedef struct -{ - Elf64_Word sh_name; /* Section name (string tbl index) */ - Elf64_Word sh_type; /* Section type */ - Elf64_Xword sh_flags; /* Section flags */ - Elf64_Addr sh_addr; /* Section virtual addr at execution */ - Elf64_Off sh_offset; /* Section file offset */ - Elf64_Xword sh_size; /* Section size in bytes */ - Elf64_Word sh_link; /* Link to another section */ - Elf64_Word sh_info; /* Additional section information */ - Elf64_Xword sh_addralign; /* Section alignment */ - Elf64_Xword sh_entsize; /* Entry size if section holds table */ -} Elf64_Shdr; - -/* 64 bit symbol table entry. */ - -typedef struct -{ - Elf64_Word st_name; /* Symbol name (string tbl index) */ - Elf64_Byte st_info; /* Symbol type and binding */ - Elf64_Byte st_other; /* No defined meaning, 0 */ - Elf64_Section st_shndx; /* Section index */ - Elf64_Addr st_value; /* Symbol value */ - Elf64_Xword st_size; /* Symbol size */ -} Elf64_Sym; - -/* The 64 bit st_info field is the same as the 32 bit one. */ - -#define ELF64_ST_BIND(val) (((unsigned char) (val)) >> 4) -#define ELF64_ST_TYPE(val) ((val) & 0xf) -#define ELF64_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf)) - -/* I have seen two different definitions of the Elf64_Rel and - Elf64_Rela structures, so we'll leave them out until Novell (or - whoever) gets their act together. */ - /* Auxiliary vector. */ /* This vector is normally only used by the program interpreter. The @@ -437,6 +478,17 @@ typedef struct } a_un; } Elf32_auxv_t; +typedef struct +{ + long int a_type; /* Entry type */ + union + { + long int a_val; /* Integer value */ + void *a_ptr; /* Pointer value */ + void (*a_fcn) (void); /* Function pointer value */ + } a_un; +} Elf64_auxv_t; + /* Legal values for a_type (entry type). */ #define AT_NULL 0 /* End of vector */ @@ -684,4 +736,38 @@ typedef Elf32_Addr Elf32_Conflict; #define STT_PARISC_MILLICODE 13 /* Millicode function entry point. */ +/* Alpha specific declarations. */ + +/* Alpha relocs. */ + +#define R_ALPHA_NONE 0 /* No reloc */ +#define R_ALPHA_REFLONG 1 /* Direct 32 bit */ +#define R_ALPHA_REFQUAD 2 /* Direct 64 bit */ +#define R_ALPHA_GPREL32 3 /* GP relative 32 bit */ +#define R_ALPHA_LITERAL 4 /* GP relative 16 bit w/optimization */ +#define R_ALPHA_LITUSE 5 /* Optimization hint for LITERAL */ +#define R_ALPHA_GPDISP 6 /* Add displacement to GP */ +#define R_ALPHA_BRADDR 7 /* PC+4 relative 23 bit shifted */ +#define R_ALPHA_HINT 8 /* PC+4 relative 16 bit shifted */ +#define R_ALPHA_SREL16 9 /* PC relative 16 bit */ +#define R_ALPHA_SREL32 10 /* PC relative 32 bit */ +#define R_ALPHA_SREL64 11 /* PC relative 64 bit */ +#define R_ALPHA_OP_PUSH 12 /* OP stack push */ +#define R_ALPHA_OP_STORE 13 /* OP stack pop and store */ +#define R_ALPHA_OP_PSUB 14 /* OP stack subtract */ +#define R_ALPHA_OP_PRSHIFT 15 /* OP stack right shift */ +#define R_ALPHA_GPVALUE 16 +#define R_ALPHA_GPRELHIGH 17 +#define R_ALPHA_GPRELLOW 18 +#define R_ALPHA_IMMED_GP_16 19 +#define R_ALPHA_IMMED_GP_HI32 20 +#define R_ALPHA_IMMED_SCN_HI32 21 +#define R_ALPHA_IMMED_BR_HI32 22 +#define R_ALPHA_IMMED_LO32 23 +#define R_ALPHA_COPY 24 /* Copy symbol at runtime */ +#define R_ALPHA_GLOB_DAT 25 /* Create GOT entry */ +#define R_ALPHA_JMP_SLOT 26 /* Create PLT entry */ +#define R_ALPHA_RELATIVE 27 /* Adjust by program base */ + + #endif /* elf.h */ diff --git a/elf/elf_hash.c b/elf/elf_hash.c deleted file mode 100644 index ee8358d753..0000000000 --- a/elf/elf_hash.c +++ /dev/null @@ -1,4 +0,0 @@ -/* Define the global function for the inline `elf_hash' in libelf.h. */ - -#define _EXTERN_INLINE /* Define the function globally. */ -#include "libelf.h" diff --git a/elf/libelf.h b/elf/libelf.h deleted file mode 100644 index b6575b9824..0000000000 --- a/elf/libelf.h +++ /dev/null @@ -1,283 +0,0 @@ -/* Interface for manipulating ELF object files; functions found in -lelf. -Copyright (C) 1995 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 -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., 675 Mass Ave, -Cambridge, MA 02139, USA. */ - -#ifndef _LIBELF_H -#define _LIBELF_H 1 - -#include -#include -#include - -__BEGIN_DECLS - -/* Commands to operate on an Elf descriptor. - The meanings are slightly different for the different functions. */ -typedef enum -{ - ELF_C_NULL = 0, - ELF_C_READ, /* Read from the file. */ - ELF_C_WRITE, /* Write the file, ignoring old contents. */ - ELF_C_CLR, /* Clear specified flag bits. */ - ELF_C_SET, /* Set specified flag bits. */ - ELF_C_FDDONE, /* Close the fd; no further io will happen. */ - ELF_C_FDREAD, /* Read the whole file, then close it. */ - ELF_C_RDWR, /* Read from and modify the file. */ - ELF_C_NUM /* Number of valid command values. */ -} Elf_Cmd; - - -/* Flag bits for `elf_flag*'. */ -#define ELF_F_DIRTY 0x1 /* Object is */ -#define ELF_F_LAYOUT 0x4 - - -/* File types. */ -typedef enum -{ - ELF_K_NONE = 0, - ELF_K_AR, - ELF_K_COFF, /* The GNU -lelf does not support COFF. */ - ELF_K_ELF, - ELF_K_NUM /* Number of valid file kinds. */ -} Elf_Kind; - - -/* Translation types. */ -typedef enum -{ - ELF_T_BYTE = 0, - ELF_T_ADDR, - ELF_T_DYN, - ELF_T_EHDR, - ELF_T_HALF, - ELF_T_OFF, - ELF_T_PHDR, - ELF_T_RELA, - ELF_T_REL, - ELF_T_SHDR, - ELF_T_SWORD, - ELF_T_SYM, - ELF_T_WORD, - ELF_T_NUM -} Elf_Type; - - -/* These types are opaque to user code; only pointers to them are used. */ -typedef struct Elf Elf; -typedef struct Elf_Scn Elf_Scn; - - -/* Archive member header. */ -typedef struct -{ - char *ar_name; - time_t ar_date; - uid_t ar_uid; - gid_t ar_gid; - mode_t ar_mode; - off_t ar_size; - char *ar_rawname; -} Elf_Arhdr; - -/* Archive symbol table. */ -typedef struct -{ - char *as_name; - size_t as_off; - unsigned long int as_hash; -} Elf_Arsym; - - -/* Data descriptor. */ -typedef struct -{ - void *d_buf; - Elf_Type d_type; - size_t d_size; - off_t d_off; /* Offset into section. */ - size_t d_align; /* Alignment in section. */ - unsigned int d_version; /* ELF version. */ -} Elf_Data; - - - -/* Open an Elf descriptor on file descriptor FD. - REF is the Elf descriptor for the containing archive (to open a member); - or the descriptor previously returned for FD (to add a user reference); - or NULL. */ -extern Elf *elf_begin __P ((int __fd, Elf_Cmd __cmd, Elf *__ref)); - -/* Finish using ELF (remove a user reference); if this is the last user - reference, its data will be freed. */ -extern int elf_end __P ((Elf *__elf)); - -/* Control th