Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/libexec/ld.elf_so/arch/powerpc Make ELF64 aware.
details: https://anonhg.NetBSD.org/src/rev/2d02a33444a9
branches: trunk
changeset: 327373:2d02a33444a9
user: matt <matt%NetBSD.org@localhost>
date: Thu Mar 06 09:34:07 2014 +0000
description:
Make ELF64 aware.
diffstat:
libexec/ld.elf_so/arch/powerpc/ppc_reloc.c | 114 +++++++++++++++++++++-------
1 files changed, 83 insertions(+), 31 deletions(-)
diffs (277 lines):
diff -r dd2358e16650 -r 2d02a33444a9 libexec/ld.elf_so/arch/powerpc/ppc_reloc.c
--- a/libexec/ld.elf_so/arch/powerpc/ppc_reloc.c Thu Mar 06 09:33:14 2014 +0000
+++ b/libexec/ld.elf_so/arch/powerpc/ppc_reloc.c Thu Mar 06 09:34:07 2014 +0000
@@ -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.50 2014/03/06 09:34:07 matt 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.50 2014/03/06 09:34:07 matt Exp $");
#endif /* not lint */
#include <stdarg.h>
@@ -46,19 +46,37 @@
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
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 @@
* 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 @@
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 @@
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 @@
*/
__syncicache(pltcall, (char *)jmptab - (char *)pltcall);
}
+#endif
}
void
@@ -167,8 +196,12 @@
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 @@
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 @@
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 @@
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 @@
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,7 +297,9 @@
int
_rtld_relocate_plt_lazy(const Obj_Entry *obj)
{
+#ifndef _LP64
Elf_Addr * const pltresolve = obj->pltgot + 8;
+#endif
const Elf_Rela *rela;
int reloff;
@@ -275,6 +310,12 @@
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.
@@ -288,9 +329,9 @@
*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;
@@ -304,6 +345,7 @@
*/
/* __syncicache(where - 3, 12); */
}
+#endif
}
return 0;
@@ -332,10 +374,19 @@
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.
+ */
+ assert(where >= (Elf_Word *)obj->pltgot);
+ assert(where < (Elf_Word *)obj->pltgot + (obj->pltrelalim - obj->pltrela));
+ *where = value;
+#else
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));
@@ -363,18 +414,18 @@
} 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,6 +433,7 @@
*where++ = 0x48000000 | (distance & 0x03fffffc);
__syncicache(where - 3, 12);
}
+#endif /* _LP64 */
if (tp)
*tp = value;
Home |
Main Index |
Thread Index |
Old Index