diff options
| author | matt <matt@NetBSD.org> | 2014-03-06 19:19:40 +0000 |
|---|---|---|
| committer | matt <matt@NetBSD.org> | 2014-03-06 19:19:40 +0000 |
| commit | fc0d1786ea0d50952fa3cc18a682d08ed8be2f19 (patch) | |
| tree | fd2f8853f2c1678ef218b9662621ec2336cec0ae /libexec | |
| parent | 544cb96e63df96fbe28e8f00651e785dc4139f91 (diff) | |
More PPC64 changes.
Nothing to do for lazy bindings.
Record DT_PPC64_GLINK and make _rtld_bind return it.
When resolving a JMP_SLOT, copy the source function descriptor into the PLTGOT
Diffstat (limited to 'libexec')
| -rw-r--r-- | libexec/ld.elf_so/arch/powerpc/ppc_reloc.c | 44 | ||||
| -rw-r--r-- | libexec/ld.elf_so/arch/powerpc/rtld_start64.S | 5 | ||||
| -rw-r--r-- | libexec/ld.elf_so/headers.c | 10 | ||||
| -rw-r--r-- | libexec/ld.elf_so/rtld.h | 6 |
4 files changed, 39 insertions, 26 deletions
diff --git a/libexec/ld.elf_so/arch/powerpc/ppc_reloc.c b/libexec/ld.elf_so/arch/powerpc/ppc_reloc.c index b1c665d310b..573f292aacf 100644 --- a/libexec/ld.elf_so/arch/powerpc/ppc_reloc.c +++ b/libexec/ld.elf_so/arch/powerpc/ppc_reloc.c @@ -1,4 +1,4 @@ -/* $NetBSD: ppc_reloc.c,v 1.50 2014/03/06 09:34:07 matt Exp $ */ +/* $NetBSD: ppc_reloc.c,v 1.51 2014/03/06 19:19:40 matt Exp $ */ /*- * Copyright (C) 1998 Tsubai Masanari @@ -30,7 +30,7 @@ #include <sys/cdefs.h> #ifndef lint -__RCSID("$NetBSD: ppc_reloc.c,v 1.50 2014/03/06 09:34:07 matt Exp $"); +__RCSID("$NetBSD: ppc_reloc.c,v 1.51 2014/03/06 19:19:40 matt Exp $"); #endif /* not lint */ #include <stdarg.h> @@ -70,8 +70,8 @@ extern const uint64_t _rtld_bind_start[3]; 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 *); @@ -297,9 +297,13 @@ _rtld_relocate_nonplt_objects(Obj_Entry *obj) int _rtld_relocate_plt_lazy(const Obj_Entry *obj) { -#ifndef _LP64 +#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; -#endif const Elf_Rela *rela; int reloff; @@ -310,12 +314,6 @@ _rtld_relocate_plt_lazy(const Obj_Entry *obj) assert(ELF_R_TYPE(rela->r_info) == R_TYPE(JMP_SLOT)); -#ifdef _LP64 - /* - * For now, simply treat then as relative. - */ - *where += (Elf_Addr)obj->relocbase; -#else if (obj->gotptr != NULL) { /* * For now, simply treat then as relative. @@ -345,8 +343,8 @@ _rtld_relocate_plt_lazy(const Obj_Entry *obj) */ /* __syncicache(where - 3, 12); */ } -#endif } +#endif /* !_LP64 */ return 0; } @@ -358,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)); @@ -370,19 +367,22 @@ _rtld_relocate_plt_object(const Obj_Entry *obj, const Elf_Rela *rela, int reloff return 0; value = (Elf_Addr)(defobj->relocbase + def->st_value); - distance = value - (Elf_Addr)where; rdbg(("bind now/fixup in %s --> new=%p", defobj->strtab + def->st_name, (void *)value)); #ifdef _LP64 /* - * For PowerPC64 we simply replace the entry in the PLTGOT with the - * address of the routine. + * 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)); - *where = value; + 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 @@ -391,7 +391,7 @@ _rtld_relocate_plt_object(const Obj_Entry *obj, const Elf_Rela *rela, int reloff 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); @@ -440,7 +440,7 @@ _rtld_relocate_plt_object(const Obj_Entry *obj, const Elf_Rela *rela, int reloff return 0; } -caddr_t +Elf_Addr _rtld_bind(const Obj_Entry *obj, Elf_Word reloff) { const Elf_Rela *rela = obj->pltrela + reloff; @@ -455,7 +455,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 diff --git a/libexec/ld.elf_so/arch/powerpc/rtld_start64.S b/libexec/ld.elf_so/arch/powerpc/rtld_start64.S index 7ec8d314e27..a2e30bfd3f5 100644 --- a/libexec/ld.elf_so/arch/powerpc/rtld_start64.S +++ b/libexec/ld.elf_so/arch/powerpc/rtld_start64.S @@ -1,4 +1,4 @@ -/* $NetBSD: rtld_start64.S,v 1.1 2014/03/06 07:47:19 matt Exp $ */ +/* $NetBSD: rtld_start64.S,v 1.2 2014/03/06 19:19:40 matt Exp $ */ /*- * Copyright (C) 1998 Tsubai Masanari @@ -107,8 +107,7 @@ ENTRY_NOPROFILE(_rtld_bind_start) CALL(_rtld_bind) // _rtld_bind(obj, reloff) mtctr %r3 - ld %r2,8(%r31) // load TOC for function - ld %r11,16(%r31) // load env ptr for function. + mr %r12,%r31 // restore r12 ld %r0,8(%r1) // get saved CR mtcr %r0 // restore it diff --git a/libexec/ld.elf_so/headers.c b/libexec/ld.elf_so/headers.c index 6da1695afb6..ca1ba19cfb4 100644 --- a/libexec/ld.elf_so/headers.c +++ b/libexec/ld.elf_so/headers.c @@ -1,4 +1,4 @@ -/* $NetBSD: headers.c,v 1.52 2013/08/03 13:17:05 skrll Exp $ */ +/* $NetBSD: headers.c,v 1.53 2014/03/06 19:19:40 matt Exp $ */ /* * Copyright 1996 John D. Polstra. @@ -40,7 +40,7 @@ #include <sys/cdefs.h> #ifndef lint -__RCSID("$NetBSD: headers.c,v 1.52 2013/08/03 13:17:05 skrll Exp $"); +__RCSID("$NetBSD: headers.c,v 1.53 2014/03/06 19:19:40 matt Exp $"); #endif /* not lint */ #include <err.h> @@ -298,10 +298,16 @@ _rtld_digest_dynamic(const char *execname, Obj_Entry *obj) break; #endif #ifdef __powerpc__ +#ifdef _LP64 + case DT_PPC64_GLINK: + obj->glink = (Elf_Addr)(obj->relocbase + dynp->d_un.d_ptr); + break; +#else case DT_PPC_GOT: obj->gotptr = (Elf_Addr *)(obj->relocbase + dynp->d_un.d_ptr); break; #endif +#endif case DT_FLAGS_1: obj->z_now = ((dynp->d_un.d_val & DF_1_BIND_NOW) != 0); diff --git a/libexec/ld.elf_so/rtld.h b/libexec/ld.elf_so/rtld.h index 69c02aeeaee..ec15ac86cbc 100644 --- a/libexec/ld.elf_so/rtld.h +++ b/libexec/ld.elf_so/rtld.h @@ -1,4 +1,4 @@ -/* $NetBSD: rtld.h,v 1.116 2013/05/09 15:38:14 christos Exp $ */ +/* $NetBSD: rtld.h,v 1.117 2014/03/06 19:19:40 matt Exp $ */ /* * Copyright 1996 John D. Polstra. @@ -259,8 +259,12 @@ typedef struct Struct_Obj_Entry { * object we know about. */ #ifdef __powerpc__ +#ifdef _LP64 + Elf_Addr glink; /* global linkage */ +#else Elf_Addr *gotptr; /* GOT table (secure-plt only) */ #endif +#endif #if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II) /* Thread Local Storage support for this module */ |
