Make ELF64 aware.
This commit is contained in:
parent
b2757928d7
commit
565a18129d
@ -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 @@ __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
|
||||
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,7 +297,9 @@ _rtld_relocate_nonplt_objects(Obj_Entry *obj)
|
||||
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 @@ _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.
|
||||
@ -288,9 +329,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;
|
||||
@ -304,6 +345,7 @@ _rtld_relocate_plt_lazy(const Obj_Entry *obj)
|
||||
*/
|
||||
/* __syncicache(where - 3, 12); */
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -332,10 +374,19 @@ _rtld_relocate_plt_object(const Obj_Entry *obj, const Elf_Rela *rela, int reloff
|
||||
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 @@ _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,6 +433,7 @@ _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;
|
||||
|
Loading…
Reference in New Issue
Block a user