Provide support for ELFv2 userland if using a newer compiler (recent clang
or gcc) and binutils >= 2.24. Not enabled by default.
This commit is contained in:
parent
87008d7b77
commit
29ba9b6124
@ -26,34 +26,59 @@
|
||||
#include <machine/asm.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#ifdef _CALL_ELF
|
||||
.abiversion _CALL_ELF
|
||||
#endif
|
||||
|
||||
.section .init,"ax",@progbits
|
||||
.align 2
|
||||
.p2align 2
|
||||
.globl _init
|
||||
#if !defined(_CALL_ELF) || _CALL_ELF == 1
|
||||
.section ".opd","aw"
|
||||
.align 3
|
||||
.p2align 3
|
||||
_init:
|
||||
.quad .L._init,.TOC.@tocbase,0
|
||||
.previous
|
||||
.type _init,@function
|
||||
|
||||
.align 4
|
||||
.p2align 4
|
||||
.L._init:
|
||||
#else
|
||||
.p2align 4
|
||||
.globl _init
|
||||
.type _init,@function
|
||||
_init:
|
||||
addis %r2, %r12, (.TOC.-_init)@ha
|
||||
addi %r2, %r2, (.TOC.-_init)@l
|
||||
.localentry _init, .-_init
|
||||
#endif
|
||||
stdu 1,-48(1)
|
||||
mflr 0
|
||||
std 0,64(1)
|
||||
|
||||
/* Fini */
|
||||
.section .fini,"ax",@progbits
|
||||
.align 2
|
||||
.p2align 2
|
||||
.globl _fini
|
||||
#if !defined(_CALL_ELF) || _CALL_ELF == 1
|
||||
.section ".opd","aw"
|
||||
.align 3
|
||||
.p2align 3
|
||||
_fini:
|
||||
.quad .L._fini,.TOC.@tocbase,0
|
||||
.previous
|
||||
.type _fini,@function
|
||||
|
||||
.align 4
|
||||
.p2align 4
|
||||
.L._fini:
|
||||
#else
|
||||
.p2align 4
|
||||
.globl _fini
|
||||
.type _fini,@function
|
||||
_fini:
|
||||
addis %r2, %r12, (.TOC.-_fini)@ha
|
||||
addi %r2, %r2, (.TOC.-_fini)@l
|
||||
.localentry _fini, .-_fini
|
||||
#endif
|
||||
stdu 1,-48(1)
|
||||
mflr 0
|
||||
std 0,64(1)
|
||||
|
@ -43,11 +43,13 @@
|
||||
#include "debug.h"
|
||||
#include "rtld.h"
|
||||
|
||||
#if !defined(_CALL_ELF) || _CALL_ELF == 1
|
||||
struct funcdesc {
|
||||
Elf_Addr addr;
|
||||
Elf_Addr toc;
|
||||
Elf_Addr env;
|
||||
};
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Process the R_PPC_COPY relocations
|
||||
@ -336,11 +338,14 @@ static int
|
||||
reloc_plt_object(Obj_Entry *obj, const Elf_Rela *rela)
|
||||
{
|
||||
Elf_Addr *where = (Elf_Addr *)(obj->relocbase + rela->r_offset);
|
||||
#if !defined(_CALL_ELF) || _CALL_ELF == 1
|
||||
Elf_Addr *glink;
|
||||
#endif
|
||||
long reloff;
|
||||
|
||||
reloff = rela - obj->pltrela;
|
||||
|
||||
#if !defined(_CALL_ELF) || _CALL_ELF == 1
|
||||
if (obj->priv == NULL)
|
||||
obj->priv = xmalloc(obj->pltrelasize);
|
||||
glink = obj->priv + reloff*sizeof(Elf_Addr)*2;
|
||||
@ -351,6 +356,10 @@ reloc_plt_object(Obj_Entry *obj, const Elf_Rela *rela)
|
||||
((struct funcdesc *)(where))->env = (Elf_Addr)glink;
|
||||
*(glink++) = (Elf_Addr)obj;
|
||||
*(glink++) = reloff*sizeof(Elf_Rela);
|
||||
#else
|
||||
dbg(" reloc_plt_object: where=%p,reloff=%lx,glink=%#lx", (void *)where, reloff, obj->glink);
|
||||
*where = (Elf_Addr)obj->glink + 4*reloff + 32;
|
||||
#endif
|
||||
|
||||
return (0);
|
||||
}
|
||||
@ -416,7 +425,11 @@ reloc_jmpslots(Obj_Entry *obj, int flags, RtldLockState *lockstate)
|
||||
|
||||
if (def == &sym_zero) {
|
||||
/* Zero undefined weak symbols */
|
||||
#if !defined(_CALL_ELF) || _CALL_ELF == 1
|
||||
bzero(where, sizeof(struct funcdesc));
|
||||
#else
|
||||
*where = 0;
|
||||
#endif
|
||||
} else {
|
||||
reloc_jmpslot(where, target, defobj, obj,
|
||||
(const Elf_Rel *) rela);
|
||||
@ -436,9 +449,6 @@ Elf_Addr
|
||||
reloc_jmpslot(Elf_Addr *wherep, Elf_Addr target, const Obj_Entry *defobj,
|
||||
const Obj_Entry *obj, const Elf_Rel *rel)
|
||||
{
|
||||
dbg(" reloc_jmpslot: where=%p, target=%p (%#lx + %#lx)",
|
||||
(void *)wherep, (void *)target, *(Elf_Addr *)target,
|
||||
(Elf_Addr)defobj->relocbase);
|
||||
|
||||
/*
|
||||
* At the PLT entry pointed at by `wherep', construct
|
||||
@ -446,6 +456,11 @@ reloc_jmpslot(Elf_Addr *wherep, Elf_Addr target, const Obj_Entry *defobj,
|
||||
* address.
|
||||
*/
|
||||
|
||||
#if !defined(_CALL_ELF) || _CALL_ELF == 1
|
||||
dbg(" reloc_jmpslot: where=%p, target=%p (%#lx + %#lx)",
|
||||
(void *)wherep, (void *)target, *(Elf_Addr *)target,
|
||||
(Elf_Addr)defobj->relocbase);
|
||||
|
||||
memcpy(wherep, (void *)target, sizeof(struct funcdesc));
|
||||
if (((struct funcdesc *)(wherep))->addr < (Elf_Addr)defobj->relocbase) {
|
||||
/*
|
||||
@ -459,8 +474,14 @@ reloc_jmpslot(Elf_Addr *wherep, Elf_Addr target, const Obj_Entry *defobj,
|
||||
((struct funcdesc *)(wherep))->toc +=
|
||||
(Elf_Addr)defobj->relocbase;
|
||||
}
|
||||
#else
|
||||
dbg(" reloc_jmpslot: where=%p, target=%p", (void *)wherep,
|
||||
(void *)target);
|
||||
|
||||
__asm __volatile("dcbst 0,%0; sync" :: "r"(wherep) : "memory");
|
||||
*wherep = target;
|
||||
#endif
|
||||
|
||||
__asm __volatile("sync" ::: "memory");
|
||||
|
||||
return (target);
|
||||
}
|
||||
@ -485,6 +506,20 @@ reloc_gnu_ifunc(Obj_Entry *obj, int flags,
|
||||
void
|
||||
init_pltgot(Obj_Entry *obj)
|
||||
{
|
||||
#if defined(_CALL_ELF) && _CALL_ELF == 2
|
||||
Elf_Addr *pltcall;
|
||||
|
||||
pltcall = obj->pltgot;
|
||||
|
||||
if (pltcall == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
pltcall[0] = (Elf_Addr)&_rtld_bind_start;
|
||||
pltcall[1] = (Elf_Addr)obj;
|
||||
|
||||
__asm __volatile("sync" ::: "memory");
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -82,9 +82,13 @@ _ENTRY(_rtld_start)
|
||||
|
||||
bl _rtld /* &_start = _rtld(sp, &exit_proc, &obj_main)*/
|
||||
nop
|
||||
#if !defined(_CALL_ELF) || _CALL_ELF == 1
|
||||
ld %r2,8(%r3)
|
||||
ld %r11,16(%r3)
|
||||
ld %r3,0(%r3)
|
||||
#else
|
||||
mr %r12,%r3
|
||||
#endif
|
||||
mtlr %r3
|
||||
|
||||
/*
|
||||
@ -106,7 +110,11 @@ _ENTRY(_rtld_start)
|
||||
* _rtld_bind_start()
|
||||
*
|
||||
* Call into the MI binder. This routine is reached via the PLT call cell
|
||||
* On entry, %r11 contains a pointer to the (object, relocation) tuple.
|
||||
*
|
||||
* For ELFv1, on entry, %r11 contains a pointer to the (object, relocation)
|
||||
* tuple.
|
||||
*
|
||||
* For ELFv2, %r11 contains an object pointer and %r0 contains the PLT index.
|
||||
*
|
||||
* Save all registers, call into the binder to resolve and fixup the external
|
||||
* routine, and then transfer to the external routine on return.
|
||||
@ -114,6 +122,7 @@ _ENTRY(_rtld_start)
|
||||
.globl _rtld_bind
|
||||
|
||||
_ENTRY(_rtld_bind_start)
|
||||
mr %r12,%r0 # shunt r0 immediately to r12 for ELFv2
|
||||
mflr %r0
|
||||
std %r0,16(%r1) # save lr
|
||||
mfcr %r0
|
||||
@ -121,7 +130,7 @@ _ENTRY(_rtld_bind_start)
|
||||
|
||||
stdu %r1,-48-12*8(%r1) # stack space for 8 regs + header
|
||||
# + 2 save regs
|
||||
std %r3,64+0*8(%r1) # save r3-r31
|
||||
std %r3,64+0*8(%r1) # save r3-r10 (arguments)
|
||||
std %r4,64+1*8(%r1)
|
||||
std %r5,64+2*8(%r1)
|
||||
std %r6,64+3*8(%r1)
|
||||
@ -129,19 +138,27 @@ _ENTRY(_rtld_bind_start)
|
||||
std %r8,64+5*8(%r1)
|
||||
std %r9,64+6*8(%r1)
|
||||
std %r10,64+7*8(%r1)
|
||||
std %r12,64+8*8(%r1)
|
||||
|
||||
#if !defined(_CALL_ELF) || _CALL_ELF == 1
|
||||
ld %r3,0(%r11)
|
||||
ld %r4,8(%r11)
|
||||
#else
|
||||
mr %r3,%r11
|
||||
mulli %r4,%r12,24 /* Multiply index by sizeof(Elf_Rela) */
|
||||
#endif
|
||||
bl _rtld_bind # target addr = _rtld_bind(obj, reloff)
|
||||
nop
|
||||
|
||||
#if !defined(_CALL_ELF) || _CALL_ELF == 1
|
||||
ld %r2,8(%r3)
|
||||
ld %r11,16(%r3)
|
||||
ld %r3,0(%r3)
|
||||
#else
|
||||
mr %r12,%r3
|
||||
#endif
|
||||
mtctr %r3 # move absolute target addr into ctr
|
||||
|
||||
ld %r3,64+0*8(%r1) # restore r3-r31
|
||||
ld %r3,64+0*8(%r1) # restore r3-r10
|
||||
ld %r4,64+1*8(%r1)
|
||||
ld %r5,64+2*8(%r1)
|
||||
ld %r6,64+3*8(%r1)
|
||||
@ -149,7 +166,6 @@ _ENTRY(_rtld_bind_start)
|
||||
ld %r8,64+5*8(%r1)
|
||||
ld %r9,64+6*8(%r1)
|
||||
ld %r10,64+7*8(%r1)
|
||||
ld %r12,64+8*8(%r1)
|
||||
|
||||
ld %r1,0(%r1) # restore stack
|
||||
ld %r0,8(%r1) # restore cr
|
||||
|
@ -1148,7 +1148,7 @@ digest_dynamic1(Obj_Entry *obj, int early, const Elf_Dyn **dyn_rpath,
|
||||
#ifdef __mips__
|
||||
case DT_MIPS_LOCAL_GOTNO:
|
||||
obj->local_gotno = dynp->d_un.d_val;
|
||||
break;
|
||||
break;
|
||||
|
||||
case DT_MIPS_SYMTABNO:
|
||||
obj->symtabno = dynp->d_un.d_val;
|
||||
@ -1163,6 +1163,12 @@ digest_dynamic1(Obj_Entry *obj, int early, const Elf_Dyn **dyn_rpath,
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef __powerpc64__
|
||||
case DT_PPC64_GLINK:
|
||||
obj->glink = (Elf_Addr) (obj->relocbase + dynp->d_un.d_ptr);
|
||||
break;
|
||||
#endif
|
||||
|
||||
case DT_FLAGS_1:
|
||||
if (dynp->d_un.d_val & DF_1_NOOPEN)
|
||||
obj->z_noopen = true;
|
||||
|
@ -187,6 +187,9 @@ typedef struct Struct_Obj_Entry {
|
||||
Elf_Word symtabno; /* Number of dynamic symbols */
|
||||
Elf_Word gotsym; /* First dynamic symbol in GOT */
|
||||
#endif
|
||||
#ifdef __powerpc64__
|
||||
Elf_Addr glink; /* GLINK PLT call stub section */
|
||||
#endif
|
||||
|
||||
const Elf_Verneed *verneed; /* Required versions. */
|
||||
Elf_Word verneednum; /* Number of entries in verneed table */
|
||||
|
@ -61,17 +61,26 @@
|
||||
#define HIDENAME(asmsym) __CONCAT(.,asmsym)
|
||||
#endif
|
||||
|
||||
#if !defined(_CALL_ELF) || _CALL_ELF == 1
|
||||
#ifdef _KERNEL
|
||||
/* ELFv1 kernel uses global dot symbols */
|
||||
#define DOT_LABEL(name) __CONCAT(.,name)
|
||||
#define TYPE_ENTRY(name) .size name,24; \
|
||||
.type DOT_LABEL(name),@function; \
|
||||
.globl DOT_LABEL(name);
|
||||
#define END_SIZE(name) .size DOT_LABEL(name),.-DOT_LABEL(name);
|
||||
#else /* !_KERNEL */
|
||||
/* ELFv1 user code uses local function entry points */
|
||||
#define DOT_LABEL(name) __CONCAT(.L.,name)
|
||||
#define TYPE_ENTRY(name) .type name,@function;
|
||||
#define END_SIZE(name) .size name,.-DOT_LABEL(name);
|
||||
#endif /* _KERNEL */
|
||||
#else
|
||||
/* ELFv2 doesn't have any of this complication */
|
||||
#define DOT_LABEL(name) name
|
||||
#define TYPE_ENTRY(name) .type name,@function;
|
||||
#define END_SIZE(name) .size name,.-DOT_LABEL(name);
|
||||
#endif
|
||||
|
||||
#define _GLOBAL(name) \
|
||||
.data; \
|
||||
|
@ -57,6 +57,7 @@ CNAME(sigcode64):
|
||||
|
||||
CNAME(sigcode64_elfv2):
|
||||
addi 1,1,-112 /* reserved space for callee */
|
||||
mflr 12 /* ELFv2 wants the address in r12 */
|
||||
blrl
|
||||
|
||||
addi 3,1,112+SF_UC /* restore sp, and get &frame->sf_uc */
|
||||
|
Loading…
x
Reference in New Issue
Block a user