Add alpha support.
Submitted by: John Birrell <jb@cimlogic.com.au> (with extra hacks by me) Obtained from: Probably NetBSD
This commit is contained in:
parent
26cdc317be
commit
13575fc46f
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=38816
@ -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>
|
||||
|
309
libexec/rtld-elf/alpha/reloc.c
Normal file
309
libexec/rtld-elf/alpha/reloc.c
Normal file
@ -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;
|
||||
}
|
169
libexec/rtld-elf/alpha/rtld_start.S
Normal file
169
libexec/rtld-elf/alpha/rtld_start.S
Normal file
@ -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
|
||||
|
||||
|
||||
|
||||
|
236
libexec/rtld-elf/amd64/reloc.c
Normal file
236
libexec/rtld-elf/amd64/reloc.c
Normal file
@ -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;
|
||||
}
|
@ -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
|
||||
|
236
libexec/rtld-elf/i386/reloc.c
Normal file
236
libexec/rtld-elf/i386/reloc.c
Normal file
@ -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;
|
||||
}
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
@ -576,62 +599,11 @@ dlcheck(void *handle)
|
||||
return obj;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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];
|
||||
}
|
||||
|
@ -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 /* } */
|
||||
|
Loading…
Reference in New Issue
Block a user