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 */
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to