NetBSD re-synchronization of the source tree

This brings our tree to NetBSD 7.0, as found on -current on the
10-10-2015.

This updates:
 - LLVM to 3.6.1
 - GCC to GCC 5.1
 - Replace minix/commands/zdump with usr.bin/zdump
 - external/bsd/libelf has moved to /external/bsd/elftoolchain/
 - Import ctwm
 - Drop sprintf from libminc

Change-Id: I149836ac18e9326be9353958bab9b266efb056f0
This commit is contained in:
2015-10-15 17:01:16 +02:00
parent 8933525b85
commit 0a6a1f1d05
32425 changed files with 2998623 additions and 1342348 deletions

View File

@@ -0,0 +1,12 @@
# $NetBSD: Makefile.inc,v 1.1 2014/08/10 05:47:37 matt Exp $
SRCS+= rtld_start.S mdreloc.c
# XXX Should not be in CPPFLAGS!
CPPFLAGS+= -fpic
CPPFLAGS+= -DELFSIZE=64
CPPFLAGS+= -DHAVE_INITFINI_ARRAY
CPPFLAGS+= -DELF_NOTE_MARCH_DESC=\"${LDELFSO_MACHINE_ARCH}\"
LDFLAGS+= -Wl,-e,_rtld_start

View File

@@ -0,0 +1,269 @@
/* $NetBSD: mdreloc.c,v 1.2 2014/08/25 20:40:52 joerg Exp $ */
/*-
* Copyright (c) 2014 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Matt Thomas of 3am Software Foundry.
*
* 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``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 FOUNDATION OR CONTRIBUTORS
* 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 <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: mdreloc.c,v 1.2 2014/08/25 20:40:52 joerg Exp $");
#endif /* not lint */
#include <sys/types.h>
#include <string.h>
#include "debug.h"
#include "rtld.h"
void _rtld_bind_start(void);
void _rtld_relocate_nonplt_self(Elf_Dyn *, Elf_Addr);
caddr_t _rtld_bind(const Obj_Entry *, Elf_Word);
void
_rtld_setup_pltgot(const Obj_Entry *obj)
{
obj->pltgot[1] = (Elf_Addr) obj;
obj->pltgot[2] = (Elf_Addr) &_rtld_bind_start;
}
void
_rtld_relocate_nonplt_self(Elf_Dyn *dynp, Elf_Addr relocbase)
{
const Elf_Rel *rel = 0, *rellim;
Elf_Addr relsz = 0;
Elf_Addr *where;
for (; dynp->d_tag != DT_NULL; dynp++) {
switch (dynp->d_tag) {
case DT_REL:
rel = (const Elf_Rel *)(relocbase + dynp->d_un.d_ptr);
break;
case DT_RELSZ:
relsz = dynp->d_un.d_val;
break;
}
}
rellim = (const Elf_Rel *)((const uint8_t *)rel + relsz);
for (; rel < rellim; rel++) {
where = (Elf_Addr *)(relocbase + rel->r_offset);
*where += (Elf_Addr)relocbase;
}
}
int
_rtld_relocate_nonplt_objects(Obj_Entry *obj)
{
for (const Elf_Rela *rela = obj->rela; rela < obj->relalim; rela++) {
Elf_Addr *where;
const Elf_Sym *def;
const Obj_Entry *defobj;
unsigned long symnum;
Elf_Addr addend;
where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
symnum = ELF_R_SYM(rela->r_info);
addend = rela->r_addend;
switch (ELF_R_TYPE(rela->r_info)) {
case R_TYPE(NONE):
break;
case R_TYPE(ABS64): /* word B + S + A */
case R_TYPE(GLOB_DAT): /* word B + S */
def = _rtld_find_symdef(symnum, obj, &defobj, false);
if (def == NULL)
return -1;
*where = addend + (Elf_Addr)defobj->relocbase +
def->st_value;
rdbg(("ABS64/GLOB_DAT %s in %s --> %p @ %p in %s",
obj->strtab + obj->symtab[symnum].st_name,
obj->path, (void *)tmp, where, defobj->path));
break;
case R_TYPE(RELATIVE): /* word B + A */
*where = addend + (Elf_Addr)obj->relocbase;
rdbg(("RELATIVE in %s --> %p", obj->path,
(void *)tmp));
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->isdynamic) {
_rtld_error(
"%s: Unexpected R_COPY relocation in shared library",
obj->path);
return -1;
}
rdbg(("COPY (avoid in main)"));
break;
case R_TLS_TYPE(TLS_DTPREL):
def = _rtld_find_symdef(symnum, obj, &defobj, false);
if (def == NULL)
return -1;
*where = addend + (Elf_Addr)(def->st_value);
rdbg(("TLS_DTPOFF32 %s in %s --> %p",
obj->strtab + obj->symtab[symnum].st_name,
obj->path, (void *)tmp));
break;
case R_TLS_TYPE(TLS_DTPMOD):
def = _rtld_find_symdef(symnum, obj, &defobj, false);
if (def == NULL)
return -1;
*where = (Elf_Addr)(defobj->tlsindex);
rdbg(("TLS_DTPMOD %s in %s --> %p",
obj->strtab + obj->symtab[symnum].st_name,
obj->path, (void *)tmp));
break;
case R_TLS_TYPE(TLS_TPREL):
def = _rtld_find_symdef(symnum, obj, &defobj, false);
if (def == NULL)
return -1;
if (!defobj->tls_done &&
_rtld_tls_offset_allocate(obj))
return -1;
*where = (Elf_Addr)def->st_value + defobj->tlsoffset +
sizeof(struct tls_tcb);
rdbg(("TLS_TPOFF32 %s in %s --> %p",
obj->strtab + obj->symtab[symnum].st_name,
obj->path, (void *)tmp));
break;
default:
rdbg(("sym = %lu, type = %lu, offset = %p, "
"contents = %p, symbol = %s",
symnum, (u_long)ELF_R_TYPE(rela->r_info),
(void *)rela->r_offset, *where,
obj->strtab + obj->symtab[symnum].st_name));
_rtld_error("%s: Unsupported relocation type %ld "
"in non-PLT relocations",
obj->path, (u_long) ELF_R_TYPE(rela->r_info));
return -1;
}
}
return 0;
}
int
_rtld_relocate_plt_lazy(const Obj_Entry *obj)
{
if (!obj->relocbase)
return 0;
for (const Elf_Rel *rel = obj->pltrel; rel < obj->pltrellim; rel++) {
Elf_Addr *where = (Elf_Addr *)(obj->relocbase + rel->r_offset);
assert(ELF_R_TYPE(rel->r_info) == R_TYPE(JUMP_SLOT));
/* Just relocate the GOT slots pointing into the PLT */
*where += (Elf_Addr)obj->relocbase;
rdbg(("fixup !main in %s --> %p", obj->path, (void *)*where));
}
return 0;
}
static int
_rtld_relocate_plt_object(const Obj_Entry *obj, const Elf_Rel *rel,
Elf_Addr *tp)
{
Elf_Addr *where = (Elf_Addr *)(obj->relocbase + rel->r_offset);
Elf_Addr new_value;
const Elf_Sym *def;
const Obj_Entry *defobj;
unsigned long info = rel->r_info;
assert(ELF_R_TYPE(info) == R_TYPE(JUMP_SLOT));
def = _rtld_find_plt_symdef(ELF_R_SYM(info), obj, &defobj, tp != NULL);
if (__predict_false(def == NULL))
return -1;
if (__predict_false(def == &_rtld_sym_zero))
return 0;
if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC) {
if (tp == NULL)
return 0;
new_value = _rtld_resolve_ifunc(defobj, def);
} else {
new_value = (Elf_Addr)(defobj->relocbase + def->st_value);
}
rdbg(("bind now/fixup in %s --> old=%p new=%p",
defobj->strtab + def->st_name, (void *)*where, (void *)new_value));
if (*where != new_value)
*where = new_value;
if (tp)
*tp = new_value;
return 0;
}
caddr_t
_rtld_bind(const Obj_Entry *obj, Elf_Word reloff)
{
const Elf_Rel *rel = obj->pltrel + reloff;
Elf_Addr new_value = 0; /* XXX gcc */
_rtld_shared_enter();
int err = _rtld_relocate_plt_object(obj, rel, &new_value);
if (err)
_rtld_die();
_rtld_shared_exit();
return (caddr_t)new_value;
}
int
_rtld_relocate_plt_objects(const Obj_Entry *obj)
{
const Elf_Rel *rel;
int err = 0;
for (rel = obj->pltrel; rel < obj->pltrellim; rel++) {
err = _rtld_relocate_plt_object(obj, rel, NULL);
if (err)
break;
}
return err;
}

View File

@@ -0,0 +1,108 @@
/* $NetBSD: rtld_start.S,v 1.1 2014/08/10 05:47:37 matt Exp $ */
/*-
* Copyright (c) 2014 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Matt Thomas of 3am Software Foundry.
*
* 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``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 FOUNDATION OR CONTRIBUTORS
* 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>
RCSID("$NetBSD: rtld_start.S,v 1.1 2014/08/10 05:47:37 matt Exp $")
/*
* void _rtld_start(void (*cleanup)(void), const Obj_Entry *obj,
* struct ps_strings *ps_strings);
*
* X0 = NULL
* X1 = NULL
* X2 = ps_strings
* X30 (LR) = 0
* X29 (FP) = 0
*/
ENTRY_NP(_rtld_start)
mov x24, x2 /* save ps_strings */
#if 1
adrp x1, _PROCEDURE_LINKAGE_TABLE_ /* load _DYNAMIC offset from GOT */
ldr x1, [x1, #:got_lo12:_PROCEDURE_LINKAGE_TABLE_]
#else
adrp x1, :got:_DYNAMIC /* load _DYNAMIC offset from GOT */
ldr x1, [x1, #:got_lo12:_DYNAMIC]
#endif
adrp x0, _DYNAMIC /* get &_DYNAMIC */
add x0, x0, #:lo12:_DYNAMIC
sub x25, x0, x1 /* relocbase = &_DYNAMIC - GOT:_DYNAMIC */
mov x1, x25 /* pass as 2nd argument */
bl _rtld_relocate_nonplt_self
sub sp, sp, #16 /* reserve space for returns */
mov x0, sp /* pointer to reserved space */
mov x1, x25 /* pass relocbase */
bl _rtld
mov x17, x0 /* save entry point */
ldp x0, x1, [sp], #16 /* pop cleanup & obj_main */
mov x2, x24 /* restore ps_strings */
br x17 /* call saved entry point */
END(_rtld_start)
/*
* Upon entry from plt0 entry:
* X17 = &PLTGOT[n]
* X16 = &PLTGOT[2]
*/
ENTRY_NP(_rtld_bind_start)
sub sp, sp, #96 /* reserve stack space */
stp x29, x30, [sp, #80] /* save FP & LR */
add x29, sp, #80 /* get new FP */
str x24, [sp, #64] /* save caller-saved register */
stp x6, x7, [sp, #48] /* save arguments */
stp x4, x5, [sp, #32] /* save arguments */
stp x2, x3, [sp, #16] /* save arguments */
stp x0, x1, [sp, #0] /* save arguments */
sub x16, x16, #16 /* adjust to &PLTGOT[0] */
mov x24, x17 /* preserve across _rtld_bind */
sub x1, x17, x16 /* x1 = &PLTGOT[N] - &PLTGOT[2] */
lsr x1, x1, #3 /* x1 = N - 2 */
ldr x0, [x16, #8] /* get obj ptr from &PLTGOT[1] */
bl _rtld_bind
str x0, [x24] /* save address in PLTGOT[N] */
mov x17, x0 /* save address */
ldp x0, x1, [sp, #0] /* restore arguments */
ldp x2, x3, [sp, #16] /* restore arguments */
ldp x4, x5, [sp, #32] /* restore arguments */
ldp x6, x7, [sp, #48] /* restore arguments */
ldr x24, [sp, #64] /* save caller-saved register */
ldp x29, x30, [sp, #80] /* restore FP & LR */
add sp, sp, #96 /* reclaim stack */
br x17 /* call bound function */
END(_rtld_bind_start)

View File

@@ -1,4 +1,4 @@
/* $NetBSD: alpha_reloc.c,v 1.40 2011/03/31 15:30:31 skrll Exp $ */
/* $NetBSD: alpha_reloc.c,v 1.41 2014/08/25 20:40:52 joerg Exp $ */
/*
* Copyright (c) 2001 Wasabi Systems, Inc.
@@ -62,7 +62,7 @@
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: alpha_reloc.c,v 1.40 2011/03/31 15:30:31 skrll Exp $");
__RCSID("$NetBSD: alpha_reloc.c,v 1.41 2014/08/25 20:40:52 joerg Exp $");
#endif /* not lint */
#include <sys/types.h>
@@ -376,7 +376,13 @@ _rtld_relocate_plt_object(const Obj_Entry *obj, const Elf_Rela *rela,
if (__predict_false(def == &_rtld_sym_zero))
return 0;
new_value = (Elf_Addr)(defobj->relocbase + def->st_value);
if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC) {
if (tp == NULL)
return 0;
new_value = _rtld_resolve_ifunc(defobj, def);
} else {
new_value = (Elf_Addr)(defobj->relocbase + def->st_value);
}
rdbg(("bind now/fixup in %s --> old=%p new=%p",
defobj->strtab + def->st_name, (void *)*where, (void *)new_value));

View File

@@ -29,12 +29,14 @@
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: find_exidx.c,v 1.3 2013/05/03 10:27:06 skrll Exp $");
__RCSID("$NetBSD: find_exidx.c,v 1.4 2014/08/10 23:35:27 matt Exp $");
#endif /* not lint */
#include "debug.h"
#include "rtld.h"
#if defined(__ARM_EABI__) && !defined(__ARM_DWARF_EH__)
_Unwind_Ptr
__gnu_Unwind_Find_exidx(_Unwind_Ptr pc, int * pcount)
{
@@ -84,3 +86,5 @@ __gnu_Unwind_Find_exidx(_Unwind_Ptr pc, int * pcount)
*pcount = count;
return start;
}
#endif

View File

@@ -1,8 +1,8 @@
/* $NetBSD: mdreloc.c,v 1.37 2011/11/18 16:10:03 joerg Exp $ */
/* $NetBSD: mdreloc.c,v 1.38 2014/08/25 20:40:52 joerg Exp $ */
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: mdreloc.c,v 1.37 2011/11/18 16:10:03 joerg Exp $");
__RCSID("$NetBSD: mdreloc.c,v 1.38 2014/08/25 20:40:52 joerg Exp $");
#endif /* not lint */
#include <sys/types.h>
@@ -179,7 +179,7 @@ _rtld_relocate_nonplt_objects(Obj_Entry *obj)
rdbg(("COPY (avoid in main)"));
break;
#if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II)
#if defined(__minix) && defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II)
case R_TYPE(TLS_DTPOFF32):
def = _rtld_find_symdef(symnum, obj, &defobj, false);
if (def == NULL)
@@ -232,7 +232,7 @@ _rtld_relocate_nonplt_objects(Obj_Entry *obj)
obj->strtab + obj->symtab[symnum].st_name,
obj->path, (void *)tmp));
break;
#endif
#endif /* defined(__minix) && defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II) */
default:
rdbg(("sym = %lu, type = %lu, offset = %p, "
@@ -288,7 +288,13 @@ _rtld_relocate_plt_object(const Obj_Entry *obj, const Elf_Rel *rel,
if (__predict_false(def == &_rtld_sym_zero))
return 0;
new_value = (Elf_Addr)(defobj->relocbase + def->st_value);
if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC) {
if (tp == NULL)
return 0;
new_value = _rtld_resolve_ifunc(defobj, def);
} else {
new_value = (Elf_Addr)(defobj->relocbase + def->st_value);
}
/* Set the Thumb bit, if needed. */
if (ELF_ST_TYPE(def->st_info) == STT_ARM_TFUNC)
new_value |= 1;

View File

@@ -1,4 +1,4 @@
/* $NetBSD: rtld_start.S,v 1.11 2012/08/13 02:53:25 matt Exp $ */
/* $NetBSD: rtld_start.S,v 1.12 2013/12/03 00:19:56 matt Exp $ */
/*-
* Copyright (c) 1998, 2002 The NetBSD Foundation, Inc.
@@ -31,55 +31,51 @@
#include <machine/asm.h>
RCSID("$NetBSD: rtld_start.S,v 1.11 2012/08/13 02:53:25 matt Exp $")
RCSID("$NetBSD: rtld_start.S,v 1.12 2013/12/03 00:19:56 matt Exp $")
.text
.align 0
.globl _rtld_start
.type _rtld_start,%function
_rtld_start:
ENTRY_NP(_rtld_start)
sub sp, sp, #8 /* make room for obj_main & exit proc */
mov r4, r0 /* save ps_strings */
movs r4, r0 /* save ps_strings */
ldr sl, .L2
ldr r5, .L2+4
ldr r0, .L2+8
.L1:
add sl, pc, sl
ldr r5, [sl, r5]
ldr r0, [sl, r0]
sub r1, sl, r5 /* relocbase */
add r0, r1, r0 /* &_DYNAMIC */
ldr r6, .Lgot
ldr r5, .Ldynamic
add r6, r6, pc /* r6 = &GOT[0]; pc = &LPIC1; */
adds r0, r6, r5 /* arg0 = &_DYNAMIC */
.LPIC1:
ldr r5, [r6] /* GOT[0] = &_DYNAMIC */
subs r5, r0, r5 /* relocbase = GOT[0] - &_DYNAMIC */
movs r1, r5 /* arg1 = relocabase */
bl _rtld_relocate_nonplt_self
sub r1, sl, r5 /* relocbase */
movs r1, r5 /* relocbase */
mov r0, sp /* sp */
bl _rtld /* call the shared loader */
mov r3, r0 /* save entry point */
movs r3, r0 /* save entry point */
#ifdef __thumb__
ldr r2, [sp, #0] /* pop r2 = cleanup */
ldr r1, [sp, #4] /* pop r1 = obj_main */
add sp, sp, #8
#else
ldr r2, [sp], #4 /* pop r2 = cleanup */
ldr r1, [sp], #4 /* pop r1 = obj_main */
mov r0, r4 /* restore ps_strings */
#ifdef _ARM_ARCH_4T
bx r3 /* jump to the entry point */
#else
mov pc, r3 /* jump to the entry point */
#endif
.L2:
.word _GLOBAL_OFFSET_TABLE_ - (.L1+8)
.word _GLOBAL_OFFSET_TABLE_(GOT)
.word _DYNAMIC(GOT)
movs r0, r4 /* restore ps_strings */
RETr(r3)
.align 0
.globl _rtld_bind_start
.type _rtld_bind_start,%function
.Lgot:
.word _GLOBAL_OFFSET_TABLE_ - .LPIC1
.Ldynamic:
.word _DYNAMIC(GOTOFF)
END(_rtld_start)
/*
* stack[0] = RA
* ip = &GOT[n+3]
* lr = &GOT[2]
*/
_rtld_bind_start:
ARM_ENTRY_NP(_rtld_bind_start)
stmdb sp!,{r0-r4,sl,fp} /* 8 byte aligned (lr already saved) */
sub r1, ip, lr /* r1 = 4 * (n + 1) */
@@ -95,9 +91,5 @@ _rtld_bind_start:
mov ip, r0 /* save new address */
ldmia sp!,{r0-r4,sl,fp,lr} /* restore the stack */
#ifdef _ARM_ARCH_4T
bx ip /* jump to the new address */
#else
mov pc, ip /* jump to the new address */
#endif
RETr(ip) /* jump to the new address */
END(_rtld_bind_start)

View File

@@ -1,4 +1,4 @@
/* $NetBSD: hppa_reloc.c,v 1.42 2012/01/06 10:38:57 skrll Exp $ */
/* $NetBSD: hppa_reloc.c,v 1.43 2014/08/25 20:40:52 joerg Exp $ */
/*-
* Copyright (c) 2002, 2004 The NetBSD Foundation, Inc.
@@ -31,7 +31,7 @@
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: hppa_reloc.c,v 1.42 2012/01/06 10:38:57 skrll Exp $");
__RCSID("$NetBSD: hppa_reloc.c,v 1.43 2014/08/25 20:40:52 joerg Exp $");
#endif /* not lint */
#include <stdlib.h>
@@ -656,9 +656,19 @@ _rtld_relocate_plt_object(const Obj_Entry *obj, const Elf_Rela *rela,
if (__predict_false(def == &_rtld_sym_zero))
return 0;
func_pc = (Elf_Addr)(defobj->relocbase + def->st_value +
rela->r_addend);
func_sl = (Elf_Addr)(defobj->pltgot);
if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC) {
if (tp == NULL)
return 0;
Elf_Addr ptr = _rtld_resolve_ifunc(defobj, def);
assert(RTLD_IS_PLABEL(ptr));
hppa_plabel *label = RTLD_GET_PLABEL(ptr);
func_pc = label->hppa_plabel_pc;
func_sl = label->hppa_plabel_sl;
} else {
func_pc = (Elf_Addr)(defobj->relocbase + def->st_value +
rela->r_addend);
func_sl = (Elf_Addr)(defobj->pltgot);
}
rdbg(("bind now/fixup in %s --> old=(%p,%p) new=(%p,%p)",
defobj->strtab + def->st_name,
@@ -710,3 +720,29 @@ _rtld_relocate_plt_objects(const Obj_Entry *obj)
}
return 0;
}
void
_rtld_call_function_void(const Obj_Entry *obj, Elf_Addr ptr)
{
volatile hppa_plabel plabel;
void (*f)(void);
plabel.hppa_plabel_pc = (Elf_Addr)ptr;
plabel.hppa_plabel_sl = (Elf_Addr)(obj->pltgot);
f = (void (*)(void))RTLD_MAKE_PLABEL(&plabel);
f();
}
Elf_Addr
_rtld_call_function_addr(const Obj_Entry *obj, Elf_Addr ptr)
{
volatile hppa_plabel plabel;
Elf_Addr (*f)(void);
plabel.hppa_plabel_pc = (Elf_Addr)ptr;
plabel.hppa_plabel_sl = (Elf_Addr)(obj->pltgot);
f = (Elf_Addr (*)(void))RTLD_MAKE_PLABEL(&plabel);
return f();
}

View File

@@ -1,8 +1,8 @@
/* $NetBSD: mdreloc.c,v 1.35 2012/11/07 07:24:46 apb Exp $ */
/* $NetBSD: mdreloc.c,v 1.37 2014/08/31 20:06:22 joerg Exp $ */
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: mdreloc.c,v 1.35 2012/11/07 07:24:46 apb Exp $");
__RCSID("$NetBSD: mdreloc.c,v 1.37 2014/08/31 20:06:22 joerg Exp $");
#endif /* not lint */
#include <sys/types.h>
@@ -120,7 +120,7 @@ _rtld_relocate_nonplt_objects(Obj_Entry *obj)
rdbg(("COPY (avoid in main)"));
break;
#if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II)
#if defined(__minix) && defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II)
case R_TYPE(TLS_TPOFF):
def = _rtld_find_symdef(symnum, obj, &defobj, false);
if (def == NULL)
@@ -176,7 +176,7 @@ _rtld_relocate_nonplt_objects(Obj_Entry *obj)
obj->path, (void *)*where));
break;
#endif
#endif /* defined(__minix) && defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II) */
default:
rdbg(("sym = %lu, type = %lu, offset = %p, "
@@ -232,7 +232,14 @@ _rtld_relocate_plt_object(const Obj_Entry *obj, const Elf_Rel *rel,
if (__predict_false(def == &_rtld_sym_zero))
return 0;
target = (Elf_Addr)(defobj->relocbase + def->st_value);
if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC) {
if (tp == NULL)
return 0;
target = _rtld_resolve_ifunc(defobj, def);
} else {
target = (Elf_Addr)(defobj->relocbase + def->st_value);
}
rdbg(("bind now/fixup in %s --> old=%p new=%p",
defobj->strtab + def->st_name, (void *)*where,
(void *)target));
@@ -276,7 +283,7 @@ _rtld_relocate_plt_objects(const Obj_Entry *obj)
return err;
}
#if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II)
#if defined(__minix) && defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II)
/*
* i386 specific GNU variant of __tls_get_addr using register based
* argument passing.
@@ -298,4 +305,4 @@ ___tls_get_addr(void *arg_)
return _rtld_tls_get_addr(tcb, idx, offset);
}
#endif
#endif /* defined(__minix) && defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II) */

View File

@@ -1,13 +1,13 @@
/* $NetBSD: mdreloc.c,v 1.29 2011/11/22 15:25:28 joerg Exp $ */
/* $NetBSD: mdreloc.c,v 1.30 2014/08/25 20:40:52 joerg Exp $ */
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: mdreloc.c,v 1.29 2011/11/22 15:25:28 joerg Exp $");
__RCSID("$NetBSD: mdreloc.c,v 1.30 2014/08/25 20:40:52 joerg Exp $");
#endif /* not lint */
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: mdreloc.c,v 1.29 2011/11/22 15:25:28 joerg Exp $");
__RCSID("$NetBSD: mdreloc.c,v 1.30 2014/08/25 20:40:52 joerg Exp $");
#endif /* not lint */
#include <sys/types.h>
@@ -223,8 +223,14 @@ _rtld_relocate_plt_object(const Obj_Entry *obj, const Elf_Rela *rela,
return 0;
assert(rela->r_addend == 0);
new_value = (Elf_Addr)(defobj->relocbase + def->st_value +
rela->r_addend);
if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC) {
if (tp == NULL)
return 0;
new_value = _rtld_resolve_ifunc(defobj, def);
} else {
new_value = (Elf_Addr)(defobj->relocbase + def->st_value +
rela->r_addend);
}
rdbg(("bind now/fixup in %s --> old=%p new=%p",
defobj->strtab + def->st_name, (void *)*where, (void *)new_value));
if (*where != new_value)

View File

@@ -1,4 +1,4 @@
/* $NetBSD: rtld_start.S,v 1.10 2013/07/18 21:57:42 matt Exp $ */
/* $NetBSD: rtld_start.S,v 1.11 2014/03/18 18:20:38 riastradh Exp $ */
/*-
* Copyright (c) 1999, 2002, 2003 The NetBSD Foundation, Inc.

View File

@@ -1,4 +1,4 @@
/* $NetBSD: mips_reloc.c,v 1.62 2011/03/25 18:07:05 joerg Exp $ */
/* $NetBSD: mips_reloc.c,v 1.63 2014/08/25 20:40:52 joerg Exp $ */
/*
* Copyright 1997 Michael L. Hitch <mhitch@montana.edu>
@@ -30,7 +30,7 @@
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: mips_reloc.c,v 1.62 2011/03/25 18:07:05 joerg Exp $");
__RCSID("$NetBSD: mips_reloc.c,v 1.63 2014/08/25 20:40:52 joerg Exp $");
#endif /* not lint */
#include <sys/types.h>
@@ -487,7 +487,13 @@ _rtld_relocate_plt_object(const Obj_Entry *obj, Elf_Word sym, Elf_Addr *tp)
if (__predict_false(def == &_rtld_sym_zero))
return 0;
new_value = (Elf_Addr)(defobj->relocbase + def->st_value);
if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC) {
if (tp == NULL)
return 0;
new_value = _rtld_resolve_ifunc(defobj, def);
} else {
new_value = (Elf_Addr)(defobj->relocbase + def->st_value);
}
rdbg(("bind now/fixup in %s --> new=%p",
defobj->strtab + def->st_name, (void *)new_value));
got[obj->local_gotno + sym - obj->gotsym] = new_value;

View File

@@ -0,0 +1,10 @@
# $NetBSD: Makefile.inc,v 1.1 2014/09/03 19:34:26 matt Exp $
SRCS+= mdreloc.c
LDFLAGS+= -Wl,-e,_rtld_start
CPPFLAGS+= -fPIC
SRCS+= rtld_start.S
CPPFLAGS+= -DELFSIZE=32
#LDFLAGS+= -Wl,--script,${.CURDIR}/arch/powerpc/ld.so.script

View File

@@ -0,0 +1,293 @@
/* $NetBSD: mdreloc.c,v 1.1 2014/09/03 19:34:26 matt Exp $ */
/*-
* Copyright (c) 2014 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Matt Thomas of 3am Software Foundry.
*
* 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``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 FOUNDATION OR CONTRIBUTORS
* 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 <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: mdreloc.c,v 1.1 2014/09/03 19:34:26 matt Exp $");
#endif /* not lint */
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <machine/cpu.h>
#include "debug.h"
#include "rtld.h"
void _rtld_bind_start(void);
Elf_Addr _rtld_bind(const Obj_Entry *, Elf_Word);
void _rtld_relocate_nonplt_self(Elf_Dyn *, Elf_Addr);
static int _rtld_relocate_plt_object(const Obj_Entry *,
const Elf_Rela *, int, Elf_Addr *);
/*
* The OR1k PLT format is simple.
*/
void
_rtld_setup_pltgot(const Obj_Entry *obj)
{
obj->pltgot[1] = (Elf_Addr) obj;
obj->pltgot[2] = (Elf_Addr) _rtld_bind_start;
dbg(("obj %s plt pltgot=%p start=%p obj=%p",
obj->path, obj->pltgot,
(void *) obj->pltgot[1], (void *) obj->pltgot[2]));
}
void
_rtld_relocate_nonplt_self(Elf_Dyn *dynp, Elf_Addr relocbase)
{
const Elf_Rela *rela = 0, *relalim;
Elf_Addr relasz = 0;
Elf_Addr *where;
for (; dynp->d_tag != DT_NULL; dynp++) {
switch (dynp->d_tag) {
case DT_RELA:
rela = (const Elf_Rela *)(relocbase + dynp->d_un.d_ptr);
break;
case DT_RELASZ:
relasz = dynp->d_un.d_val;
break;
}
}
relalim = (const Elf_Rela *)((const uint8_t *)rela + relasz);
for (; rela < relalim; rela++) {
where = (Elf_Addr *)(relocbase + rela->r_offset);
*where = (Elf_Addr)(relocbase + rela->r_addend);
}
}
int
_rtld_relocate_nonplt_objects(Obj_Entry *obj)
{
const Elf_Rela *rela;
for (rela = obj->rela; rela < obj->relalim; rela++) {
Elf_Addr *where;
const Elf_Sym *def;
const Obj_Entry *defobj;
Elf_Addr tmp;
unsigned long symnum;
where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
symnum = ELF_R_SYM(rela->r_info);
switch (ELF_R_TYPE(rela->r_info)) {
#if 1 /* XXX Should not be necessary. */
case R_TYPE(JMP_SLOT):
#endif
case R_TYPE(NONE):
break;
case R_TYPE(32): /* <address> S + A */
case R_TYPE(GLOB_DAT): /* <address> S + A */
def = _rtld_find_symdef(symnum, 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(("32/GLOB_DAT %s in %s --> %p in %s",
obj->strtab + obj->symtab[symnum].st_name,
obj->path, (void *)*where, defobj->path));
break;
case R_TYPE(RELATIVE): /* <address> B + A */
*where = (Elf_Addr)(obj->relocbase + rela->r_addend);
rdbg(("RELATIVE in %s --> %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->isdynamic) {
_rtld_error(
"%s: Unexpected R_COPY relocation in shared library",
obj->path);
return -1;
}
rdbg(("COPY (avoid in main)"));
break;
case R_TYPE(TLS_DTPMOD):
def = _rtld_find_symdef(symnum, obj, &defobj, false);
if (def == NULL)
return -1;
*where = (Elf_Addr)defobj->tlsindex;
rdbg(("DTPMOD32 %s in %s --> %p in %s",
obj->strtab + obj->symtab[symnum].st_name,
obj->path, (void *)*where, defobj->path));
break;
case R_TYPE(TLS_DTPOFF):
def = _rtld_find_symdef(symnum, obj, &defobj, false);
if (def == NULL)
return -1;
if (!defobj->tls_done && _rtld_tls_offset_allocate(obj))
return -1;
*where = (Elf_Addr)(def->st_value + rela->r_addend
- TLS_DTV_OFFSET);
rdbg(("DTPOFF %s in %s --> %p in %s",
obj->strtab + obj->symtab[symnum].st_name,
obj->path, (void *)*where, defobj->path));
break;
case R_TYPE(TLS_TPOFF):
def = _rtld_find_symdef(symnum, obj, &defobj, false);
if (def == NULL)
return -1;
if (!defobj->tls_done && _rtld_tls_offset_allocate(obj))
return -1;
*where = (Elf_Addr)(def->st_value + rela->r_addend
+ defobj->tlsoffset - TLS_TP_OFFSET);
rdbg(("TPREL %s in %s --> %p in %s",
obj->strtab + obj->symtab[symnum].st_name,
obj->path, (void *)*where, defobj->path));
break;
default:
rdbg(("sym = %lu, type = %lu, offset = %p, "
"addend = %p, contents = %p, symbol = %s",
symnum, (u_long)ELF_R_TYPE(rela->r_info),
(void *)rela->r_offset, (void *)rela->r_addend,
(void *)*where,
obj->strtab + obj->symtab[symnum].st_name));
_rtld_error("%s: Unsupported relocation type %ld "
"in non-PLT relocations",
obj->path, (u_long) ELF_R_TYPE(rela->r_info));
return -1;
}
}
return 0;
}
int
_rtld_relocate_plt_lazy(const Obj_Entry *obj)
{
const Elf_Rela *rela;
int reloff;
for (rela = obj->pltrela, reloff = 0;
rela < obj->pltrelalim;
rela++, reloff++) {
Elf_Word *where = (Elf_Word *)(obj->relocbase + rela->r_offset);
assert(ELF_R_TYPE(rela->r_info) == R_TYPE(JMP_SLOT));
/*
* For now, simply treat then as relative.
*/
*where += (Elf_Addr)obj->relocbase;
}
return 0;
}
static int
_rtld_relocate_plt_object(const Obj_Entry *obj, const Elf_Rela *rela, int reloff, Elf_Addr *tp)
{
Elf_Word *where = (Elf_Word *)(obj->relocbase + rela->r_offset);
Elf_Addr value;
const Elf_Sym *def;
const Obj_Entry *defobj;
unsigned long info = rela->r_info;
assert(ELF_R_TYPE(info) == R_TYPE(JMP_SLOT));
def = _rtld_find_plt_symdef(ELF_R_SYM(info), obj, &defobj, tp != NULL);
if (__predict_false(def == NULL))
return -1;
if (__predict_false(def == &_rtld_sym_zero))
return 0;
value = (Elf_Addr)(defobj->relocbase + def->st_value);
rdbg(("bind now/fixup in %s --> new=%p",
defobj->strtab + def->st_name, (void *)value));
/*
* Simply replace the entry in GOT with the
* address of the routine.
*/
assert(where >= (Elf_Word *)obj->pltgot);
assert(where < (Elf_Word *)obj->pltgot + (obj->pltrelalim - obj->pltrela));
*where = value;
if (tp)
*tp = value;
return 0;
}
Elf_Addr
_rtld_bind(const Obj_Entry *obj, Elf_Word reloff)
{
const Elf_Rela *rela = obj->pltrela + reloff;
Elf_Addr new_value;
int err;
new_value = 0; /* XXX gcc */
_rtld_shared_enter();
err = _rtld_relocate_plt_object(obj, rela, reloff, &new_value);
if (err)
_rtld_die();
_rtld_shared_exit();
return new_value;
}
int
_rtld_relocate_plt_objects(const Obj_Entry *obj)
{
const Elf_Rela *rela;
int reloff;
for (rela = obj->pltrela, reloff = 0; rela < obj->pltrelalim; rela++, reloff++) {
if (_rtld_relocate_plt_object(obj, rela, reloff, NULL) < 0)
return -1;
}
return 0;
}

View File

@@ -0,0 +1,118 @@
/* $NetBSD: rtld_start.S,v 1.1 2014/09/03 19:34:26 matt Exp $ */
/*-
* Copyright (c) 2014 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Matt Thomas of 3am Software Foundry.
*
* 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``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 FOUNDATION OR CONTRIBUTORS
* 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>
.globl _rtld_start
.globl _rtld
#define CF_LEN (3*__SIZEOF_POINTER__)
#define CF_OBJ (2*__SIZEOF_POINTER__)
#define CF_CLEANUP (1*__SIZEOF_POINTER__)
/*
* void ___start(void (*cleanup)(void), const Obj_Entry *obj,
* struct ps_strings *ps_strings);
*/
ENTRY_NP(_rtld_start)
l.sw CF_LEN(r1), r1 # reserve some stack space
#if 0
l.ori r26, r3, 0 # obj (should be 0)
l.ori r28, r4, 0 # cleanup (should be 0)
#endif
l.ori r30, r5, 0 # ps_strings
l.addi r1, r1, -CF_LEN
PIC_GOTSETUP(r16)
l.movhi r3, gotoffhi(_DYNAMIC) # get _DYNAMIC gotoff address
l.ori r3, r3, gotofflo(_DYNAMIC)
l.lwz r7, 0(r16) # get base-relative &_DYNAMIC
l.add r3, r3, r16 # r3 = _DYNAMIC actual address
l.sub r24, r3, r7 # r24 = relocbase
l.ori r4, r24, 0 # r4 = relocbase
l.jal _C_LABEL(_rtld_relocate_nonplt_self)
l.nop
l.addi r3, r1, CF_CLEANUP
l.ori r4, r24, 0 # r4 = relocbase
l.jal _C_LABEL(_rtld) # _start = _rtld(sp, relocbase)
l.nop
l.lwz r3, CF_OBJ(r1) # obj
l.lwz r4, CF_CLEANUP(r1) # cleanup
l.ori r5, r30, 0 # ps_strings
l.addi r1, r1, CF_LEN # pop stack
l.jalr r11 # _start(obj, cleanup, ps_strings)
l.ori r13, r0, 1 # _exit()
l.sys 0
END(_rtld_start)
.globl _rtld_bind
/*
* r11 = rela offset
* r12 = GOT[1] (&obj)
* r15 = GOT[2] (&_rtld_bind_start)
*/
ENTRY_NP(_rtld_bind_start)
l.sw -4(r1), r9 # save lr
l.sw -8(r1), r8 # save arg5
l.sw -12(r1), r7 # save arg4
l.sw -16(r1), r6 # save arg3
l.sw -20(r1), r5 # save arg2
l.sw -24(r1), r4 # save arg1
l.sw -28(r1), r3 # save arg0
l.sw -32(r1), r1 # establish stack frame
l.addi r1, r1, -32
l.ori r3, r12, 0 # obj
l.ori r4, r11, 0 # reloff
l.jal _C_LABEL(_rtld_bind) # _rtld_bind(obj, reloff)
l.nop
l.addi r1, r1, 32 # pop stack frame
l.lwz r3, -28(r1) # restore arg0
l.lwz r4, -24(r1) # restore arg1
l.lwz r5, -20(r1) # restore arg2
l.lwz r6, -16(r1) # restore arg3
l.lwz r7, -12(r1) # restore arg4
l.lwz r8, -8(r1) # restore arg5
l.lwz r9, -4(r1) # restore lr
l.jr r11 # jump to routine
l.nop
END(_rtld_bind_start)

View File

@@ -1,11 +1,15 @@
# $NetBSD: Makefile.inc,v 1.12 2011/10/26 15:56:58 chs Exp $
SRCS+= rtld_start.S ppc_reloc.c
# XXX Should not be in CPPFLAGS!
CPPFLAGS+= -fpic
CPPFLAGS+= -DELFSIZE=32
# $NetBSD: Makefile.inc,v 1.15 2014/08/15 09:40:07 matt Exp $
SRCS+= ppc_reloc.c
LDFLAGS+= -Wl,-e,_rtld_start
CPPFLAGS+= -fPIC
.if ${LDELFSO_MACHINE_ARCH} == "powerpc64"
SRCS+= rtld_start64.S
CPPFLAGS+= -DELFSIZE=64
.else
SRCS+= rtld_start.S
CPPFLAGS+= -DELFSIZE=32
LDFLAGS+= -Wl,--script,${.CURDIR}/arch/powerpc/ld.so.script
.endif

View File

@@ -1,6 +1,6 @@
OUTPUT_FORMAT("elf32-powerpc", "elf32-powerpc",
"elf32-powerpc")
OUTPUT_ARCH(powerpc)
OUTPUT_ARCH(powerpc:common)
ENTRY(_start)
/* Do we need any of these for elf?
__DYNAMIC = 0; */

View File

@@ -1,4 +1,4 @@
/* $NetBSD: ppc_reloc.c,v 1.49 2011/03/25 18:07:06 joerg Exp $ */
/* $NetBSD: ppc_reloc.c,v 1.53 2014/08/25 20:40:52 joerg Exp $ */
/*-
* Copyright (C) 1998 Tsubai Masanari
@@ -30,7 +30,7 @@
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: ppc_reloc.c,v 1.49 2011/03/25 18:07:06 joerg Exp $");
__RCSID("$NetBSD: ppc_reloc.c,v 1.53 2014/08/25 20:40:52 joerg Exp $");
#endif /* not lint */
#include <stdarg.h>
@@ -46,19 +46,37 @@ __RCSID("$NetBSD: ppc_reloc.c,v 1.49 2011/03/25 18:07:06 joerg Exp $");
void _rtld_powerpc_pltcall(Elf_Word);
void _rtld_powerpc_pltresolve(Elf_Word, Elf_Word);
#define ha(x) ((((u_int32_t)(x) & 0x8000) ? \
((u_int32_t)(x) + 0x10000) : (u_int32_t)(x)) >> 16)
#define l(x) ((u_int32_t)(x) & 0xffff)
#define __u64(x) ((uint64_t)(x))
#define __u32(x) ((uint32_t)(x))
#define __ha48 __u64(0xffffffff8000)
#define __ha32 __u64(0xffff8000)
#define __ha16 __u32(0x8000)
#define __ha(x,n) ((((x) >> (n)) + (((x) & __ha##n) == __ha##n)) & 0xffff)
#define __hi(x,n) (((x) >> (n)) & 0xffff)
#ifdef __LP64
#define highesta(x) __ha(__u64(x), 48)
#define highest(x) __hi(__u64(x), 48)
#define higher(x) __ha(__u64(x), 32)
#define higher(x) __hi(__u64(x), 32)
#endif
#define ha(x) __ha(__u32(x), 16)
#define hi(x) __hi(__u32(x), 16)
#define lo(x) (__u32(x) & 0xffff)
#ifdef _LP64
/* function descriptor for _rtld_bind_start */
extern const uint64_t _rtld_bind_start[3];
#else
void _rtld_bind_bssplt_start(void);
void _rtld_bind_secureplt_start(void);
#endif
Elf_Addr _rtld_bind(const Obj_Entry *, Elf_Word);
void _rtld_relocate_nonplt_self(Elf_Dyn *, Elf_Addr);
caddr_t _rtld_bind(const Obj_Entry *, Elf_Word);
static int _rtld_relocate_plt_object(const Obj_Entry *,
const Elf_Rela *, int, Elf_Addr *);
/*
* The PPC PLT format consists of three sections:
* The PPC32 PLT format consists of three sections:
* (1) The "pltcall" and "pltresolve" glue code. This is always 18 words.
* (2) The code part of the PLT entries. There are 2 words per entry for
* up to 8192 entries, then 4 words per entry for any additional entries.
@@ -67,15 +85,19 @@ static int _rtld_relocate_plt_object(const Obj_Entry *,
* per entry).
*/
/*
* Setup the plt glue routines (for bss-plt).
*/
#define PLTCALL_SIZE 20
#define PLTRESOLVE_SIZE 24
void
_rtld_setup_pltgot(const Obj_Entry *obj)
{
#ifdef _LP64
/*
* For powerpc64, just copy the function descriptor to pltgot[0].
*/
if (obj->pltgot != NULL) {
obj->pltgot[0] = (Elf_Addr) _rtld_bind_start[0];
obj->pltgot[1] = (Elf_Addr) _rtld_bind_start[1];
obj->pltgot[2] = (Elf_Addr) obj;
}
#else
/*
* Secure-PLT is much more sane.
*/
@@ -86,6 +108,12 @@ _rtld_setup_pltgot(const Obj_Entry *obj)
obj->path, obj->gotptr,
(void *) obj->gotptr[1], (void *) obj->gotptr[2]));
} else {
/*
* Setup the plt glue routines (for bss-plt).
*/
#define BSSPLTCALL_SIZE 20
#define BSSPLTRESOLVE_SIZE 24
Elf_Word *pltcall, *pltresolve;
Elf_Word *jmptab;
int N = obj->pltrelalim - obj->pltrela;
@@ -101,17 +129,17 @@ _rtld_setup_pltgot(const Obj_Entry *obj)
pltcall = obj->pltgot;
jmptab = pltcall + 18 + N * 2;
memcpy(pltcall, _rtld_powerpc_pltcall, PLTCALL_SIZE);
memcpy(pltcall, _rtld_powerpc_pltcall, BSSPLTCALL_SIZE);
pltcall[1] |= ha(jmptab);
pltcall[2] |= l(jmptab);
pltcall[2] |= lo(jmptab);
pltresolve = obj->pltgot + 8;
memcpy(pltresolve, _rtld_powerpc_pltresolve, PLTRESOLVE_SIZE);
memcpy(pltresolve, _rtld_powerpc_pltresolve, BSSPLTRESOLVE_SIZE);
pltresolve[0] |= ha(_rtld_bind_bssplt_start);
pltresolve[1] |= l(_rtld_bind_bssplt_start);
pltresolve[1] |= lo(_rtld_bind_bssplt_start);
pltresolve[3] |= ha(obj);
pltresolve[4] |= l(obj);
pltresolve[4] |= lo(obj);
/*
* Invalidate the icache for only the code part of the PLT
@@ -119,6 +147,7 @@ _rtld_setup_pltgot(const Obj_Entry *obj)
*/
__syncicache(pltcall, (char *)jmptab - (char *)pltcall);
}
#endif
}
void
@@ -167,8 +196,12 @@ _rtld_relocate_nonplt_objects(Obj_Entry *obj)
case R_TYPE(NONE):
break;
case R_TYPE(32): /* word32 S + A */
case R_TYPE(GLOB_DAT): /* word32 S + A */
#ifdef _LP64
case R_TYPE(ADDR64): /* <address> S + A */
#else
case R_TYPE(ADDR32): /* <address> S + A */
#endif
case R_TYPE(GLOB_DAT): /* <address> S + A */
def = _rtld_find_symdef(symnum, obj, &defobj, false);
if (def == NULL)
return -1;
@@ -182,7 +215,7 @@ _rtld_relocate_nonplt_objects(Obj_Entry *obj)
obj->path, (void *)*where, defobj->path));
break;
case R_TYPE(RELATIVE): /* word32 B + A */
case R_TYPE(RELATIVE): /* <address> B + A */
*where = (Elf_Addr)(obj->relocbase + rela->r_addend);
rdbg(("RELATIVE in %s --> %p", obj->path,
(void *)*where));
@@ -204,7 +237,7 @@ _rtld_relocate_nonplt_objects(Obj_Entry *obj)
rdbg(("COPY (avoid in main)"));
break;
case R_TYPE(DTPMOD32):
case R_TYPE(DTPMOD):
def = _rtld_find_symdef(symnum, obj, &defobj, false);
if (def == NULL)
return -1;
@@ -215,7 +248,7 @@ _rtld_relocate_nonplt_objects(Obj_Entry *obj)
obj->path, (void *)*where, defobj->path));
break;
case R_TYPE(DTPREL32):
case R_TYPE(DTPREL):
def = _rtld_find_symdef(symnum, obj, &defobj, false);
if (def == NULL)
return -1;
@@ -230,7 +263,7 @@ _rtld_relocate_nonplt_objects(Obj_Entry *obj)
obj->path, (void *)*where, defobj->path));
break;
case R_TYPE(TPREL32):
case R_TYPE(TPREL):
def = _rtld_find_symdef(symnum, obj, &defobj, false);
if (def == NULL)
return -1;
@@ -264,6 +297,12 @@ _rtld_relocate_nonplt_objects(Obj_Entry *obj)
int
_rtld_relocate_plt_lazy(const Obj_Entry *obj)
{
#ifdef _LP64
/*
* For PowerPC64, the plt stubs handle an empty function descriptor
* so there's nothing to do.
*/
#else
Elf_Addr * const pltresolve = obj->pltgot + 8;
const Elf_Rela *rela;
int reloff;
@@ -288,9 +327,9 @@ _rtld_relocate_plt_lazy(const Obj_Entry *obj)
*where++ = 0x39600000 | reloff;
} else {
/* lis r11,ha(reloff) */
/* addi r11,l(reloff) */
/* addi r11,lo(reloff) */
*where++ = 0x3d600000 | ha(reloff);
*where++ = 0x396b0000 | l(reloff);
*where++ = 0x396b0000 | lo(reloff);
}
/* b pltresolve */
distance = (Elf_Addr)pltresolve - (Elf_Addr)where;
@@ -305,6 +344,7 @@ _rtld_relocate_plt_lazy(const Obj_Entry *obj)
/* __syncicache(where - 3, 12); */
}
}
#endif /* !_LP64 */
return 0;
}
@@ -316,7 +356,6 @@ _rtld_relocate_plt_object(const Obj_Entry *obj, const Elf_Rela *rela, int reloff
Elf_Addr value;
const Elf_Sym *def;
const Obj_Entry *defobj;
int distance;
unsigned long info = rela->r_info;
assert(ELF_R_TYPE(info) == R_TYPE(JMP_SLOT));
@@ -327,20 +366,38 @@ _rtld_relocate_plt_object(const Obj_Entry *obj, const Elf_Rela *rela, int reloff
if (__predict_false(def == &_rtld_sym_zero))
return 0;
value = (Elf_Addr)(defobj->relocbase + def->st_value);
distance = value - (Elf_Addr)where;
if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC) {
if (tp == NULL)
return 0;
value = _rtld_resolve_ifunc(defobj, def);
} else {
value = (Elf_Addr)(defobj->relocbase + def->st_value);
}
rdbg(("bind now/fixup in %s --> new=%p",
defobj->strtab + def->st_name, (void *)value));
#ifdef _LP64
/*
* For PowerPC64 we simply replace the function descriptor in the
* PLTGOT with the one from source object.
*/
assert(where >= (Elf_Word *)obj->pltgot);
assert(where < (Elf_Word *)obj->pltgot + (obj->pltrelalim - obj->pltrela));
const Elf_Addr * const fdesc = (Elf_Addr *) value;
where[0] = fdesc[0];
where[1] = fdesc[1];
where[2] = fdesc[2];
#else
ptrdiff_t distance = value - (Elf_Addr)where;
if (obj->gotptr != NULL) {
/*
* For Secure-PLT we simply replace the entry in GOT with the address
* of the routine.
* For Secure-PLT we simply replace the entry in GOT with the
* address of the routine.
*/
assert(where >= (Elf_Word *)obj->pltgot);
assert(where < (Elf_Word *)obj->pltgot + (obj->pltrelalim - obj->pltrela));
*where = value;
} else if (abs(distance) < 32*1024*1024) { /* inside 32MB? */
} else if (labs(distance) < 32*1024*1024) { /* inside 32MB? */
/* b value # branch directly */
*where = 0x48000000 | (distance & 0x03fffffc);
__syncicache(where, 4);
@@ -363,18 +420,18 @@ _rtld_relocate_plt_object(const Obj_Entry *obj, const Elf_Rela *rela, int reloff
} else {
#ifdef notyet
/* lis r11,ha(value) */
/* addi r11,l(value) */
/* addi r11,lo(value) */
/* mtctr r11 */
/* bctr */
*where++ = 0x3d600000 | ha(value);
*where++ = 0x396b0000 | l(value);
*where++ = 0x396b0000 | lo(value);
*where++ = 0x7d6903a6;
*where++ = 0x4e800420;
#else
/* lis r11,ha(reloff) */
/* addi r11,l(reloff) */
/* addi r11,lo(reloff) */
*where++ = 0x3d600000 | ha(reloff);
*where++ = 0x396b0000 | l(reloff);
*where++ = 0x396b0000 | lo(reloff);
#endif
}
/* b pltcall */
@@ -382,13 +439,14 @@ _rtld_relocate_plt_object(const Obj_Entry *obj, const Elf_Rela *rela, int reloff
*where++ = 0x48000000 | (distance & 0x03fffffc);
__syncicache(where - 3, 12);
}
#endif /* _LP64 */
if (tp)
*tp = value;
return 0;
}
caddr_t
Elf_Addr
_rtld_bind(const Obj_Entry *obj, Elf_Word reloff)
{
const Elf_Rela *rela = obj->pltrela + reloff;
@@ -403,7 +461,11 @@ _rtld_bind(const Obj_Entry *obj, Elf_Word reloff)
_rtld_die();
_rtld_shared_exit();
return (caddr_t)new_value;
#ifdef _LP64
return obj->glink;
#else
return new_value;
#endif
}
int

View File

@@ -0,0 +1,128 @@
/* $NetBSD: rtld_start64.S,v 1.2 2014/03/06 19:19:40 matt Exp $ */
/*-
* Copyright (C) 1998 Tsubai Masanari
* Portions copyright 2002 Charles M. Hannum <root@ihack.net>
* 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>
.globl _rtld_relocate_nonplt_self
.globl _rtld
.text
ENTRY_NOPROFILE(_rtld_start)
mr %r23,%r3 // argc
mr %r24,%r4 // argv
mr %r25,%r5 // envp
/* mr %r26,%r6 // obj (always 0) */
/* mr %r27,%r7 // cleanup (always 0) */
mr %r28,%r8 // ps_strings
li %r0,0
stdu %r0,-64(%r1) // terminate stack chain
std %r2,40(%r1) // save TOC
std %r0,16(%r1) // ditto
bcl 20,31,1f
1: mflr %r30
ld %r3,0(%r2) // TOC[0] = &TOC
sub %r29,%r2,%r3 // compute relocbase
addis %r3,%r3,_DYNAMIC-1b@ha // get _DYNAMIC actual address
addi %r3,%r3,_DYNAMIC-1b@l
mr %r4,%r29 // r4 = relocbase
CALL(_rtld_relocate_nonplt_self)
addi %r3,%r1,48 // sp = <local variable space>
mr %r4,%r29 // r4 = relocbase
CALL(_rtld) // _start = _rtld(sp, relocbase)
ld %r0,0(%r3) // func address
ld %r2,8(%r3) // TOC address
ld %r11,16(%r3) // environment pointer
mtctr %r0 // so we can call it.
mr %r3,%r23 // argc
mr %r4,%r24 // argv
mr %r5,%r25 // envp
ld %r6,56(%r1) // obj = <localvar>[1]
ld %r7,48(%r1) // cleanup = <localvar>[0]
mr %r8,%r28 // ps_strings
bctrl // _start(argc, argv, envp, obj, cleanup, ps_strings)
nop
li %r0,1 // _exit()
sc
END(_rtld_start)
.globl _rtld_bind
/*
* %r0 has the index of the rela, %r12 has a pointer to the plt entry.
*/
ENTRY_NOPROFILE(_rtld_bind_start)
std %r3,-72(%r1) // save argument register
std %r4,-64(%r1) // save argument register
std %r5,-56(%r1) // save argument register
std %r6,-48(%r1) // save argument register
std %r7,-40(%r1) // save argument register
std %r8,-32(%r1) // save argument register
std %r9,-24(%r1) // save argument register
std %r10,-16(%r1) // save argument register
std %r31,-8(%r1) // save register
stdu %r1,-(48+80)(%r1) // create back chain
mflr %r10
std %r10,16(%r1) // save LR
mfcr %r9
std %r9,8(%r1) // save CR to be safe
mr %r31, %r12 // save this across bind call
mr %r3, %r11 // obj
mr %r4, %r0 // reloff
CALL(_rtld_bind) // _rtld_bind(obj, reloff)
mtctr %r3
mr %r12,%r31 // restore r12
ld %r0,8(%r1) // get saved CR
mtcr %r0 // restore it
ld %r0,16(%r1) // get saved LR
mtlr %r0 // restore it
addi %r1,%r1,(48+80) // adjust stack
ld %r3,-72(%r1) // restore argument register
ld %r4,-64(%r1) // restore argument register
ld %r5,-56(%r1) // restore argument register
ld %r6,-48(%r1) // restore argument register
ld %r7,-40(%r1) // restore argument register
ld %r8,-32(%r1) // restore argument register
ld %r9,-24(%r1) // restore argument register
ld %r10,-16(%r1) // restore argument register
ld %r31,-8(%r1) // restore register
bctr
END(_rtld_bind_start)

View File

@@ -0,0 +1,15 @@
# $NetBSD: Makefile.inc,v 1.1 2014/09/19 17:36:25 matt Exp $
SRCS+= rtld_start.S mdreloc.c
# XXX Should not be in CPPFLAGS!
CPPFLAGS+= -fpic
.if ${LDELFSO_MACHINE_ARCH} == "riscv64"
CPPFLAGS+= -DELFSIZE=64
.else
CPPFLAGS+= -DELFSIZE=32
.endif
CPPFLAGS+= -DHAVE_INITFINI_ARRAY
LDFLAGS+= -Wl,-e,_rtld_start

View File

@@ -0,0 +1,258 @@
/* $NetBSD: mdreloc.c,v 1.2 2015/03/27 23:14:53 matt Exp $ */
/*-
* Copyright (c) 2014 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Matt Thomas of 3am Software Foundry.
*
* 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``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 FOUNDATION OR CONTRIBUTORS
* 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 <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: mdreloc.c,v 1.2 2015/03/27 23:14:53 matt Exp $");
#endif /* not lint */
#include <sys/types.h>
#include <sys/endian.h>
#include <sys/tls.h>
#include <stdlib.h>
#include <string.h>
#include "debug.h"
#include "rtld.h"
void _rtld_bind_start(void);
void _rtld_relocate_nonplt_self(Elf_Dyn *, Elf_Addr);
void *_rtld_bind(const Obj_Entry *, Elf_Word);
void
_rtld_setup_pltgot(const Obj_Entry *obj)
{
obj->pltgot[0] = (Elf_Addr) &_rtld_bind_start;
obj->pltgot[1] = (Elf_Addr) obj;
}
void
_rtld_relocate_nonplt_self(Elf_Dyn *dynp, Elf_Addr relocbase)
{
const Elf_Rela *rela = NULL, *relalim;
Elf_Addr relasz = 0;
for (; dynp->d_tag != DT_NULL; dynp++) {
switch (dynp->d_tag) {
case DT_RELA:
rela = (const Elf_Rela *)(relocbase + dynp->d_un.d_ptr);
break;
case DT_RELASZ:
relasz = dynp->d_un.d_val;
break;
}
}
relalim = (const Elf_Rela *)((uintptr_t)rela + relasz);
for (; rela < relalim; rela++) {
Elf_Word r_type = ELF_R_TYPE(rela->r_info);
Elf_Addr *where = (Elf_Addr *)(relocbase + rela->r_offset);
switch (r_type) {
case R_TYPE(RELATIVE): {
Elf_Addr val = relocbase + rela->r_addend;
*where = val;
rdbg(("RELATIVE/L(%p) -> %p in <self>",
where, (void *)val));
break;
}
case R_TYPE(NONE):
break;
default:
abort();
}
}
}
int
_rtld_relocate_nonplt_objects(Obj_Entry *obj)
{
const Elf_Rela *rela;
const Elf_Sym *def;
const Obj_Entry *defobj;
for (rela = obj->rela; rela < obj->relalim; rela++) {
Elf_Addr * const where =
(Elf_Addr *)(obj->relocbase + rela->r_offset);
const Elf_Word r_symndx = ELF_R_SYM(rela->r_info);
const Elf_Word r_type = ELF_R_TYPE(rela->r_info);
switch (r_type) {
case R_TYPE(NONE):
break;
case R_TYPE(RELATIVE): {
def = obj->symtab + r_symndx;
Elf_Addr val = (Elf_Addr)obj->relocbase + rela->r_addend;
rdbg(("RELATIVE(%p) -> %p (%s) in %s",
where, (void *)val,
obj->strtab + def->st_name, obj->path));
*where = val;
break;
}
case R_TYPESZ(ADDR): {
def = _rtld_find_symdef(r_symndx, obj, &defobj, false);
if (def == NULL)
return -1;
Elf_Addr val = (Elf_Addr)defobj->relocbase + rela->r_addend;
*where = val;
rdbg(("ADDR %s in %s --> %p in %s",
obj->strtab + obj->symtab[r_symndx].st_name,
obj->path, (void *)val, defobj->path));
break;
}
case R_TYPESZ(TLS_DTPMOD): {
def = _rtld_find_symdef(r_symndx, obj, &defobj, false);
if (def == NULL)
return -1;
Elf_Addr val = (Elf_Addr)defobj->tlsindex + rela->r_addend;
*where = val;
rdbg(("DTPMOD %s in %s --> %p in %s",
obj->strtab + obj->symtab[r_symndx].st_name,
obj->path, (void *)val, defobj->path));
break;
}
case R_TYPESZ(TLS_DTPREL): {
Elf_Addr old = *where;
Elf_Addr val = old;
def = _rtld_find_symdef(r_symndx, obj, &defobj, false);
if (def == NULL)
return -1;
if (!defobj->tls_done && _rtld_tls_offset_allocate(obj))
return -1;
val = (Elf_Addr)def->st_value - TLS_DTV_OFFSET;
*where = val;
rdbg(("DTPREL %s in %s --> %p in %s",
obj->strtab + obj->symtab[r_symndx].st_name,
obj->path, (void *)val, defobj->path));
break;
}
default:
rdbg(("sym = %lu, type = %lu, offset = %p, "
"addend = %p, contents = %p, symbol = %s",
(u_long)r_symndx, (u_long)r_type,
(void *)rela->r_offset, (void *)rela->r_addend,
(void *)load_ptr(where, sizeof(Elf_Addr)),
obj->strtab + obj->symtab[r_symndx].st_name));
_rtld_error("%s: Unsupported relocation type %ld "
"in non-PLT relocations",
obj->path, (u_long)r_type);
return -1;
}
}
return 0;
}
int
_rtld_relocate_plt_lazy(const Obj_Entry *obj)
{
/* PLT fixups were done above in the GOT relocation. */
return 0;
}
static int
_rtld_relocate_plt_object(const Obj_Entry *obj, const Elf_Rel *rel,
Elf_Addr *tp)
{
const Obj_Entry *defobj;
Elf_Addr new_value;
assert(ELF_R_TYPE(rel->r_info) == R_TYPE(JMP_SLOT));
const Elf_Sym *def = _rtld_find_plt_symdef(ELF_R_SYM(rel->r_info),
obj, &defobj, tp != NULL);
if (__predict_false(def == NULL))
return -1;
if (__predict_false(def == &_rtld_sym_zero))
return -1;
if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC) {
if (tp == NULL)
return 0;
new_value = _rtld_resolve_ifunc(defobj, def);
} else {
new_value = (Elf_Addr)(defobj->relocbase + def->st_value);
}
rdbg(("bind now/fixup in %s --> new=%p",
defobj->strtab + def->st_name, (void *)new_value));
*(Elf_Addr *)(obj->relocbase + rel->r_offset) = new_value;
if (tp)
*tp = new_value;
return 0;
}
void *
_rtld_bind(const Obj_Entry *obj, Elf_Word reloff)
{
const Elf_Rel *pltrel = (const Elf_Rel *)(obj->pltrel + reloff);
Elf_Addr new_value;
int err;
_rtld_shared_enter();
err = _rtld_relocate_plt_object(obj, pltrel, &new_value);
if (err)
_rtld_die();
_rtld_shared_exit();
return (caddr_t)new_value;
}
int
_rtld_relocate_plt_objects(const Obj_Entry *obj)
{
for (const Elf_Rel *rel = obj->pltrel; rel < obj->pltrellim; rel++) {
if (_rtld_relocate_plt_object(obj, rel, NULL) < 0)
return -1;
}
return 0;
}

View File

@@ -0,0 +1,116 @@
/* $NetBSD: rtld_start.S,v 1.2 2015/03/27 23:14:53 matt Exp $ */
/*-
* Copyright (c) 2014 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Matt Thomas of 3am Software Foundry.
*
* 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 NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``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 FOUNDATION OR CONTRIBUTORS
* 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>
.globl _C_LABEL(_rtld_relocate_nonplt_self)
.globl _C_LABEL(_rtld)
/*
* void
* ___start(void (*cleanup)(void),
* const Obj_Entry *obj,
* struct ps_strings *ps_strings)
*/
ENTRY(_rtld_start)
move s0, sp # save stack pointer
addi sp, sp, -4*__SIZEOF_POINTER__
# adjust stack pointer
# -> 2*PTR_SIZE(sp) for atexit
# -> 3*PTR_SIZE(sp) for obj_main
move s1, a2 # save ps_strings pointer
.L0: auipc gp, %pcrel_hi(_GLOBAL_OFFSET_TABLE_)
PTR_L t0, %pcrel_lo(.L0)(gp) # &_DYNAMIC
.L1: auipc a0, %pcrel_hi(_DYNAMIC)
addi a0, a0, %pcrel_lo(.L1)
sub s2, a0, t0 # save for _rtld
move a1, s2
call _C_LABEL(_rtld_relocate_nonplt_self)
move a1, s2 # relocbase
addi a0, sp, 2*__SIZEOF_POINTER__ # sp
call _C_LABEL(_rtld) # a0 = _rtld(sp, relocbase)
mv t0, a0
PTR_L a0, 2*__SIZEOF_POINTER__(sp) # cleanup function
PTR_L a1, 3*__SIZEOF_POINTER__(sp) # obj_main entry
move a2, s1 # restore ps_strings
move sp, s0 # readjust stack
move s0, zero # break stack chain
jr t0 # _start(cleanup, obj_main, ps_strings);
END(_rtld_start)
#define XCALLFRAME_SIZ (12*SZREG)
#define XCALLFRAME_RA (8*SZREG)
#define XCALLFRAME_A7 (7*SZREG)
#define XCALLFRAME_A6 (6*SZREG)
#define XCALLFRAME_A5 (5*SZREG)
#define XCALLFRAME_A4 (4*SZREG)
#define XCALLFRAME_A3 (3*SZREG)
#define XCALLFRAME_A2 (2*SZREG)
#define XCALLFRAME_A1 (1*SZREG)
#define XCALLFRAME_A0 (0*SZREG)
/*
* t0 = obj pointer
* t1 = reloc offset
*/
ENTRY_NP(_rtld_bind_start)
addi sp, sp, -XCALLFRAME_SIZ // save arguments on stack
REG_S a0, XCALLFRAME_A0(sp)
REG_S a1, XCALLFRAME_A1(sp)
REG_S a2, XCALLFRAME_A2(sp)
REG_S a3, XCALLFRAME_A3(sp)
REG_S a4, XCALLFRAME_A4(sp)
REG_S a5, XCALLFRAME_A5(sp)
REG_S a6, XCALLFRAME_A6(sp)
REG_S a7, XCALLFRAME_A7(sp)
REG_S ra, XCALLFRAME_RA(sp)
mv a0, t0 /* object from got.plt[1] */
mv a1, t1 /* reloc offset */
call _C_LABEL(_rtld_bind)
mv t0, a0 /* save function pointer */
REG_L a0, XCALLFRAME_A0(sp)
REG_L a1, XCALLFRAME_A1(sp)
REG_L a2, XCALLFRAME_A2(sp)
REG_L a3, XCALLFRAME_A3(sp)
REG_L a4, XCALLFRAME_A4(sp)
REG_L a5, XCALLFRAME_A5(sp)
REG_L a6, XCALLFRAME_A6(sp)
REG_L a7, XCALLFRAME_A7(sp)
REG_L ra, XCALLFRAME_RA(sp)
addi sp, sp, XCALLFRAME_SIZ
jr t0
END(_rtld_bind_start)

View File

@@ -1,13 +1,13 @@
/* $NetBSD: mdreloc.c,v 1.30 2011/03/25 18:07:06 joerg Exp $ */
/* $NetBSD: mdreloc.c,v 1.31 2014/08/25 20:40:52 joerg Exp $ */
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: mdreloc.c,v 1.30 2011/03/25 18:07:06 joerg Exp $");
__RCSID("$NetBSD: mdreloc.c,v 1.31 2014/08/25 20:40:52 joerg Exp $");
#endif /* not lint */
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: mdreloc.c,v 1.30 2011/03/25 18:07:06 joerg Exp $");
__RCSID("$NetBSD: mdreloc.c,v 1.31 2014/08/25 20:40:52 joerg Exp $");
#endif /* not lint */
#include <sys/types.h>
@@ -282,7 +282,13 @@ _rtld_relocate_plt_object(const Obj_Entry *obj, const Elf_Rela *rela, Elf_Addr *
if (__predict_false(def == &_rtld_sym_zero))
return 0;
new_value = (Elf_Addr)(defobj->relocbase + def->st_value);
if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC) {
if (tp == NULL)
return 0;
new_value = _rtld_resolve_ifunc(defobj, def);
} else {
new_value = (Elf_Addr)(defobj->relocbase + def->st_value);
}
rdbg(("bind now/fixup in %s --> old=%p new=%p",
defobj->strtab + def->st_name, (void *)*where, (void *)new_value));
if (*where != new_value)

View File

@@ -1,4 +1,4 @@
/* $NetBSD: mdreloc.c,v 1.47 2011/03/31 12:47:01 nakayama Exp $ */
/* $NetBSD: mdreloc.c,v 1.48 2014/08/25 20:40:52 joerg Exp $ */
/*-
* Copyright (c) 1999, 2002 The NetBSD Foundation, Inc.
@@ -31,7 +31,7 @@
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: mdreloc.c,v 1.47 2011/03/31 12:47:01 nakayama Exp $");
__RCSID("$NetBSD: mdreloc.c,v 1.48 2014/08/25 20:40:52 joerg Exp $");
#endif /* not lint */
#include <errno.h>
@@ -448,7 +448,13 @@ _rtld_relocate_plt_object(const Obj_Entry *obj, const Elf_Rela *rela, Elf_Addr *
if (__predict_false(def == &_rtld_sym_zero))
return 0;
value = (Elf_Addr)(defobj->relocbase + def->st_value);
if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC) {
if (tp == NULL)
return 0;
value = _rtld_resolve_ifunc(defobj, def);
} else {
value = (Elf_Addr)(defobj->relocbase + def->st_value);
}
rdbg(("bind now/fixup in %s --> new=%p",
defobj->strtab + def->st_name, (void *)value));

View File

@@ -1,4 +1,4 @@
/* $NetBSD: mdreloc.c,v 1.55 2013/10/03 10:45:57 martin Exp $ */
/* $NetBSD: mdreloc.c,v 1.57 2014/08/25 20:40:53 joerg Exp $ */
/*-
* Copyright (c) 2000 Eduardo Horvath.
@@ -32,7 +32,7 @@
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: mdreloc.c,v 1.55 2013/10/03 10:45:57 martin Exp $");
__RCSID("$NetBSD: mdreloc.c,v 1.57 2014/08/25 20:40:53 joerg Exp $");
#endif /* not lint */
#include <errno.h>
@@ -170,7 +170,7 @@ static const long reloc_target_bitmask[] = {
_BM(10), _BM(13), _BM(22), /* GOT10, GOT13, GOT22 */
_BM(10), _BM(22), /* _PC10, _PC22 */
_BM(30), 0, /* _WPLT30, _COPY */
_BM(32), _BM(32), _BM(32), /* _GLOB_DAT, JMP_SLOT, _RELATIVE */
-1, _BM(32), -1, /* _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 */
@@ -192,18 +192,18 @@ static const long reloc_target_bitmask[] = {
/*
* Instruction templates:
*/
#define BAA 0x10400000 /* ba,a %xcc, 0 */
#define BAA 0x30680000 /* ba,a %xcc, 0 */
#define SETHI 0x03000000 /* sethi %hi(0), %g1 */
#define JMP 0x81c06000 /* jmpl %g1+%lo(0), %g0 */
#define NOP 0x01000000 /* sethi %hi(0), %g0 */
#define OR 0x82806000 /* or %g1, 0, %g1 */
#define XOR 0x82c06000 /* xor %g1, 0, %g1 */
#define MOV71 0x8283a000 /* or %o7, 0, %g1 */
#define MOV17 0x9c806000 /* or %g1, 0, %o7 */
#define OR 0x82106000 /* or %g1, 0, %g1 */
#define XOR 0x82186000 /* xor %g1, 0, %g1 */
#define MOV71 0x8213e000 /* or %o7, 0, %g1 */
#define MOV17 0x9e106000 /* or %g1, 0, %o7 */
#define CALL 0x40000000 /* call 0 */
#define SLLX 0x8b407000 /* sllx %g1, 0, %g1 */
#define SLLX 0x83287000 /* sllx %g1, 0, %g1 */
#define SETHIG5 0x0b000000 /* sethi %hi(0), %g5 */
#define ORG5 0x82804005 /* or %g1, %g5, %g1 */
#define ORG5 0x82104005 /* or %g1, %g5, %g1 */
/* %hi(v)/%lo(v) with variable shift */
@@ -602,9 +602,15 @@ _rtld_relocate_plt_object(const Obj_Entry *obj, const Elf_Rela *rela,
if (__predict_false(def == &_rtld_sym_zero))
return 0;
value = (Elf_Addr)(defobj->relocbase + def->st_value);
rdbg(("bind now/fixup in %s --> new=%p",
defobj->strtab + def->st_name, (void *)value));
if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC) {
if (tp == NULL)
return 0;
value = _rtld_resolve_ifunc(defobj, def);
} else {
value = (Elf_Addr)(defobj->relocbase + def->st_value);
}
rdbg(("bind now/fixup in %s at %p --> new=%p",
defobj->strtab + def->st_name, (void*)where, (void *)value));
/*
* At the PLT entry pointed at by `where', we now construct a direct
@@ -696,7 +702,7 @@ _rtld_relocate_plt_object(const Obj_Entry *obj, const Elf_Rela *rela,
*
*/
where[3] = JMP;
where[2] = XOR | ((~value) & 0x00001fff);
where[2] = XOR | (value & 0x00003ff) | 0x1c00;
where[1] = SETHI | HIVAL(~value, 10);
__asm volatile("iflush %0+12" : : "r" (where));
__asm volatile("iflush %0+8" : : "r" (where));

View File

@@ -1,13 +1,13 @@
/* $NetBSD: mdreloc.c,v 1.28 2011/03/25 18:07:07 joerg Exp $ */
/* $NetBSD: mdreloc.c,v 1.30 2014/08/25 20:40:53 joerg Exp $ */
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: mdreloc.c,v 1.28 2011/03/25 18:07:07 joerg Exp $");
__RCSID("$NetBSD: mdreloc.c,v 1.30 2014/08/25 20:40:53 joerg Exp $");
#endif /* not lint */
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: mdreloc.c,v 1.28 2011/03/25 18:07:07 joerg Exp $");
__RCSID("$NetBSD: mdreloc.c,v 1.30 2014/08/25 20:40:53 joerg Exp $");
#endif /* not lint */
#include <sys/types.h>
@@ -142,7 +142,8 @@ _rtld_relocate_plt_lazy(const Obj_Entry *obj)
/* Just relocate the GOT slots pointing into the PLT */
*where += (Elf_Addr)obj->relocbase;
rdbg(("fixup !main in %s --> %p", obj->path, (void *)*where));
rdbg(("lazy fixup pltgot %p in %s --> %p", where, obj->path,
(void *)*where));
}
return 0;
@@ -165,9 +166,15 @@ _rtld_relocate_plt_object(const Obj_Entry *obj, const Elf_Rela *rela, Elf_Addr *
if (__predict_false(def == &_rtld_sym_zero))
return 0;
new_value = (Elf_Addr)(defobj->relocbase + def->st_value +
rela->r_addend);
rdbg(("bind now/fixup in %s --> old=%p new=%p",
if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC) {
if (tp == NULL)
return 0;
new_value = _rtld_resolve_ifunc(defobj, def);
} else {
new_value = (Elf_Addr)(defobj->relocbase + def->st_value +
rela->r_addend);
}
rdbg(("bind now/fixup pltgot %p in %s --> old=%p new=%p", where,
defobj->strtab + def->st_name, (void *)*where, (void *)new_value));
if (*where != new_value)
*where = new_value;

View File

@@ -1,4 +1,4 @@
/* $NetBSD: rtld_start.S,v 1.16 2003/03/02 22:03:40 mycroft Exp $ */
/* $NetBSD: rtld_start.S,v 1.24 2014/08/17 16:57:37 matt Exp $ */
/*
* Copyright 1996 Matt Thomas <matt@3am-software.com>
@@ -53,26 +53,226 @@ ENTRY(_rtld_start, 0)
movq (%sp)+,%r7 /* grab cleanup and obj_main into %r7/%r8 */
jmp 2(%r0) /* jump to entry point + 2 */
END(_rtld_start)
/*
* Lazy binding entry point, called via PLT.
*
* Note: Some functions rely on there not being an additional call frame;
* hence the `optimization' to avoid the callg opportunistically.
* Lazy binding entry point, called via PLT via JMP into pltgot[1].
* SP+4: address to relocation offset
* SP+0: obj entry points
*/
ALTENTRY(_rtld_bind_start)
pushr $0x3f /* save R0-R5 */
movq 24(%sp),%r0 /* get addresses of plt.got & reloc index */
pushl (%r1) /* push relocation index */
pushl %r1 /* need to preserve r1 */
movq -8(%fp),%r0 /* get addresses of plt.got & reloc index */
pushl (%r1) /* push relocation offset */
pushl %r0 /* push address of obj entry */
calls $2,_rtld_bind
movl %r0,28(%sp) /* save return address onto stack */
bicw3 6(%fp),(%r0),%r0/* does the entry mask save any additional regs */
popr $0x3f /* restore R0-R5 (cond flags not modified) */
bneq 4f /* yes? do it the hard way */
addl2 $4,%sp /* no? skip past plt.got on stack */
addl2 $2,(%sp) /* skip past the mask */
rsb /* and jump to it */
4: addl2 $4,%sp
callg (%ap),*(%sp)+ /* return value from _rtld_bind() == actual */
ret
/*
* This code checks to see if we got called via a call{s,g} $n,*pcrel32
* This is by far the most common case (a call indirectly via the PLT).
*/
subl3 $7,16(%fp),%r1 /* return address */
bicb3 $1,(%r1),%r2 /* fetch opcode of instruction */
cmpb $0xfa,%r2 /* is it calls/callg */
jneq 20f /* no it isn't */
cmpb $0xff,2(%r1) /* and deferred 32-bit PC displacement? */
jneq 20f /* no it isn't */
/*
* This makes sure the longword with the PLT's address has been updated
* to point to the routine's address. If it hasn't, then returning
* would put us in an infinite loop. Instead we punt and fake up a
* callframe.
*/
movl 3(%r1),%r3 /* get displacement */
addl2 16(%fp),%r3 /* add ending location */
cmpl (%r3),%r0 /* does it contain the routine address? */
#ifdef DEBUG
jneq 30f /* no it doesn't, die */
#else
jneq 20f /* no it doesn't, go fake a new callframe */
#endif
11: movl %r1,16(%fp) /* backup to the calls/callg */
jbc $29,4(%fp),12f /* skip if this was a callg */
clrl (%ap) /* clear argument count */
12: movl (%sp)+,%r1 /* restore r1 */
ret /* return and redo the call */
#if 1
20:
/*
* Since the calling standard says only r6-r11 should be saved,
* that simplies things for us. That means we can use r0-r5 as
* temporaries without worrying about preserving them. This means
* can hold the current fixed callframe in r2-r5 as we build the
* callframe without having to worry about overwriting the existing
* callframe.
*/
extzv $0,$12,(%r0),%r1/* get routine's save mask */
bitw $0x3f,%r1 /* does the routine use r0-r5? */
jneq 30f /* yes, that sucks */
jbc $29,4(%fp),27f /* handle callg */
movq 4(%fp),%r2 /* fetch callframe status & saved AP */
movq 12(%fp),%r4 /* fetch callframe saved FP & PC */
insv %r1,$16,$12,%r2 /* update save mask */
movl (%sp)+,%fp /* use fp to keep saved r1 */
movl %ap,%sp /* reset stack to top of callframe */
22: pushr %r1 /* push registers */
movq %r4,-(%sp) /* push callframe saved FP & PC */
movq %r2,-(%sp) /* push callframe status & saved AP */
pushl $0 /* push condition handler */
movl %fp,%r1 /* restore r1 */
movl %sp,%fp /* sp == fp now */
#if 1
jmp 2(%r0) /* jump past entry mask */
#else
/*
* More correct but IV/DV are never set so ignore doing this for now.
*/
movpsl -(%sp) /* push PSL */
clrb (%sp) /* clear user flags */
jbc $14,(%r0),24f /* IV need to be set? */
bisb2 $0x20,(%sp) /* yes, set it. */
24: jbc $15,(%r0),25f /* DV need to be set? */
bisb2 $0x80,(%sp) /* yes, set it. */
25: pushab 2(%r0) /* push address of first instruction */
rei /* and go to it (updating PSW) */
#endif
/*
* Count how many registers are being used for callg.
*/
27: movl $0x32212110,%r3 /* bit counts */
extzv $6,$3,%r1,%r2 /* extract bits 6-8 */
ashl $2,%r2,%r2 /* shift by 2 */
extzv %r2,$4,%r3,%r4 /* extract count */
extzv $9,$3,%r1,%r2 /* extract bits 9-11 */
ashl $2,%r2,%r2 /* shift by 2 */
extzv %r2,$4,%r3,%r5 /* extract count */
movq 4(%fp),%r2 /* fetch callframe status & saved AP */
insv %r1,$16,$12,%r2 /* update save mask */
addl3 %r4,%r5,%r1 /* add counts and discard them */
movq 12(%fp),%r4 /* fetch callframe saved FP & PC */
moval 20(%fp)[%r1],%sp/* pop callframe */
extzv $16,$12,%r2,%r1 /* get save mask back */
jbr 22b /* now build the new callframe */
30:
calls $0,_C_LABEL(_rtld_die)
#else
/*
* Check to see if called via call? $n,w^off(reg)
*/
20: addl2 $2,%r1 /* 16-bit displacement */
bicb3 $1,(%r1),%r2 /* fetch opcode of instruction */
cmpb $0xfa,%r2 /* is it calls/callg */
jneq 30f /* no it isn't */
bicb3 $0x1f,2(%r1),%r3/* extract addressing mode */
cmpb $0xc0,%r3 /* 16-bit displacement? */
jeql 11b /* yes, redo the call */
halt
/*
* Check to see if called via call? $n,b^off(reg)
*/
30: incl %r1 /* 8-bit displacement */
bicb3 $1,(%r1),%r2 /* fetch opcode of instruction */
cmpb $0xfa,%r2 /* is it calls/callg */
jneq 40f /* no it isn't */
bicb3 $0x1f,2(%r1),%r3/* extract addressing mode */
cmpb $0xa0,%r3 /* 8-bit displacement? */
jeql 11b /* yes, redo the call */
halt
/*
* Check to see if called via call? $n,(reg)
*/
40: incl %r1 /* no displacement */
bicb3 $1,(%r1),%r2 /* fetch opcode of instruction */
cmpb $0xfa,%r2 /* is it calls/callg */
jeql 41f /* yes it is */
halt /* no, die die die */
41: bicb3 $0x0f,2(%r1),%r2/* extract addressing mode */
bicb3 $0xf0,2(%r1),%r3/* extract register */
extzv $0,$12,6(%fp),%r4/* extract saved mask */
cmpb $0x60,%r2 /* register deferred? */
jeql 42f /* yes, deal with it */
cmpb $0x90,%r2 /* autoincrement deferred? */
jeql 70f /* yes, deal with it */
halt /* no, die die die */
42: cmpw %r4,$0xffc /* did we save r2-r11? */
jneq 50f /* no, deal with it */
jbc %r3,%r4,43f /* is the register in the saved mask? */
/*
* We saved r2-r11, so it's easy to replace the saved register with
* the right value by indexing into saved register (offset by 8).
*/
movl %r0,(20-8)(%fp)[%r3] /* replace address in saved registers */
jbr 11b /* go back and redo call */
/*
* Must have been called via r0 or r1 which are saved locally.
* So move the routine address in the appropriate slot on the stack.
*/
43: movl %r0,(%sp)[%r3]
jbr 11b /* go back and redo call */
50: jbs %r3,%r4,60f /* is the register in the saved mask? */
jbs %r3,$0x3f,43b /* is it r0-r5? */
/*
* The register used for the call was not saved so we need to move
* the new function address into it so the re-call will use the new
* address.
*/
pushl %r0 /* save function address on the stack */
ashl %r5,$1,%r0 /* create a bitmask for the register */
popr %r0 /* pop it off the stack. */
jbr 11b /* and redo the call */
60: clrl %r2 /* starting offset into saved registers */
clrl %r5 /* start with register 0 */
61: cmpl %r2,%r3 /* is the register to save? */
jneq 62f /* no, advance to next */
movl %r0,20(%fp)[%r5]/* yes, save return address in saved reg */
jbr 11b /* and return the call */
62: jbc %r5,%r4,63f /* is this register saved? */
incl %r5 /* yes, account for it */
63: incl %r2 /* increment register number */
jbr 61b /* and loop */
70: cmpb %r3,$12
blss 71f
halt
71: cmpw %r4,$0xffc /* did we save r2-r11? */
jneq 72f /* no, deal with it */
subl2 $4,(20-8)(%fp)[%r3] /* backup incremented register */
jbr 11b /* and redo the call.
72: jbs %r3,%r4,80f
jbs %r3,%3f,74f
ashl %r5,$1,%r0 /* create a bitmask for the register */
pushr %r0 /* pop it off the stack. */
subl2 $4,(%sp) /* backup incremented register */
popr %r0 /* pop it off the stack. */
jbr 11b /* and redo the call.
73: subl2 %4,(%sp)[%r3] /* backup incremented register */
jbr 11b /* and redo the call.
80: clrl %r2 /* starting offset into saved registers */
clrl %r5 /* start with register 0 */
81: cmpl %r2,%r3 /* is the register to save? */
jneq 82f /* no, advance to next */
subl $4,20(%fp)[%r5] /* yes, backup incremented register */
jbr 11b /* and return the call */
82: jbc %r5,%r4,83f /* is this register saved? */
incl %r5 /* yes, account for it */
83: incl %r2 /* increment register number */
jbr 81b /* and loop */
#endif
END(_rtld_bind_start)

View File

@@ -1,4 +1,4 @@
/* $NetBSD: mdreloc.c,v 1.40 2011/03/25 18:07:07 joerg Exp $ */
/* $NetBSD: mdreloc.c,v 1.41 2014/08/25 20:40:53 joerg Exp $ */
/*
* Copyright (c) 2001 Wasabi Systems, Inc.
@@ -68,7 +68,7 @@
#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: mdreloc.c,v 1.40 2011/03/25 18:07:07 joerg Exp $");
__RCSID("$NetBSD: mdreloc.c,v 1.41 2014/08/25 20:40:53 joerg Exp $");
#endif /* not lint */
#include <sys/types.h>
@@ -313,8 +313,15 @@ _rtld_relocate_plt_object(const Obj_Entry *obj, const Elf_Rela *rela, Elf_Addr *
if (__predict_false(def == &_rtld_sym_zero))
return 0;
new_value = (Elf_Addr)(defobj->relocbase + def->st_value +
rela->r_addend);
if (ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC) {
if (tp == NULL)
return 0;
new_value = _rtld_resolve_ifunc(defobj, def);
} else {
new_value = (Elf_Addr)(defobj->relocbase + def->st_value +
rela->r_addend);
}
rdbg(("bind now/fixup in %s --> old=%p new=%p",
defobj->strtab + def->st_name, (void *)*where, (void *)new_value));
if (*where != new_value)