mirror of
https://sourceware.org/git/glibc.git
synced 2025-07-29 11:41:21 +03:00
Mon Jun 10 06:14:03 1996 Roland McGrath <roland@delasyd.gnu.ai.mit.edu>
* 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 <roland@delasyd.gnu.ai.mit.edu> * 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 <roland@delasyd.gnu.ai.mit.edu> * 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 <libelf.h> 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 <roland@delasyd.gnu.ai.mit.edu> * 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 <rth@tamu.edu> * 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.
This commit is contained in:
108
ChangeLog
108
ChangeLog
@ -1,3 +1,111 @@
|
|||||||
|
Mon Jun 10 06:14:03 1996 Roland McGrath <roland@delasyd.gnu.ai.mit.edu>
|
||||||
|
|
||||||
|
* 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 <roland@delasyd.gnu.ai.mit.edu>
|
||||||
|
|
||||||
|
* 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 <roland@delasyd.gnu.ai.mit.edu>
|
||||||
|
|
||||||
|
* 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 <libelf.h> 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 <roland@delasyd.gnu.ai.mit.edu>
|
||||||
|
|
||||||
|
* 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 <rth@tamu.edu>
|
||||||
|
|
||||||
|
* 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 <roland@delasyd.gnu.ai.mit.edu>
|
Mon Jun 10 02:22:24 1996 Roland McGrath <roland@delasyd.gnu.ai.mit.edu>
|
||||||
|
|
||||||
* sysdeps/unix/sysv/linux/configure.in: New file, start with configure.
|
* sysdeps/unix/sysv/linux/configure.in: New file, start with configure.
|
||||||
|
34
elf/Makefile
34
elf/Makefile
@ -20,19 +20,26 @@
|
|||||||
|
|
||||||
subdir := elf
|
subdir := elf
|
||||||
|
|
||||||
headers := elf.h libelf.h link.h dlfcn.h
|
headers = elf.h link.h dlfcn.h
|
||||||
routines := init-first
|
routines = init-first $(dl-routines) dl-open dl-symbol dl-support
|
||||||
|
|
||||||
extra-libs = libelf libdl
|
# The core dynamic linking functions are in libc for the static and
|
||||||
libelf-routines := elf_hash
|
# profiled libraries.
|
||||||
libdl-routines := dlopen dlclose dlsym dlerror dladdr
|
dl-routines = $(addprefix dl-,load lookup object reloc deps \
|
||||||
libdl-inhibit-o = $(filter-out .so,$(object-suffixes)) # Build only shared.
|
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
|
||||||
|
|
||||||
rtld-routines := rtld $(addprefix dl-,minimal load lookup object reloc \
|
# ld.so uses those routines, plus some special stuff for being the program
|
||||||
deps runtime sysdep error init fini)
|
# 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 \
|
distribute = $(rtld-routines:=.c) dynamic-link.h do-rel.h dl-machine.h \
|
||||||
soinit.c sofini.c ldd.sh.in linux-compat.c
|
soinit.c sofini.c ldd.sh.in linux-compat.c
|
||||||
|
|
||||||
|
extra-libs = libdl
|
||||||
|
libdl-routines := dlopen dlclose dlsym dlerror dladdr
|
||||||
|
|
||||||
|
|
||||||
all: # Make this the default target; it will be defined in Rules.
|
all: # Make this the default target; it will be defined in Rules.
|
||||||
|
|
||||||
include ../Makeconfig
|
include ../Makeconfig
|
||||||
@ -43,7 +50,7 @@ generated = librtld.so dl-allobjs.so
|
|||||||
install-others = $(slibdir)/$(rtld-installed-name)
|
install-others = $(slibdir)/$(rtld-installed-name)
|
||||||
install-bin = ldd
|
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.
|
# to run programs during the `make others' pass.
|
||||||
lib-noranlib: $(objpfx)ld.so $(addprefix $(objpfx),$(extra-objs))
|
lib-noranlib: $(objpfx)ld.so $(addprefix $(objpfx),$(extra-objs))
|
||||||
|
|
||||||
@ -81,16 +88,17 @@ $(LINK.o) -nostdlib -nostartfiles -shared -o $@ \
|
|||||||
-Wl,-rpath=$(default-rpath) $^
|
-Wl,-rpath=$(default-rpath) $^
|
||||||
endef
|
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
|
# The Linux-compatible dynamic linker shared object is just the same
|
||||||
# with one object file of compatibility initialization code added.
|
# with one object file of compatibility initialization code added.
|
||||||
$(objpfx)ld-linux.so.1: $(objpfx)linux-compat.so
|
$(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
|
$(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)/$(rtld-installed-name): $(objpfx)ld.so; $(do-install-program)
|
||||||
$(slibdir)/ld-linux.so.1: $(objpfx)ld-linux.so.1; $(do-install-program)
|
$(slibdir)/ld-linux.so.1: $(objpfx)ld-linux.so.1; $(do-install-program)
|
||||||
|
@ -56,7 +56,7 @@ _dl_map_object_deps (struct link_map *map)
|
|||||||
{
|
{
|
||||||
const char *strtab
|
const char *strtab
|
||||||
= ((void *) l->l_addr + l->l_info[DT_STRTAB]->d_un.d_ptr);
|
= ((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)
|
for (d = l->l_ld; d->d_tag != DT_NULL; ++d)
|
||||||
if (d->d_tag == DT_NEEDED)
|
if (d->d_tag == DT_NEEDED)
|
||||||
{
|
{
|
||||||
@ -97,28 +97,3 @@ _dl_map_object_deps (struct link_map *map)
|
|||||||
scanp->map->l_reserved = 0;
|
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;
|
|
||||||
}
|
|
||||||
|
@ -24,7 +24,7 @@ Cambridge, MA 02139, USA. */
|
|||||||
/* Run initializers for MAP and its dependencies, in inverse dependency
|
/* Run initializers for MAP and its dependencies, in inverse dependency
|
||||||
order (that is, leaf nodes first). */
|
order (that is, leaf nodes first). */
|
||||||
|
|
||||||
Elf32_Addr
|
ElfW(Addr)
|
||||||
_dl_init_next (struct link_map *map)
|
_dl_init_next (struct link_map *map)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
133
elf/dl-load.c
133
elf/dl-load.c
@ -60,6 +60,7 @@ Cambridge, MA 02139, USA. */
|
|||||||
#define STRING(x) #x
|
#define STRING(x) #x
|
||||||
|
|
||||||
int _dl_zerofd = -1;
|
int _dl_zerofd = -1;
|
||||||
|
size_t _dl_pagesize;
|
||||||
|
|
||||||
|
|
||||||
/* Try to open NAME in one of the directories in DIRPATH.
|
/* 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;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
buf = alloca (strlen (dirpath) + 1 + namelen);
|
buf = __alloca (strlen (dirpath) + 1 + namelen);
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
|
size_t buflen;
|
||||||
|
|
||||||
dirpath = p;
|
dirpath = p;
|
||||||
p = strpbrk (dirpath, ":;");
|
p = strpbrk (dirpath, ":;");
|
||||||
if (p == NULL)
|
if (p == NULL)
|
||||||
p = strchr (dirpath, '\0');
|
p = strchr (dirpath, '\0');
|
||||||
|
|
||||||
if (p == dirpath)
|
if (p == dirpath)
|
||||||
/* Two adjacent colons, or a colon at the beginning or the end of
|
{
|
||||||
the path means to search the current directory. */
|
/* Two adjacent colons, or a colon at the beginning or the end of
|
||||||
(void) memcpy (buf, name, namelen);
|
the path means to search the current directory. */
|
||||||
|
(void) memcpy (buf, name, namelen);
|
||||||
|
buflen = namelen;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Construct the pathname to try. */
|
/* Construct the pathname to try. */
|
||||||
(void) memcpy (buf, dirpath, p - dirpath);
|
(void) memcpy (buf, dirpath, p - dirpath);
|
||||||
buf[p - dirpath] = '/';
|
buf[p - dirpath] = '/';
|
||||||
(void) memcpy (&buf[(p - dirpath) + 1], name, namelen);
|
(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)
|
if (fd != -1)
|
||||||
{
|
{
|
||||||
*realname = strdup (buf);
|
*realname = malloc (buflen);
|
||||||
return fd;
|
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)
|
if (errno != ENOENT && errno != EACCES)
|
||||||
/* The file exists and is readable, but something went wrong. */
|
/* The file exists and is readable, but something went wrong. */
|
||||||
@ -117,7 +135,6 @@ open_path (const char *name, size_t namelen,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Map in the shared object file NAME. */
|
/* Map in the shared object file NAME. */
|
||||||
|
|
||||||
struct link_map *
|
struct link_map *
|
||||||
@ -163,9 +180,19 @@ _dl_map_object (struct link_map *loader, const char *name)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
fd = open (name, O_RDONLY);
|
fd = __open (name, O_RDONLY);
|
||||||
if (fd != -1)
|
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)
|
if (fd == -1)
|
||||||
@ -182,25 +209,24 @@ struct link_map *
|
|||||||
_dl_map_object_from_fd (const char *name, int fd, char *realname)
|
_dl_map_object_from_fd (const char *name, int fd, char *realname)
|
||||||
{
|
{
|
||||||
struct link_map *l = NULL;
|
struct link_map *l = NULL;
|
||||||
const size_t pagesize = getpagesize ();
|
|
||||||
void *file_mapping = NULL;
|
void *file_mapping = NULL;
|
||||||
size_t mapping_size = 0;
|
size_t mapping_size = 0;
|
||||||
|
|
||||||
#define LOSE(s) lose (0, (s))
|
#define LOSE(s) lose (0, (s))
|
||||||
void lose (int code, const char *msg)
|
void lose (int code, const char *msg)
|
||||||
{
|
{
|
||||||
(void) close (fd);
|
(void) __close (fd);
|
||||||
if (file_mapping)
|
if (file_mapping)
|
||||||
munmap (file_mapping, mapping_size);
|
__munmap (file_mapping, mapping_size);
|
||||||
_dl_signal_error (code, l ? l->l_name : name, msg);
|
_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)
|
int prot, int fixed, off_t offset)
|
||||||
{
|
{
|
||||||
caddr_t mapat = mmap ((caddr_t) mapstart, len, prot,
|
caddr_t mapat = __mmap ((caddr_t) mapstart, len, prot,
|
||||||
fixed|MAP_COPY|MAP_FILE,
|
fixed|MAP_COPY|MAP_FILE,
|
||||||
fd, offset);
|
fd, offset);
|
||||||
if (mapat == (caddr_t) -1)
|
if (mapat == (caddr_t) -1)
|
||||||
lose (errno, "failed to map segment from shared object");
|
lose (errno, "failed to map segment from shared object");
|
||||||
return mapat;
|
return mapat;
|
||||||
@ -213,11 +239,11 @@ _dl_map_object_from_fd (const char *name, int fd, char *realname)
|
|||||||
{
|
{
|
||||||
void *result;
|
void *result;
|
||||||
if (file_mapping)
|
if (file_mapping)
|
||||||
munmap (file_mapping, mapping_size);
|
__munmap (file_mapping, mapping_size);
|
||||||
mapping_size = (location + size + 1 + pagesize - 1);
|
mapping_size = (location + size + 1 + _dl_pagesize - 1);
|
||||||
mapping_size &= ~(pagesize - 1);
|
mapping_size &= ~(_dl_pagesize - 1);
|
||||||
result = mmap (file_mapping, mapping_size, PROT_READ,
|
result = __mmap (file_mapping, mapping_size, PROT_READ,
|
||||||
MAP_COPY|MAP_FILE, fd, 0);
|
MAP_COPY|MAP_FILE, fd, 0);
|
||||||
if (result == (void *) -1)
|
if (result == (void *) -1)
|
||||||
lose (errno, "cannot map file data");
|
lose (errno, "cannot map file data");
|
||||||
file_mapping = result;
|
file_mapping = result;
|
||||||
@ -225,9 +251,9 @@ _dl_map_object_from_fd (const char *name, int fd, char *realname)
|
|||||||
return file_mapping + location;
|
return file_mapping + location;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Elf32_Ehdr *header;
|
const ElfW(Ehdr) *header;
|
||||||
const Elf32_Phdr *phdr;
|
const ElfW(Phdr) *phdr;
|
||||||
const Elf32_Phdr *ph;
|
const ElfW(Phdr) *ph;
|
||||||
int type;
|
int type;
|
||||||
|
|
||||||
/* Look again to see if the real name matched another already loaded. */
|
/* 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.
|
/* The object is already loaded.
|
||||||
Just bump its reference count and return it. */
|
Just bump its reference count and return it. */
|
||||||
close (fd);
|
__close (fd);
|
||||||
free (realname);
|
free (realname);
|
||||||
++l->l_opencount;
|
++l->l_opencount;
|
||||||
return l;
|
return l;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_dl_pagesize == 0)
|
||||||
|
_dl_pagesize = __getpagesize ();
|
||||||
|
|
||||||
/* Map in the first page to read the header. */
|
/* Map in the first page to read the header. */
|
||||||
header = map (0, sizeof *header);
|
header = map (0, sizeof *header);
|
||||||
|
|
||||||
@ -260,8 +289,10 @@ _dl_map_object_from_fd (const char *name, int fd, char *realname)
|
|||||||
#endif
|
#endif
|
||||||
)
|
)
|
||||||
LOSE ("invalid ELF header");
|
LOSE ("invalid ELF header");
|
||||||
if (header->e_ident[EI_CLASS] != ELFCLASS32)
|
#define ELF32_CLASS ELFCLASS32
|
||||||
LOSE ("ELF file class not 32-bit");
|
#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)
|
if (header->e_ident[EI_DATA] != byteorder)
|
||||||
LOSE ("ELF file data encoding not " byteorder_name);
|
LOSE ("ELF file data encoding not " byteorder_name);
|
||||||
if (header->e_ident[EI_VERSION] != EV_CURRENT)
|
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));
|
LOSE ("ELF file version not " STRING(EV_CURRENT));
|
||||||
if (! elf_machine_matches_host (header->e_machine))
|
if (! elf_machine_matches_host (header->e_machine))
|
||||||
LOSE ("ELF file machine architecture not " ELF_MACHINE_NAME);
|
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");
|
LOSE ("ELF file's phentsize not the expected size");
|
||||||
|
|
||||||
/* Enter the new object in the list of loaded objects. */
|
/* 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;
|
l->l_entry = header->e_entry;
|
||||||
type = header->e_type;
|
type = header->e_type;
|
||||||
l->l_phnum = header->e_phnum;
|
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. */
|
/* Scan the program header table, collecting its load commands. */
|
||||||
struct loadcmd
|
struct loadcmd
|
||||||
{
|
{
|
||||||
Elf32_Addr mapstart, mapend, dataend, allocend;
|
ElfW(Addr) mapstart, mapend, dataend, allocend;
|
||||||
off_t mapoff;
|
off_t mapoff;
|
||||||
int prot;
|
int prot;
|
||||||
} loadcmds[l->l_phnum], *c;
|
} loadcmds[l->l_phnum], *c;
|
||||||
@ -320,15 +351,15 @@ _dl_map_object_from_fd (const char *name, int fd, char *realname)
|
|||||||
case PT_LOAD:
|
case PT_LOAD:
|
||||||
/* A load command tells us to map in part of the file.
|
/* A load command tells us to map in part of the file.
|
||||||
We record the load commands and process them all later. */
|
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");
|
LOSE ("ELF load command alignment not page-aligned");
|
||||||
if ((ph->p_vaddr - ph->p_offset) % ph->p_align)
|
if ((ph->p_vaddr - ph->p_offset) % ph->p_align)
|
||||||
LOSE ("ELF load command address/offset not properly aligned");
|
LOSE ("ELF load command address/offset not properly aligned");
|
||||||
{
|
{
|
||||||
struct loadcmd *c = &loadcmds[nloadcmds++];
|
struct loadcmd *c = &loadcmds[nloadcmds++];
|
||||||
c->mapstart = ph->p_vaddr & ~(ph->p_align - 1);
|
c->mapstart = ph->p_vaddr & ~(ph->p_align - 1);
|
||||||
c->mapend = ((ph->p_vaddr + ph->p_filesz + pagesize - 1)
|
c->mapend = ((ph->p_vaddr + ph->p_filesz + _dl_pagesize - 1)
|
||||||
& ~(pagesize - 1));
|
& ~(_dl_pagesize - 1));
|
||||||
c->dataend = ph->p_vaddr + ph->p_filesz;
|
c->dataend = ph->p_vaddr + ph->p_filesz;
|
||||||
c->allocend = ph->p_vaddr + ph->p_memsz;
|
c->allocend = ph->p_vaddr + ph->p_memsz;
|
||||||
c->mapoff = ph->p_offset & ~(ph->p_align - 1);
|
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. */
|
/* 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. */
|
/* Now process the load commands and map segments into memory. */
|
||||||
c = loadcmds;
|
c = loadcmds;
|
||||||
@ -362,16 +393,16 @@ _dl_map_object_from_fd (const char *name, int fd, char *realname)
|
|||||||
mapat = map_segment (c->mapstart,
|
mapat = map_segment (c->mapstart,
|
||||||
loadcmds[nloadcmds - 1].allocend - c->mapstart,
|
loadcmds[nloadcmds - 1].allocend - c->mapstart,
|
||||||
c->prot, 0, c->mapoff);
|
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;
|
/* Change protection on the excess portion to disallow all access;
|
||||||
the portions we do not remap later will be inaccessible as if
|
the portions we do not remap later will be inaccessible as if
|
||||||
unallocated. Then jump into the normal segment-mapping loop to
|
unallocated. Then jump into the normal segment-mapping loop to
|
||||||
handle the portion of the segment past the end of the file
|
handle the portion of the segment past the end of the file
|
||||||
mapping. */
|
mapping. */
|
||||||
mprotect (mapat + c->mapend,
|
__mprotect (mapat + c->mapend,
|
||||||
loadcmds[nloadcmds - 1].allocend - c->mapend,
|
loadcmds[nloadcmds - 1].allocend - c->mapend,
|
||||||
0);
|
0);
|
||||||
goto postmap;
|
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,
|
/* Extra zero pages should appear at the end of this segment,
|
||||||
after the data mapped from the file. */
|
after the data mapped from the file. */
|
||||||
Elf32_Addr zero, zeroend, zeropage;
|
ElfW(Addr) zero, zeroend, zeropage;
|
||||||
|
|
||||||
zero = l->l_addr + c->dataend;
|
zero = l->l_addr + c->dataend;
|
||||||
zeroend = l->l_addr + c->allocend;
|
zeroend = l->l_addr + c->allocend;
|
||||||
zeropage = (zero + pagesize - 1) & ~(pagesize - 1);
|
zeropage = (zero + _dl_pagesize - 1) & ~(_dl_pagesize - 1);
|
||||||
|
|
||||||
if (zeroend < zeropage)
|
if (zeroend < zeropage)
|
||||||
/* All the extra data is in the last page of the segment.
|
/* 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)
|
if ((c->prot & PROT_WRITE) == 0)
|
||||||
{
|
{
|
||||||
/* Dag nab it. */
|
/* Dag nab it. */
|
||||||
if (mprotect ((caddr_t) (zero & ~(pagesize - 1)),
|
if (__mprotect ((caddr_t) (zero & ~(_dl_pagesize - 1)),
|
||||||
pagesize, c->prot|PROT_WRITE) < 0)
|
_dl_pagesize, c->prot|PROT_WRITE) < 0)
|
||||||
lose (errno, "cannot change memory protections");
|
lose (errno, "cannot change memory protections");
|
||||||
}
|
}
|
||||||
memset ((void *) zero, 0, zeropage - zero);
|
memset ((void *) zero, 0, zeropage - zero);
|
||||||
if ((c->prot & PROT_WRITE) == 0)
|
if ((c->prot & PROT_WRITE) == 0)
|
||||||
mprotect ((caddr_t) (zero & ~(pagesize - 1)),
|
__mprotect ((caddr_t) (zero & ~(_dl_pagesize - 1)),
|
||||||
pagesize, c->prot);
|
_dl_pagesize, c->prot);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (zeroend > zeropage)
|
if (zeroend > zeropage)
|
||||||
{
|
{
|
||||||
/* Map the remaining zero pages in from the zero fill FD. */
|
/* Map the remaining zero pages in from the zero fill FD. */
|
||||||
caddr_t mapat;
|
caddr_t mapat;
|
||||||
mapat = mmap ((caddr_t) zeropage, zeroend - zeropage, c->prot,
|
mapat = __mmap ((caddr_t) zeropage, zeroend - zeropage,
|
||||||
MAP_ANON|MAP_PRIVATE|MAP_FIXED,
|
c->prot, MAP_ANON|MAP_PRIVATE|MAP_FIXED,
|
||||||
_dl_zerofd, 0);
|
_dl_zerofd, 0);
|
||||||
if (mapat == (caddr_t) -1)
|
if (mapat == (caddr_t) -1)
|
||||||
lose (errno, "cannot map zero-fill pages");
|
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");
|
LOSE ("object file has no dynamic section");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
(Elf32_Addr) l->l_ld += l->l_addr;
|
(ElfW(Addr)) l->l_ld += l->l_addr;
|
||||||
|
|
||||||
if (l->l_phdr == 0)
|
if (l->l_phdr == 0)
|
||||||
l->l_phdr = (void *) ((const Elf32_Ehdr *) l->l_addr)->e_phoff;
|
l->l_phdr = (void *) ((const ElfW(Ehdr) *) l->l_addr)->e_phoff;
|
||||||
(Elf32_Addr) l->l_phdr += l->l_addr;
|
(ElfW(Addr)) l->l_phdr += l->l_addr;
|
||||||
|
|
||||||
elf_get_dynamic_info (l->l_ld, l->l_info);
|
elf_get_dynamic_info (l->l_ld, l->l_info);
|
||||||
if (l->l_info[DT_HASH])
|
if (l->l_info[DT_HASH])
|
||||||
|
103
elf/dl-lookup.c
103
elf/dl-lookup.c
@ -18,27 +18,48 @@ not, write to the Free Software Foundation, Inc., 675 Mass Ave,
|
|||||||
Cambridge, MA 02139, USA. */
|
Cambridge, MA 02139, USA. */
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <libelf.h>
|
|
||||||
#include <link.h>
|
#include <link.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
|
|
||||||
|
/* 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
|
/* 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,
|
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
|
then a PLT entry cannot satisfy the reference; some different binding
|
||||||
must be found. */
|
must be found. */
|
||||||
|
|
||||||
Elf32_Addr
|
ElfW(Addr)
|
||||||
_dl_lookup_symbol (const char *undef_name, const Elf32_Sym **ref,
|
_dl_lookup_symbol (const char *undef_name, const ElfW(Sym) **ref,
|
||||||
struct link_map *symbol_scope[2],
|
struct link_map *symbol_scope[2],
|
||||||
const char *reference_name,
|
const char *reference_name,
|
||||||
Elf32_Addr reloc_addr,
|
ElfW(Addr) reloc_addr,
|
||||||
int noplt)
|
int noplt)
|
||||||
{
|
{
|
||||||
unsigned long int hash = elf_hash (undef_name);
|
const unsigned long int hash = _dl_elf_hash (undef_name);
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
Elf32_Addr a;
|
ElfW(Addr) a;
|
||||||
const Elf32_Sym *s;
|
const ElfW(Sym) *s;
|
||||||
} weak_value = { 0, NULL };
|
} weak_value = { 0, NULL };
|
||||||
size_t i;
|
size_t i;
|
||||||
struct link_map **scope, *map;
|
struct link_map **scope, *map;
|
||||||
@ -48,9 +69,9 @@ _dl_lookup_symbol (const char *undef_name, const Elf32_Sym **ref,
|
|||||||
if (*scope)
|
if (*scope)
|
||||||
for (i = 0; i < (*scope)->l_nsearchlist; ++i)
|
for (i = 0; i < (*scope)->l_nsearchlist; ++i)
|
||||||
{
|
{
|
||||||
const Elf32_Sym *symtab;
|
const ElfW(Sym) *symtab;
|
||||||
const char *strtab;
|
const char *strtab;
|
||||||
Elf32_Word symidx;
|
ElfW(Word) symidx;
|
||||||
|
|
||||||
map = (*scope)->l_searchlist[i];
|
map = (*scope)->l_searchlist[i];
|
||||||
|
|
||||||
@ -63,7 +84,7 @@ _dl_lookup_symbol (const char *undef_name, const Elf32_Sym **ref,
|
|||||||
symidx != STN_UNDEF;
|
symidx != STN_UNDEF;
|
||||||
symidx = map->l_chain[symidx])
|
symidx = map->l_chain[symidx])
|
||||||
{
|
{
|
||||||
const Elf32_Sym *sym = &symtab[symidx];
|
const ElfW(Sym) *sym = &symtab[symidx];
|
||||||
|
|
||||||
if (sym->st_value == 0 || /* No value. */
|
if (sym->st_value == 0 || /* No value. */
|
||||||
/* Cannot resolve to the location being filled in. */
|
/* 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. */
|
(noplt && sym->st_shndx == SHN_UNDEF)) /* Reject PLT. */
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
switch (ELF32_ST_TYPE (sym->st_info))
|
switch (ELFW(ST_TYPE) (sym->st_info))
|
||||||
{
|
{
|
||||||
case STT_NOTYPE:
|
case STT_NOTYPE:
|
||||||
case STT_FUNC:
|
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. */
|
/* Not the symbol we are looking for. */
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
switch (ELF32_ST_BIND (sym->st_info))
|
switch (ELFW(ST_BIND) (sym->st_info))
|
||||||
{
|
{
|
||||||
case STB_GLOBAL:
|
case STB_GLOBAL:
|
||||||
/* Global definition. Just what we need. */
|
/* 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
|
/* We could find no value for a strong reference. */
|
||||||
access to dynamic linker functionality without using -ldl and
|
const char msg[] = "undefined symbol: ";
|
||||||
thereby brining the dynamic linker's symbols into scope, we
|
char buf[sizeof msg + strlen (undef_name)];
|
||||||
recognize a few magical symbol names and resolve them to the
|
memcpy (buf, msg, sizeof msg - 1);
|
||||||
addresses of functions inside the dynamic linker. */
|
memcpy (&buf[sizeof msg - 1], undef_name,
|
||||||
|
sizeof buf - sizeof msg + 1);
|
||||||
struct magic
|
_dl_signal_error (0, reference_name, buf);
|
||||||
{
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
*ref = weak_value.s;
|
*ref = weak_value.s;
|
||||||
@ -155,23 +150,11 @@ _dl_lookup_symbol (const char *undef_name, const Elf32_Sym **ref,
|
|||||||
void
|
void
|
||||||
_dl_setup_hash (struct link_map *map)
|
_dl_setup_hash (struct link_map *map)
|
||||||
{
|
{
|
||||||
Elf32_Word *hash = (void *) map->l_addr + map->l_info[DT_HASH]->d_un.d_ptr;
|
ElfW(Word) *hash = (void *) map->l_addr + map->l_info[DT_HASH]->d_un.d_ptr;
|
||||||
Elf32_Word nchain;
|
ElfW(Word) nchain;
|
||||||
map->l_nbuckets = *hash++;
|
map->l_nbuckets = *hash++;
|
||||||
nchain = *hash++;
|
nchain = *hash++;
|
||||||
map->l_buckets = hash;
|
map->l_buckets = hash;
|
||||||
hash += map->l_nbuckets;
|
hash += map->l_nbuckets;
|
||||||
map->l_chain = hash;
|
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;
|
|
||||||
}
|
|
||||||
|
@ -34,10 +34,9 @@ void *
|
|||||||
malloc (size_t n)
|
malloc (size_t n)
|
||||||
{
|
{
|
||||||
extern int _dl_zerofd;
|
extern int _dl_zerofd;
|
||||||
static size_t pagesize;
|
|
||||||
|
|
||||||
if (pagesize == 0)
|
if (_dl_pagesize == 0)
|
||||||
pagesize = __getpagesize ();
|
_dl_pagesize = __getpagesize ();
|
||||||
|
|
||||||
if (_dl_zerofd == -1)
|
if (_dl_zerofd == -1)
|
||||||
_dl_zerofd = _dl_sysdep_open_zero_fill ();
|
_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. */
|
/* Consume any unused space in the last page of our data segment. */
|
||||||
extern int _end;
|
extern int _end;
|
||||||
alloc_ptr = &_end;
|
alloc_ptr = &_end;
|
||||||
alloc_end = (void *) 0 + (((alloc_ptr - (void *) 0) + pagesize - 1)
|
alloc_end = (void *) 0 + (((alloc_ptr - (void *) 0) + _dl_pagesize - 1)
|
||||||
& ~(pagesize - 1));
|
& ~(_dl_pagesize - 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Make sure the allocation pointer is ideally aligned. */
|
/* Make sure the allocation pointer is ideally aligned. */
|
||||||
@ -59,13 +58,13 @@ malloc (size_t n)
|
|||||||
{
|
{
|
||||||
/* Insufficient space left; allocate another page. */
|
/* Insufficient space left; allocate another page. */
|
||||||
caddr_t page;
|
caddr_t page;
|
||||||
assert (n <= pagesize);
|
assert (n <= _dl_pagesize);
|
||||||
page = mmap (0, pagesize, PROT_READ|PROT_WRITE,
|
page = __mmap (0, _dl_pagesize, PROT_READ|PROT_WRITE,
|
||||||
MAP_ANON|MAP_PRIVATE, _dl_zerofd, 0);
|
MAP_ANON|MAP_PRIVATE, _dl_zerofd, 0);
|
||||||
assert (page != (caddr_t) -1);
|
assert (page != (caddr_t) -1);
|
||||||
if (page != alloc_end)
|
if (page != alloc_end)
|
||||||
alloc_ptr = page;
|
alloc_ptr = page;
|
||||||
alloc_end = page + pagesize;
|
alloc_end = page + _dl_pagesize;
|
||||||
}
|
}
|
||||||
|
|
||||||
alloc_last_block = (void *) alloc_ptr;
|
alloc_last_block = (void *) alloc_ptr;
|
||||||
|
45
elf/dl-open.c
Normal file
45
elf/dl-open.c
Normal file
@ -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 <link.h>
|
||||||
|
#include <dlfcn.h>
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
@ -28,8 +28,6 @@ Cambridge, MA 02139, USA. */
|
|||||||
void
|
void
|
||||||
_dl_relocate_object (struct link_map *l, int lazy)
|
_dl_relocate_object (struct link_map *l, int lazy)
|
||||||
{
|
{
|
||||||
const size_t pagesize = getpagesize ();
|
|
||||||
|
|
||||||
if (l->l_relocated)
|
if (l->l_relocated)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -37,17 +35,17 @@ _dl_relocate_object (struct link_map *l, int lazy)
|
|||||||
{
|
{
|
||||||
/* Bletch. We must make read-only segments writable
|
/* Bletch. We must make read-only segments writable
|
||||||
long enough to relocate them. */
|
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)
|
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)
|
if (ph->p_type == PT_LOAD && (ph->p_flags & PF_W) == 0)
|
||||||
{
|
{
|
||||||
caddr_t mapstart = ((caddr_t) l->l_addr +
|
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 +
|
caddr_t mapend = ((caddr_t) l->l_addr +
|
||||||
((ph->p_vaddr + ph->p_memsz + pagesize - 1)
|
((ph->p_vaddr + ph->p_memsz + _dl_pagesize - 1)
|
||||||
& ~(pagesize - 1)));
|
& ~(_dl_pagesize - 1)));
|
||||||
if (mprotect (mapstart, mapend - mapstart,
|
if (__mprotect (mapstart, mapend - mapstart,
|
||||||
PROT_READ|PROT_WRITE) < 0)
|
PROT_READ|PROT_WRITE) < 0)
|
||||||
_dl_signal_error (errno, l->l_name,
|
_dl_signal_error (errno, l->l_name,
|
||||||
"cannot make segment writable for relocation");
|
"cannot make segment writable for relocation");
|
||||||
}
|
}
|
||||||
@ -59,8 +57,8 @@ _dl_relocate_object (struct link_map *l, int lazy)
|
|||||||
const char *strtab
|
const char *strtab
|
||||||
= ((void *) l->l_addr + l->l_info[DT_STRTAB]->d_un.d_ptr);
|
= ((void *) l->l_addr + l->l_info[DT_STRTAB]->d_un.d_ptr);
|
||||||
|
|
||||||
Elf32_Addr resolve (const Elf32_Sym **ref,
|
ElfW(Addr) resolve (const ElfW(Sym) **ref,
|
||||||
Elf32_Addr reloc_addr, int noplt)
|
ElfW(Addr) reloc_addr, int noplt)
|
||||||
{
|
{
|
||||||
return _dl_lookup_symbol (strtab + (*ref)->st_name, ref, scope,
|
return _dl_lookup_symbol (strtab + (*ref)->st_name, ref, scope,
|
||||||
l->l_name, reloc_addr, noplt);
|
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])
|
if (l->l_info[DT_TEXTREL])
|
||||||
{
|
{
|
||||||
/* Undo the protection change we made before relocating. */
|
/* 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)
|
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)
|
if (ph->p_type == PT_LOAD && (ph->p_flags & PF_W) == 0)
|
||||||
{
|
{
|
||||||
caddr_t mapstart = ((caddr_t) l->l_addr +
|
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 +
|
caddr_t mapend = ((caddr_t) l->l_addr +
|
||||||
((ph->p_vaddr + ph->p_memsz + pagesize - 1)
|
((ph->p_vaddr + ph->p_memsz + _dl_pagesize - 1)
|
||||||
& ~(pagesize - 1)));
|
& ~(_dl_pagesize - 1)));
|
||||||
int prot = 0;
|
int prot = 0;
|
||||||
if (ph->p_flags & PF_R)
|
if (ph->p_flags & PF_R)
|
||||||
prot |= PROT_READ;
|
prot |= PROT_READ;
|
||||||
if (ph->p_flags & PF_X)
|
if (ph->p_flags & PF_X)
|
||||||
prot |= PROT_EXEC;
|
prot |= PROT_EXEC;
|
||||||
if (mprotect (mapstart, mapend - mapstart, prot) < 0)
|
if (__mprotect (mapstart, mapend - mapstart, prot) < 0)
|
||||||
_dl_signal_error (errno, l->l_name,
|
_dl_signal_error (errno, l->l_name,
|
||||||
"can't restore segment prot after reloc");
|
"can't restore segment prot after reloc");
|
||||||
}
|
}
|
||||||
|
@ -24,9 +24,9 @@ Cambridge, MA 02139, USA. */
|
|||||||
#define elf_machine_rel 1
|
#define elf_machine_rel 1
|
||||||
#define elf_machine_rela 2
|
#define elf_machine_rela 2
|
||||||
#if elf_machine_relplt == elf_machine_rel
|
#if elf_machine_relplt == elf_machine_rel
|
||||||
#define PLTREL Elf32_Rel
|
#define PLTREL ElfW(Rel)
|
||||||
#elif elf_machine_relplt == elf_machine_rela
|
#elif elf_machine_relplt == elf_machine_rela
|
||||||
#define PLTREL Elf32_Rela
|
#define PLTREL ElfW(Rela)
|
||||||
#else
|
#else
|
||||||
#error "dl-machine.h bug: elf_machine_relplt not rel or rela"
|
#error "dl-machine.h bug: elf_machine_relplt not rel or rela"
|
||||||
#endif
|
#endif
|
||||||
@ -37,11 +37,11 @@ Cambridge, MA 02139, USA. */
|
|||||||
in the trampoline code will be a local PC-relative call. Tell the
|
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. */
|
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
|
#ifdef ELF_MACHINE_RUNTIME_FIXUP_ARGS
|
||||||
ELF_MACHINE_RUNTIME_FIXUP_ARGS,
|
ELF_MACHINE_RUNTIME_FIXUP_ARGS,
|
||||||
#endif
|
#endif
|
||||||
struct link_map *l, Elf32_Word reloc_offset)
|
struct link_map *l, ElfW(Word) reloc_offset)
|
||||||
__attribute__ ((unused));
|
__attribute__ ((unused));
|
||||||
|
|
||||||
/* This function is called through a special trampoline from the PLT the
|
/* 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
|
to that address. Future calls will bounce directly from the PLT to the
|
||||||
function. */
|
function. */
|
||||||
|
|
||||||
static Elf32_Addr
|
static ElfW(Addr)
|
||||||
fixup (
|
fixup (
|
||||||
#ifdef ELF_MACHINE_RUNTIME_FIXUP_ARGS
|
#ifdef ELF_MACHINE_RUNTIME_FIXUP_ARGS
|
||||||
ELF_MACHINE_RUNTIME_FIXUP_ARGS,
|
ELF_MACHINE_RUNTIME_FIXUP_ARGS,
|
||||||
#endif
|
#endif
|
||||||
struct link_map *l, Elf32_Word reloc_offset)
|
struct link_map *l, ElfW(Word) reloc_offset)
|
||||||
{
|
{
|
||||||
const Elf32_Sym *const symtab
|
const ElfW(Sym) *const symtab
|
||||||
= (const Elf32_Sym *) (l->l_addr + l->l_info[DT_SYMTAB]->d_un.d_ptr);
|
= (const ElfW(Sym) *) (l->l_addr + l->l_info[DT_SYMTAB]->d_un.d_ptr);
|
||||||
const char *strtab =
|
const char *strtab =
|
||||||
(const char *) (l->l_addr + l->l_info[DT_STRTAB]->d_un.d_ptr);
|
(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 +
|
= (const void *) (l->l_addr + l->l_info[DT_JMPREL]->d_un.d_ptr +
|
||||||
reloc_offset);
|
reloc_offset);
|
||||||
|
|
||||||
Elf32_Addr resolve (const Elf32_Sym **ref,
|
ElfW(Addr) resolve (const ElfW(Sym) **ref,
|
||||||
Elf32_Addr reloc_addr, int noplt)
|
ElfW(Addr) reloc_addr, int noplt)
|
||||||
{
|
{
|
||||||
struct link_map *scope[2] = { _dl_loaded, NULL };
|
struct link_map *scope[2] = { _dl_loaded, NULL };
|
||||||
return _dl_lookup_symbol (strtab + (*ref)->st_name, ref,
|
return _dl_lookup_symbol (strtab + (*ref)->st_name, ref,
|
||||||
@ -76,9 +76,9 @@ fixup (
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Perform the specified relocation. */
|
/* 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
51
elf/dl-support.c
Normal file
51
elf/dl-support.c
Normal file
@ -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 <assert.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
/* 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");
|
||||||
|
}
|
||||||
|
|
33
elf/dl-symbol.c
Normal file
33
elf/dl-symbol.c
Normal file
@ -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 <stddef.h>
|
||||||
|
#include <link.h>
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
}
|
@ -25,9 +25,9 @@ Cambridge, MA 02139, USA. */
|
|||||||
int
|
int
|
||||||
dladdr (void *address, Dl_info *info)
|
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;
|
struct link_map *l, *match;
|
||||||
const Elf32_Sym *symtab, *matchsym;
|
const ElfW(Sym) *symtab, *matchsym;
|
||||||
const char *strtab;
|
const char *strtab;
|
||||||
|
|
||||||
/* Find the highest-addressed object that ADDRESS is not below. */
|
/* 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)
|
for (matchsym = NULL; (void *) symtab < (void *) strtab; ++symtab)
|
||||||
if (addr >= match->l_addr + symtab->st_value && !matchsym ||
|
if (addr >= match->l_addr + symtab->st_value && !matchsym ||
|
||||||
matchsym->st_value < symtab->st_value &&
|
matchsym->st_value < symtab->st_value &&
|
||||||
ELF32_ST_BIND (symtab->st_info) == STB_GLOBAL ||
|
ELFW(ST_BIND) (symtab->st_info) == STB_GLOBAL ||
|
||||||
ELF32_ST_BIND (symtab->st_info) == STB_WEAK)
|
ELFW(ST_BIND) (symtab->st_info) == STB_WEAK)
|
||||||
matchsym = symtab;
|
matchsym = symtab;
|
||||||
|
|
||||||
if (matchsym)
|
if (matchsym)
|
||||||
|
@ -65,7 +65,7 @@ dlclose (void *handle)
|
|||||||
{
|
{
|
||||||
/* That was the last reference, and this was a dlopen-loaded
|
/* That was the last reference, and this was a dlopen-loaded
|
||||||
object. We can unmap it. */
|
object. We can unmap it. */
|
||||||
const Elf32_Phdr *ph;
|
const ElfW(Phdr) *ph;
|
||||||
|
|
||||||
if (map->l_info[DT_FINI])
|
if (map->l_info[DT_FINI])
|
||||||
/* Call its termination function. */
|
/* Call its termination function. */
|
||||||
@ -76,8 +76,8 @@ dlclose (void *handle)
|
|||||||
for (ph = map->l_phdr; ph < &map->l_phdr[map->l_phnum]; ++ph)
|
for (ph = map->l_phdr; ph < &map->l_phdr[map->l_phnum]; ++ph)
|
||||||
if (ph->p_type == PT_LOAD)
|
if (ph->p_type == PT_LOAD)
|
||||||
{
|
{
|
||||||
Elf32_Addr mapstart = ph->p_vaddr & ~(ph->p_align - 1);
|
ElfW(Addr) mapstart = ph->p_vaddr & ~(ph->p_align - 1);
|
||||||
Elf32_Addr mapend = ((ph->p_vaddr + ph->p_memsz
|
ElfW(Addr) mapend = ((ph->p_vaddr + ph->p_memsz
|
||||||
+ ph->p_align - 1)
|
+ ph->p_align - 1)
|
||||||
& ~(ph->p_align - 1));
|
& ~(ph->p_align - 1));
|
||||||
munmap ((caddr_t) mapstart, mapend - mapstart);
|
munmap ((caddr_t) mapstart, mapend - mapstart);
|
||||||
|
@ -27,8 +27,8 @@ void *
|
|||||||
dlsym (void *handle, const char *name)
|
dlsym (void *handle, const char *name)
|
||||||
{
|
{
|
||||||
struct link_map *map = handle;
|
struct link_map *map = handle;
|
||||||
Elf32_Addr loadbase;
|
ElfW(Addr) loadbase;
|
||||||
const Elf32_Sym *ref = NULL;
|
const ElfW(Sym) *ref = NULL;
|
||||||
void doit (void)
|
void doit (void)
|
||||||
{
|
{
|
||||||
struct link_map *scope[2] = { map, NULL };
|
struct link_map *scope[2] = { map, NULL };
|
||||||
|
24
elf/do-rel.h
24
elf/do-rel.h
@ -21,9 +21,9 @@ Cambridge, MA 02139, USA. */
|
|||||||
`elf_dynamic_do_rel' and `elf_dynamic_do_rela'. */
|
`elf_dynamic_do_rel' and `elf_dynamic_do_rela'. */
|
||||||
|
|
||||||
#ifdef DO_RELA
|
#ifdef DO_RELA
|
||||||
#define elf_dynamic_do_rel elf_dynamic_do_rela
|
#define elf_dynamic_do_rel elf_dynamic_do_rela
|
||||||
#define Elf32_Rel Elf32_Rela
|
#define Rel Rela
|
||||||
#define elf_machine_rel elf_machine_rela
|
#define elf_machine_rel elf_machine_rela
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@ -37,15 +37,15 @@ Cambridge, MA 02139, USA. */
|
|||||||
static inline void
|
static inline void
|
||||||
elf_dynamic_do_rel (struct link_map *map,
|
elf_dynamic_do_rel (struct link_map *map,
|
||||||
int reltag, int sztag,
|
int reltag, int sztag,
|
||||||
Elf32_Addr (*resolve) (const Elf32_Sym **symbol,
|
ElfW(Addr) (*resolve) (const ElfW(Sym) **symbol,
|
||||||
Elf32_Addr reloc_addr, int noplt),
|
ElfW(Addr) reloc_addr, int noplt),
|
||||||
int lazy)
|
int lazy)
|
||||||
{
|
{
|
||||||
const Elf32_Sym *const symtab
|
const ElfW(Sym) *const symtab
|
||||||
= (const Elf32_Sym *) (map->l_addr + map->l_info[DT_SYMTAB]->d_un.d_ptr);
|
= (const ElfW(Sym) *) (map->l_addr + map->l_info[DT_SYMTAB]->d_un.d_ptr);
|
||||||
const Elf32_Rel *r
|
const ElfW(Rel) *r
|
||||||
= (const Elf32_Rel *) (map->l_addr + map->l_info[reltag]->d_un.d_ptr);
|
= (const ElfW(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(Rel) *end = &r[map->l_info[sztag]->d_un.d_val / sizeof *r];
|
||||||
|
|
||||||
if (lazy)
|
if (lazy)
|
||||||
/* Doing lazy PLT relocations; they need very little info. */
|
/* 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);
|
elf_machine_lazy_rel (map, r);
|
||||||
else
|
else
|
||||||
for (; r < end; ++r)
|
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 elf_dynamic_do_rel
|
||||||
#undef Elf32_Rel
|
#undef Rel
|
||||||
#undef elf_machine_rel
|
#undef elf_machine_rel
|
||||||
|
@ -25,7 +25,7 @@ Cambridge, MA 02139, USA. */
|
|||||||
/* Read the dynamic section at DYN and fill in INFO with indices DT_*. */
|
/* Read the dynamic section at DYN and fill in INFO with indices DT_*. */
|
||||||
|
|
||||||
static inline void
|
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;
|
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])
|
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])
|
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])
|
if (info[DT_PLTREL])
|
||||||
assert (info[DT_PLTREL]->d_un.d_val == DT_REL ||
|
assert (info[DT_PLTREL]->d_un.d_val == DT_REL ||
|
||||||
info[DT_PLTREL]->d_un.d_val == DT_RELA);
|
info[DT_PLTREL]->d_un.d_val == DT_RELA);
|
||||||
|
244
elf/elf.h
244
elf/elf.h
@ -23,16 +23,37 @@ Cambridge, MA 02139, USA. */
|
|||||||
#define _ELF_H 1
|
#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
|
/* Type for a 16-bit quantity. */
|
||||||
these types. */
|
|
||||||
|
|
||||||
typedef unsigned int Elf32_Addr __attribute__ ((mode (SI)));
|
|
||||||
typedef unsigned int Elf32_Half __attribute__ ((mode (HI)));
|
typedef unsigned int Elf32_Half __attribute__ ((mode (HI)));
|
||||||
typedef unsigned int Elf32_Off __attribute__ ((mode (SI)));
|
typedef unsigned int Elf64_Half __attribute__ ((mode (HI)));
|
||||||
typedef int Elf32_Sword __attribute__ ((mode (SI)));
|
|
||||||
|
/* Types for signed and unsigned 32-bit quantities. */
|
||||||
typedef unsigned int Elf32_Word __attribute__ ((mode (SI)));
|
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 Elf64_Addr __attribute__ ((mode (DI)));
|
||||||
|
|
||||||
|
/* Type of file offsets. */
|
||||||
|
typedef unsigned int Elf32_Off __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. */
|
/* 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_Half e_shstrndx; /* Section header string table index */
|
||||||
} Elf32_Ehdr;
|
} 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
|
/* 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
|
array. The macros under each EI_* macro are the values the byte
|
||||||
may have. */
|
may have. */
|
||||||
@ -125,6 +164,8 @@ typedef struct
|
|||||||
pick large random numbers (0x8523, 0xa7f2, etc.) to minimize the
|
pick large random numbers (0x8523, 0xa7f2, etc.) to minimize the
|
||||||
chances of collision with official or non-GNU unofficial values. */
|
chances of collision with official or non-GNU unofficial values. */
|
||||||
|
|
||||||
|
#define EM_ALPHA 0x9026
|
||||||
|
|
||||||
/* Legal values for e_version (version). */
|
/* Legal values for e_version (version). */
|
||||||
|
|
||||||
#define EV_NONE 0 /* Invalid ELF 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_Word sh_entsize; /* Entry size if section holds table */
|
||||||
} Elf32_Shdr;
|
} 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. */
|
/* Special section indices. */
|
||||||
|
|
||||||
#define SHN_UNDEF 0 /* Undefined section */
|
#define SHN_UNDEF 0 /* Undefined section */
|
||||||
@ -192,9 +247,19 @@ typedef struct
|
|||||||
Elf32_Word st_size; /* Symbol size */
|
Elf32_Word st_size; /* Symbol size */
|
||||||
unsigned char st_info; /* Symbol type and binding */
|
unsigned char st_info; /* Symbol type and binding */
|
||||||
unsigned char st_other; /* No defined meaning, 0 */
|
unsigned char st_other; /* No defined meaning, 0 */
|
||||||
Elf32_Half st_shndx; /* Section index */
|
Elf32_Section st_shndx; /* Section index */
|
||||||
} Elf32_Sym;
|
} 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. */
|
/* Special section index. */
|
||||||
|
|
||||||
#define SHN_UNDEF 0 /* No section, undefined symbol. */
|
#define SHN_UNDEF 0 /* No section, undefined symbol. */
|
||||||
@ -205,6 +270,11 @@ typedef struct
|
|||||||
#define ELF32_ST_TYPE(val) ((val) & 0xf)
|
#define ELF32_ST_TYPE(val) ((val) & 0xf)
|
||||||
#define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type) & 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). */
|
/* Legal values for ST_BIND subfield of st_info (symbol binding). */
|
||||||
|
|
||||||
#define STB_LOCAL 0 /* Local symbol */
|
#define STB_LOCAL 0 /* Local symbol */
|
||||||
@ -241,6 +311,17 @@ typedef struct
|
|||||||
Elf32_Word r_info; /* Relocation type and symbol index */
|
Elf32_Word r_info; /* Relocation type and symbol index */
|
||||||
} Elf32_Rel;
|
} 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). */
|
/* Relocation table entry with addend (in section of type SHT_RELA). */
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
@ -250,6 +331,13 @@ typedef struct
|
|||||||
Elf32_Sword r_addend; /* Addend */
|
Elf32_Sword r_addend; /* Addend */
|
||||||
} Elf32_Rela;
|
} 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. */
|
/* How to extract and insert information held in the r_info field. */
|
||||||
|
|
||||||
#define ELF32_R_SYM(val) ((val) >> 8)
|
#define ELF32_R_SYM(val) ((val) >> 8)
|
||||||
@ -262,7 +350,8 @@ typedef struct
|
|||||||
|
|
||||||
/* Program segment header. */
|
/* Program segment header. */
|
||||||
|
|
||||||
typedef struct {
|
typedef struct
|
||||||
|
{
|
||||||
Elf32_Word p_type; /* Segment type */
|
Elf32_Word p_type; /* Segment type */
|
||||||
Elf32_Off p_offset; /* Segment file offset */
|
Elf32_Off p_offset; /* Segment file offset */
|
||||||
Elf32_Addr p_vaddr; /* Segment virtual address */
|
Elf32_Addr p_vaddr; /* Segment virtual address */
|
||||||
@ -273,6 +362,18 @@ typedef struct {
|
|||||||
Elf32_Word p_align; /* Segment alignment */
|
Elf32_Word p_align; /* Segment alignment */
|
||||||
} Elf32_Phdr;
|
} 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). */
|
/* Legal values for p_type (segment type). */
|
||||||
|
|
||||||
#define PT_NULL 0 /* Program header table entry unused */
|
#define PT_NULL 0 /* Program header table entry unused */
|
||||||
@ -316,6 +417,16 @@ typedef struct
|
|||||||
} d_un;
|
} d_un;
|
||||||
} Elf32_Dyn;
|
} 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). */
|
/* Legal values for d_tag (dynamic entry type). */
|
||||||
|
|
||||||
#define DT_NULL 0 /* Marks end of dynamic section */
|
#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_HIPROC 0x7fffffff /* End of processor-specific */
|
||||||
#define DT_PROCNUM DT_MIPS_NUM /* Most used by any processor */
|
#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. */
|
/* Auxiliary vector. */
|
||||||
|
|
||||||
/* This vector is normally only used by the program interpreter. The
|
/* This vector is normally only used by the program interpreter. The
|
||||||
@ -437,6 +478,17 @@ typedef struct
|
|||||||
} a_un;
|
} a_un;
|
||||||
} Elf32_auxv_t;
|
} 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). */
|
/* Legal values for a_type (entry type). */
|
||||||
|
|
||||||
#define AT_NULL 0 /* End of vector */
|
#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. */
|
#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 */
|
#endif /* elf.h */
|
||||||
|
@ -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"
|
|
283
elf/libelf.h
283
elf/libelf.h
@ -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 <sys/cdefs.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <elf.h>
|
|
||||||
|
|
||||||
__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 the library's access to the file descriptor for ELF.
|
|
||||||
CMD is either ELF_C_FDDONE or ELF_C_FDREAD. */
|
|
||||||
extern int elf_cntl __P ((Elf *__elf, Elf_Cmd __cmd));
|
|
||||||
|
|
||||||
|
|
||||||
/* Return a string describing an ELF error number. */
|
|
||||||
extern __const char *elf_errmsg __P ((int __errno));
|
|
||||||
|
|
||||||
/* Return the ELF error number for the last failed operation. */
|
|
||||||
extern int elf_errno __P ((void));
|
|
||||||
|
|
||||||
/* Set the byte value used to fill sections for alignment. */
|
|
||||||
extern void elf_fill __P ((int __fillchar));
|
|
||||||
|
|
||||||
/* The following functions `elf_flag*' all operate the same way:
|
|
||||||
CMD is either ELF_C_SET or ELF_C_CLR; FLAGS are `ELF_F_*' above,
|
|
||||||
which are set or cleared for the object the call relates to. */
|
|
||||||
|
|
||||||
/* Modify flags affecting the file as a whole (?). */
|
|
||||||
extern unsigned int elf_flagelf __P ((Elf *__elf, Elf_Cmd __cmd,
|
|
||||||
unsigned int __flags));
|
|
||||||
/* Modify flags affecting DATA. */
|
|
||||||
extern unsigned int elf_flagdata __P ((Elf_Data *__data, Elf_Cmd __cmd,
|
|
||||||
unsigned int __flags));
|
|
||||||
/* Modify flags affecting the ELF header. */
|
|
||||||
extern unsigned int elf_flagehdr __P ((Elf *__elf, Elf_Cmd __cmd,
|
|
||||||
unsigned int __flags));
|
|
||||||
/* Modify flags affecting the ELF program header. */
|
|
||||||
extern unsigned int elf_flagphdr __P ((Elf *__elf, Elf_Cmd __cmd,
|
|
||||||
unsigned int __flags));
|
|
||||||
/* Modify flags affecting the given section's data. */
|
|
||||||
extern unsigned int elf_flagscn __P ((Elf_Scn *__scn, Elf_Cmd __cmd,
|
|
||||||
unsigned int __flags));
|
|
||||||
/* Modify flags affecting the given section's header. */
|
|
||||||
extern unsigned int elf_flagshdr __P ((Elf_Scn *__scn, Elf_Cmd __cmd,
|
|
||||||
unsigned int __flags));
|
|
||||||
|
|
||||||
|
|
||||||
extern size_t elf32_fsize __P ((Elf_Type __type, size_t __count,
|
|
||||||
unsigned int __ver));
|
|
||||||
|
|
||||||
/* Return the archive header for ELF, which must describe an archive. */
|
|
||||||
extern Elf_Arhdr *elf_getarhdr __P ((Elf *__elf));
|
|
||||||
|
|
||||||
/* Return the archive symbol table for ELF, and store
|
|
||||||
in *NELTSP the number of elements in the table. */
|
|
||||||
extern Elf_Arsym *elf_getarsym __P ((Elf *__elf, size_t *__neltsp));
|
|
||||||
|
|
||||||
/* Return the file offset for the beginning of ELF.
|
|
||||||
If ELF describes an archive member, this points to the member header. */
|
|
||||||
extern off_t elf_getbase __P ((Elf *__elf));
|
|
||||||
|
|
||||||
/* Extract the data from a section. */
|
|
||||||
extern Elf_Data *elf_getdata __P ((Elf_Scn *__scn, Elf_Data *__data));
|
|
||||||
|
|
||||||
/* Extract the ELF header from the file. */
|
|
||||||
extern Elf32_Ehdr *elf32_getehdr __P ((Elf *__elf));
|
|
||||||
|
|
||||||
/* Extract the initial ELF identification bytes from the file.
|
|
||||||
If PTR is nonnull, the number of identification bytes is stored there. */
|
|
||||||
extern char *elf_getident __P((Elf *__elf, size_t *__ptr));
|
|
||||||
|
|
||||||
/* Extract the ELF program header from the file. */
|
|
||||||
extern Elf32_Phdr *elf32_getphdr __P ((Elf *__elf));
|
|
||||||
|
|
||||||
/* Extract the indicated section from the file. */
|
|
||||||
extern Elf_Scn *elf_getscn __P ((Elf *__elf, size_t __index));
|
|
||||||
|
|
||||||
/* Extract the section header from the section. */
|
|
||||||
extern Elf32_Shdr *elf32_getshdr __P ((Elf_Scn *__scn));
|
|
||||||
|
|
||||||
/* Return the index of the section following SCN. */
|
|
||||||
extern size_t elf_ndxscn __P ((Elf_Scn *__scn));
|
|
||||||
|
|
||||||
|
|
||||||
/* Standard ELF symbol name hash function. */
|
|
||||||
extern unsigned long int elf_hash __P ((__const char *__name));
|
|
||||||
|
|
||||||
#if defined (__OPTIMIZE__) || defined (_EXTERN_INLINE)
|
|
||||||
#ifndef _EXTERN_INLINE
|
|
||||||
#define _EXTERN_INLINE extern __inline
|
|
||||||
#endif
|
|
||||||
_EXTERN_INLINE unsigned long int
|
|
||||||
elf_hash (__const char *__name)
|
|
||||||
{
|
|
||||||
/* This is the hashing function specified by the ELF ABI. */
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Return the kind of file ELF describes. */
|
|
||||||
extern Elf_Kind elf_kind __P ((Elf *__elf));
|
|
||||||
|
|
||||||
extern Elf_Data *elf_newdata __P ((Elf_Scn *__scn));
|
|
||||||
|
|
||||||
/* Create the ELF header for ELF. */
|
|
||||||
extern Elf32_Ehdr *elf32_newehdr __P ((Elf *__elf));
|
|
||||||
|
|
||||||
/* Create the program header for ELF, with COUNT segments. */
|
|
||||||
extern Elf32_Phdr *elf32_newphdr __P ((Elf *__elf, size_t __count));
|
|
||||||
|
|
||||||
/* Create a new section in ELF. */
|
|
||||||
extern Elf_Scn *elf_newscn __P ((Elf *__elf));
|
|
||||||
|
|
||||||
/* Return the section following SCN. */
|
|
||||||
extern Elf_Scn *elf_nextscn __P ((Elf *__elf, Elf_Scn *__scn));
|
|
||||||
|
|
||||||
/* Set up ELF to read the next archive member. */
|
|
||||||
extern Elf_Cmd elf_next __P ((Elf *__elf));
|
|
||||||
|
|
||||||
/* Set up ELF (which must describe an archive) to read the
|
|
||||||
archive member that starts at file position OFFSET. */
|
|
||||||
extern size_t elf_rand __P ((Elf *__elf, size_t __offset));
|
|
||||||
|
|
||||||
extern Elf_Data *elf_rawdata __P ((Elf_Scn *__scn, Elf_Data *__data));
|
|
||||||
|
|
||||||
/* Read the entire file into memory; store its size in *PTR. */
|
|
||||||
extern char *elf_rawfile __P ((Elf *__elf, size_t *__ptr));
|
|
||||||
|
|
||||||
/* Return a pointer to the string at OFFSET bytes into the string table.
|
|
||||||
SECTION is the index of the SHT_STRTAB section in ELF. */
|
|
||||||
extern char *elf_strptr __P ((Elf *__elf, size_t __section, size_t __offset));
|
|
||||||
|
|
||||||
/* If CMD is ELF_C_NULL, update ELF's data structures based on any
|
|
||||||
user modifications, and set the ELF_F_DIRTY flag if anything changed.
|
|
||||||
If CMD is ELF_C_WRITE, do that and then write the changes to the file. */
|
|
||||||
extern off_t elf_update __P ((Elf *__elf, Elf_Cmd __cmd));
|
|
||||||
|
|
||||||
/* Handle ELF version VER. Return the old version handled,
|
|
||||||
or EV_NONE if VER is unrecognized. */
|
|
||||||
extern unsigned int elf_version __P ((unsigned int __ver));
|
|
||||||
|
|
||||||
extern Elf_Data *elf32_xlatetof __P ((Elf_Data *__dst, const Elf_Data *__src,
|
|
||||||
unsigned int __encode));
|
|
||||||
extern Elf_Data *elf32_xlatetom __P ((Elf_Data *__dst, const Elf_Data *__src,
|
|
||||||
unsigned int __encode));
|
|
||||||
|
|
||||||
__END_DECLS
|
|
||||||
|
|
||||||
#endif /* _LIBELF_H */
|
|
47
elf/link.h
47
elf/link.h
@ -20,8 +20,20 @@ Cambridge, MA 02139, USA. */
|
|||||||
#ifndef _LINK_H
|
#ifndef _LINK_H
|
||||||
#define _LINK_H 1
|
#define _LINK_H 1
|
||||||
|
|
||||||
|
#define __need_size_t
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
#include <elf.h>
|
#include <elf.h>
|
||||||
|
|
||||||
|
#define __ELF_WORDSIZE 32 /* XXX */
|
||||||
|
|
||||||
|
/* We use this macro to refer to ELF types independent of the native wordsize.
|
||||||
|
`ElfW(TYPE)' is used in place of `Elf32_TYPE' or `Elf64_TYPE'. */
|
||||||
|
#define ElfW(type) _ElfW (Elf, __ELF_WORDSIZE, type)
|
||||||
|
#define ELFW(type) _ElfW (ELF, __ELF_WORDSIZE, type)
|
||||||
|
#define _ElfW(e,w,t) _ElfW_1 (e, w, _##t)
|
||||||
|
#define _ElfW_1(e,w,t) e##w##t
|
||||||
|
|
||||||
|
|
||||||
/* Rendezvous structure used by the run-time dynamic linker to communicate
|
/* Rendezvous structure used by the run-time dynamic linker to communicate
|
||||||
details of shared object loading to the debugger. If the executable's
|
details of shared object loading to the debugger. If the executable's
|
||||||
@ -39,7 +51,7 @@ struct r_debug
|
|||||||
library or unmap it, and again when the mapping change is complete.
|
library or unmap it, and again when the mapping change is complete.
|
||||||
The debugger can set a breakpoint at this address if it wants to
|
The debugger can set a breakpoint at this address if it wants to
|
||||||
notice shared object mapping changes. */
|
notice shared object mapping changes. */
|
||||||
Elf32_Addr r_brk;
|
ElfW(Addr) r_brk;
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
/* This state value describes the mapping change taking place when
|
/* This state value describes the mapping change taking place when
|
||||||
@ -49,7 +61,7 @@ struct r_debug
|
|||||||
RT_DELETE, /* Beginning to remove an object mapping. */
|
RT_DELETE, /* Beginning to remove an object mapping. */
|
||||||
} r_state;
|
} r_state;
|
||||||
|
|
||||||
Elf32_Addr r_ldbase; /* Base address the linker is loaded at. */
|
ElfW(Addr) r_ldbase; /* Base address the linker is loaded at. */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* This symbol refers to the "dynamic structure" in the `.dynamic' section
|
/* This symbol refers to the "dynamic structure" in the `.dynamic' section
|
||||||
@ -59,7 +71,7 @@ struct r_debug
|
|||||||
if (dyn->d_tag == DT_DEBUG) r_debug = (struct r_debug) dyn->d_un.d_ptr;
|
if (dyn->d_tag == DT_DEBUG) r_debug = (struct r_debug) dyn->d_un.d_ptr;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
extern Elf32_Dyn _DYNAMIC[];
|
extern ElfW(Dyn) _DYNAMIC[];
|
||||||
|
|
||||||
|
|
||||||
/* Structure describing a loaded shared object. The `l_next' and `l_prev'
|
/* Structure describing a loaded shared object. The `l_next' and `l_prev'
|
||||||
@ -73,9 +85,9 @@ struct link_map
|
|||||||
/* These first few members are part of the protocol with the debugger.
|
/* These first few members are part of the protocol with the debugger.
|
||||||
This is the same format used in SVR4. */
|
This is the same format used in SVR4. */
|
||||||
|
|
||||||
Elf32_Addr l_addr; /* Base address shared object is loaded at. */
|
ElfW(Addr) l_addr; /* Base address shared object is loaded at. */
|
||||||
char *l_name; /* Absolute file name object was found in. */
|
char *l_name; /* Absolute file name object was found in. */
|
||||||
Elf32_Dyn *l_ld; /* Dynamic section of the shared object. */
|
ElfW(Dyn) *l_ld; /* Dynamic section of the shared object. */
|
||||||
struct link_map *l_next, *l_prev; /* Chain of loaded objects. */
|
struct link_map *l_next, *l_prev; /* Chain of loaded objects. */
|
||||||
|
|
||||||
/* All following members are internal to the dynamic linker.
|
/* All following members are internal to the dynamic linker.
|
||||||
@ -85,10 +97,10 @@ struct link_map
|
|||||||
/* Indexed pointers to dynamic section.
|
/* Indexed pointers to dynamic section.
|
||||||
[0,DT_NUM) are indexed by the processor-independent tags.
|
[0,DT_NUM) are indexed by the processor-independent tags.
|
||||||
[DT_NUM,DT_NUM+DT_PROCNUM] are indexed by the tag minus DT_LOPROC. */
|
[DT_NUM,DT_NUM+DT_PROCNUM] are indexed by the tag minus DT_LOPROC. */
|
||||||
Elf32_Dyn *l_info[DT_NUM + DT_PROCNUM];
|
ElfW(Dyn) *l_info[DT_NUM + DT_PROCNUM];
|
||||||
const Elf32_Phdr *l_phdr; /* Pointer to program header table in core. */
|
const ElfW(Phdr) *l_phdr; /* Pointer to program header table in core. */
|
||||||
Elf32_Word l_phnum; /* Number of program header entries. */
|
ElfW(Addr) l_entry; /* Entry point location. */
|
||||||
Elf32_Addr l_entry; /* Entry point location. */
|
ElfW(Half) l_phnum; /* Number of program header entries. */
|
||||||
|
|
||||||
/* Array of DT_NEEDED dependencies and their dependencies, in
|
/* Array of DT_NEEDED dependencies and their dependencies, in
|
||||||
dependency order for symbol lookup. This is null before the
|
dependency order for symbol lookup. This is null before the
|
||||||
@ -97,8 +109,8 @@ struct link_map
|
|||||||
unsigned int l_nsearchlist;
|
unsigned int l_nsearchlist;
|
||||||
|
|
||||||
/* Symbol hash table. */
|
/* Symbol hash table. */
|
||||||
Elf32_Word l_nbuckets;
|
ElfW(Word) l_nbuckets;
|
||||||
const Elf32_Word *l_buckets, *l_chain;
|
const ElfW(Word) *l_buckets, *l_chain;
|
||||||
|
|
||||||
unsigned int l_opencount; /* Reference count for dlopen/dlclose. */
|
unsigned int l_opencount; /* Reference count for dlopen/dlclose. */
|
||||||
enum /* Where this object came from. */
|
enum /* Where this object came from. */
|
||||||
@ -123,6 +135,9 @@ struct link_map
|
|||||||
user interface to run-time dynamic linking. */
|
user interface to run-time dynamic linking. */
|
||||||
|
|
||||||
|
|
||||||
|
/* Cached value of `getpagesize ()'. */
|
||||||
|
extern size_t _dl_pagesize;
|
||||||
|
|
||||||
/* File descriptor referring to the zero-fill device. */
|
/* File descriptor referring to the zero-fill device. */
|
||||||
extern int _dl_zerofd;
|
extern int _dl_zerofd;
|
||||||
|
|
||||||
@ -209,15 +224,15 @@ extern struct link_map *_dl_open (struct link_map *loader,
|
|||||||
being fixed up and the chosen symbol cannot be one with this value. If
|
being fixed up and the chosen symbol cannot be one with this value. If
|
||||||
NOPLT is nonzero, then the reference must not be resolved to a PLT
|
NOPLT is nonzero, then the reference must not be resolved to a PLT
|
||||||
entry. */
|
entry. */
|
||||||
extern Elf32_Addr _dl_lookup_symbol (const char *undef,
|
extern ElfW(Addr) _dl_lookup_symbol (const char *undef,
|
||||||
const Elf32_Sym **sym,
|
const ElfW(Sym) **sym,
|
||||||
struct link_map *symbol_scope[2],
|
struct link_map *symbol_scope[2],
|
||||||
const char *reference_name,
|
const char *reference_name,
|
||||||
Elf32_Addr reloc_addr,
|
ElfW(Addr) reloc_addr,
|
||||||
int noplt);
|
int noplt);
|
||||||
|
|
||||||
/* Look up symbol NAME in MAP's scope and return its run-time address. */
|
/* Look up symbol NAME in MAP's scope and return its run-time address. */
|
||||||
extern Elf32_Addr _dl_symbol_value (struct link_map *map, const char *name);
|
extern ElfW(Addr) _dl_symbol_value (struct link_map *map, const char *name);
|
||||||
|
|
||||||
|
|
||||||
/* Structure describing the dynamic linker itself. */
|
/* Structure describing the dynamic linker itself. */
|
||||||
@ -242,7 +257,7 @@ extern void _dl_relocate_object (struct link_map *map, int lazy);
|
|||||||
its dependencies that has not yet been run. When there are no more
|
its dependencies that has not yet been run. When there are no more
|
||||||
initializers to be run, this returns zero. The functions are returned
|
initializers to be run, this returns zero. The functions are returned
|
||||||
in the order they should be called. */
|
in the order they should be called. */
|
||||||
extern Elf32_Addr _dl_init_next (struct link_map *map);
|
extern ElfW(Addr) _dl_init_next (struct link_map *map);
|
||||||
|
|
||||||
/* Call the finalizer functions of all shared objects whose
|
/* Call the finalizer functions of all shared objects whose
|
||||||
initializer functions have completed. */
|
initializer functions have completed. */
|
||||||
|
@ -32,9 +32,9 @@ Cambridge, MA 02139, USA. */
|
|||||||
void
|
void
|
||||||
_init (void)
|
_init (void)
|
||||||
{
|
{
|
||||||
const Elf32_Sym *ref = NULL;
|
const ElfW(Sym) *ref = NULL;
|
||||||
struct link_map *scope[2] = { _dl_loaded, NULL };
|
struct link_map *scope[2] = { _dl_loaded, NULL };
|
||||||
Elf32_Addr loadbase = _dl_lookup_symbol ("atexit", &ref, scope,
|
ElfW(Addr) loadbase = _dl_lookup_symbol ("atexit", &ref, scope,
|
||||||
"<ld-linux.so.1 initialization>",
|
"<ld-linux.so.1 initialization>",
|
||||||
0, 1);
|
0, 1);
|
||||||
(*(__typeof (atexit) *) (loadbase + ref->st_value)) (&_dl_fini);
|
(*(__typeof (atexit) *) (loadbase + ref->st_value)) (&_dl_fini);
|
||||||
|
42
elf/rtld.c
42
elf/rtld.c
@ -35,10 +35,10 @@ RTLD_START
|
|||||||
After this, file access calls and getenv must work. This is responsible
|
After this, file access calls and getenv must work. This is responsible
|
||||||
for setting _dl_secure if we need to be secure (e.g. setuid),
|
for setting _dl_secure if we need to be secure (e.g. setuid),
|
||||||
and for setting _dl_argc and _dl_argv, and then calling _dl_main. */
|
and for setting _dl_argc and _dl_argv, and then calling _dl_main. */
|
||||||
extern Elf32_Addr _dl_sysdep_start (void **start_argptr,
|
extern ElfW(Addr) _dl_sysdep_start (void **start_argptr,
|
||||||
void (*dl_main) (const Elf32_Phdr *phdr,
|
void (*dl_main) (const ElfW(Phdr) *phdr,
|
||||||
Elf32_Word phent,
|
ElfW(Half) phent,
|
||||||
Elf32_Addr *user_entry));
|
ElfW(Addr) *user_entry));
|
||||||
extern void _dl_sysdep_start_cleanup (void);
|
extern void _dl_sysdep_start_cleanup (void);
|
||||||
|
|
||||||
int _dl_secure;
|
int _dl_secure;
|
||||||
@ -46,15 +46,15 @@ int _dl_argc;
|
|||||||
char **_dl_argv;
|
char **_dl_argv;
|
||||||
const char *_dl_rpath;
|
const char *_dl_rpath;
|
||||||
|
|
||||||
struct r_debug dl_r_debug;
|
struct r_debug _dl_r_debug;
|
||||||
|
|
||||||
static void dl_main (const Elf32_Phdr *phdr,
|
static void dl_main (const ElfW(Phdr) *phdr,
|
||||||
Elf32_Word phent,
|
ElfW(Half) phent,
|
||||||
Elf32_Addr *user_entry);
|
ElfW(Addr) *user_entry);
|
||||||
|
|
||||||
struct link_map _dl_rtld_map;
|
struct link_map _dl_rtld_map;
|
||||||
|
|
||||||
Elf32_Addr
|
ElfW(Addr)
|
||||||
_dl_start (void *arg)
|
_dl_start (void *arg)
|
||||||
{
|
{
|
||||||
struct link_map bootstrap_map;
|
struct link_map bootstrap_map;
|
||||||
@ -120,17 +120,17 @@ void _start (void);
|
|||||||
unsigned int _dl_skip_args; /* Nonzero if we were run directly. */
|
unsigned int _dl_skip_args; /* Nonzero if we were run directly. */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
dl_main (const Elf32_Phdr *phdr,
|
dl_main (const ElfW(Phdr) *phdr,
|
||||||
Elf32_Word phent,
|
ElfW(Half) phent,
|
||||||
Elf32_Addr *user_entry)
|
ElfW(Addr) *user_entry)
|
||||||
{
|
{
|
||||||
const Elf32_Phdr *ph;
|
const ElfW(Phdr) *ph;
|
||||||
struct link_map *l;
|
struct link_map *l;
|
||||||
const char *interpreter_name;
|
const char *interpreter_name;
|
||||||
int lazy;
|
int lazy;
|
||||||
int list_only = 0;
|
int list_only = 0;
|
||||||
|
|
||||||
if (*user_entry == (Elf32_Addr) &_start)
|
if (*user_entry == (ElfW(Addr)) &_start)
|
||||||
{
|
{
|
||||||
/* Ho ho. We are not the program interpreter! We are the program
|
/* Ho ho. We are not the program interpreter! We are the program
|
||||||
itself! This means someone ran ld.so as a command. Well, that
|
itself! This means someone ran ld.so as a command. Well, that
|
||||||
@ -240,7 +240,7 @@ of this helper program; chances are you did not intend to run this program.\n",
|
|||||||
/* There is a DT_DEBUG entry in the dynamic section. Fill it in
|
/* There is a DT_DEBUG entry in the dynamic section. Fill it in
|
||||||
with the run-time address of the r_debug structure, which we
|
with the run-time address of the r_debug structure, which we
|
||||||
will set up later to communicate with the debugger. */
|
will set up later to communicate with the debugger. */
|
||||||
l->l_info[DT_DEBUG]->d_un.d_ptr = (Elf32_Addr) &dl_r_debug;
|
l->l_info[DT_DEBUG]->d_un.d_ptr = (ElfW(Addr)) &_dl_r_debug;
|
||||||
|
|
||||||
/* Put the link_map for ourselves on the chain so it can be found by
|
/* Put the link_map for ourselves on the chain so it can be found by
|
||||||
name. */
|
name. */
|
||||||
@ -292,9 +292,9 @@ of this helper program; chances are you did not intend to run this program.\n",
|
|||||||
|
|
||||||
for (i = 1; i < _dl_argc; ++i)
|
for (i = 1; i < _dl_argc; ++i)
|
||||||
{
|
{
|
||||||
const Elf32_Sym *ref = NULL;
|
const ElfW(Sym) *ref = NULL;
|
||||||
struct link_map *scope[2] ={ _dl_loaded, NULL };
|
struct link_map *scope[2] ={ _dl_loaded, NULL };
|
||||||
Elf32_Addr loadbase
|
ElfW(Addr) loadbase
|
||||||
= _dl_lookup_symbol (_dl_argv[i], &ref, scope, "argument", 0, 0);
|
= _dl_lookup_symbol (_dl_argv[i], &ref, scope, "argument", 0, 0);
|
||||||
char buf[20], *bp;
|
char buf[20], *bp;
|
||||||
buf[sizeof buf - 1] = '\0';
|
buf[sizeof buf - 1] = '\0';
|
||||||
@ -345,10 +345,10 @@ of this helper program; chances are you did not intend to run this program.\n",
|
|||||||
_dl_relocate_object (&_dl_rtld_map, lazy);
|
_dl_relocate_object (&_dl_rtld_map, lazy);
|
||||||
|
|
||||||
/* Tell the debugger where to find the map of loaded objects. */
|
/* Tell the debugger where to find the map of loaded objects. */
|
||||||
dl_r_debug.r_version = 1 /* R_DEBUG_VERSION XXX */;
|
_dl_r_debug.r_version = 1 /* R_DEBUG_VERSION XXX */;
|
||||||
dl_r_debug.r_ldbase = _dl_rtld_map.l_addr; /* Record our load address. */
|
_dl_r_debug.r_ldbase = _dl_rtld_map.l_addr; /* Record our load address. */
|
||||||
dl_r_debug.r_map = _dl_loaded;
|
_dl_r_debug.r_map = _dl_loaded;
|
||||||
dl_r_debug.r_brk = (Elf32_Addr) &_dl_r_debug_state;
|
_dl_r_debug.r_brk = (ElfW(Addr)) &_dl_r_debug_state;
|
||||||
|
|
||||||
if (_dl_rtld_map.l_info[DT_INIT])
|
if (_dl_rtld_map.l_info[DT_INIT])
|
||||||
{
|
{
|
||||||
|
@ -270,7 +270,7 @@ _dl_sysdep_message (const char *msg, ...)
|
|||||||
it will get the user's definition (i.e. usually libc's). */
|
it will get the user's definition (i.e. usually libc's). */
|
||||||
|
|
||||||
int
|
int
|
||||||
open (const char *file_name, int mode, ...)
|
__open (const char *file_name, int mode, ...)
|
||||||
{
|
{
|
||||||
enum retry_type doretry;
|
enum retry_type doretry;
|
||||||
char retryname[1024]; /* XXX string_t LOSES! */
|
char retryname[1024]; /* XXX string_t LOSES! */
|
||||||
@ -495,7 +495,7 @@ open (const char *file_name, int mode, ...)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
close (int fd)
|
__close (int fd)
|
||||||
{
|
{
|
||||||
if (fd != (int) MACH_PORT_NULL)
|
if (fd != (int) MACH_PORT_NULL)
|
||||||
__mach_port_deallocate (__mach_task_self (), (mach_port_t) fd);
|
__mach_port_deallocate (__mach_task_self (), (mach_port_t) fd);
|
||||||
@ -503,7 +503,7 @@ close (int fd)
|
|||||||
}
|
}
|
||||||
|
|
||||||
caddr_t
|
caddr_t
|
||||||
mmap (caddr_t addr, size_t len, int prot, int flags, int fd, off_t offset)
|
__mmap (caddr_t addr, size_t len, int prot, int flags, int fd, off_t offset)
|
||||||
{
|
{
|
||||||
error_t err;
|
error_t err;
|
||||||
vm_prot_t vmprot;
|
vm_prot_t vmprot;
|
||||||
@ -554,9 +554,9 @@ _exit (int status)
|
|||||||
}
|
}
|
||||||
|
|
||||||
weak_symbol (_exit)
|
weak_symbol (_exit)
|
||||||
weak_symbol (open)
|
weak_symbol (__open)
|
||||||
weak_symbol (close)
|
weak_symbol (__close)
|
||||||
weak_symbol (mmap)
|
weak_symbol (__mmap)
|
||||||
|
|
||||||
|
|
||||||
/* This function is called by interruptible RPC stubs. For initial
|
/* This function is called by interruptible RPC stubs. For initial
|
||||||
|
Reference in New Issue
Block a user