diff --git a/libexec/ld.elf_so/Makefile b/libexec/ld.elf_so/Makefile index c84b3015666d..360d7dd2ff21 100644 --- a/libexec/ld.elf_so/Makefile +++ b/libexec/ld.elf_so/Makefile @@ -1,4 +1,4 @@ -# $NetBSD: Makefile,v 1.21 1999/02/21 18:10:24 kleink Exp $ +# $NetBSD: Makefile,v 1.22 1999/02/24 18:31:00 christos Exp $ .include # for OBJECT_FMT definition @@ -8,7 +8,7 @@ PROG= ld.elf_so .if (${MACHINE} == "alpha") || (${MACHINE_ARCH} == "mips") || \ (${MACHINE_ARCH} == "powerpc") || (${MACHINE} == "sparc64") || \ - (${MACHINE} == "i386") + (${MACHINE} == "i386") || (${MACHINE} == "sparc") # Adds SRCS, CPPFLAGS, LDFLAGS, etc. Must go first so MD startup source # is first. .if exists(${.CURDIR}/arch/${MACHINE_ARCH}/Makefile.inc) @@ -21,11 +21,13 @@ CLIBOBJ!=cd ${.CURDIR}/../../lib/libc; \ SRCS+= rtld.c reloc.c symbol.c malloc.c xmalloc.c xprintf.c debug.c \ map_object.c load.c search.c headers.c paths.c CPPFLAGS+= -Wall -DLIBDIR=\"${LIBDIR}\" -D_PATH_RTLD=\"${BINDIR}/${PROG}\" +CPPFLAGS+= -I${.CURDIR} CPPFLAGS+= -DDEBUG -DRTLD_LOADER #CPPFLAGS+= -DRTLD_DEBUG -DRTLD_DEBUG_RELOC LDADD+= -L${DESTDIR}/${LIBDIR} -L${CLIBOBJ} -non_shared -lc_pic DPADD+= ${LIBC_PIC} +CFLAGS+=-g .if (${OBJECT_FMT} == "ELF") # to be installed diff --git a/libexec/ld.elf_so/arch/i386/Makefile.inc b/libexec/ld.elf_so/arch/i386/Makefile.inc index 72323f4922a2..becc2b09bdc0 100644 --- a/libexec/ld.elf_so/arch/i386/Makefile.inc +++ b/libexec/ld.elf_so/arch/i386/Makefile.inc @@ -1,6 +1,6 @@ -# $NetBSD: Makefile.inc,v 1.1 1999/01/10 18:21:24 christos Exp $ +# $NetBSD: Makefile.inc,v 1.2 1999/02/24 18:31:00 christos Exp $ SRCS+= rtld_start.S -CPPFLAGS+= -fpic -DELFSIZE=32 +CPPFLAGS+= -fpic -DELFSIZE=32 -DRTLD_RELOCATE_SELF LDFLAGS+= -Bshareable -Bsymbolic -e .rtld_start diff --git a/libexec/ld.elf_so/debug.h b/libexec/ld.elf_so/debug.h index 6c73d526f1f6..20d5d8a5a551 100644 --- a/libexec/ld.elf_so/debug.h +++ b/libexec/ld.elf_so/debug.h @@ -1,4 +1,4 @@ -/* $NetBSD: debug.h,v 1.2 1999/01/10 17:19:01 christos Exp $ */ +/* $NetBSD: debug.h,v 1.3 1999/02/24 18:31:00 christos Exp $ */ /* * Copyright 1996 John D. Polstra. @@ -51,9 +51,14 @@ extern void debug_printf(const char *, ...) extern int debug; #ifdef DEBUG /* { */ -#define dbg(format, args...) debug_printf(format, ## args) +#define dbg(format, args...) debug_printf(format, ## args) #else /* } { */ -#define dbg(format, args...) ((void) 0) +#define dbg(format, args...) ((void) 0) #endif /* } */ +#ifdef RTLD_DEBUG_RELOC +#define rdbg(f, format, args...) if (f) debug_printf(format, ## args) +#else +#define rdbg(f, format, args...) ((void) 0) +#endif #endif /* } */ diff --git a/libexec/ld.elf_so/headers.c b/libexec/ld.elf_so/headers.c index 6937114acd72..878671fb1cc1 100644 --- a/libexec/ld.elf_so/headers.c +++ b/libexec/ld.elf_so/headers.c @@ -1,4 +1,4 @@ -/* $NetBSD: headers.c,v 1.2 1998/03/25 04:13:01 mhitch Exp $ */ +/* $NetBSD: headers.c,v 1.3 1999/02/24 18:31:00 christos Exp $ */ /* * Copyright 1996 John D. Polstra. @@ -229,7 +229,8 @@ _rtld_digest_dynamic( obj->pltrelalim = (const Elf_RelA *) ((caddr_t) obj->pltrela + pltrelasize); if (dyn_rpath != NULL) { - _rtld_add_paths(&obj->rpaths, obj->strtab + dyn_rpath->d_un.d_val); + _rtld_add_paths(&obj->rpaths, obj->strtab + dyn_rpath->d_un.d_val, + true); } } diff --git a/libexec/ld.elf_so/load.c b/libexec/ld.elf_so/load.c index a8fe0a5d6cd1..b862a604f3b4 100644 --- a/libexec/ld.elf_so/load.c +++ b/libexec/ld.elf_so/load.c @@ -1,4 +1,4 @@ -/* $NetBSD: load.c,v 1.1 1996/12/16 20:37:59 cgd Exp $ */ +/* $NetBSD: load.c,v 1.2 1999/02/24 18:31:00 christos Exp $ */ /* * Copyright 1996 John D. Polstra. @@ -62,7 +62,8 @@ */ Obj_Entry * _rtld_load_object( - char *filepath) + char *filepath, + bool dodebug) { Obj_Entry *obj; @@ -92,11 +93,12 @@ _rtld_load_object( #ifdef RTLD_LOADER _rtld_linkmap_add(obj); /* for GDB */ #endif - - dbg(" %p .. %p: %s", obj->mapbase, - obj->mapbase + obj->mapsize - 1, obj->path); - if (obj->textrel) - dbg(" WARNING: %s has impure text", obj->path); + if (dodebug) { + dbg(" %p .. %p: %s", obj->mapbase, + obj->mapbase + obj->mapsize - 1, obj->path); + if (obj->textrel) + dbg(" WARNING: %s has impure text", obj->path); + } } else free(filepath); @@ -126,7 +128,7 @@ _rtld_load_needed_objects( if (libpath == NULL) { status = -1; } else { - needed->obj = _rtld_load_object(libpath); + needed->obj = _rtld_load_object(libpath, true); if (needed->obj == NULL) status = -1; /* FIXME - cleanup */ } diff --git a/libexec/ld.elf_so/paths.c b/libexec/ld.elf_so/paths.c index c8055b7556a9..15f0f97a1143 100644 --- a/libexec/ld.elf_so/paths.c +++ b/libexec/ld.elf_so/paths.c @@ -1,4 +1,4 @@ -/* $NetBSD: paths.c,v 1.2 1997/10/08 08:55:36 mrg Exp $ */ +/* $NetBSD: paths.c,v 1.3 1999/02/24 18:31:00 christos Exp $ */ /* * Copyright 1996 Matt Thomas @@ -62,7 +62,8 @@ _rtld_find_path( void _rtld_add_paths( Search_Path **path_p, - const char *pathstr) + const char *pathstr, + bool dodebug) { Search_Path *path, **head_p = path_p; @@ -96,7 +97,8 @@ _rtld_add_paths( (*path_p) = path; path_p = &path->sp_next; - dbg(" added path \"%s\"", path->sp_path); + if (dodebug) + dbg(" added path \"%s\"", path->sp_path); } if (ep[0] == '\0') diff --git a/libexec/ld.elf_so/reloc.c b/libexec/ld.elf_so/reloc.c index 5a13b5a1a59d..989a58ddbca7 100644 --- a/libexec/ld.elf_so/reloc.c +++ b/libexec/ld.elf_so/reloc.c @@ -1,4 +1,4 @@ -/* $NetBSD: reloc.c,v 1.10 1999/02/24 12:20:30 pk Exp $ */ +/* $NetBSD: reloc.c,v 1.11 1999/02/24 18:31:00 christos Exp $ */ /* * Copyright 1996 John D. Polstra. @@ -64,39 +64,39 @@ */ static int _rtld_do_copy_relocation( - const Obj_Entry *dstobj, - const Elf_RelA *rela) + const Obj_Entry *dstobj, + const Elf_RelA *rela, + bool dodebug) { - void *dstaddr = (void *) (dstobj->relocbase + rela->r_offset); - const Elf_Sym *dstsym = dstobj->symtab + ELF_R_SYM(rela->r_info); - const char *name = dstobj->strtab + dstsym->st_name; - unsigned long hash = _rtld_elf_hash(name); - size_t size = dstsym->st_size; - const void *srcaddr; - const Elf_Sym *srcsym; - Obj_Entry *srcobj; + void *dstaddr = (void *)(dstobj->relocbase + rela->r_offset); + const Elf_Sym *dstsym = dstobj->symtab + ELF_R_SYM(rela->r_info); + const char *name = dstobj->strtab + dstsym->st_name; + unsigned long hash = _rtld_elf_hash(name); + size_t size = dstsym->st_size; + const void *srcaddr; + const Elf_Sym *srcsym; + Obj_Entry *srcobj; - for (srcobj = dstobj->next; srcobj != NULL; srcobj = srcobj->next) - if ((srcsym = _rtld_symlook_obj(name, hash, srcobj, false)) != NULL) - break; + for (srcobj = dstobj->next; srcobj != NULL; srcobj = srcobj->next) + if ((srcsym = _rtld_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); -#ifdef RTLD_DEBUG_RELOC - dbg("COPY %s %s %s --> src=%p dst=%p *dst= %p size %d", - dstobj->path, srcobj->path, name, (void *)srcaddr, (void *)dstaddr, - (void *)*(long *)dstaddr, size); -#endif - return 0; + 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); + (void)memcpy(dstaddr, srcaddr, size); + rdbg(dodebug, "COPY %s %s %s --> src=%p dst=%p *dst= %p size %d", + dstobj->path, srcobj->path, name, (void *)srcaddr, + (void *)dstaddr, (void *)*(long *)dstaddr, size); + return 0; } #endif /* __alpha__ || __powerpc__ || __i386__ */ - + + /* * Process the special R_xxx_COPY relocations in the main program. These * copy data from a shared object into a region in the main program's BSS @@ -106,243 +106,309 @@ _rtld_do_copy_relocation( */ int _rtld_do_copy_relocations( - const Obj_Entry *dstobj) + const Obj_Entry *dstobj, + bool dodebug) { - assert(dstobj->mainprog); /* COPY relocations are invalid elsewhere */ + assert(dstobj->mainprog); /* COPY relocations are invalid + * elsewhere */ #if defined(__alpha__) || defined(__powerpc__) || defined(__i386__) - if (dstobj->rel != NULL) { - const Elf_Rel *rel; - for (rel = dstobj->rel; rel < dstobj->rellim; ++rel) { - if (ELF_R_TYPE(rel->r_info) == R_TYPE(COPY)) { - Elf_RelA ourrela; - ourrela.r_info = rel->r_info; - ourrela.r_offset = rel->r_offset; - ourrela.r_addend = 0; - if (_rtld_do_copy_relocation(dstobj, &ourrela) < 0) - return -1; - } + if (dstobj->rel != NULL) { + const Elf_Rel *rel; + for (rel = dstobj->rel; rel < dstobj->rellim; ++rel) { + if (ELF_R_TYPE(rel->r_info) == R_TYPE(COPY)) { + Elf_RelA ourrela; + ourrela.r_info = rel->r_info; + ourrela.r_offset = rel->r_offset; + ourrela.r_addend = 0; + if (_rtld_do_copy_relocation(dstobj, + &ourrela, dodebug) < 0) + return -1; + } + } } - } - - if (dstobj->rela != NULL) { - const Elf_RelA *rela; - for (rela = dstobj->rela; rela < dstobj->relalim; ++rela) { - if (ELF_R_TYPE(rela->r_info) == R_TYPE(COPY)) { - if (_rtld_do_copy_relocation(dstobj, rela) < 0) - return -1; - } + if (dstobj->rela != NULL) { + const Elf_RelA *rela; + for (rela = dstobj->rela; rela < dstobj->relalim; ++rela) { + if (ELF_R_TYPE(rela->r_info) == R_TYPE(COPY)) { + if (_rtld_do_copy_relocation(dstobj, rela, + dodebug) < 0) + return -1; + } + } } - } #endif /* __alpha__ || __powerpc__ || __i386__ */ - return 0; + return 0; } -#ifdef __sparc__ -/* - * The following table holds for each relocation type: - * - the width in bits of the memory location the relocation - * applies to (not currently used) - * - the number of bits the relocation value must be shifted to the - * right (i.e. discard least significant bits) to fit into - * the appropriate field in the instruction word. - * - flags indicating whether - * * the relocation involves a symbol - * * the relocation is relative to the current position - * * the relocation is for a GOT entry - * * the relocation is relative to the load address - * - */ -#define _RF_S 0x80000000 /* Resolve symbol */ -#define _RF_A 0x40000000 /* Use addend */ -#define _RF_P 0x20000000 /* Location relative */ -#define _RF_G 0x10000000 /* GOT offset */ -#define _RF_B 0x08000000 /* Load address relative */ -#define _RF_SZ(s) (((s) & 0xff) << 8) /* memory target size */ -#define _RF_RS(s) ( (s) & 0xff) /* right shift */ -static int reloc_target_flags[] = { - 0, /* NONE */ - _RF_S|_RF_A| _RF_SZ(8) | _RF_RS(0), /* RELOC_8 */ - _RF_S|_RF_A| _RF_SZ(16) | _RF_RS(0), /* RELOC_16 */ - _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(0), /* RELOC_32 */ - _RF_S|_RF_A|_RF_P| _RF_SZ(8) | _RF_RS(0), /* DISP_8 */ - _RF_S|_RF_A|_RF_P| _RF_SZ(16) | _RF_RS(0), /* DISP_16 */ - _RF_S|_RF_A|_RF_P| _RF_SZ(32) | _RF_RS(0), /* DISP_32 */ - _RF_S|_RF_A|_RF_P| _RF_SZ(32) | _RF_RS(2), /* WDISP_30 */ - _RF_S|_RF_A|_RF_P| _RF_SZ(32) | _RF_RS(2), /* WDISP_22 */ - _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(10), /* HI22 */ - _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(0), /* 22 */ - _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(0), /* 13 */ - _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(0), /* LO10 */ - _RF_G| _RF_SZ(32) | _RF_RS(0), /* GOT10 */ - _RF_G| _RF_SZ(32) | _RF_RS(0), /* GOT13 */ - _RF_G| _RF_SZ(32) | _RF_RS(10), /* GOT22 */ - _RF_S|_RF_A|_RF_P| _RF_SZ(32) | _RF_RS(0), /* PC10 */ - _RF_S|_RF_A|_RF_P| _RF_SZ(32) | _RF_RS(10), /* PC22 */ - _RF_A|_RF_P| _RF_SZ(32) | _RF_RS(2), /* WPLT30 */ - _RF_SZ(32) | _RF_RS(0), /* COPY */ - _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(0), /* GLOB_DAT */ - _RF_SZ(32) | _RF_RS(0), /* JMP_SLOT */ - _RF_A| _RF_SZ(32) | _RF_RS(0), /* RELATIVE */ - _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(0), /* UA_32 */ - /*unknown*/ _RF_SZ(32) | _RF_RS(0), /* PLT32 */ - /*unknown*/ _RF_SZ(32) | _RF_RS(0), /* HIPLT22 */ - /*unknown*/ _RF_SZ(32) | _RF_RS(0), /* LOPLT10 */ - /*unknown*/ _RF_SZ(32) | _RF_RS(0), /* LOPLT10 */ - /*unknown*/ _RF_SZ(32) | _RF_RS(0), /* PCPLT22 */ - /*unknown*/ _RF_SZ(32) | _RF_RS(0), /* PCPLT32 */ - _RF_S|_RF_A|/*unknown*/ _RF_SZ(32) | _RF_RS(0), /* 10 */ - _RF_S|_RF_A|/*unknown*/ _RF_SZ(32) | _RF_RS(0), /* 11 */ - _RF_S|_RF_A|/*unknown*/ _RF_SZ(32) | _RF_RS(0), /* 64 */ - _RF_S|_RF_A|/*unknown*/ _RF_SZ(32) | _RF_RS(0), /* OLO10 */ - _RF_S|_RF_A|/*unknown*/ _RF_SZ(32) | _RF_RS(0), /* HH22 */ - _RF_S|_RF_A|/*unknown*/ _RF_SZ(32) | _RF_RS(0), /* HM10 */ - _RF_S|_RF_A|/*unknown*/ _RF_SZ(32) | _RF_RS(0), /* LM22 */ - _RF_S|_RF_A|_RF_P|/*unknown*/ _RF_SZ(32) | _RF_RS(0), /* WDISP16 */ - _RF_S|_RF_A|_RF_P|/*unknown*/ _RF_SZ(32) | _RF_RS(0), /* WDISP19 */ - /*unknown*/ _RF_SZ(32) | _RF_RS(0), /* GLOB_JMP */ - /*unknown*/ _RF_SZ(32) | _RF_RS(0), /* 7 */ - /*unknown*/ _RF_SZ(32) | _RF_RS(0), /* 5 */ - /*unknown*/ _RF_SZ(32) | _RF_RS(0), /* 6 */ -}; - -#define RELOC_RESOLVE_SYMBOL(t) ((reloc_target_flags[t] & _RF_S) != 0) -#define RELOC_PC_RELATIVE(t) ((reloc_target_flags[t] & _RF_P) != 0) -#define RELOC_TARGET_SIZE(t) ((reloc_target_flags[t] >> 8) & 0xff) -#define RELOC_VALUE_RIGHTSHIFT(t) (reloc_target_flags[t] & 0xff) - -static int reloc_target_bitmask[] = { -#define _BM(x) (~(-(1ULL << (x)))) - 0, /* NONE */ - _BM(8), _BM(16), _BM(32), /* RELOC_8, _16, _32 */ - _BM(8), _BM(16), _BM(32), /* DISP8, DISP16, DISP32 */ - _BM(30), _BM(22), /* WDISP30, WDISP22 */ - _BM(22), _BM(22), /* HI22, _22 */ - _BM(13), _BM(10), /* RELOC_13, _LO10 */ - _BM(10), _BM(13), _BM(22), /* GOT10, GOT13, GOT22 */ - _BM(10), _BM(22), /* _PC10, _PC22 */ - _BM(30), 0, /* _WPLT30, _COPY */ - -1, -1, _BM(22), /* _GLOB_DAT, JMP_SLOT, _RELATIVE */ - _BM(32), _BM(32), /* _UA32, PLT32 */ - _BM(22), _BM(10), /* _HIPLT22, LOPLT10 */ - _BM(32), _BM(22), _BM(10), /* _PCPLT32, _PCPLT22, _PCPLT10 */ - _BM(10), _BM(11), -1, /* _10, _11, _64 */ - _BM(10), _BM(22), /* _OLO10, _HH22 */ - _BM(10), _BM(22), /* _HM10, _LM22 */ - _BM(16), _BM(19), /* _WDISP16, _WDISP19 */ - -1, /* GLOB_JMP */ - _BM(7), _BM(5), _BM(6) /* _7, _5, _6 */ -#undef _BM -}; -#define RELOC_VALUE_BITMASK(t) (reloc_target_bitmask[t]) - -static int +#ifndef __sparc__ +int _rtld_relocate_nonplt_object( - const Obj_Entry *obj, - const Elf_RelA *rela) + const Obj_Entry * obj, + const Elf_RelA * rela, + bool dodebug) { - Elf_Addr *where = (Elf_Addr *) (obj->relocbase + rela->r_offset); - Elf_Word type, value, mask; + Elf_Addr *where = (Elf_Addr *)(obj->relocbase + rela->r_offset); + const Elf_Sym *def; + const Obj_Entry *defobj; + extern Elf_Addr _GLOBAL_OFFSET_TABLE_[]; + extern Elf_Dyn _DYNAMIC; + Elf_Addr tmp; - type = ELF_R_TYPE(rela->r_info); - if (type == R_TYPE(NONE)) - return (0); + switch (ELF_R_TYPE(rela->r_info)) { - /* - * We use the fact that relocation types are an `enum' - * Note: R_SPARC_6 is currently numerically largest. - */ - if (type > R_TYPE(6)) - return (-1); + case R_TYPE(NONE): + break; - value = rela->r_addend; - if (RELOC_RESOLVE_SYMBOL(type)) { - const Elf_Sym *def; - const Obj_Entry *defobj; +#ifdef __i386__ + case R_TYPE(GOT32): - /* Find the symbol */ - def = _rtld_find_symdef(_rtld_objlist, rela->r_info, - NULL, obj, &defobj, false); + def = _rtld_find_symdef(_rtld_objlist, rela->r_info, NULL, obj, + &defobj, false); if (def == NULL) - return (-1); + return -1; - /* Add in the symbol's absolute address */ - value += (Elf_Word)(defobj->relocbase + def->st_value); + tmp = (Elf_Addr)(defobj->relocbase + def->st_value); + if (*where != tmp) + *where = tmp; + rdbg(dodebug, "GOT32 %s in %s --> %p in %s", + defobj->strtab + def->st_name, obj->path, + (void *)*where, defobj->path); + break; + + case R_TYPE(PC32): + /* + * I don't think the dynamic linker should ever see this + * type of relocation. But the binutils-2.6 tools sometimes + * generate it. + */ + + def = _rtld_find_symdef(_rtld_objlist, rela->r_info, NULL, obj, + &defobj, false); + if (def == NULL) + return -1; + + *where += (Elf_Addr)(defobj->relocbase + def->st_value) - + (Elf_Addr)where; + rdbg(dodebug, "PC32 %s in %s --> %p in %s", + defobj->strtab + def->st_name, obj->path, + (void *)*where, defobj->path); + break; + + case R_TYPE(32): + def = _rtld_find_symdef(_rtld_objlist, rela->r_info, NULL, obj, + &defobj, false); + if (def == NULL) + return -1; + + *where += (Elf_Addr)(defobj->relocbase + def->st_value); + rdbg(dodebug, "32 %s in %s --> %p in %s", + defobj->strtab + def->st_name, obj->path, + (void *)*where, defobj->path); + break; +#endif /* __i386__ */ + +#ifdef __alpha__ + case R_TYPE(REFQUAD): + def = _rtld_find_symdef(_rtld_objlist, rela->r_info, NULL, obj, + &defobj, false); + if (def == NULL) + return -1; + + tmp = (Elf_Addr)(defobj->relocbase + def->st_value) + + *where + rela->r_addend; + if (*where != tmp_value) + *where = tmp_value; + rdbg(dodebug, "REFQUAD %s in %s --> %p in %s", + defobj->strtab + def->st_name, obj->path, + (void *)*where, defobj->path); + break; +#endif /* __alpha__ */ + +#if defined(__i386__) || defined(__alpha__) + case R_TYPE(GLOB_DAT): + def = _rtld_find_symdef(_rtld_objlist, rela->r_info, NULL, 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); + rdbg(dodebug, "GLOB_DAT %s in %s --> %p in %s", + defobj->strtab + def->st_name, obj->path, + (void *)*where, defobj->path); + break; + + case R_TYPE(RELATIVE): + if (obj != &_rtld_objself || + (caddr_t)where < (caddr_t)_GLOBAL_OFFSET_TABLE_ || + (caddr_t)where >= (caddr_t)&_DYNAMIC) { + *where += (Elf_Addr)obj->relocbase; + rdbg(dodebug, "RELATIVE in %s --> %p", obj->path, + (void *)*where); + } + else + rdbg(dodebug, "RELATIVE in %s stays at %p", + obj->path, (void *)*where); + break; + + case R_TYPE(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; + } + rdbg(dodebug, "COPY (avoid in main)"); + break; +#endif /* __i386__ || __alpha__ */ + +#ifdef __mips__ + case R_TYPE(REL32): + /* 32-bit PC-relative reference */ + def = obj->symtab + ELF_R_SYM(rela->r_info); + + if (ELF_SYM_BIND(def->st_info) == Elf_estb_local && + (ELF_SYM_TYPE(def->st_info) == Elf_estt_section || + ELF_SYM_TYPE(def->st_info) == Elf_estt_notype)) { + *where += (Elf_Addr)obj->relocbase; + rdbg(dodebug, "REL32 in %s --> %p", obj->path, + (void *)*where); + } else { + /* XXX maybe do something re: bootstrapping? */ + def = _rtld_find_symdef(_rtld_objlist, rela->r_info, + NULL, obj, &defobj, false); + if (def == NULL) + return -1; + *where += (Elf_Addr)(defobj->relocbase + def->st_value); + rdbg(dodebug, "REL32 %s in %s --> %p in %s", + defobj->strtab + def->st_name, obj->path, + (void *)*where, defobj->path); + } + break; + +#endif /* __mips__ */ + +#ifdef __powerpc__ + case R_TYPE(32): /* word32 S + A */ + case R_TYPE(GLOB_DAT): /* word32 S + A */ + def = _rtld_find_symdef(_rtld_objlist, rela->r_info, NULL, obj, + &defobj, false); + if (def == NULL) + return -1; + + tmp = (Elf_Addr)(defobj->relocbase + def->st_value + + rela->r_addend); + + if (*where != tmp) + *where = tmp; + rdbg(dodebug, "32/GLOB_DAT %s in %s --> %p in %s", + defobj->strtab + def->st_name, obj->path, + (void *)*where, defobj->path); + break; + + case R_TYPE(COPY): + rdbg(dodebug, "COPY"); + break; + + case R_TYPE(JMP_SLOT): + rdbg(dodebug, "JMP_SLOT"); + break; + + case R_TYPE(RELATIVE): /* word32 B + A */ + tmp = (Elf_Addr)(obj->relocbase + rela->r_addend); + if (obj == &_rtld_objself && *where == tmp; + break; /* GOT - already done */ + + *where = tmp; + rdbg(dodebug, "RELATIVE in %s --> %p", obj->path, + (void *)*where); + break; +#endif /* __powerpc__ */ + + default: + def = _rtld_find_symdef(_rtld_objlist, rela->r_info, NULL, obj, + &defobj, true); + rdbg(dodebug, "sym = %lu, type = %lu, offset = %p, " + "addend = %p, contents = %p, symbol = %s", + (u_long)ELF_R_SYM(rela->r_info), + (u_long)ELF_R_TYPE(rela->r_info), + (void *)rela->r_offset, (void *)rela->r_addend, + (void *)*where, + def ? defobj->strtab + def->st_name : "??"); + _rtld_error("%s: Unsupported relocation type %d" + "in non-PLT relocations\n", + obj->path, ELF_R_TYPE(rela->r_info)); + return -1; } - - if (RELOC_PC_RELATIVE(type)) { - value -= (Elf_Word)where; - } - - mask = RELOC_VALUE_BITMASK(type); - value >>= RELOC_VALUE_RIGHTSHIFT(type); - value &= mask; - - /* We ignore alignment restrictions here */ - *where &= ~mask; - *where |= value; - return (0); + return 0; } -static int -__rtld_relocate_plt_object( - const Obj_Entry *obj, - const Elf_RelA *rela, - bool bind_now, - caddr_t *addrp) -{ - const Elf_Sym *def; - const Obj_Entry *defobj; - Elf_Addr *where = (Elf_Addr *) (obj->relocbase + rela->r_offset); - Elf_Addr value; - if (bind_now == 0 && obj->pltgot != NULL) - return (0); + +int +_rtld_relocate_plt_object( + const Obj_Entry * obj, + const Elf_RelA * rela, + caddr_t *addrp, + bool bind_now, + bool dodebug) +{ + Elf_Addr *where = (Elf_Addr *)(obj->relocbase + rela->r_offset); + Elf_Addr new_value; /* Fully resolve procedure addresses now */ - assert(ELF_R_TYPE(rela->r_info) == R_TYPE(JMP_SLOT)); - - def = _rtld_find_symdef(_rtld_objlist, rela->r_info, - NULL, obj, &defobj, true); - if (def == NULL) - return (-1); - - value = (Elf_Addr) (defobj->relocbase + def->st_value); - -#ifdef RTLD_DEBUG_RELOC - dbg("bind now %d/fixup in %s --> old=%p new=%p", - (int)bind_now, - defobj->strtab + def->st_name, - (void *)*where, (void *)value); +#if defined(__powerpc__) + return _rtld_reloc_powerpc_plt(obj, rela, bind_now); #endif +#if defined(__alpha__) || defined(__i386__) + if (bind_now || obj->pltgot == NULL) { + const Elf_Sym *def; + const Obj_Entry *defobj; + + assert(ELF_R_TYPE(rela->r_info) == R_TYPE(JMP_SLOT)); + + def = _rtld_find_symdef(_rtld_objlist, rela->r_info, NULL, obj, + &defobj, true); + if (def == NULL) + return -1; + + new_value = (Elf_Addr)(defobj->relocbase + def->st_value); + rdbg(dodebug, "bind now %d/fixup in %s --> old=%p new=%p", + (int)bind_now, + defobj->strtab + def->st_name, + (void *)*where, (void *)new_value); + } else +#endif /* __alpha__ || __i386__ */ + if (!obj->mainprog) { + /* Just relocate the GOT slots pointing into the PLT */ + new_value = *where + (Elf_Addr)(obj->relocbase); + rdbg(dodebug, "fixup !main in %s --> %p", obj->path, + (void *)*where); + } else { + return 0; + } /* - * At the PLT entry pointed at by `where', we now construct - * a direct transfer to the now fully resolved function - * address. The resulting code in the jump slot is: - * - * sethi %hi(addr), %g1 - * jmp %g1+%lo(addr) - * nop ! delay slot - */ -#define SETHI 0x03000000 -#define JMP 0x81c06000 -#define NOP 0x01000000 - where[0] = SETHI | ((value >> 10) & 0x003fffff); - where[1] = JMP | (value & 0x000003ff); - where[2] = NOP; - + * Since this page is probably copy-on-write, let's not write + * it unless we really really have to. + */ + if (*where != new_value) + *where = new_value; if (addrp != NULL) - *addrp = (caddr_t)value; - - return (0); + *addrp = *(caddr_t *)(obj->relocbase + rela->r_offset); + return 0; } - -#define _rtld_relocate_plt_object(obj, rela, bind_now) \ - __rtld_relocate_plt_object(obj, rela, bind_now, NULL) +#endif /* __sparc__ */ caddr_t _rtld_bind( @@ -350,360 +416,26 @@ _rtld_bind( Elf_Word reloff) { const Elf_RelA *rela; - Elf_RelA ourrela; - caddr_t addr; + Elf_RelA ourrela; + caddr_t addr; if (obj->pltrel != NULL) { const Elf_Rel *rel; - rel = (const Elf_Rel *) ((caddr_t) obj->pltrel + reloff); + rel = (const Elf_Rel *)((caddr_t) obj->pltrel + reloff); ourrela.r_info = rel->r_info; ourrela.r_offset = rel->r_offset; rela = &ourrela; } else { - rela = (const Elf_RelA *) ((caddr_t) obj->pltrela + reloff); + rela = (const Elf_RelA *)((caddr_t) obj->pltrela + reloff); } - if (__rtld_relocate_plt_object(obj, rela, true, &addr) < 0) + if (_rtld_relocate_plt_object(obj, rela, &addr, true, true) < 0) _rtld_die(); - return (addr); - return *(caddr_t *)(obj->relocbase + rela->r_offset); + return addr; } -#else /* __sparc__ */ - -static int -_rtld_relocate_nonplt_object( - 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_TYPE(NONE): - break; - -#ifdef __i386__ - case R_TYPE(GOT32): { - const Elf_Sym *def; - const Obj_Entry *defobj; - - def = _rtld_find_symdef(_rtld_objlist, rela->r_info, NULL, 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); -#ifdef RTLD_DEBUG_RELOC - dbg("GOT32 %s in %s --> %p in %s", - defobj->strtab + def->st_name, obj->path, - (void *)*where, defobj->path); -#endif - break; - } - - case R_TYPE(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 = _rtld_find_symdef(_rtld_objlist, rela->r_info, NULL, obj, &defobj, false); - if (def == NULL) - return -1; - - *where += (Elf_Addr) (defobj->relocbase + def->st_value) - - (Elf_Addr) where; -#ifdef RTLD_DEBUG_RELOC - dbg("PC32 %s in %s --> %p in %s", - defobj->strtab + def->st_name, obj->path, - (void *)*where, defobj->path); -#endif - break; - } - - case R_TYPE(32): { - const Elf_Sym *def; - const Obj_Entry *defobj; - - def = _rtld_find_symdef(_rtld_objlist, rela->r_info, NULL, obj, &defobj, false); - if (def == NULL) - return -1; - - *where += (Elf_Addr)(defobj->relocbase + def->st_value); -#ifdef RTLD_DEBUG_RELOC - dbg("32 %s in %s --> %p in %s", - defobj->strtab + def->st_name, obj->path, - (void *)*where, defobj->path); -#endif - break; - } -#endif /* __i386__ */ - -#ifdef __alpha__ - case R_ALPHA_REFQUAD: { - const Elf_Sym *def; - const Obj_Entry *defobj; - Elf_Addr tmp_value; - - def = _rtld_find_symdef(_rtld_objlist, rela->r_info, NULL, 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; -#ifdef RTLD_DEBUG_RELOC - dbg("REFQUAD %s in %s --> %p in %s", - defobj->strtab + def->st_name, obj->path, - (void *)*where, defobj->path); -#endif - break; - } -#endif /* __alpha__ */ - -#if defined(__i386__) || defined(__alpha__) - case R_TYPE(GLOB_DAT): - { - const Elf_Sym *def; - const Obj_Entry *defobj; - - def = _rtld_find_symdef(_rtld_objlist, rela->r_info, NULL, 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); -#ifdef RTLD_DEBUG_RELOC - dbg("GLOB_DAT %s in %s --> %p in %s", - defobj->strtab + def->st_name, obj->path, - (void *)*where, defobj->path); -#endif - break; - } - - case R_TYPE(RELATIVE): { - extern Elf_Addr _GLOBAL_OFFSET_TABLE_[]; - extern Elf_Dyn _DYNAMIC; - - if (obj != &_rtld_objself || - (caddr_t)where < (caddr_t)_GLOBAL_OFFSET_TABLE_ || - (caddr_t)where >= (caddr_t)&_DYNAMIC) { - *where += (Elf_Addr) obj->relocbase; -#ifdef RTLD_DEBUG_RELOC - dbg("RELATIVE in %s --> %p", obj->path, (void *)*where); -#endif - } -#ifdef RTLD_DEBUG_RELOC - else - dbg("RELATIVE in %s stays at %p", obj->path, (void *)*where); -#endif - break; - } - - case R_TYPE(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; - } -#ifdef RTLD_DEBUG_RELOC - dbg("COPY (avoid in main)"); -#endif - break; - } -#endif /* __i386__ || __alpha__ */ - -#ifdef __mips__ - case R_TYPE(REL32): { - /* 32-bit PC-relative reference */ - - const Elf_Sym *def; - const Obj_Entry *defobj; - - def = obj->symtab + ELF_R_SYM(rela->r_info); - - if (ELF_SYM_BIND(def->st_info) == Elf_estb_local && - (ELF_SYM_TYPE(def->st_info) == Elf_estt_section || - ELF_SYM_TYPE(def->st_info) == Elf_estt_notype)) { - *where += (Elf_Addr) obj->relocbase; -#ifdef RTLD_DEBUG_RELOC - dbg("REL32 in %s --> %p", obj->path, (void *)*where); -#endif - } else { -/* XXX maybe do something re: bootstrapping? */ - def = _rtld_find_symdef(_rtld_objlist, rela->r_info, NULL, obj, - &defobj, false); - if (def == NULL) - return -1; - *where += (Elf_Addr)(defobj->relocbase + def->st_value); -#ifdef RTLD_DEBUG_RELOC - dbg("REL32 %s in %s --> %p in %s", - defobj->strtab + def->st_name, obj->path, - (void *)*where, defobj->path); -#endif - } - break; - } - -#endif /* mips */ - -#ifdef __powerpc__ - case R_TYPE(32): /* word32 S + A */ - case R_TYPE(GLOB_DAT): { /* word32 S + A */ - const Elf_Sym *def; - const Obj_Entry *defobj; - Elf_Addr x; - - def = _rtld_find_symdef(_rtld_objlist, rela->r_info, NULL, obj, &defobj, false); - if (def == NULL) - return -1; - - x = (Elf_Addr)(defobj->relocbase + def->st_value + rela->r_addend); - - if (*where != x) - *where = x; -#ifdef RTLD_DEBUG_RELOC - dbg("32/GLOB_DAT %s in %s --> %p in %s", - defobj->strtab + def->st_name, obj->path, - (void *)*where, defobj->path); -#endif - break; - } - - case R_TYPE(COPY): -#ifdef RTLD_DEBUG_RELOC - dbg("COPY"); -#endif - break; - - case R_TYPE(JMP_SLOT): -#ifdef RTLD_DEBUG_RELOC - dbg("JMP_SLOT"); -#endif - break; - - case R_TYPE(RELATIVE): { /* word32 B + A */ - if (obj == &_rtld_objself && - *where == (Elf_Addr)obj->relocbase + rela->r_addend) - break; /* GOT - already done */ - - *where = (Elf_Addr)obj->relocbase + rela->r_addend; -#ifdef RTLD_DEBUG_RELOC - dbg("RELATIVE in %s --> %p", obj->path, (void *)*where); -#endif - break; - } -#endif /* __powerpc__ */ - - default: { - const Elf_Sym *def; - const Obj_Entry *defobj; - - def = _rtld_find_symdef(_rtld_objlist, rela->r_info, NULL, obj, &defobj, true); - dbg("sym = %lu, type = %lu, offset = %p, addend = %p, contents = %p, symbol = %s", - (u_long)ELF_R_SYM(rela->r_info), (u_long)ELF_R_TYPE(rela->r_info), - (void *)rela->r_offset, (void *)rela->r_addend, (void *)*where, - def ? defobj->strtab + def->st_name : "??"); - _rtld_error("%s: Unsupported relocation type %d in non-PLT relocations\n", - obj->path, ELF_R_TYPE(rela->r_info)); - return -1; - } - } - return 0; -} - - - -static int -_rtld_relocate_plt_object( - const Obj_Entry *obj, - const Elf_RelA *rela, - bool bind_now) -{ - Elf_Addr *where = (Elf_Addr *) (obj->relocbase + rela->r_offset); - Elf_Addr new_value; - - /* Fully resolve procedure addresses now */ - -#if defined(__powerpc__) - return _rtld_reloc_powerpc_plt(obj, rela, bind_now); -#endif - -#if defined(__alpha__) || defined(__i386__) /* (jrs) */ - if (bind_now || obj->pltgot == NULL) { - const Elf_Sym *def; - const Obj_Entry *defobj; - - assert(ELF_R_TYPE(rela->r_info) == R_TYPE(JMP_SLOT)); - - def = _rtld_find_symdef(_rtld_objlist, rela->r_info, NULL, obj, &defobj, true); - if (def == NULL) - return -1; - - new_value = (Elf_Addr) (defobj->relocbase + def->st_value); -#ifdef RTLD_DEBUG_RELOC - dbg("bind now %d/fixup in %s --> old=%p new=%p", - (int)bind_now, - defobj->strtab + def->st_name, - (void *)*where, (void *)new_value); -#endif - } else -#endif /* __alpha__ (jrs) */ - if (!obj->mainprog) { - /* Just relocate the GOT slots pointing into the PLT */ - new_value = *where + (Elf_Addr) (obj->relocbase); -#ifdef RTLD_DEBUG_RELOC - dbg("fixup !main in %s --> %p", obj->path, (void *)*where); -#endif - } else { - return 0; - } - /* - * Since this page is probably copy-on-write, let's not write - * it unless we really really have to. - */ - if (*where != new_value) - *where = new_value; - return 0; -} - -caddr_t -_rtld_bind( - const Obj_Entry *obj, - Elf_Word reloff) -{ - const Elf_RelA *rela; - Elf_RelA ourrela; - - if (obj->pltrel != NULL) { - ourrela.r_info = ((const Elf_Rel *) ((caddr_t) obj->pltrel + reloff))->r_info; - ourrela.r_offset = ((const Elf_Rel *) ((caddr_t) obj->pltrel + reloff))->r_offset; - rela = &ourrela; - } else { - rela = (const Elf_RelA *) ((caddr_t) obj->pltrela + reloff); - } - - if (_rtld_relocate_plt_object(obj, rela, true) < 0) - _rtld_die(); - - return *(caddr_t *)(obj->relocbase + rela->r_offset); -} -#endif /* __sparc__ */ - /* * Relocate newly-loaded shared objects. The argument is a pointer to * the Obj_Entry for the first such object. All objects from the first @@ -712,148 +444,159 @@ _rtld_bind( */ int _rtld_relocate_objects( - Obj_Entry *first, - bool bind_now) + Obj_Entry * first, + bool bind_now, + bool dodebug) { - Obj_Entry *obj; - int ok = 1; + Obj_Entry *obj; + int ok = 1; - for (obj = first; obj != NULL; obj = obj->next) { + for (obj = first; obj != NULL; obj = obj->next) { + 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", obj->path); + return -1; + } + rdbg(dodebug, " relocating %s (%ld/%ld rel/rela, " + "%ld/%ld plt rel/rela)", + obj->path, + (long)(obj->rellim - obj->rel), + (long)(obj->relalim - obj->rela), + (long)(obj->pltrellim - obj->pltrel), + (long)(obj->pltrelalim - obj->pltrela)); - 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", - obj->path); - return -1; - } - - dbg(" relocating %s (%ld/%ld rel/rela, %ld/%ld plt rel/rela)", - obj->path, - (long)(obj->rellim - obj->rel), (long)(obj->relalim - obj->rela), - (long)(obj->pltrellim - obj->pltrel), - (long)(obj->pltrelalim - obj->pltrela)); - - if (obj->textrel) { - /* There are relocations to the write-protected text segment. */ - if (mprotect(obj->mapbase, obj->textsize, - PROT_READ|PROT_WRITE|PROT_EXEC) == -1) { - _rtld_error("%s: Cannot write-enable text segment: %s", - obj->path, xstrerror(errno)); - return -1; - } - } - - if (obj->rel != NULL) { - /* Process the non-PLT relocations. */ - const Elf_Rel *rel; - for (rel = obj->rel; rel < obj->rellim; ++rel) { - Elf_RelA ourrela; - ourrela.r_info = rel->r_info; - ourrela.r_offset = rel->r_offset; + if (obj->textrel) { + /* + * There are relocations to the write-protected text + * segment. + */ + if (mprotect(obj->mapbase, obj->textsize, + PROT_READ | PROT_WRITE | PROT_EXEC) == -1) { + _rtld_error("%s: Cannot write-enable text " + "segment: %s", obj->path, xstrerror(errno)); + return -1; + } + } + if (obj->rel != NULL) { + /* Process the non-PLT relocations. */ + const Elf_Rel *rel; + for (rel = obj->rel; rel < obj->rellim; ++rel) { + Elf_RelA ourrela; + ourrela.r_info = rel->r_info; + ourrela.r_offset = rel->r_offset; #if defined(__mips__) - /* rel->r_offset is not valid on mips? */ - if (ELF_R_TYPE(ourrela.r_info) == R_TYPE(NONE)) - ourrela.r_addend = 0; - else + /* rel->r_offset is not valid on mips? */ + if (ELF_R_TYPE(ourrela.r_info) == R_TYPE(NONE)) + ourrela.r_addend = 0; + else #endif - ourrela.r_addend = *(Elf_Word *) (obj->relocbase + rel->r_offset); + ourrela.r_addend = + *(Elf_Word *)(obj->relocbase + + rel->r_offset); - if (_rtld_relocate_nonplt_object(obj, &ourrela) < 0) - ok = 0; - } - } - - if (obj->rela != NULL) { - /* Process the non-PLT relocations. */ - const Elf_RelA *rela; - for (rela = obj->rela; rela < obj->relalim; ++rela) { - if (_rtld_relocate_nonplt_object(obj, rela) < 0) - ok = 0; - } - } - - if (obj->textrel) { /* Re-protected the text segment. */ - if (mprotect(obj->mapbase, obj->textsize, - PROT_READ|PROT_EXEC) == -1) { - _rtld_error("%s: Cannot write-protect text segment: %s", - obj->path, xstrerror(errno)); - return -1; - } - } - - /* Process the PLT relocations. */ - if (obj->pltrel != NULL) { - const Elf_Rel *rel; - for (rel = obj->pltrel; rel < obj->pltrellim; ++rel) { - Elf_RelA ourrela; - ourrela.r_info = rel->r_info; - ourrela.r_offset = rel->r_offset; - ourrela.r_addend = *(Elf_Word *) (obj->relocbase + rel->r_offset); - if (_rtld_relocate_plt_object(obj, &ourrela, bind_now) < 0) - ok = 0; - } - } - - if (obj->pltrela != NULL) { - const Elf_RelA *rela; - for (rela = obj->pltrela; rela < obj->pltrelalim; ++rela) { - if (_rtld_relocate_plt_object(obj, rela, bind_now) < 0) - ok = 0; - } - } - - if (!ok) - return -1; + if (_rtld_relocate_nonplt_object(obj, &ourrela, + dodebug) < 0) + ok = 0; + } + } + if (obj->rela != NULL) { + /* Process the non-PLT relocations. */ + const Elf_RelA *rela; + for (rela = obj->rela; rela < obj->relalim; ++rela) { + if (_rtld_relocate_nonplt_object(obj, rela, + dodebug) < 0) + ok = 0; + } + } + if (obj->textrel) { /* Re-protected the text segment. */ + if (mprotect(obj->mapbase, obj->textsize, + PROT_READ | PROT_EXEC) == -1) { + _rtld_error("%s: Cannot write-protect text " + "segment: %s", obj->path, xstrerror(errno)); + return -1; + } + } + /* Process the PLT relocations. */ + if (obj->pltrel != NULL) { + const Elf_Rel *rel; + for (rel = obj->pltrel; rel < obj->pltrellim; ++rel) { + Elf_RelA ourrela; + ourrela.r_info = rel->r_info; + ourrela.r_offset = rel->r_offset; + ourrela.r_addend = + *(Elf_Word *)(obj->relocbase + + rel->r_offset); + if (_rtld_relocate_plt_object(obj, &ourrela, + NULL, bind_now, dodebug) < 0) + ok = 0; + } + } + if (obj->pltrela != NULL) { + const Elf_RelA *rela; + for (rela = obj->pltrela; rela < obj->pltrelalim; + ++rela) { + if (_rtld_relocate_plt_object(obj, rela, + NULL, bind_now, dodebug) < 0) + ok = 0; + } + } + if (!ok) + return -1; - /* Set some sanity-checking numbers in the Obj_Entry. */ - obj->magic = RTLD_MAGIC; - obj->version = RTLD_VERSION; + /* Set some sanity-checking numbers in the Obj_Entry. */ + obj->magic = RTLD_MAGIC; + obj->version = RTLD_VERSION; - /* Fill in the dynamic linker entry points. */ - obj->dlopen = _rtld_dlopen; - obj->dlsym = _rtld_dlsym; - obj->dlerror = _rtld_dlerror; - obj->dlclose = _rtld_dlclose; + /* Fill in the dynamic linker entry points. */ + obj->dlopen = _rtld_dlopen; + obj->dlsym = _rtld_dlsym; + obj->dlerror = _rtld_dlerror; + obj->dlclose = _rtld_dlclose; - /* Set the special PLTGOT entries. */ - if (obj->pltgot != NULL) { + /* Set the special PLTGOT entries. */ + if (obj->pltgot != NULL) { #if defined(__i386__) - obj->pltgot[1] = (Elf_Addr) obj; - obj->pltgot[2] = (Elf_Addr) &_rtld_bind_start; + obj->pltgot[1] = (Elf_Addr) obj; + obj->pltgot[2] = (Elf_Addr) & _rtld_bind_start; #endif #if defined(__alpha__) - /* This function will be called to perform the relocation. */ - obj->pltgot[2] = (Elf_Addr) &_rtld_bind_start; - /* Identify this shared object */ - obj->pltgot[3] = (Elf_Addr) obj; + /* + * This function will be called to perform the + * relocation. + */ + obj->pltgot[2] = (Elf_Addr) & _rtld_bind_start; + /* Identify this shared object */ + obj->pltgot[3] = (Elf_Addr) obj; #endif #if defined(__mips__) - _rtld_relocate_mips_got(obj); + _rtld_relocate_mips_got(obj); - obj->pltgot[0] = (Elf_Addr) &_rtld_bind_start; - /* XXX only if obj->pltgot[1] & 0x80000000 ?? */ - obj->pltgot[1] |= (Elf_Addr) obj; + obj->pltgot[0] = (Elf_Addr) & _rtld_bind_start; + /* XXX only if obj->pltgot[1] & 0x80000000 ?? */ + obj->pltgot[1] |= (Elf_Addr) obj; #endif #if defined(__powerpc__) - _rtld_setup_powerpc_plt(obj); + _rtld_setup_powerpc_plt(obj); #endif #if defined(__sparc__) - /* - * PLTGOT is the PLT on the sparc. - * The first entry holds the call the dynamic linker. - * We construct a `call' instruction that transfers - * to `_rtld_bind_start()'. - * The second entry holds the object identification. - * Note: each PLT entry is three words long. - */ - obj->pltgot[1] = 0x40000000 | - ((Elf_Addr)&_rtld_bind_start - (Elf_Addr)&obj->pltgot[1]); - obj->pltgot[3] = (Elf_Addr) obj; + /* + * PLTGOT is the PLT on the sparc. + * The first entry holds the call the dynamic linker. + * We construct a `call' instruction that transfers + * to `_rtld_bind_start()'. + * The second entry holds the object identification. + * Note: each PLT entry is three words long. + */ + obj->pltgot[1] = 0x40000000 | + ((Elf_Addr)&_rtld_bind_start - + (Elf_Addr)&obj->pltgot[1]); + obj->pltgot[3] = (Elf_Addr) obj; #endif + } } - } - return 0; + return 0; } diff --git a/libexec/ld.elf_so/rtld.c b/libexec/ld.elf_so/rtld.c index 53d2231ff0d3..9aa36afefce7 100644 --- a/libexec/ld.elf_so/rtld.c +++ b/libexec/ld.elf_so/rtld.c @@ -1,4 +1,4 @@ -/* $NetBSD: rtld.c,v 1.12 1999/01/10 18:18:56 christos Exp $ */ +/* $NetBSD: rtld.c,v 1.13 1999/02/24 18:31:00 christos Exp $ */ /* * Copyright 1996 John D. Polstra. @@ -127,45 +127,62 @@ static void _rtld_init( caddr_t mapbase) { - _rtld_add_paths(&_rtld_paths, RTLD_DEFAULT_LIBRARY_PATH); + Obj_Entry objself; /* The dynamic linker shared object */ +#ifdef RTLD_RELOCATE_SELF + int dodebug = false; +#else + int dodebug = true; +#endif /* Conjure up an Obj_Entry structure for the dynamic linker. */ - - _rtld_objself.path = _rtld_path; - _rtld_objself.rtld = true; - _rtld_objself.mapbase = mapbase; -#if defined(__mips__) || defined(__i386__) + objself.path = NULL; + objself.rtld = true; + objself.mapbase = mapbase; +#if defined(__mips__) /* - * mips and i386 ld.so currently linked at load address, + * mips and ld.so currently linked at load address, * so no relocation needed */ - _rtld_objself.relocbase = 0; + objself.relocbase = 0; #else - _rtld_objself.relocbase = mapbase; + objself.relocbase = mapbase; #endif - _rtld_objself.pltgot = NULL; + objself.pltgot = NULL; #ifdef OLD_GOT - _rtld_objself.dynamic = (Elf_Dyn *) _GLOBAL_OFFSET_TABLE_[0]; + objself.dynamic = (Elf_Dyn *)_GLOBAL_OFFSET_TABLE_[0]; #else - _rtld_objself.dynamic = &_DYNAMIC; + objself.dynamic = (Elf_Dyn *)&_DYNAMIC; #endif - _rtld_digest_dynamic(&_rtld_objself); +#ifdef RTLD_RELOCATE_SELF + /* We have not been relocated yet, so fix the dynamic address */ + objself.dynamic = (Elf_Dyn *)((u_long)mapbase + (char *) objself.dynamic); +#endif /* RTLD_RELOCATE_SELF */ + + _rtld_digest_dynamic(&objself); #ifdef __alpha__ -/* XXX XXX XXX */ -_rtld_objself.pltgot = NULL; + /* XXX XXX XXX */ + objself.pltgot = NULL; #endif - assert(_rtld_objself.needed == NULL); + assert(objself.needed == NULL); #if !defined(__mips__) && !defined(__i386__) /* no relocation for mips/i386 */ - assert(!_rtld_objself.textrel); + assert(!objself.textrel); #endif + _rtld_relocate_objects(&objself, true, dodebug); + + /* + * Now that we relocated ourselves, we can use globals. + */ + _rtld_objself = objself; + + _rtld_objself.path = _rtld_path; + _rtld_add_paths(&_rtld_paths, RTLD_DEFAULT_LIBRARY_PATH, true); + /* Set up the _rtld_objlist pointer, so that rtld symbols can be found. */ _rtld_objlist = &_rtld_objself; - _rtld_relocate_objects(&_rtld_objself, true); - /* Make the object list empty again. */ _rtld_objlist = NULL; _rtld_objtail = &_rtld_objlist; @@ -217,7 +234,7 @@ _rtld( bool bind_now = 0; const char *ld_bind_now; const char **argv; -#ifdef RTLD_DEBUG +#if defined(RTLD_DEBUG) && !defined(RTLD_RELOCATE_SELF) int i = 0; #endif @@ -229,12 +246,12 @@ _rtld( */ /* Find the auxiliary vector on the stack. */ /* first Elf_Word reserved to address of exit routine */ -#ifdef RTLD_DEBUG - xprintf("sp = %p, argc = %d, argv = %p <%s>\n", sp, sp[2], +#if defined(RTLD_DEBUG) && !defined(RTLD_RELOCATE_SELF) + dbg("sp = %p, argc = %d, argv = %p <%s>\n", sp, sp[2], &sp[3], (char *)sp[3]); - xprintf("got is at %p, dynamic is at %p\n", _GLOBAL_OFFSET_TABLE_, &_DYNAMIC); + dbg("got is at %p, dynamic is at %p\n", _GLOBAL_OFFSET_TABLE_, &_DYNAMIC); debug = 1; - xprintf("_ctype_ is %p\n", _ctype_); + dbg("_ctype_ is %p\n", _ctype_); #endif sp += 2; /* skip over return argument space */ @@ -242,8 +259,8 @@ _rtld( sp += sp[0] + 2; /* Skip over argc, arguments, and NULL terminator */ env = (char **) sp; while (*sp++ != 0) { /* Skip over environment, and NULL terminator */ -#ifdef RTLD_DEBUG - xprintf("env[%d] = %p %s\n", i++, (void *)sp[-1], (char *)sp[-1]); +#if defined(RTLD_DEBUG) && !defined(RTLD_RELOCATE_SELF) + dbg("env[%d] = %p %s\n", i++, (void *)sp[-1], (char *)sp[-1]); #endif } aux = (const AuxInfo *) sp; @@ -273,7 +290,7 @@ _rtld( _rtld_init((caddr_t) pAUX_base->au_v); #ifdef RTLD_DEBUG - xprintf("_ctype_ is %p\n", _ctype_); + dbg("_ctype_ is %p\n", _ctype_); #endif __progname = _rtld_objself.path; @@ -290,7 +307,7 @@ _rtld( if (ld_debug != NULL && *ld_debug != '\0') debug = 1; #endif - _rtld_add_paths(&_rtld_paths, getenv("LD_LIBRARY_PATH")); + _rtld_add_paths(&_rtld_paths, getenv("LD_LIBRARY_PATH"), true); } dbg("%s is initialized, base address = %p", __progname, @@ -341,11 +358,11 @@ _rtld( _rtld_die(); dbg("relocating objects"); - if (_rtld_relocate_objects(_rtld_objmain, bind_now) == -1) + if (_rtld_relocate_objects(_rtld_objmain, bind_now, true) == -1) _rtld_die(); dbg("doing copy relocations"); - if (_rtld_do_copy_relocations(_rtld_objmain) == -1) + if (_rtld_do_copy_relocations(_rtld_objmain, true) == -1) _rtld_die(); dbg("calling _init functions"); @@ -482,7 +499,7 @@ _rtld_dlopen( } else { char *path = _rtld_find_library(name, NULL); if (path != NULL) - obj = _rtld_load_object(path); + obj = _rtld_load_object(path, true); } if (obj != NULL) { @@ -494,7 +511,8 @@ _rtld_dlopen( if (_rtld_load_needed_objects(obj) == -1) { --obj->dl_refcount; obj = NULL; - } else if (_rtld_relocate_objects(obj, (mode & 3) == RTLD_NOW) == -1) { + } else if (_rtld_relocate_objects(obj, (mode & 3) == RTLD_NOW, + true) == -1) { --obj->dl_refcount; obj = NULL; } else { diff --git a/libexec/ld.elf_so/rtld.h b/libexec/ld.elf_so/rtld.h index e69bc75df594..29f3903d2db8 100644 --- a/libexec/ld.elf_so/rtld.h +++ b/libexec/ld.elf_so/rtld.h @@ -1,4 +1,4 @@ -/* $NetBSD: rtld.h,v 1.6 1998/11/24 11:34:30 tsubai Exp $ */ +/* $NetBSD: rtld.h,v 1.7 1999/02/24 18:31:00 christos Exp $ */ /* * Copyright 1996 John D. Polstra. @@ -51,7 +51,11 @@ #define SVR4_LIBDIRLEN (sizeof SVR4_LIBDIR - 1) #ifndef PAGESIZE -#define PAGESIZE CLBYTES +# ifndef __sparc__ +# define PAGESIZE CLBYTES +# else +# define PAGESIZE 8192 /* NPBG is not constant! */ +# endif #endif #define round_down(x) ((x) & ~(PAGESIZE-1)) #define round_up(x) round_down((x) + PAGESIZE - 1) @@ -189,17 +193,21 @@ extern Obj_Entry *_rtld_digest_phdr(const Elf_Phdr *, int, caddr_t); /* load.c */ -extern Obj_Entry *_rtld_load_object(char *path); +extern Obj_Entry *_rtld_load_object(char *path, bool); extern int _rtld_load_needed_objects(Obj_Entry *); /* path.c */ -extern void _rtld_add_paths(Search_Path **, const char *); +extern void _rtld_add_paths(Search_Path **, const char *, bool); /* reloc.c */ -extern int _rtld_do_copy_relocations(const Obj_Entry *); +extern int _rtld_do_copy_relocations(const Obj_Entry *, bool); extern caddr_t _rtld_bind(const Obj_Entry *, Elf_Word); -extern int _rtld_relocate_objects(Obj_Entry *, bool); +extern int _rtld_relocate_objects(Obj_Entry *, bool, bool); +extern int _rtld_relocate_nonplt_object(const Obj_Entry *, const Elf_RelA *, + bool); +extern int _rtld_relocate_plt_object(const Obj_Entry *, const Elf_RelA *, + caddr_t *, bool, bool); /* search.c */