summaryrefslogtreecommitdiffstats
path: root/libexec
diff options
context:
space:
mode:
authordfr <dfr@FreeBSD.org>1998-09-04 19:03:57 +0000
committerdfr <dfr@FreeBSD.org>1998-09-04 19:03:57 +0000
commitb5ab30c0dc5fcbceebb8fe7939b9b22b365dbb81 (patch)
treeb5d0a554c070d669d34d1dd16aedbdc80ac19468 /libexec
parentcc6d00dd2e04653dd42a1e017648ef5a6865205e (diff)
downloadFreeBSD-src-b5ab30c0dc5fcbceebb8fe7939b9b22b365dbb81.zip
FreeBSD-src-b5ab30c0dc5fcbceebb8fe7939b9b22b365dbb81.tar.gz
Add alpha support.
Submitted by: John Birrell <jb@cimlogic.com.au> (with extra hacks by me) Obtained from: Probably NetBSD
Diffstat (limited to 'libexec')
-rw-r--r--libexec/rtld-elf/Makefile20
-rw-r--r--libexec/rtld-elf/alpha/reloc.c309
-rw-r--r--libexec/rtld-elf/alpha/rtld_start.S169
-rw-r--r--libexec/rtld-elf/amd64/reloc.c236
-rw-r--r--libexec/rtld-elf/amd64/rtld_start.S13
-rw-r--r--libexec/rtld-elf/i386/reloc.c236
-rw-r--r--libexec/rtld-elf/i386/rtld_start.S13
-rw-r--r--libexec/rtld-elf/malloc.c11
-rw-r--r--libexec/rtld-elf/map_object.c56
-rw-r--r--libexec/rtld-elf/rtld.c336
-rw-r--r--libexec/rtld-elf/rtld.h23
11 files changed, 1145 insertions, 277 deletions
diff --git a/libexec/rtld-elf/Makefile b/libexec/rtld-elf/Makefile
index f206711..e565161 100644
--- a/libexec/rtld-elf/Makefile
+++ b/libexec/rtld-elf/Makefile
@@ -1,17 +1,25 @@
#
-# $Id: Makefile,v 1.2 1998/04/30 07:47:58 dfr Exp $
+# $Id: Makefile,v 1.3 1998/08/17 04:59:15 jdp Exp $
#
PROG= ld-elf.so.1
-SRCS= rtld_start.S rtld.c map_object.c malloc.c xmalloc.c debug.c
+SRCS= rtld_start.S rtld.c map_object.c malloc.c xmalloc.c debug.c \
+ reloc.c
NOMAN= true
-CFLAGS+= -elf -fpic -DFREEBSD_ELF
-CFLAGS+= -Wall
-LDFLAGS+= -elf -nostdlib -Wl,-Bshareable,-Bsymbolic
+CFLAGS+= -fpic -Wall -DFREEBSD_ELF -I${.CURDIR}
LDADD+= -lc_pic
+
+.if ${MACHINE_ARCH} == "alpha"
+CFLAGS+= -mno-fp-regs
+LDFLAGS+= -nostdlib -Wl,-Bshareable,-Bsymbolic -e .rtld_start
+.elif ${MACHINE_ARCH} == "i386"
+CFLAGS+= -elf
+LDFLAGS+= -elf -nostdlib -Wl,-Bshareable,-Bsymbolic
+.endif
+
# Atomic installation with "-C" is very important for this program.
INSTALLFLAGS+= -C
-.PATH: ${.CURDIR}/${MACHINE}
+.PATH: ${.CURDIR}/${MACHINE_ARCH}
.include <bsd.prog.mk>
diff --git a/libexec/rtld-elf/alpha/reloc.c b/libexec/rtld-elf/alpha/reloc.c
new file mode 100644
index 0000000..e43b12a
--- /dev/null
+++ b/libexec/rtld-elf/alpha/reloc.c
@@ -0,0 +1,309 @@
+/*-
+ * Copyright 1996-1998 John D. Polstra.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $Id: rtld.c,v 1.3 1998/05/01 08:39:27 dfr Exp $
+ */
+
+/*
+ * Dynamic linker for ELF.
+ *
+ * John Polstra <jdp@polstra.com>.
+ */
+
+#include <sys/param.h>
+#include <sys/mman.h>
+
+#include <dlfcn.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "debug.h"
+#include "rtld.h"
+
+/*
+ * Debugging support.
+ */
+
+#define assert(cond) ((cond) ? (void) 0 :\
+ (msg("oops: " __XSTRING(__LINE__) "\n"), abort()))
+#define msg(s) (write(1, s, strlen(s)))
+#define trace() msg("trace: " __XSTRING(__LINE__) "\n");
+
+extern Elf_Dyn _DYNAMIC;
+
+/* Relocate a non-PLT object with addend. */
+static int
+reloc_non_plt_obj(Obj_Entry *obj_rtld, const Obj_Entry *obj,
+ const Elf_Rela *rela)
+{
+ Elf_Addr *where = (Elf_Addr *) (obj->relocbase + rela->r_offset);
+
+ switch (ELF_R_TYPE(rela->r_info)) {
+
+ case R_ALPHA_REFQUAD: {
+ const Elf_Sym *def;
+ const Obj_Entry *defobj;
+ Elf_Addr tmp_value;
+
+ def = find_symdef(ELF_R_SYM(rela->r_info), obj,
+ &defobj, false);
+ if (def == NULL)
+ return -1;
+
+ tmp_value = (Elf_Addr) (defobj->relocbase +
+ def->st_value) + *where + rela->r_addend;
+ if (*where != tmp_value)
+ *where = tmp_value;
+ }
+ break;
+
+ case R_ALPHA_GLOB_DAT: {
+ const Elf_Sym *def;
+ const Obj_Entry *defobj;
+
+ def = find_symdef(ELF_R_SYM(rela->r_info), obj,
+ &defobj, false);
+ if (def == NULL)
+ return -1;
+
+ if (*where != (Elf_Addr) (defobj->relocbase +
+ def->st_value))
+ *where = (Elf_Addr) (defobj->relocbase +
+ def->st_value);
+ }
+ break;
+
+ case R_ALPHA_RELATIVE: {
+ if (obj != obj_rtld ||
+ (caddr_t)where < (caddr_t)_GLOBAL_OFFSET_TABLE_ ||
+ (caddr_t)where >= (caddr_t)&_DYNAMIC)
+ *where += (Elf_Addr) obj->relocbase;
+ }
+ break;
+
+ case R_ALPHA_COPY: {
+ /*
+ * These are deferred until all other relocations
+ * have been done. All we do here is make sure
+ * that the COPY relocation is not in a shared
+ * library. They are allowed only in executable
+ * files.
+ */
+ if (!obj->mainprog) {
+ _rtld_error("%s: Unexpected R_COPY "
+ " relocation in shared library",
+ obj->path);
+ return -1;
+ }
+ }
+ break;
+
+ default:
+ _rtld_error("%s: Unsupported relocation type %d"
+ " in non-PLT relocations\n", obj->path,
+ ELF_R_TYPE(rela->r_info));
+ return -1;
+ }
+ return(0);
+}
+
+/* Process the non-PLT relocations. */
+int
+reloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld)
+{
+ const Elf_Rel *rellim;
+ const Elf_Rel *rel;
+ const Elf_Rela *relalim;
+ const Elf_Rela *rela;
+
+ /* Perform relocations without addend if there are any: */
+ rellim = (const Elf_Rel *) ((caddr_t) obj->rel + obj->relsize);
+ for (rel = obj->rel; obj->rel != NULL && rel < rellim; rel++) {
+ Elf_Rela locrela;
+
+ locrela.r_info = rel->r_info;
+ locrela.r_offset = rel->r_offset;
+ locrela.r_addend = 0;
+ if (reloc_non_plt_obj(obj_rtld, obj, &locrela))
+ return -1;
+ }
+
+ /* Perform relocations with addend if there are any: */
+ relalim = (const Elf_Rela *) ((caddr_t) obj->rela + obj->relasize);
+ for (rela = obj->rela; obj->rela != NULL && rela < relalim; rela++) {
+ if (reloc_non_plt_obj(obj_rtld, obj, rela))
+ return -1;
+ }
+ return 0;
+}
+
+/* Process the PLT relocations. */
+int
+reloc_plt(Obj_Entry *obj, bool bind_now)
+{
+ const Elf_Rel *rellim;
+ const Elf_Rel *rel;
+ const Elf_Rela *relalim;
+ const Elf_Rela *rela;
+
+ /* Process the PLT relocations without addend if there are any. */
+ rellim = (const Elf_Rel *) ((caddr_t) obj->pltrel + obj->pltrelsize);
+ if (bind_now) {
+ /* Fully resolve procedure addresses now */
+ for (rel = obj->pltrel; obj->pltrel != NULL && rel < rellim;
+ rel++) {
+ Elf_Addr *where = (Elf_Addr *) (obj->relocbase + rel->r_offset);
+ const Elf_Sym *def;
+ const Obj_Entry *defobj;
+
+ assert(ELF_R_TYPE(rel->r_info) == R_ALPHA_JMP_SLOT);
+
+ def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj, true);
+ if (def == NULL)
+ return -1;
+
+ *where = (Elf_Addr) (defobj->relocbase + def->st_value);
+ }
+ } else { /* Just relocate the GOT slots pointing into the PLT */
+ for (rel = obj->pltrel; obj->pltrel != NULL && rel < rellim;
+ rel++) {
+ Elf_Addr *where = (Elf_Addr *)
+ (obj->relocbase + rel->r_offset);
+ *where += (Elf_Addr) obj->relocbase;
+ }
+ }
+
+ /* Process the PLT relocations with addend if there are any. */
+ relalim = (const Elf_Rela *) ((caddr_t) obj->pltrela +
+ obj->pltrelasize);
+ if (bind_now) {
+ /* Fully resolve procedure addresses now */
+ for (rela = obj->pltrela; obj->pltrela != NULL && rela < relalim;
+ rel++) {
+ Elf_Addr *where = (Elf_Addr *) (obj->relocbase +
+ rela->r_offset);
+ const Elf_Sym *def;
+ const Obj_Entry *defobj;
+
+ assert(ELF_R_TYPE(rela->r_info) == R_ALPHA_JMP_SLOT);
+
+ def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, true);
+ if (def == NULL)
+ return -1;
+
+ *where = (Elf_Addr) (defobj->relocbase + def->st_value);
+ }
+ } else { /* Just relocate the GOT slots pointing into the PLT */
+ for (rela = obj->pltrela; obj->pltrela != NULL && rela < relalim;
+ rela++) {
+ Elf_Addr *where = (Elf_Addr *)
+ (obj->relocbase + rela->r_offset);
+ *where += (Elf_Addr) obj->relocbase;
+ }
+ }
+ return 0;
+}
+
+/* Process an R_ALPHA_COPY relocation. */
+static int
+do_copy_relocation(Obj_Entry *dstobj, const Elf_Rela *rela)
+{
+ void *dstaddr;
+ const Elf_Sym *dstsym;
+ const char *name;
+ unsigned long hash;
+ size_t size;
+ const void *srcaddr;
+ const Elf_Sym *srcsym;
+ Obj_Entry *srcobj;
+
+ dstaddr = (void *) (dstobj->relocbase + rela->r_offset);
+ dstsym = dstobj->symtab + ELF_R_SYM(rela->r_info);
+ name = dstobj->strtab + dstsym->st_name;
+ hash = elf_hash(name);
+ size = dstsym->st_size;
+
+ for (srcobj = dstobj->next; srcobj != NULL; srcobj = srcobj->next)
+ if ((srcsym = symlook_obj(name, hash, srcobj, false)) != NULL)
+ break;
+
+ if (srcobj == NULL) {
+ _rtld_error("Undefined symbol \"%s\" referenced from COPY"
+ " relocation in %s", name, dstobj->path);
+ return -1;
+ }
+
+ srcaddr = (const void *) (srcobj->relocbase + srcsym->st_value);
+ memcpy(dstaddr, srcaddr, size);
+ return 0;
+}
+
+/*
+ * Process the special R_ALPHA_COPY relocations in the main program. These
+ * copy data from a shared object into a region in the main program's BSS
+ * segment.
+ *
+ * Returns 0 on success, -1 on failure.
+ */
+int
+do_copy_relocations(Obj_Entry *dstobj)
+{
+ const Elf_Rel *rellim;
+ const Elf_Rel *rel;
+ const Elf_Rela *relalim;
+ const Elf_Rela *rela;
+
+ assert(dstobj->mainprog); /* COPY relocations are invalid elsewhere */
+
+ rellim = (const Elf_Rel *) ((caddr_t) dstobj->rel + dstobj->relsize);
+ for (rel = dstobj->rel; dstobj->rel != NULL && rel < rellim; rel++) {
+ if (ELF_R_TYPE(rel->r_info) == R_ALPHA_COPY) {
+ Elf_Rela locrela;
+
+ locrela.r_info = rel->r_info;
+ locrela.r_offset = rel->r_offset;
+ locrela.r_addend = 0;
+ if (do_copy_relocation(dstobj, &locrela))
+ return -1;
+ }
+ }
+
+ relalim = (const Elf_Rela *) ((caddr_t) dstobj->rela +
+ dstobj->relasize);
+ for (rela = dstobj->rela; dstobj->rela != NULL && rela < relalim;
+ rela++) {
+ if (ELF_R_TYPE(rela->r_info) == R_ALPHA_COPY) {
+ if (do_copy_relocation(dstobj, rela))
+ return -1;
+ }
+ }
+
+ return 0;
+}
diff --git a/libexec/rtld-elf/alpha/rtld_start.S b/libexec/rtld-elf/alpha/rtld_start.S
new file mode 100644
index 0000000..e93829f
--- /dev/null
+++ b/libexec/rtld-elf/alpha/rtld_start.S
@@ -0,0 +1,169 @@
+/* $Id$ */
+/* From: NetBSD: rtld_start.S,v 1.1 1996/12/16 20:38:09 cgd Exp */
+
+/*
+ * Copyright 1996 Matt Thomas <matt@3am-software.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+#include <machine/pal.h>
+
+.extern _GLOBAL_OFFSET_TABLE_
+
+LEAF(_rtld_start, 0) /* XXX */
+ .set noreorder
+ br pv, $33
+$33: LDGP(pv)
+
+ /* save away the stack pointer */
+
+ lda s0, 0(sp) /* get argc from stack */
+ lda sp, -16(sp) /* space for arguments */
+
+ /* save ps_strings pointer */
+ mov a3, s1
+
+ /* Step 1 -- Figure out the displacement */
+
+ br t2, $34 /* get our PC */
+$34: ldiq t3, $34 /* get where the linker thought we were */
+ subq t2, t3, t8 /* calculate the displacement */
+
+
+ /* Step 2 -- Find bounds of global offset table */
+
+ lda t5, _GLOBAL_OFFSET_TABLE_
+ addq t8, t5, t9 /* add the displacement */
+ lda t4, _DYNAMIC
+ addq t8, t4, t10 /* add the displacement */
+
+ /*
+ * Step 3 -- Every entry in the global offset table needs to
+ * modified for the displacement before any code will work.
+ */
+
+$35: ldq t1, 0(t9) /* load the value */
+ addq t8, t1, t1 /* add the displacement */
+ stq t1, 0(t9) /* save the new value */
+ lda t9, 8(t9) /* point to next entry */
+ cmpult t9, t10, t1 /* are we done? */
+ bne t1, $35 /* no, do more */
+
+ /*
+ * Ya! Things are far enough so we can do some dynamic linking!
+ */
+
+ lda a0, 0(s0) /* initial sp */
+ lda a1, -16(s0) /* address for exit proc */
+ lda a2, -8(s0) /* address for obj_main */
+ CALL(_rtld) /* v0 = _rtld(sp, &exit_proc, &obj_main); */
+
+ ldq a1, -16(s0) /* our atexit function */
+ ldq a2, -8(s0) /* obj_main entry */
+ lda sp, 16(sp) /* readjust our stack */
+ mov s0, a0 /* stack pointer */
+ mov s1, a3 /* ps_strings pointer */
+ mov v0, t12
+ jsr ra, (v0), 0 /* (*_start)(sp, cleanup, obj); */
+ ldgp gp, 0(ra)
+
+ CALL(exit)
+ halt
+END(_rtld_start)
+
+ .set noat
+ .globl _rtld_bind_start
+ .ent _rtld_bind_start
+_rtld_bind_start:
+
+ lda sp, -168(sp)
+ .frame sp, 168, $26
+ /* Preserve all registers that C normally doesn't. */
+ stq $26, 0(sp)
+ stq $0, 8(sp)
+ stq $1, 16(sp)
+ stq $2, 24(sp)
+ stq $3, 32(sp)
+ stq $4, 40(sp)
+ stq $5, 48(sp)
+ stq $6, 56(sp)
+ stq $7, 64(sp)
+ stq $8, 72(sp)
+ stq $16, 80(sp)
+ stq $17, 88(sp)
+ stq $18, 96(sp)
+ stq $19, 104(sp)
+ stq $20, 112(sp)
+ stq $21, 120(sp)
+ stq $22, 128(sp)
+ stq $23, 136(sp)
+ stq $24, 144(sp)
+ stq $25, 152(sp)
+ stq $29, 160(sp)
+ .mask 0x27ff01ff, -168
+ /* Set up our $gp */
+ br gp, $100
+$100: ldgp gp, 0(gp)
+ .prologue 1
+ /* Set up the arguments for _rtld_bind. */
+ ldq a0, 8(t12) /* object structure */
+ mov at_reg, a1 /* offset of reloc entry */
+ CALL(_rtld_bind)
+
+ /* Move the destination address into position. */
+ mov $0, $27
+ /* Restore program registers. */
+ ldq $26, 0(sp)
+ ldq $0, 8(sp)
+ ldq $1, 16(sp)
+ ldq $2, 24(sp)
+ ldq $3, 32(sp)
+ ldq $4, 40(sp)
+ ldq $5, 48(sp)
+ ldq $6, 56(sp)
+ ldq $7, 64(sp)
+ ldq $8, 72(sp)
+ ldq $16, 80(sp)
+ ldq $17, 88(sp)
+ ldq $18, 96(sp)
+ ldq $19, 104(sp)
+ ldq $20, 112(sp)
+ ldq $21, 120(sp)
+ ldq $22, 128(sp)
+ ldq $23, 136(sp)
+ ldq $24, 144(sp)
+ ldq $25, 152(sp)
+ ldq $29, 160(sp)
+ /* Flush the Icache after having modified the .plt code. */
+ imb
+ /* Clean up and turn control to the destination */
+ lda sp, 168(sp)
+ jmp $31, ($27)
+ .end _rtld_bind_start
+
+
+
+
diff --git a/libexec/rtld-elf/amd64/reloc.c b/libexec/rtld-elf/amd64/reloc.c
new file mode 100644
index 0000000..d34d892
--- /dev/null
+++ b/libexec/rtld-elf/amd64/reloc.c
@@ -0,0 +1,236 @@
+/*-
+ * Copyright 1996-1998 John D. Polstra.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $Id: rtld.c,v 1.3 1998/05/01 08:39:27 dfr Exp $
+ */
+
+/*
+ * Dynamic linker for ELF.
+ *
+ * John Polstra <jdp@polstra.com>.
+ */
+
+#include <sys/param.h>
+#include <sys/mman.h>
+
+#include <dlfcn.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "debug.h"
+#include "rtld.h"
+
+/*
+ * Debugging support.
+ */
+
+#define assert(cond) ((cond) ? (void) 0 :\
+ (msg("oops: " __XSTRING(__LINE__) "\n"), abort()))
+#define msg(s) (write(1, s, strlen(s)))
+#define trace() msg("trace: " __XSTRING(__LINE__) "\n");
+
+/*
+ * Process the special R_386_COPY relocations in the main program. These
+ * copy data from a shared object into a region in the main program's BSS
+ * segment.
+ *
+ * Returns 0 on success, -1 on failure.
+ */
+int
+do_copy_relocations(Obj_Entry *dstobj)
+{
+ const Elf_Rel *rellim;
+ const Elf_Rel *rel;
+
+ assert(dstobj->mainprog); /* COPY relocations are invalid elsewhere */
+
+ rellim = (const Elf_Rel *) ((caddr_t) dstobj->rel + dstobj->relsize);
+ for (rel = dstobj->rel; rel < rellim; rel++) {
+ if (ELF_R_TYPE(rel->r_info) == R_386_COPY) {
+ void *dstaddr;
+ const Elf_Sym *dstsym;
+ const char *name;
+ unsigned long hash;
+ size_t size;
+ const void *srcaddr;
+ const Elf_Sym *srcsym;
+ Obj_Entry *srcobj;
+
+ dstaddr = (void *) (dstobj->relocbase + rel->r_offset);
+ dstsym = dstobj->symtab + ELF_R_SYM(rel->r_info);
+ name = dstobj->strtab + dstsym->st_name;
+ hash = elf_hash(name);
+ size = dstsym->st_size;
+
+ for (srcobj = dstobj->next; srcobj != NULL; srcobj = srcobj->next)
+ if ((srcsym = symlook_obj(name, hash, srcobj, false)) != NULL)
+ break;
+
+ if (srcobj == NULL) {
+ _rtld_error("Undefined symbol \"%s\" referenced from COPY"
+ " relocation in %s", name, dstobj->path);
+ return -1;
+ }
+
+ srcaddr = (const void *) (srcobj->relocbase + srcsym->st_value);
+ memcpy(dstaddr, srcaddr, size);
+ }
+ }
+
+ return 0;
+}
+
+/* Process the non-PLT relocations. */
+int
+reloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld)
+{
+ const Elf_Rel *rellim;
+ const Elf_Rel *rel;
+
+ rellim = (const Elf_Rel *) ((caddr_t) obj->rel + obj->relsize);
+ for (rel = obj->rel; rel < rellim; rel++) {
+ Elf_Addr *where = (Elf_Addr *) (obj->relocbase + rel->r_offset);
+
+ switch (ELF_R_TYPE(rel->r_info)) {
+
+ case R_386_NONE:
+ break;
+
+ case R_386_32:
+ {
+ const Elf_Sym *def;
+ const Obj_Entry *defobj;
+
+ def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj,
+ false);
+ if (def == NULL)
+ return -1;
+
+ *where += (Elf_Addr) (defobj->relocbase + def->st_value);
+ }
+ break;
+
+ case R_386_PC32:
+ /*
+ * I don't think the dynamic linker should ever see this
+ * type of relocation. But the binutils-2.6 tools sometimes
+ * generate it.
+ */
+ {
+ const Elf_Sym *def;
+ const Obj_Entry *defobj;
+
+ def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj,
+ false);
+ if (def == NULL)
+ return -1;
+
+ *where +=
+ (Elf_Addr) (defobj->relocbase + def->st_value) -
+ (Elf_Addr) where;
+ }
+ break;
+
+ case R_386_COPY:
+ /*
+ * These are deferred until all other relocations have
+ * been done. All we do here is make sure that the COPY
+ * relocation is not in a shared library. They are allowed
+ * only in executable files.
+ */
+ if (!obj->mainprog) {
+ _rtld_error("%s: Unexpected R_386_COPY relocation"
+ " in shared library", obj->path);
+ return -1;
+ }
+ break;
+
+ case R_386_GLOB_DAT:
+ {
+ const Elf_Sym *def;
+ const Obj_Entry *defobj;
+
+ def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj,
+ false);
+ if (def == NULL)
+ return -1;
+
+ *where = (Elf_Addr) (defobj->relocbase + def->st_value);
+ }
+ break;
+
+ case R_386_RELATIVE:
+ *where += (Elf_Addr) obj->relocbase;
+ break;
+
+ default:
+ _rtld_error("%s: Unsupported relocation type %d"
+ " in non-PLT relocations\n", obj->path,
+ ELF_R_TYPE(rel->r_info));
+ return -1;
+ }
+ }
+ return 0;
+}
+
+/* Process the PLT relocations. */
+int
+reloc_plt(Obj_Entry *obj, bool bind_now)
+{
+ const Elf_Rel *rellim;
+ const Elf_Rel *rel;
+
+ /* Process the PLT relocations. */
+ rellim = (const Elf_Rel *) ((caddr_t) obj->pltrel + obj->pltrelsize);
+ if (bind_now) {
+ /* Fully resolve procedure addresses now */
+ for (rel = obj->pltrel; rel < rellim; rel++) {
+ Elf_Addr *where = (Elf_Addr *)
+ (obj->relocbase + rel->r_offset);
+ const Elf_Sym *def;
+ const Obj_Entry *defobj;
+
+ assert(ELF_R_TYPE(rel->r_info) == R_386_JMP_SLOT);
+
+ def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj, true);
+ if (def == NULL)
+ return -1;
+
+ *where = (Elf_Addr) (defobj->relocbase + def->st_value);
+ }
+ } else { /* Just relocate the GOT slots pointing into the PLT */
+ for (rel = obj->pltrel; rel < rellim; rel++) {
+ Elf_Addr *where = (Elf_Addr *)
+ (obj->relocbase + rel->r_offset);
+ *where += (Elf_Addr) obj->relocbase;
+ }
+ }
+ return 0;
+}
diff --git a/libexec/rtld-elf/amd64/rtld_start.S b/libexec/rtld-elf/amd64/rtld_start.S
index f82e564..d678f2e 100644
--- a/libexec/rtld-elf/amd64/rtld_start.S
+++ b/libexec/rtld-elf/amd64/rtld_start.S
@@ -22,7 +22,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $Id: rtld_start.S,v 1.6 1998/03/05 21:05:53 jdp Exp $
+ * $Id: rtld_start.S,v 1.1.1.1 1998/03/07 19:24:35 jdp Exp $
*/
.text
@@ -32,12 +32,17 @@
.rtld_start:
xorl %ebp,%ebp # Clear frame pointer for good form
movl %esp,%eax # Save initial stack pointer
- subl $4,%esp # A place to store exit procedure addr
- pushl %esp # Pass its address to rtld
+ subl $8,%esp # A place to store exit procedure addr
+ movl %esp,%ebx # save address of exit proc
+ movl %esp,%ecx # construct address of obj_main
+ addl $4,%ecx
+ pushl %ecx # Pass address of obj_main
+ pushl %ebx # Pass address of exit proc
pushl %eax # Pass initial stack pointer to rtld
call _rtld@PLT # Call rtld(sp); returns entry point
- addl $8,%esp # Remove arguments from stack
+ addl $12,%esp # Remove arguments from stack
popl %edx # Get exit procedure address
+ addl $4,%esp # Ignore obj_main
/*
* At this point, %eax contains the entry point of the main program, and
* %edx contains a pointer to a termination function that should be
diff --git a/libexec/rtld-elf/i386/reloc.c b/libexec/rtld-elf/i386/reloc.c
new file mode 100644
index 0000000..d34d892
--- /dev/null
+++ b/libexec/rtld-elf/i386/reloc.c
@@ -0,0 +1,236 @@
+/*-
+ * Copyright 1996-1998 John D. Polstra.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $Id: rtld.c,v 1.3 1998/05/01 08:39:27 dfr Exp $
+ */
+
+/*
+ * Dynamic linker for ELF.
+ *
+ * John Polstra <jdp@polstra.com>.
+ */
+
+#include <sys/param.h>
+#include <sys/mman.h>
+
+#include <dlfcn.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "debug.h"
+#include "rtld.h"
+
+/*
+ * Debugging support.
+ */
+
+#define assert(cond) ((cond) ? (void) 0 :\
+ (msg("oops: " __XSTRING(__LINE__) "\n"), abort()))
+#define msg(s) (write(1, s, strlen(s)))
+#define trace() msg("trace: " __XSTRING(__LINE__) "\n");
+
+/*
+ * Process the special R_386_COPY relocations in the main program. These
+ * copy data from a shared object into a region in the main program's BSS
+ * segment.
+ *
+ * Returns 0 on success, -1 on failure.
+ */
+int
+do_copy_relocations(Obj_Entry *dstobj)
+{
+ const Elf_Rel *rellim;
+ const Elf_Rel *rel;
+
+ assert(dstobj->mainprog); /* COPY relocations are invalid elsewhere */
+
+ rellim = (const Elf_Rel *) ((caddr_t) dstobj->rel + dstobj->relsize);
+ for (rel = dstobj->rel; rel < rellim; rel++) {
+ if (ELF_R_TYPE(rel->r_info) == R_386_COPY) {
+ void *dstaddr;
+ const Elf_Sym *dstsym;
+ const char *name;
+ unsigned long hash;
+ size_t size;
+ const void *srcaddr;
+ const Elf_Sym *srcsym;
+ Obj_Entry *srcobj;
+
+ dstaddr = (void *) (dstobj->relocbase + rel->r_offset);
+ dstsym = dstobj->symtab + ELF_R_SYM(rel->r_info);
+ name = dstobj->strtab + dstsym->st_name;
+ hash = elf_hash(name);
+ size = dstsym->st_size;
+
+ for (srcobj = dstobj->next; srcobj != NULL; srcobj = srcobj->next)
+ if ((srcsym = symlook_obj(name, hash, srcobj, false)) != NULL)
+ break;
+
+ if (srcobj == NULL) {
+ _rtld_error("Undefined symbol \"%s\" referenced from COPY"
+ " relocation in %s", name, dstobj->path);
+ return -1;
+ }
+
+ srcaddr = (const void *) (srcobj->relocbase + srcsym->st_value);
+ memcpy(dstaddr, srcaddr, size);
+ }
+ }
+
+ return 0;
+}
+
+/* Process the non-PLT relocations. */
+int
+reloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld)
+{
+ const Elf_Rel *rellim;
+ const Elf_Rel *rel;
+
+ rellim = (const Elf_Rel *) ((caddr_t) obj->rel + obj->relsize);
+ for (rel = obj->rel; rel < rellim; rel++) {
+ Elf_Addr *where = (Elf_Addr *) (obj->relocbase + rel->r_offset);
+
+ switch (ELF_R_TYPE(rel->r_info)) {
+
+ case R_386_NONE:
+ break;
+
+ case R_386_32:
+ {
+ const Elf_Sym *def;
+ const Obj_Entry *defobj;
+
+ def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj,
+ false);
+ if (def == NULL)
+ return -1;
+
+ *where += (Elf_Addr) (defobj->relocbase + def->st_value);
+ }
+ break;
+
+ case R_386_PC32:
+ /*
+ * I don't think the dynamic linker should ever see this
+ * type of relocation. But the binutils-2.6 tools sometimes
+ * generate it.
+ */
+ {
+ const Elf_Sym *def;
+ const Obj_Entry *defobj;
+
+ def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj,
+ false);
+ if (def == NULL)
+ return -1;
+
+ *where +=
+ (Elf_Addr) (defobj->relocbase + def->st_value) -
+ (Elf_Addr) where;
+ }
+ break;
+
+ case R_386_COPY:
+ /*
+ * These are deferred until all other relocations have
+ * been done. All we do here is make sure that the COPY
+ * relocation is not in a shared library. They are allowed
+ * only in executable files.
+ */
+ if (!obj->mainprog) {
+ _rtld_error("%s: Unexpected R_386_COPY relocation"
+ " in shared library", obj->path);
+ return -1;
+ }
+ break;
+
+ case R_386_GLOB_DAT:
+ {
+ const Elf_Sym *def;
+ const Obj_Entry *defobj;
+
+ def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj,
+ false);
+ if (def == NULL)
+ return -1;
+
+ *where = (Elf_Addr) (defobj->relocbase + def->st_value);
+ }
+ break;
+
+ case R_386_RELATIVE:
+ *where += (Elf_Addr) obj->relocbase;
+ break;
+
+ default:
+ _rtld_error("%s: Unsupported relocation type %d"
+ " in non-PLT relocations\n", obj->path,
+ ELF_R_TYPE(rel->r_info));
+ return -1;
+ }
+ }
+ return 0;
+}
+
+/* Process the PLT relocations. */
+int
+reloc_plt(Obj_Entry *obj, bool bind_now)
+{
+ const Elf_Rel *rellim;
+ const Elf_Rel *rel;
+
+ /* Process the PLT relocations. */
+ rellim = (const Elf_Rel *) ((caddr_t) obj->pltrel + obj->pltrelsize);
+ if (bind_now) {
+ /* Fully resolve procedure addresses now */
+ for (rel = obj->pltrel; rel < rellim; rel++) {
+ Elf_Addr *where = (Elf_Addr *)
+ (obj->relocbase + rel->r_offset);
+ const Elf_Sym *def;
+ const Obj_Entry *defobj;
+
+ assert(ELF_R_TYPE(rel->r_info) == R_386_JMP_SLOT);
+
+ def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj, true);
+ if (def == NULL)
+ return -1;
+
+ *where = (Elf_Addr) (defobj->relocbase + def->st_value);
+ }
+ } else { /* Just relocate the GOT slots pointing into the PLT */
+ for (rel = obj->pltrel; rel < rellim; rel++) {
+ Elf_Addr *where = (Elf_Addr *)
+ (obj->relocbase + rel->r_offset);
+ *where += (Elf_Addr) obj->relocbase;
+ }
+ }
+ return 0;
+}
diff --git a/libexec/rtld-elf/i386/rtld_start.S b/libexec/rtld-elf/i386/rtld_start.S
index f82e564..d678f2e 100644
--- a/libexec/rtld-elf/i386/rtld_start.S
+++ b/libexec/rtld-elf/i386/rtld_start.S
@@ -22,7 +22,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $Id: rtld_start.S,v 1.6 1998/03/05 21:05:53 jdp Exp $
+ * $Id: rtld_start.S,v 1.1.1.1 1998/03/07 19:24:35 jdp Exp $
*/
.text
@@ -32,12 +32,17 @@
.rtld_start:
xorl %ebp,%ebp # Clear frame pointer for good form
movl %esp,%eax # Save initial stack pointer
- subl $4,%esp # A place to store exit procedure addr
- pushl %esp # Pass its address to rtld
+ subl $8,%esp # A place to store exit procedure addr
+ movl %esp,%ebx # save address of exit proc
+ movl %esp,%ecx # construct address of obj_main
+ addl $4,%ecx
+ pushl %ecx # Pass address of obj_main
+ pushl %ebx # Pass address of exit proc
pushl %eax # Pass initial stack pointer to rtld
call _rtld@PLT # Call rtld(sp); returns entry point
- addl $8,%esp # Remove arguments from stack
+ addl $12,%esp # Remove arguments from stack
popl %edx # Get exit procedure address
+ addl $4,%esp # Ignore obj_main
/*
* At this point, %eax contains the entry point of the main program, and
* %edx contains a pointer to a termination function that should be
diff --git a/libexec/rtld-elf/malloc.c b/libexec/rtld-elf/malloc.c
index a451700..6689796 100644
--- a/libexec/rtld-elf/malloc.c
+++ b/libexec/rtld-elf/malloc.c
@@ -33,7 +33,7 @@
#if defined(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)malloc.c 5.11 (Berkeley) 2/23/91";*/
-static char *rcsid = "$Id: malloc.c,v 1.2 1996/01/19 18:36:54 jdp Exp $";
+static char *rcsid = "$Id: malloc.c,v 1.1.1.1 1998/03/07 19:24:35 jdp Exp $";
#endif /* LIBC_SCCS and not lint */
/*
@@ -156,7 +156,8 @@ malloc(nbytes)
size_t nbytes;
{
register union overhead *op;
- register int bucket, n;
+ register int bucket;
+ register long n;
register unsigned amt;
/*
@@ -168,7 +169,7 @@ malloc(nbytes)
if (morepages(NPOOLPAGES) == 0)
return NULL;
op = (union overhead *)(pagepool_start);
- n = n - sizeof (*op) - ((int)op & (n - 1));
+ n = n - sizeof (*op) - ((long)op & (n - 1));
if (n < 0)
n += pagesz;
if (n) {
@@ -462,12 +463,12 @@ int n;
if (pagepool_end - pagepool_start > pagesz) {
caddr_t addr = (caddr_t)
- (((int)pagepool_start + pagesz - 1) & ~(pagesz - 1));
+ (((long)pagepool_start + pagesz - 1) & ~(pagesz - 1));
if (munmap(addr, pagepool_end - addr) != 0)
warn("morepages: munmap %p", addr);
}
- offset = (int)pagepool_start - ((int)pagepool_start & ~(pagesz - 1));
+ offset = (long)pagepool_start - ((long)pagepool_start & ~(pagesz - 1));
if ((pagepool_start = mmap(0, n * pagesz,
PROT_READ|PROT_WRITE,
diff --git a/libexec/rtld-elf/map_object.c b/libexec/rtld-elf/map_object.c
index 0e33b3c..a393bb8 100644
--- a/libexec/rtld-elf/map_object.c
+++ b/libexec/rtld-elf/map_object.c
@@ -22,7 +22,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $Id: map_object.c,v 1.2 1998/03/06 22:14:53 jdp Exp $
+ * $Id: map_object.c,v 1.1.1.1 1998/03/07 19:24:35 jdp Exp $
*/
#include <sys/param.h>
@@ -50,31 +50,31 @@ map_object(int fd)
{
Obj_Entry *obj;
union {
- Elf32_Ehdr hdr;
+ Elf_Ehdr hdr;
char buf[PAGE_SIZE];
} u;
int nbytes;
- Elf32_Phdr *phdr;
- Elf32_Phdr *phlimit;
- Elf32_Phdr *segs[2];
+ Elf_Phdr *phdr;
+ Elf_Phdr *phlimit;
+ Elf_Phdr *segs[2];
int nsegs;
- Elf32_Phdr *phdyn;
- Elf32_Phdr *phphdr;
+ Elf_Phdr *phdyn;
+ Elf_Phdr *phphdr;
caddr_t mapbase;
size_t mapsize;
- Elf32_Off base_offset;
- Elf32_Addr base_vaddr;
- Elf32_Addr base_vlimit;
+ Elf_Off base_offset;
+ Elf_Addr base_vaddr;
+ Elf_Addr base_vlimit;
caddr_t base_addr;
- Elf32_Off data_offset;
- Elf32_Addr data_vaddr;
- Elf32_Addr data_vlimit;
+ Elf_Off data_offset;
+ Elf_Addr data_vaddr;
+ Elf_Addr data_vlimit;
caddr_t data_addr;
- Elf32_Addr clear_vaddr;
+ Elf_Addr clear_vaddr;
caddr_t clear_addr;
size_t nclear;
- Elf32_Addr bss_vaddr;
- Elf32_Addr bss_vlimit;
+ Elf_Addr bss_vaddr;
+ Elf_Addr bss_vlimit;
caddr_t bss_addr;
if ((nbytes = read(fd, u.buf, PAGE_SIZE)) == -1) {
@@ -83,7 +83,7 @@ map_object(int fd)
}
/* Make sure the file is valid */
- if (nbytes < sizeof(Elf32_Ehdr)
+ if (nbytes < sizeof(Elf_Ehdr)
|| u.hdr.e_ident[EI_MAG0] != ELFMAG0
|| u.hdr.e_ident[EI_MAG1] != ELFMAG1
|| u.hdr.e_ident[EI_MAG2] != ELFMAG2
@@ -91,8 +91,8 @@ map_object(int fd)
_rtld_error("Invalid file format");
return NULL;
}
- if (u.hdr.e_ident[EI_CLASS] != ELFCLASS32
- || u.hdr.e_ident[EI_DATA] != ELFDATA2LSB) {
+ if (u.hdr.e_ident[EI_CLASS] != ELF_TARG_CLASS
+ || u.hdr.e_ident[EI_DATA] != ELF_TARG_DATA) {
_rtld_error("Unsupported file layout");
return NULL;
}
@@ -105,7 +105,7 @@ map_object(int fd)
_rtld_error("Unsupported file type");
return NULL;
}
- if (u.hdr.e_machine != EM_386) {
+ if (u.hdr.e_machine != ELF_TARG_MACH) {
_rtld_error("Unsupported machine");
return NULL;
}
@@ -115,9 +115,9 @@ map_object(int fd)
* not strictly required by the ABI specification, but it seems to
* always true in practice. And, it simplifies things considerably.
*/
- assert(u.hdr.e_phentsize == sizeof(Elf32_Phdr));
- assert(u.hdr.e_phoff + u.hdr.e_phnum*sizeof(Elf32_Phdr) <= PAGE_SIZE);
- assert(u.hdr.e_phoff + u.hdr.e_phnum*sizeof(Elf32_Phdr) <= nbytes);
+ assert(u.hdr.e_phentsize == sizeof(Elf_Phdr));
+ assert(u.hdr.e_phoff + u.hdr.e_phnum*sizeof(Elf_Phdr) <= PAGE_SIZE);
+ assert(u.hdr.e_phoff + u.hdr.e_phnum*sizeof(Elf_Phdr) <= nbytes);
/*
* Scan the program header entries, and save key information.
@@ -125,7 +125,7 @@ map_object(int fd)
* We rely on there being exactly two load segments, text and data,
* in that order.
*/
- phdr = (Elf32_Phdr *) (u.buf + u.hdr.e_phoff);
+ phdr = (Elf_Phdr *) (u.buf + u.hdr.e_phoff);
phlimit = phdr + u.hdr.e_phnum;
nsegs = 0;
phdyn = NULL;
@@ -156,8 +156,8 @@ map_object(int fd)
}
assert(nsegs == 2);
- assert(segs[0]->p_align <= PAGE_SIZE);
- assert(segs[1]->p_align <= PAGE_SIZE);
+ assert(segs[0]->p_align >= PAGE_SIZE);
+ assert(segs[1]->p_align >= PAGE_SIZE);
/*
* Map the entire address space of the object, to stake out our
@@ -219,12 +219,12 @@ map_object(int fd)
base_vaddr;
obj->vaddrbase = base_vaddr;
obj->relocbase = mapbase - base_vaddr;
- obj->dynamic = (const Elf32_Dyn *)
+ obj->dynamic = (const Elf_Dyn *)
(mapbase + (phdyn->p_vaddr - base_vaddr));
if (u.hdr.e_entry != 0)
obj->entry = (caddr_t) (mapbase + (u.hdr.e_entry - base_vaddr));
if (phphdr != NULL) {
- obj->phdr = (const Elf32_Phdr *)
+ obj->phdr = (const Elf_Phdr *)
(mapbase + (phphdr->p_vaddr - base_vaddr));
obj->phsize = phphdr->p_memsz;
}
diff --git a/libexec/rtld-elf/rtld.c b/libexec/rtld-elf/rtld.c
index 9decc12..c52efa0 100644
--- a/libexec/rtld-elf/rtld.c
+++ b/libexec/rtld-elf/rtld.c
@@ -22,7 +22,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $Id: rtld.c,v 1.5 1998/09/02 02:00:20 jdp Exp $
+ * $Id: rtld.c,v 1.6 1998/09/02 02:51:12 jdp Exp $
*/
/*
@@ -72,15 +72,11 @@ static void call_fini_functions(Obj_Entry *);
static void call_init_functions(Obj_Entry *);
static void die(void);
static void digest_dynamic(Obj_Entry *);
-static Obj_Entry *digest_phdr(const Elf32_Phdr *, int, caddr_t);
+static Obj_Entry *digest_phdr(const Elf_Phdr *, int, caddr_t);
static Obj_Entry *dlcheck(void *);
-static int do_copy_relocations(Obj_Entry *);
-static unsigned long elf_hash(const char *);
static char *find_library(const char *, const Obj_Entry *);
-static const Elf32_Sym *find_symdef(unsigned long, const Obj_Entry *,
- const Obj_Entry **, bool);
static void init_rtld(caddr_t);
-static bool is_exported(const Elf32_Sym *);
+static bool is_exported(const Elf_Sym *);
static void linkmap_add(Obj_Entry *);
static void linkmap_delete(Obj_Entry *);
static int load_needed_objects(Obj_Entry *);
@@ -89,8 +85,6 @@ static Obj_Entry *obj_from_addr(const void *);
static int relocate_objects(Obj_Entry *, bool);
static void rtld_exit(void);
static char *search_library_path(const char *, const char *);
-static const Elf32_Sym *symlook_obj(const char *, unsigned long,
- const Obj_Entry *, bool);
static void unref_object_dag(Obj_Entry *);
static void trace_loaded_objects(Obj_Entry *obj);
@@ -109,11 +103,13 @@ extern void _rtld_bind_start(void);
*/
#ifdef __i386__
#define get_got_address() \
- ({ Elf32_Addr *thegot; \
+ ({ Elf_Addr *thegot; \
__asm__("movl %%ebx,%0" : "=rm"(thegot)); \
thegot; })
+#elif __alpha__
+#define get_got_address() NULL
#else
-#error "This file only supports the i386 architecture"
+#error "This file only supports the i386 and alpha architectures"
#endif
/*
@@ -135,6 +131,8 @@ static Obj_Entry obj_rtld; /* The dynamic linker shared object */
#define GDB_STATE(s) r_debug.r_state = s; r_debug_state();
+extern Elf_Dyn _DYNAMIC;
+
/*
* These are the functions the dynamic linker exports to application
* programs. They are the only symbols the dynamic linker is willing
@@ -167,20 +165,21 @@ char **environ;
* sequence of "auxiliary vector" entries.
*
* The second argument points to a place to store the dynamic linker's
- * exit procedure pointer.
+ * exit procedure pointer and the third to a place to store the main
+ * program's object.
*
* The return value is the main program's entry point.
*/
func_ptr_type
-_rtld(Elf32_Word *sp, func_ptr_type *exit_proc)
+_rtld(Elf_Addr *sp, func_ptr_type *exit_proc, Obj_Entry **objp)
{
- Elf32_Auxinfo *aux_info[AT_COUNT];
+ Elf_Auxinfo *aux_info[AT_COUNT];
int i;
int argc;
char **argv;
char **env;
- Elf32_Auxinfo *aux;
- Elf32_Auxinfo *auxp;
+ Elf_Auxinfo *aux;
+ Elf_Auxinfo *auxp;
/*
* On entry, the dynamic linker itself has not been relocated yet.
@@ -196,7 +195,7 @@ _rtld(Elf32_Word *sp, func_ptr_type *exit_proc)
env = (char **) sp;
while (*sp++ != 0) /* Skip over environment, and NULL terminator */
;
- aux = (Elf32_Auxinfo *) sp;
+ aux = (Elf_Auxinfo *) sp;
/* Digest the auxiliary vector. */
for (i = 0; i < AT_COUNT; i++)
@@ -239,17 +238,17 @@ _rtld(Elf32_Word *sp, func_ptr_type *exit_proc)
if (obj_main == NULL)
die();
} else { /* Main program already loaded. */
- const Elf32_Phdr *phdr;
+ const Elf_Phdr *phdr;
int phnum;
caddr_t entry;
dbg("processing main program's program header");
assert(aux_info[AT_PHDR] != NULL);
- phdr = (const Elf32_Phdr *) aux_info[AT_PHDR]->a_un.a_ptr;
+ phdr = (const Elf_Phdr *) aux_info[AT_PHDR]->a_un.a_ptr;
assert(aux_info[AT_PHNUM] != NULL);
phnum = aux_info[AT_PHNUM]->a_un.a_val;
assert(aux_info[AT_PHENT] != NULL);
- assert(aux_info[AT_PHENT]->a_un.a_val == sizeof(Elf32_Phdr));
+ assert(aux_info[AT_PHENT]->a_un.a_val == sizeof(Elf_Phdr));
assert(aux_info[AT_ENTRY] != NULL);
entry = (caddr_t) aux_info[AT_ENTRY]->a_un.a_ptr;
obj_main = digest_phdr(phdr, phnum, entry);
@@ -294,24 +293,27 @@ _rtld(Elf32_Word *sp, func_ptr_type *exit_proc)
r_debug_state(); /* say hello to gdb! */
/* Return the exit procedure and the program entry point. */
- *exit_proc = (func_ptr_type) rtld_exit;
+ *exit_proc = rtld_exit;
+ *objp = obj_main;
return (func_ptr_type) obj_main->entry;
}
caddr_t
-_rtld_bind(const Obj_Entry *obj, Elf32_Word reloff)
+_rtld_bind(const Obj_Entry *obj, Elf_Word reloff)
{
- const Elf32_Rel *rel;
- const Elf32_Sym *def;
+ const Elf_Rel *rel;
+ const Elf_Sym *def;
const Obj_Entry *defobj;
- Elf32_Addr *where;
+ Elf_Addr *where;
caddr_t target;
- rel = (const Elf32_Rel *) ((caddr_t) obj->pltrel + reloff);
- assert(ELF32_R_TYPE(rel->r_info) == R_386_JMP_SLOT);
+ if (obj->pltrel)
+ rel = (const Elf_Rel *) ((caddr_t) obj->pltrel + reloff);
+ else
+ rel = (const Elf_Rel *) ((caddr_t) obj->pltrela + reloff);
- where = (Elf32_Addr *) (obj->relocbase + rel->r_offset);
- def = find_symdef(ELF32_R_SYM(rel->r_info), obj, &defobj, true);
+ where = (Elf_Addr *) (obj->relocbase + rel->r_offset);
+ def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj, true);
if (def == NULL)
die();
@@ -321,7 +323,7 @@ _rtld_bind(const Obj_Entry *obj, Elf32_Word reloff)
defobj->strtab + def->st_name, basename(obj->path),
target, basename(defobj->path));
- *where = (Elf32_Addr) target;
+ *where = (Elf_Addr) target;
return target;
}
@@ -388,15 +390,16 @@ die(void)
static void
digest_dynamic(Obj_Entry *obj)
{
- const Elf32_Dyn *dynp;
+ const Elf_Dyn *dynp;
Needed_Entry **needed_tail = &obj->needed;
- const Elf32_Dyn *dyn_rpath = NULL;
+ const Elf_Dyn *dyn_rpath = NULL;
+ int plttype = DT_REL;
for (dynp = obj->dynamic; dynp->d_tag != DT_NULL; dynp++) {
switch (dynp->d_tag) {
case DT_REL:
- obj->rel = (const Elf32_Rel *) (obj->relocbase + dynp->d_un.d_ptr);
+ obj->rel = (const Elf_Rel *) (obj->relocbase + dynp->d_un.d_ptr);
break;
case DT_RELSZ:
@@ -404,11 +407,11 @@ digest_dynamic(Obj_Entry *obj)
break;
case DT_RELENT:
- assert(dynp->d_un.d_val == sizeof(Elf32_Rel));
+ assert(dynp->d_un.d_val == sizeof(Elf_Rel));
break;
case DT_JMPREL:
- obj->pltrel = (const Elf32_Rel *)
+ obj->pltrel = (const Elf_Rel *)
(obj->relocbase + dynp->d_un.d_ptr);
break;
@@ -417,22 +420,29 @@ digest_dynamic(Obj_Entry *obj)
break;
case DT_RELA:
+ obj->rela = (const Elf_Rela *) (obj->relocbase + dynp->d_un.d_ptr);
+ break;
+
case DT_RELASZ:
+ obj->relasize = dynp->d_un.d_val;
+ break;
+
case DT_RELAENT:
- assert(0); /* Should never appear for i386 */
+ assert(dynp->d_un.d_val == sizeof(Elf_Rela));
break;
case DT_PLTREL:
- assert(dynp->d_un.d_val == DT_REL); /* For the i386 */
+ plttype = dynp->d_un.d_val;
+ assert(dynp->d_un.d_val == DT_REL || plttype == DT_RELA);
break;
case DT_SYMTAB:
- obj->symtab = (const Elf32_Sym *)
+ obj->symtab = (const Elf_Sym *)
(obj->relocbase + dynp->d_un.d_ptr);
break;
case DT_SYMENT:
- assert(dynp->d_un.d_val == sizeof(Elf32_Sym));
+ assert(dynp->d_un.d_val == sizeof(Elf_Sym));
break;
case DT_STRTAB:
@@ -445,7 +455,7 @@ digest_dynamic(Obj_Entry *obj)
case DT_HASH:
{
- const Elf32_Word *hashtab = (const Elf32_Word *)
+ const Elf_Addr *hashtab = (const Elf_Addr *)
(obj->relocbase + dynp->d_un.d_ptr);
obj->nbuckets = hashtab[0];
obj->nchains = hashtab[1];
@@ -468,7 +478,7 @@ digest_dynamic(Obj_Entry *obj)
break;
case DT_PLTGOT:
- obj->got = (Elf32_Addr *) (obj->relocbase + dynp->d_un.d_ptr);
+ obj->got = (Elf_Addr *) (obj->relocbase + dynp->d_un.d_ptr);
break;
case DT_TEXTREL:
@@ -502,11 +512,24 @@ digest_dynamic(Obj_Entry *obj)
case DT_DEBUG:
/* XXX - not implemented yet */
dbg("Filling in DT_DEBUG entry");
- ((Elf32_Dyn*)dynp)->d_un.d_ptr = (Elf32_Addr) &r_debug;
+ ((Elf_Dyn*)dynp)->d_un.d_ptr = (Elf_Addr) &r_debug;
break;
+
+ default:
+ xprintf("Ignored d_tag %d\n",dynp->d_tag);
+ break;
}
}
+ obj->traced = false;
+
+ if (plttype == DT_RELA) {
+ obj->pltrela = (const Elf_Rela *) obj->pltrel;
+ obj->pltrel = NULL;
+ obj->pltrelasize = obj->pltrelsize;
+ obj->pltrelsize = 0;
+ }
+
if (dyn_rpath != NULL)
obj->rpath = obj->strtab + dyn_rpath->d_un.d_val;
}
@@ -518,19 +541,19 @@ digest_dynamic(Obj_Entry *obj)
* returns an Obj_Entry structure.
*/
static Obj_Entry *
-digest_phdr(const Elf32_Phdr *phdr, int phnum, caddr_t entry)
+digest_phdr(const Elf_Phdr *phdr, int phnum, caddr_t entry)
{
Obj_Entry *obj = CNEW(Obj_Entry);
- const Elf32_Phdr *phlimit = phdr + phnum;
- const Elf32_Phdr *ph;
+ const Elf_Phdr *phlimit = phdr + phnum;
+ const Elf_Phdr *ph;
int nsegs = 0;
for (ph = phdr; ph < phlimit; ph++) {
switch (ph->p_type) {
case PT_PHDR:
- assert((const Elf32_Phdr *) ph->p_vaddr == phdr);
- obj->phdr = (const Elf32_Phdr *) ph->p_vaddr;
+ assert((const Elf_Phdr *) ph->p_vaddr == phdr);
+ obj->phdr = (const Elf_Phdr *) ph->p_vaddr;
obj->phsize = ph->p_memsz;
break;
@@ -550,7 +573,7 @@ digest_phdr(const Elf32_Phdr *phdr, int phnum, caddr_t entry)
break;
case PT_DYNAMIC:
- obj->dynamic = (const Elf32_Dyn *) ph->p_vaddr;
+ obj->dynamic = (const Elf_Dyn *) ph->p_vaddr;
break;
}
}
@@ -577,61 +600,10 @@ dlcheck(void *handle)
}
/*
- * Process the special R_386_COPY relocations in the main program. These
- * copy data from a shared object into a region in the main program's BSS
- * segment.
- *
- * Returns 0 on success, -1 on failure.
- */
-static int
-do_copy_relocations(Obj_Entry *dstobj)
-{
- const Elf32_Rel *rellim;
- const Elf32_Rel *rel;
-
- assert(dstobj->mainprog); /* COPY relocations are invalid elsewhere */
-
- rellim = (const Elf32_Rel *) ((caddr_t) dstobj->rel + dstobj->relsize);
- for (rel = dstobj->rel; rel < rellim; rel++) {
- if (ELF32_R_TYPE(rel->r_info) == R_386_COPY) {
- void *dstaddr;
- const Elf32_Sym *dstsym;
- const char *name;
- unsigned long hash;
- size_t size;
- const void *srcaddr;
- const Elf32_Sym *srcsym;
- Obj_Entry *srcobj;
-
- dstaddr = (void *) (dstobj->relocbase + rel->r_offset);
- dstsym = dstobj->symtab + ELF32_R_SYM(rel->r_info);
- name = dstobj->strtab + dstsym->st_name;
- hash = elf_hash(name);
- size = dstsym->st_size;
-
- for (srcobj = dstobj->next; srcobj != NULL; srcobj = srcobj->next)
- if ((srcsym = symlook_obj(name, hash, srcobj, false)) != NULL)
- break;
-
- if (srcobj == NULL) {
- _rtld_error("Undefined symbol \"%s\" referenced from COPY"
- " relocation in %s", name, dstobj->path);
- return -1;
- }
-
- srcaddr = (const void *) (srcobj->relocbase + srcsym->st_value);
- memcpy(dstaddr, srcaddr, size);
- }
- }
-
- return 0;
-}
-
-/*
* Hash function for symbol table lookup. Don't even think about changing
* this. It is specified by the System V ABI.
*/
-static unsigned long
+unsigned long
elf_hash(const char *name)
{
const unsigned char *p = (const unsigned char *) name;
@@ -687,13 +659,13 @@ find_library(const char *name, const Obj_Entry *refobj)
* no definition was found. Returns a pointer to the Obj_Entry of the
* defining object via the reference parameter DEFOBJ_OUT.
*/
-static const Elf32_Sym *
+const Elf_Sym *
find_symdef(unsigned long symnum, const Obj_Entry *refobj,
const Obj_Entry **defobj_out, bool in_plt)
{
- const Elf32_Sym *ref;
- const Elf32_Sym *strongdef;
- const Elf32_Sym *weakdef;
+ const Elf_Sym *ref;
+ const Elf_Sym *strongdef;
+ const Elf_Sym *weakdef;
const Obj_Entry *obj;
const Obj_Entry *strongobj;
const Obj_Entry *weakobj;
@@ -705,7 +677,7 @@ find_symdef(unsigned long symnum, const Obj_Entry *refobj,
hash = elf_hash(name);
if (refobj->symbolic) { /* Look first in the referencing object */
- const Elf32_Sym *def = symlook_obj(name, hash, refobj, in_plt);
+ const Elf_Sym *def = symlook_obj(name, hash, refobj, in_plt);
if (def != NULL) {
*defobj_out = refobj;
return def;
@@ -723,9 +695,9 @@ find_symdef(unsigned long symnum, const Obj_Entry *refobj,
strongobj = weakobj = NULL;
for (obj = obj_list; obj != NULL; obj = obj->next) {
if (obj != refobj || !refobj->symbolic) {
- const Elf32_Sym *def = symlook_obj(name, hash, obj, in_plt);
+ const Elf_Sym *def = symlook_obj(name, hash, obj, in_plt);
if (def != NULL) {
- if (ELF32_ST_BIND(def->st_info) == STB_WEAK) {
+ if (ELF_ST_BIND(def->st_info) == STB_WEAK) {
if (weakdef == NULL) {
weakdef = def;
weakobj = obj;
@@ -747,9 +719,9 @@ find_symdef(unsigned long symnum, const Obj_Entry *refobj,
* can be resolved from the dynamic linker.
*/
if (strongdef == NULL) {
- const Elf32_Sym *def = symlook_obj(name, hash, &obj_rtld, in_plt);
+ const Elf_Sym *def = symlook_obj(name, hash, &obj_rtld, in_plt);
if (def != NULL && is_exported(def)) {
- if (ELF32_ST_BIND(def->st_info) == STB_WEAK) {
+ if (ELF_ST_BIND(def->st_info) == STB_WEAK) {
if (weakdef == NULL) {
weakdef = def;
weakobj = &obj_rtld;
@@ -789,9 +761,17 @@ init_rtld(caddr_t mapbase)
obj_rtld.mapbase = mapbase;
obj_rtld.relocbase = mapbase;
obj_rtld.got = get_got_address();
- obj_rtld.dynamic = (const Elf32_Dyn *) (obj_rtld.mapbase + obj_rtld.got[0]);
+#ifdef __alpha__
+ obj_rtld.dynamic = (const Elf_Dyn *) &_DYNAMIC;
+#else
+ obj_rtld.dynamic = (const Elf_Dyn *) (obj_rtld.mapbase + obj_rtld.got[0]);
+#endif
digest_dynamic(&obj_rtld);
+#ifdef __alpha__
+/* XXX XXX XXX */
+obj_rtld.got = NULL;
+#endif
assert(obj_rtld.needed == NULL);
assert(!obj_rtld.textrel);
@@ -813,7 +793,7 @@ init_rtld(caddr_t mapbase)
}
static bool
-is_exported(const Elf32_Sym *def)
+is_exported(const Elf_Sym *def)
{
func_ptr_type value;
const func_ptr_type *p;
@@ -914,7 +894,7 @@ obj_from_addr(const void *addr)
endhash = elf_hash(END_SYM);
for (obj = obj_list; obj != NULL; obj = obj->next) {
- const Elf32_Sym *endsym;
+ const Elf_Sym *endsym;
if (addr < (void *) obj->mapbase)
continue;
@@ -938,9 +918,6 @@ relocate_objects(Obj_Entry *first, bool bind_now)
Obj_Entry *obj;
for (obj = first; obj != NULL; obj = obj->next) {
- const Elf32_Rel *rellim;
- const Elf32_Rel *rel;
-
if (obj->nbuckets == 0 || obj->nchains == 0 || obj->buckets == NULL ||
obj->symtab == NULL || obj->strtab == NULL) {
_rtld_error("%s: Shared object has no run-time symbol table",
@@ -959,89 +936,8 @@ relocate_objects(Obj_Entry *first, bool bind_now)
}
/* Process the non-PLT relocations. */
- rellim = (const Elf32_Rel *) ((caddr_t) obj->rel + obj->relsize);
- for (rel = obj->rel; rel < rellim; rel++) {
- Elf32_Addr *where = (Elf32_Addr *) (obj->relocbase + rel->r_offset);
-
- switch (ELF32_R_TYPE(rel->r_info)) {
-
- case R_386_NONE:
- break;
-
- case R_386_32:
- {
- const Elf32_Sym *def;
- const Obj_Entry *defobj;
-
- def = find_symdef(ELF32_R_SYM(rel->r_info), obj, &defobj,
- false);
- if (def == NULL)
- return -1;
-
- *where += (Elf32_Addr) (defobj->relocbase + def->st_value);
- }
- break;
-
- case R_386_PC32:
- /*
- * I don't think the dynamic linker should ever see this
- * type of relocation. But the binutils-2.6 tools sometimes
- * generate it.
- */
- {
- const Elf32_Sym *def;
- const Obj_Entry *defobj;
-
- def = find_symdef(ELF32_R_SYM(rel->r_info), obj, &defobj,
- false);
- if (def == NULL)
- return -1;
-
- *where +=
- (Elf32_Addr) (defobj->relocbase + def->st_value) -
- (Elf32_Addr) where;
- }
- break;
-
- case R_386_COPY:
- /*
- * These are deferred until all other relocations have
- * been done. All we do here is make sure that the COPY
- * relocation is not in a shared library. They are allowed
- * only in executable files.
- */
- if (!obj->mainprog) {
- _rtld_error("%s: Unexpected R_386_COPY relocation"
- " in shared library", obj->path);
- return -1;
- }
- break;
-
- case R_386_GLOB_DAT:
- {
- const Elf32_Sym *def;
- const Obj_Entry *defobj;
-
- def = find_symdef(ELF32_R_SYM(rel->r_info), obj, &defobj,
- false);
- if (def == NULL)
- return -1;
-
- *where = (Elf32_Addr) (defobj->relocbase + def->st_value);
- }
- break;
-
- case R_386_RELATIVE:
- *where += (Elf32_Addr) obj->relocbase;
- break;
-
- default:
- _rtld_error("%s: Unsupported relocation type %d"
- " in non-PLT relocations\n", obj->path,
- ELF32_R_TYPE(rel->r_info));
+ if (reloc_non_plt(obj, &obj_rtld))
return -1;
- }
- }
if (obj->textrel) { /* Re-protected the text segment. */
if (mprotect(obj->mapbase, obj->textsize,
@@ -1053,30 +949,8 @@ relocate_objects(Obj_Entry *first, bool bind_now)
}
/* Process the PLT relocations. */
- rellim = (const Elf32_Rel *) ((caddr_t) obj->pltrel + obj->pltrelsize);
- if (bind_now) {
- /* Fully resolve procedure addresses now */
- for (rel = obj->pltrel; rel < rellim; rel++) {
- Elf32_Addr *where = (Elf32_Addr *)
- (obj->relocbase + rel->r_offset);
- const Elf32_Sym *def;
- const Obj_Entry *defobj;
-
- assert(ELF32_R_TYPE(rel->r_info) == R_386_JMP_SLOT);
-
- def = find_symdef(ELF32_R_SYM(rel->r_info), obj, &defobj, true);
- if (def == NULL)
- return -1;
-
- *where = (Elf32_Addr) (defobj->relocbase + def->st_value);
- }
- } else { /* Just relocate the GOT slots pointing into the PLT */
- for (rel = obj->pltrel; rel < rellim; rel++) {
- Elf32_Addr *where = (Elf32_Addr *)
- (obj->relocbase + rel->r_offset);
- *where += (Elf32_Addr) obj->relocbase;
- }
- }
+ if (reloc_plt(obj, bind_now))
+ return -1;
/*
* Set up the magic number and version in the Obj_Entry. These
@@ -1088,8 +962,16 @@ relocate_objects(Obj_Entry *first, bool bind_now)
/* Set the special GOT entries. */
if (obj->got) {
- obj->got[1] = (Elf32_Addr) obj;
- obj->got[2] = (Elf32_Addr) &_rtld_bind_start;
+#ifdef __i386__
+ obj->got[1] = (Elf_Addr) obj;
+ obj->got[2] = (Elf_Addr) &_rtld_bind_start;
+#endif
+#ifdef __alpha__
+ /* This function will be called to perform the relocation. */
+ obj->got[2] = (Elf_Addr) &_rtld_bind_start;
+ /* Identify this shared object */
+ obj->got[3] = (Elf_Addr) obj;
+#endif
}
}
@@ -1239,7 +1121,7 @@ dlsym(void *handle, const char *name)
{
const Obj_Entry *obj;
unsigned long hash;
- const Elf32_Sym *def;
+ const Elf_Sym *def;
hash = elf_hash(name);
def = NULL;
@@ -1341,14 +1223,14 @@ r_debug_state(void)
* The symbol's hash value is passed in for efficiency reasons; that
* eliminates many recomputations of the hash value.
*/
-static const Elf32_Sym *
+const Elf_Sym *
symlook_obj(const char *name, unsigned long hash, const Obj_Entry *obj,
bool in_plt)
{
unsigned long symnum = obj->buckets[hash % obj->nbuckets];
while (symnum != STN_UNDEF) {
- const Elf32_Sym *symp;
+ const Elf_Sym *symp;
const char *strp;
assert(symnum < obj->nchains);
@@ -1359,7 +1241,7 @@ symlook_obj(const char *name, unsigned long hash, const Obj_Entry *obj,
if (strcmp(name, strp) == 0)
return symp->st_shndx != SHN_UNDEF ||
(!in_plt && symp->st_value != 0 &&
- ELF32_ST_TYPE(symp->st_info) == STT_FUNC) ? symp : NULL;
+ ELF_ST_TYPE(symp->st_info) == STT_FUNC) ? symp : NULL;
symnum = obj->chains[symnum];
}
diff --git a/libexec/rtld-elf/rtld.h b/libexec/rtld-elf/rtld.h
index 679a676..f1a9afd 100644
--- a/libexec/rtld-elf/rtld.h
+++ b/libexec/rtld-elf/rtld.h
@@ -22,7 +22,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $Id: rtld.h,v 1.3 1998/08/21 03:29:40 jb Exp $
+ * $Id: rtld.h,v 1.4 1998/09/02 02:51:12 jdp Exp $
*/
#ifndef RTLD_H /* { */
@@ -88,15 +88,19 @@ typedef struct Struct_Obj_Entry {
Elf_Addr *got; /* GOT table */
const Elf_Rel *rel; /* Relocation entries */
unsigned long relsize; /* Size in bytes of relocation info */
+ const Elf_Rela *rela; /* Relocation entries with addend */
+ unsigned long relasize; /* Size in bytes of addend relocation info */
const Elf_Rel *pltrel; /* PLT relocation entries */
unsigned long pltrelsize; /* Size in bytes of PLT relocation info */
+ const Elf_Rela *pltrela; /* PLT relocation entries with addend */
+ unsigned long pltrelasize; /* Size in bytes of PLT addend reloc info */
const Elf_Sym *symtab; /* Symbol table */
const char *strtab; /* String table */
unsigned long strsize; /* Size in bytes of string table */
- const Elf_Word *buckets; /* Hash table buckets array */
+ const Elf_Addr *buckets; /* Hash table buckets array */
unsigned long nbuckets; /* Number of buckets */
- const Elf_Word *chains; /* Hash table chain array */
+ const Elf_Addr *chains; /* Hash table chain array */
unsigned long nchains; /* Number of chains */
const char *rpath; /* Search path specified in object */
@@ -122,5 +126,18 @@ extern Obj_Entry *map_object(int);
extern void *xcalloc(size_t);
extern void *xmalloc(size_t);
extern char *xstrdup(const char *);
+extern Elf_Addr _GLOBAL_OFFSET_TABLE_[];
+
+/*
+ * Function declarations.
+ */
+int do_copy_relocations(Obj_Entry *);
+int reloc_non_plt(Obj_Entry *, Obj_Entry *);
+int reloc_plt(Obj_Entry *, bool);
+unsigned long elf_hash(const char *);
+const Elf_Sym *find_symdef(unsigned long, const Obj_Entry *,
+ const Obj_Entry **, bool);
+const Elf_Sym *symlook_obj(const char *, unsigned long,
+ const Obj_Entry *, bool);
#endif /* } */
OpenPOWER on IntegriCloud