Index: contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/PPC.cpp =================================================================== --- contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/PPC.cpp +++ contrib/llvm/tools/clang/lib/Driver/ToolChains/Arch/PPC.cpp @@ -116,7 +116,8 @@ const ArgList &Args) { if (Args.getLastArg(options::OPT_msecure_plt)) return ppc::ReadGOTPtrMode::SecurePlt; - if (Triple.isOSOpenBSD()) + if (Triple.isOSOpenBSD() || + (Triple.isOSFreeBSD() && Triple.getOSMajorVersion() >= 13)) return ppc::ReadGOTPtrMode::SecurePlt; else return ppc::ReadGOTPtrMode::Bss; Index: gnu/usr.bin/cc/cc_tools/Makefile.hdrs =================================================================== --- gnu/usr.bin/cc/cc_tools/Makefile.hdrs +++ gnu/usr.bin/cc/cc_tools/Makefile.hdrs @@ -21,6 +21,9 @@ TARGET_INC+= ${GCC_CPU}/unix.h TARGET_INC+= ${GCC_CPU}/att.h .endif +.if ${TARGET_CPUARCH} == "powerpc" +TARGET_INC+= ${GCC_CPU}/secureplt.h +.endif TARGET_INC+= dbxelf.h TARGET_INC+= elfos-undef.h TARGET_INC+= elfos.h Index: gnu/usr.bin/cc/cc_tools/auto-host.h =================================================================== --- gnu/usr.bin/cc/cc_tools/auto-host.h +++ gnu/usr.bin/cc/cc_tools/auto-host.h @@ -261,7 +261,7 @@ /* Define if your assembler supports R_PPC_REL16 relocs. */ #ifndef USED_FOR_TARGET -#define HAVE_AS_REL16 +#define HAVE_AS_REL16 1 #endif Index: lib/libc/powerpc/SYS.h =================================================================== --- lib/libc/powerpc/SYS.h +++ lib/libc/powerpc/SYS.h @@ -44,7 +44,7 @@ #define SYSCALL(name) \ .text; \ .align 2; \ -2: b PIC_PLT(CNAME(HIDENAME(cerror))); \ +2: b CNAME(HIDENAME(cerror)); \ ENTRY(__sys_##name); \ WEAK_REFERENCE(__sys_##name, name); \ WEAK_REFERENCE(__sys_##name, _##name); \ @@ -58,15 +58,14 @@ WEAK_REFERENCE(__sys_##name, _##name); \ _SYSCALL(name); \ bnslr; \ - b PIC_PLT(CNAME(HIDENAME(cerror))) + b CNAME(HIDENAME(cerror)) #define RSYSCALL(name) \ .text; \ .align 2; \ -2: b PIC_PLT(CNAME(HIDENAME(cerror))); \ ENTRY(__sys_##name); \ WEAK_REFERENCE(__sys_##name, name); \ WEAK_REFERENCE(__sys_##name, _##name); \ _SYSCALL(name); \ bnslr; \ - b PIC_PLT(CNAME(HIDENAME(cerror))) + b CNAME(HIDENAME(cerror)) Index: lib/libc/powerpc/gen/_ctx_start.S =================================================================== --- lib/libc/powerpc/gen/_ctx_start.S +++ lib/libc/powerpc/gen/_ctx_start.S @@ -35,12 +35,12 @@ mtlr %r14 blrl /* branch to start function */ mr %r3,%r15 /* pass pointer to ucontext as argument */ - bl PIC_PLT(CNAME(_ctx_done)) /* branch to ctxt completion func */ + bl CNAME(_ctx_done) /* branch to ctxt completion func */ /* * we should never return from the * above branch. */ - bl PIC_PLT(CNAME(abort)) /* abort */ + bl CNAME(abort) /* abort */ END(_cts_start) .section .note.GNU-stack,"",%progbits Index: lib/libc/powerpc/sys/cerror.S =================================================================== --- lib/libc/powerpc/sys/cerror.S +++ lib/libc/powerpc/sys/cerror.S @@ -40,16 +40,27 @@ */ HIDENAME(cerror): mflr %r0 - stwu %r1,-16(%r1) /* allocate new stack frame */ - stw %r0,20(%r1) /* and save lr, r31 */ - stw %r31,8(%r1) + stwu %r1,-20(%r1) /* allocate new stack frame */ + stw %r0,24(%r1) /* and save lr, r31 */ + stw %r31,12(%r1) +#ifdef __PIC__ + stw %r30,8(%r1) + bcl 20,31,1f +1: + mflr %r30 + addis %r30,%r30,_GLOBAL_OFFSET_TABLE_-1b@ha + addi %r30,%r30,_GLOBAL_OFFSET_TABLE_-1b@l +#endif mr %r31,%r3 /* stash errval in callee-saved register */ bl PIC_PLT(CNAME(__error)) stw %r31,0(%r3) /* store errval into &errno */ - lwz %r0,20(%r1) - lwz %r31,8(%r1) + lwz %r0,24(%r1) + lwz %r31,12(%r1) +#ifdef __PIC__ + lwz %r30,8(%r1) +#endif mtlr %r0 - la %r1,16(%r1) + la %r1,20(%r1) li %r3,-1 li %r4,-1 blr /* return to callers caller */ Index: libexec/rtld-elf/powerpc/reloc.c =================================================================== --- libexec/rtld-elf/powerpc/reloc.c +++ libexec/rtld-elf/powerpc/reloc.c @@ -57,6 +57,8 @@ #define JMPTAB_BASE(N) (18 + N*2 + ((N > PLT_EXTENDED_BEGIN) ? \ (N - PLT_EXTENDED_BEGIN)*2 : 0)) +void _rtld_bind_secureplt_start(void); + /* * Process the R_PPC_COPY relocations */ @@ -361,6 +363,11 @@ if (reloff < 0) return (-1); + if (obj->gotptr != NULL) { + *where += (Elf_Addr)obj->relocbase; + return (0); + } + pltlongresolve = obj->pltgot + 5; pltresolve = pltlongresolve + 5; @@ -425,7 +432,7 @@ * Sync the icache for the byte range represented by the * trampoline routines and call slots. */ - if (obj->pltgot != NULL) + if (obj->pltgot != NULL && obj->gotptr == NULL) __syncicache(obj->pltgot, JMPTAB_BASE(N)*4); return (0); @@ -501,6 +508,14 @@ */ offset = target - (Elf_Addr)wherep; + if (obj->gotptr != NULL) { + assert(wherep >= (Elf_Word *)obj->pltgot); + assert(wherep < + (Elf_Word *)obj->pltgot + obj->pltrelasize); + *wherep = target; + goto out; + } + if (abs((int)offset) < 32*1024*1024) { /* inside 32MB? */ /* b value # branch directly */ *wherep = 0x48000000 | (offset & 0x03fffffc); @@ -579,6 +594,16 @@ return; } + /* Handle Secure-PLT first, if applicable. */ + if (obj->gotptr != NULL) { + obj->gotptr[1] = (Elf_Addr)_rtld_bind_secureplt_start; + obj->gotptr[2] = (Elf_Addr)obj; + dbg("obj %s secure-plt gotptr=%p start=%p obj=%p", + obj->path, obj->gotptr, + (void *)obj->gotptr[1], (void *)obj->gotptr[2]); + return; + } + /* * From the SVR4 PPC ABI: * Index: libexec/rtld-elf/powerpc/rtld_start.S =================================================================== --- libexec/rtld-elf/powerpc/rtld_start.S +++ libexec/rtld-elf/powerpc/rtld_start.S @@ -52,35 +52,22 @@ * - use link-time constants to determine offset to the * _DYNAMIC section and the GOT. Add these to the PC to * convert to absolute addresses. - * - sync icache to allow execution of the SVR4 ABI-specified - * blrl instruction preceding the GOT - * - Use this instruction to determine the GOT absolute address * - read GOT[0], which is the SVR4 ABI-specified link-time * value of _DYNAMIC. Subtract this value from the absolute * value to determine the load address * - call reloc_non_plt_self() to fix up ld-elf.so's relocations */ - bl 1f - .long _DYNAMIC-. - .long _GLOBAL_OFFSET_TABLE_-. /* branch lr + 4 */ -1: - mflr %r3 /* PC value at .long */ - lwz %r4,4(%r3) - add %r4,%r4,%r3 /* &_GLOBAL_OFFSET_TABLE-4, blrl insn. */ - dcbst %r0,%r4 /* sync i-cache with d-cache */ - sync - icbi %r0,%r4 - isync - - lwz %r4,0(%r3) /* offset to _DYNAMIC */ - add %r3,%r4,%r3 /* r3 = &_DYNAMIC, absolute value */ - - bl _GLOBAL_OFFSET_TABLE_@local-4 - mflr %r4 /* &_GLOBAL_OFFSET_TABLE_, absolute value */ - lwz %r4,0(%r4) /* linker &_DYNAMIC, from got[0] */ - subf %r4,%r4,%r3 /* subtract to calculate relocbase */ - - bl reloc_non_plt_self@plt /* reloc_non_plt_self(&_DYNAMIC,base) */ + bcl 20,31,1f +1: mflr %r30 + mr %r3,%r30 # save for _DYNAMIC + addis %r30,%r30,_GLOBAL_OFFSET_TABLE_-1b@ha + addi %r30,%r30,_GLOBAL_OFFSET_TABLE_-1b@l + addis %r3,%r3,_DYNAMIC-1b@ha # get _DYNAMIC actual address + addi %r3,%r3,_DYNAMIC-1b@l + lwz %r28,0(%r30) # get base-relative &_DYNAMIC + sub %r28,%r3,%r28 # r28 = relocbase + mr %r4,%r28 # r4 = relocbase + bl reloc_non_plt_self /* reloc_non_plt_self(&_DYNAMIC,base) */ /* * The _rtld() function likes to see a stack layout containing @@ -95,7 +82,7 @@ addi %r4,%r1,8 /* &exit_proc on stack */ addi %r5,%r1,12 /* &obj_main on stack */ - bl _rtld@plt /* &_start = _rtld(sp, &exit_proc, &obj_main)*/ + bl _rtld /* &_start = _rtld(sp, &exit_proc, &obj_main)*/ mtlr %r3 /* @@ -114,6 +101,29 @@ li %r0,1 /* _exit() */ sc +/* + * _rtld_bind_secureplt_start() + * + * Call into the MI binder (Secure-PLT stub). + * secure-plt expects %r11 to be the offset to the rela entry. + * bss-plt expects %r11 to be index of the rela entry. + * So for bss-plt, we multiply the index by 12 to get the offset. + */ +_ENTRY(_rtld_bind_secureplt_start) + stwu %r1,-160(%r1) # stack space for 29 regs + r0/lr/cr + stw %r0,20(%r1) # save r0 + + /* + * Instead of division which is costly we will use multiplicative + * inverse. a / n = ((a * inv(n)) >> 32) + * where inv(n) = (0x100000000 + n - 1) / n + */ + mr %r0,%r11 + lis %r11,0x15555556@h # load multiplicative inverse of 12 + ori %r11,%r11,0x15555556@l + mulhwu %r11,%r11,%r0 # get high half of multiplication + b 1f + /* * _rtld_bind_start() * @@ -129,6 +139,7 @@ _ENTRY(_rtld_bind_start) stwu %r1,-160(%r1) # stack space for 29 regs + r0/lr/cr stw %r0,20(%r1) # save r0 +1: mflr %r0 stw %r0,16(%r1) # save lr mfcr %r0 @@ -137,7 +148,7 @@ mr %r3,%r12 # obj mulli %r4,%r11,12 # rela index * sizeof(Elf_Rela) - bl _rtld_bind@PLT # target addr = _rtld_bind(obj, reloff) + bl _rtld_bind # target addr = _rtld_bind(obj, reloff) mtctr %r3 # move absolute target addr into ctr lmw %r3,24(%r1) # restore r3-r31 Index: libexec/rtld-elf/rtld.h =================================================================== --- libexec/rtld-elf/rtld.h +++ libexec/rtld-elf/rtld.h @@ -190,8 +190,12 @@ Elf_Word gotsym; /* First dynamic symbol in GOT */ Elf_Addr *mips_pltgot; /* Second PLT GOT */ #endif +#ifdef __powerpc__ #ifdef __powerpc64__ Elf_Addr glink; /* GLINK PLT call stub section */ +#else + Elf_Addr *gotptr; /* GOT pointer (secure-plt only) */ +#endif #endif const Elf_Verneed *verneed; /* Required versions. */ Index: libexec/rtld-elf/rtld.c =================================================================== --- libexec/rtld-elf/rtld.c +++ libexec/rtld-elf/rtld.c @@ -1286,10 +1286,16 @@ #endif +#ifdef __powerpc__ #ifdef __powerpc64__ case DT_PPC64_GLINK: obj->glink = (Elf_Addr)(obj->relocbase + dynp->d_un.d_ptr); break; +#else + case DT_PPC_GOT: + obj->gotptr = (Elf_Addr *)(obj->relocbase + dynp->d_un.d_ptr); + break; +#endif #endif case DT_FLAGS_1: