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:
Nathan Whitehorn 2015-12-03 00:10:57 +00:00
parent 87008d7b77
commit 29ba9b6124
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=291668
7 changed files with 111 additions and 16 deletions

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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 */

View File

@ -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; \

View File

@ -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 */