Date: Thu, 3 Dec 2015 00:10:57 +0000 (UTC) From: Nathan Whitehorn <nwhitehorn@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r291668 - in head: lib/csu/powerpc64 libexec/rtld-elf libexec/rtld-elf/powerpc64 sys/powerpc/include sys/powerpc/powerpc Message-ID: <201512030010.tB30AvNc077043@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: nwhitehorn Date: Thu Dec 3 00:10:57 2015 New Revision: 291668 URL: https://svnweb.freebsd.org/changeset/base/291668 Log: Provide support for ELFv2 userland if using a newer compiler (recent clang or gcc) and binutils >= 2.24. Not enabled by default. Modified: head/lib/csu/powerpc64/crti.S head/libexec/rtld-elf/powerpc64/reloc.c head/libexec/rtld-elf/powerpc64/rtld_start.S head/libexec/rtld-elf/rtld.c head/libexec/rtld-elf/rtld.h head/sys/powerpc/include/asm.h head/sys/powerpc/powerpc/sigcode64.S Modified: head/lib/csu/powerpc64/crti.S ============================================================================== --- head/lib/csu/powerpc64/crti.S Thu Dec 3 00:08:50 2015 (r291667) +++ head/lib/csu/powerpc64/crti.S Thu Dec 3 00:10:57 2015 (r291668) @@ -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) Modified: head/libexec/rtld-elf/powerpc64/reloc.c ============================================================================== --- head/libexec/rtld-elf/powerpc64/reloc.c Thu Dec 3 00:08:50 2015 (r291667) +++ head/libexec/rtld-elf/powerpc64/reloc.c Thu Dec 3 00:10:57 2015 (r291668) @@ -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 E ((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 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 * 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 ((struct funcdesc *)(wherep))->toc += (Elf_Addr)defobj->relocbase; } +#else + dbg(" reloc_jmpslot: where=%p, target=%p", (void *)wherep, + (void *)target); + + *wherep = target; +#endif - __asm __volatile("dcbst 0,%0; sync" :: "r"(wherep) : "memory"); + __asm __volatile("sync" ::: "memory"); return (target); } @@ -485,6 +506,20 @@ reloc_gnu_ifunc(Obj_Entry *obj, int flag 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 Modified: head/libexec/rtld-elf/powerpc64/rtld_start.S ============================================================================== --- head/libexec/rtld-elf/powerpc64/rtld_start.S Thu Dec 3 00:08:50 2015 (r291667) +++ head/libexec/rtld-elf/powerpc64/rtld_start.S Thu Dec 3 00:10:57 2015 (r291668) @@ -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 Modified: head/libexec/rtld-elf/rtld.c ============================================================================== --- head/libexec/rtld-elf/rtld.c Thu Dec 3 00:08:50 2015 (r291667) +++ head/libexec/rtld-elf/rtld.c Thu Dec 3 00:10:57 2015 (r291668) @@ -1148,7 +1148,7 @@ digest_dynamic1(Obj_Entry *obj, int earl #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 earl 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; Modified: head/libexec/rtld-elf/rtld.h ============================================================================== --- head/libexec/rtld-elf/rtld.h Thu Dec 3 00:08:50 2015 (r291667) +++ head/libexec/rtld-elf/rtld.h Thu Dec 3 00:10:57 2015 (r291668) @@ -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 */ Modified: head/sys/powerpc/include/asm.h ============================================================================== --- head/sys/powerpc/include/asm.h Thu Dec 3 00:08:50 2015 (r291667) +++ head/sys/powerpc/include/asm.h Thu Dec 3 00:10:57 2015 (r291668) @@ -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; \ Modified: head/sys/powerpc/powerpc/sigcode64.S ============================================================================== --- head/sys/powerpc/powerpc/sigcode64.S Thu Dec 3 00:08:50 2015 (r291667) +++ head/sys/powerpc/powerpc/sigcode64.S Thu Dec 3 00:10:57 2015 (r291668) @@ -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 */
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201512030010.tB30AvNc077043>