diff options
Diffstat (limited to 'packages/glibc/2.17/0061-glibc-ppc64le-39.patch')
-rw-r--r-- | packages/glibc/2.17/0061-glibc-ppc64le-39.patch | 508 |
1 files changed, 508 insertions, 0 deletions
diff --git a/packages/glibc/2.17/0061-glibc-ppc64le-39.patch b/packages/glibc/2.17/0061-glibc-ppc64le-39.patch new file mode 100644 index 0000000..f837d99 --- /dev/null +++ b/packages/glibc/2.17/0061-glibc-ppc64le-39.patch @@ -0,0 +1,508 @@ +# commit 696caf1d002ff059ddd20fd5eaccd76229c14850 +# Author: Ulrich Weigand <Ulrich.Weigand@de.ibm.com> +# Date: Wed Dec 4 06:51:11 2013 -0600 +# +# PowerPC64 ELFv2 ABI 2/6: Remove function descriptors +# +# This patch adds support for the ELFv2 ABI feature to remove function +# descriptors. See this GCC patch for in-depth discussion: +# http://gcc.gnu.org/ml/gcc-patches/2013-11/msg01141.html +# +# This mostly involves two types of changes: updating assembler source +# files to the new logic, and updating the dynamic loader. +# +# After the refactoring in the previous patch, most of the assembler source +# changes can be handled simply by providing ELFv2 versions of the +# macros in sysdep.h. One somewhat non-obvious change is in __GI__setjmp: +# this used to "fall through" to the immediately following __setjmp ENTRY +# point. This is no longer safe in the ELFv2 since ENTRY defines both +# a global and a local entry point, and you cannot simply fall through +# to a global entry point as it requires r12 to be set up. +# +# Also, makecontext needs to be updated to set up registers according to +# the new ABI for calling into the context's start routine. +# +# The dynamic linker changes mostly consist of removing special code +# to handle function descriptors. We also need to support the new PLT +# and glink format used by the the ELFv2 linker, see: +# https://sourceware.org/ml/binutils/2013-10/msg00376.html +# +# In addition, the dynamic linker now verifies that the dynamic libraries +# it loads match its own ABI. +# +# The hack in VDSO_IFUNC_RET to "synthesize" a function descriptor +# for vDSO routines is also no longer necessary for ELFv2. +# +diff -urN glibc-2.17-c758a686/elf/elf.h glibc-2.17-c758a686/elf/elf.h +--- glibc-2.17-c758a686/elf/elf.h 2014-05-29 13:58:25.000000000 -0500 ++++ glibc-2.17-c758a686/elf/elf.h 2014-05-29 13:58:25.000000000 -0500 +@@ -2263,6 +2263,12 @@ + #define R_PPC64_REL16_HI 251 /* half16 (sym+add-.)@h */ + #define R_PPC64_REL16_HA 252 /* half16 (sym+add-.)@ha */ + ++/* e_flags bits specifying ABI. ++ 1 for original function descriptor using ABI, ++ 2 for revised ABI without function descriptors, ++ 0 for unspecified or not using any features affected by the differences. */ ++#define EF_PPC64_ABI 3 ++ + /* PowerPC64 specific values for the Dyn d_tag field. */ + #define DT_PPC64_GLINK (DT_LOPROC + 0) + #define DT_PPC64_OPD (DT_LOPROC + 1) +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/crti.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/crti.S +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/crti.S 2014-05-29 13:58:25.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/crti.S 2014-05-29 13:58:25.000000000 -0500 +@@ -64,6 +64,7 @@ + ENTRY_2(_init) + .align ALIGNARG (2) + BODY_LABEL (_init): ++ LOCALENTRY(_init) + mflr 0 + std 0, 16(r1) + stdu r1, -112(r1) +@@ -81,6 +82,7 @@ + ENTRY_2(_fini) + .align ALIGNARG (2) + BODY_LABEL (_fini): ++ LOCALENTRY(_fini) + mflr 0 + std 0, 16(r1) + stdu r1, -112(r1) +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/dl-irel.h glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/dl-irel.h +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/dl-irel.h 2014-05-29 13:58:25.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/dl-irel.h 2014-05-29 13:58:25.000000000 -0500 +@@ -50,7 +50,11 @@ + { + Elf64_Addr *const reloc_addr = (void *) reloc->r_offset; + Elf64_Addr value = elf_ifunc_invoke(reloc->r_addend); ++#if _CALL_ELF != 2 + *(Elf64_FuncDesc *) reloc_addr = *(Elf64_FuncDesc *) value; ++#else ++ *reloc_addr = value; ++#endif + } + else + __libc_fatal ("unexpected reloc type in static binary"); +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/dl-machine.h glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/dl-machine.h +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/dl-machine.h 2014-05-29 13:58:25.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/dl-machine.h 2014-05-29 14:05:46.000000000 -0500 +@@ -31,6 +31,7 @@ + in l_info array. */ + #define DT_PPC64(x) (DT_PPC64_##x - DT_LOPROC + DT_NUM) + ++#if _CALL_ELF != 2 + /* A PowerPC64 function descriptor. The .plt (procedure linkage + table) and .opd (official procedure descriptor) sections are + arrays of these. */ +@@ -40,6 +41,7 @@ + Elf64_Addr fd_toc; + Elf64_Addr fd_aux; + } Elf64_FuncDesc; ++#endif + + #define ELF_MULT_MACHINES_SUPPORTED + +@@ -47,6 +49,18 @@ + static inline int + elf_machine_matches_host (const Elf64_Ehdr *ehdr) + { ++ /* Verify that the binary matches our ABI version. */ ++ if ((ehdr->e_flags & EF_PPC64_ABI) != 0) ++ { ++#if _CALL_ELF != 2 ++ if ((ehdr->e_flags & EF_PPC64_ABI) != 1) ++ return 0; ++#else ++ if ((ehdr->e_flags & EF_PPC64_ABI) != 2) ++ return 0; ++#endif ++ } ++ + return ehdr->e_machine == EM_PPC64; + } + +@@ -124,6 +138,7 @@ + " .align 2\n" \ + " " ENTRY_2(_start) "\n" \ + BODY_PREFIX "_start:\n" \ ++" " LOCALENTRY(_start) "\n" \ + /* We start with the following on the stack, from top: \ + argc (4 bytes); \ + arguments for program (terminated by NULL); \ +@@ -165,6 +180,7 @@ + Changing these is strongly discouraged (not least because argc is \ + passed by value!). */ \ + BODY_PREFIX "_dl_start_user:\n" \ ++" " LOCALENTRY(_dl_start_user) "\n" \ + /* the address of _start in r30. */ \ + " mr 30,3\n" \ + /* &_dl_argc in 29, &_dl_argv in 27, and _dl_loaded in 28. */ \ +@@ -256,8 +272,22 @@ + relocations behave "normally", ie. always use the real address + like PLT relocations. So always set ELF_RTYPE_CLASS_PLT. */ + ++#if _CALL_ELF != 2 + #define elf_machine_type_class(type) \ + (ELF_RTYPE_CLASS_PLT | (((type) == R_PPC64_COPY) * ELF_RTYPE_CLASS_COPY)) ++#else ++/* And now that you have read that large comment, you can disregard it ++ all for ELFv2. ELFv2 does need the special SHN_UNDEF treatment. */ ++#define IS_PPC64_TLS_RELOC(R) \ ++ (((R) >= R_PPC64_TLS && (R) <= R_PPC64_DTPREL16_HIGHESTA) \ ++ || ((R) >= R_PPC64_TPREL16_HIGH && (R) <= R_PPC64_DTPREL16_HIGHA)) ++ ++#define elf_machine_type_class(type) \ ++ ((((type) == R_PPC64_JMP_SLOT \ ++ || (type) == R_PPC64_ADDR24 \ ++ || IS_PPC64_TLS_RELOC (type)) * ELF_RTYPE_CLASS_PLT) \ ++ | (((type) == R_PPC64_COPY) * ELF_RTYPE_CLASS_COPY)) ++#endif + + /* A reloc type used for ld.so cmdline arg lookups to reject PLT entries. */ + #define ELF_MACHINE_JMP_SLOT R_PPC64_JMP_SLOT +@@ -266,8 +296,19 @@ + #define ELF_MACHINE_NO_REL 1 + + /* Stuff for the PLT. */ ++#if _CALL_ELF != 2 + #define PLT_INITIAL_ENTRY_WORDS 3 ++#define PLT_ENTRY_WORDS 3 + #define GLINK_INITIAL_ENTRY_WORDS 8 ++/* The first 32k entries of glink can set an index and branch using two ++ instructions; past that point, glink uses three instructions. */ ++#define GLINK_ENTRY_WORDS(I) (((I) < 0x8000)? 2 : 3) ++#else ++#define PLT_INITIAL_ENTRY_WORDS 2 ++#define PLT_ENTRY_WORDS 1 ++#define GLINK_INITIAL_ENTRY_WORDS 8 ++#define GLINK_ENTRY_WORDS(I) 1 ++#endif + + #define PPC_DCBST(where) asm volatile ("dcbst 0,%0" : : "r"(where) : "memory") + #define PPC_DCBT(where) asm volatile ("dcbt 0,%0" : : "r"(where) : "memory") +@@ -312,17 +353,12 @@ + + if (lazy) + { +- /* The function descriptor of the appropriate trampline +- routine is used to set the 1st and 2nd doubleword of the +- plt_reserve. */ +- Elf64_FuncDesc *resolve_fd; + Elf64_Word glink_offset; +- /* the plt_reserve area is the 1st 3 doublewords of the PLT */ +- Elf64_FuncDesc *plt_reserve = (Elf64_FuncDesc *) plt; + Elf64_Word offset; ++ Elf64_Addr dlrr; + +- resolve_fd = (Elf64_FuncDesc *) (profile ? _dl_profile_resolve +- : _dl_runtime_resolve); ++ dlrr = (Elf64_Addr) (profile ? _dl_profile_resolve ++ : _dl_runtime_resolve); + if (profile && GLRO(dl_profile) != NULL + && _dl_name_match_p (GLRO(dl_profile), map)) + /* This is the object we are looking for. Say that we really +@@ -330,20 +366,33 @@ + GL(dl_profile_map) = map; + + ++#if _CALL_ELF != 2 + /* We need to stuff the address/TOC of _dl_runtime_resolve + into doublewords 0 and 1 of plt_reserve. Then we need to + stuff the map address into doubleword 2 of plt_reserve. + This allows the GLINK0 code to transfer control to the + correct trampoline which will transfer control to fixup + in dl-machine.c. */ +- plt_reserve->fd_func = resolve_fd->fd_func; +- plt_reserve->fd_toc = resolve_fd->fd_toc; +- plt_reserve->fd_aux = (Elf64_Addr) map; ++ { ++ /* The plt_reserve area is the 1st 3 doublewords of the PLT. */ ++ Elf64_FuncDesc *plt_reserve = (Elf64_FuncDesc *) plt; ++ Elf64_FuncDesc *resolve_fd = (Elf64_FuncDesc *) dlrr; ++ plt_reserve->fd_func = resolve_fd->fd_func; ++ plt_reserve->fd_toc = resolve_fd->fd_toc; ++ plt_reserve->fd_aux = (Elf64_Addr) map; + #ifdef RTLD_BOOTSTRAP +- /* When we're bootstrapping, the opd entry will not have +- been relocated yet. */ +- plt_reserve->fd_func += l_addr; +- plt_reserve->fd_toc += l_addr; ++ /* When we're bootstrapping, the opd entry will not have ++ been relocated yet. */ ++ plt_reserve->fd_func += l_addr; ++ plt_reserve->fd_toc += l_addr; ++#endif ++ } ++#else ++ /* When we don't have function descriptors, the first doubleword ++ of the PLT holds the address of _dl_runtime_resolve, and the ++ second doubleword holds the map address. */ ++ plt[0] = dlrr; ++ plt[1] = (Elf64_Addr) map; + #endif + + /* Set up the lazy PLT entries. */ +@@ -354,14 +403,8 @@ + { + + plt[offset] = (Elf64_Xword) &glink[glink_offset]; +- offset += 3; +- /* The first 32k entries of glink can set an index and +- branch using two instructions; Past that point, +- glink uses three instructions. */ +- if (i < 0x8000) +- glink_offset += 2; +- else +- glink_offset += 3; ++ offset += PLT_ENTRY_WORDS; ++ glink_offset += GLINK_ENTRY_WORDS (i); + } + + /* Now, we've modified data. We need to write the changes from +@@ -389,6 +432,7 @@ + const Elf64_Rela *reloc, + Elf64_Addr *reloc_addr, Elf64_Addr finaladdr) + { ++#if _CALL_ELF != 2 + Elf64_FuncDesc *plt = (Elf64_FuncDesc *) reloc_addr; + Elf64_FuncDesc *rel = (Elf64_FuncDesc *) finaladdr; + Elf64_Addr offset = 0; +@@ -426,6 +470,9 @@ + plt->fd_func = rel->fd_func + offset; + PPC_DCBST (&plt->fd_func); + PPC_ISYNC; ++#else ++ *reloc_addr = finaladdr; ++#endif + + return finaladdr; + } +@@ -433,6 +480,7 @@ + static inline void __attribute__ ((always_inline)) + elf_machine_plt_conflict (Elf64_Addr *reloc_addr, Elf64_Addr finaladdr) + { ++#if _CALL_ELF != 2 + Elf64_FuncDesc *plt = (Elf64_FuncDesc *) reloc_addr; + Elf64_FuncDesc *rel = (Elf64_FuncDesc *) finaladdr; + +@@ -443,6 +491,9 @@ + PPC_DCBST (&plt->fd_aux); + PPC_DCBST (&plt->fd_toc); + PPC_SYNC; ++#else ++ *reloc_addr = finaladdr; ++#endif + } + + /* Return the final value of a plt relocation. */ +@@ -512,6 +563,7 @@ + resolve_ifunc (Elf64_Addr value, + const struct link_map *map, const struct link_map *sym_map) + { ++#if _CALL_ELF != 2 + #ifndef RESOLVE_CONFLICT_FIND_MAP + /* The function we are calling may not yet have its opd entry relocated. */ + Elf64_FuncDesc opd; +@@ -529,6 +581,7 @@ + value = (Elf64_Addr) &opd; + } + #endif ++#endif + return ((Elf64_Addr (*) (unsigned long int)) value) (GLRO(dl_hwcap)); + } + +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/setjmp-common.S glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/setjmp-common.S +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/setjmp-common.S 2014-05-29 13:58:25.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/setjmp-common.S 2014-05-29 14:00:27.000000000 -0500 +@@ -55,21 +55,22 @@ + that saves r2 since the call won't go via a plt call stub. See + bugz #269. __GI__setjmp is used in csu/libc-start.c when + HAVE_CLEANUP_JMP_BUF is defined. */ +-ENTRY (BP_SYM (__GI__setjmp)) ++ENTRY (__GI__setjmp) + std r2,40(r1) /* Save the callers TOC in the save area. */ +- cfi_endproc +-END_2 (BP_SYM (__GI__setjmp)) +-/* Fall thru. */ ++ CALL_MCOUNT 1 ++ li r4,0 /* Set second argument to 0. */ ++ b JUMPTARGET (GLUE(__sigsetjmp,_ent)) ++END (__GI__setjmp) + #endif + +-ENTRY (BP_SYM (_setjmp)) ++ENTRY (_setjmp) + CALL_MCOUNT 1 + li r4,0 /* Set second argument to 0. */ + b JUMPTARGET (GLUE(__sigsetjmp,_ent)) +-END (BP_SYM (_setjmp)) ++END (_setjmp) + libc_hidden_def (_setjmp) + +-ENTRY (BP_SYM (__sigsetjmp)) ++ENTRY (__sigsetjmp) + CALL_MCOUNT 2 + JUMPTARGET(GLUE(__sigsetjmp,_ent)): + CHECK_BOUNDS_BOTH_WIDE_LIT (r3, r8, r9, JB_SIZE) +@@ -215,18 +216,18 @@ + li r3,0 + blr + #elif defined SHARED +- b JUMPTARGET (BP_SYM (__sigjmp_save)) ++ b JUMPTARGET (__sigjmp_save) + #else + mflr r0 + std r0,16(r1) + stdu r1,-112(r1) + cfi_adjust_cfa_offset(112) + cfi_offset(lr,16) +- bl JUMPTARGET (BP_SYM (__sigjmp_save)) ++ bl JUMPTARGET (__sigjmp_save) + nop + ld r0,112+16(r1) + addi r1,r1,112 + mtlr r0 + blr + #endif +-END (BP_SYM (__sigsetjmp)) ++END (__sigsetjmp) +diff -urN glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/sysdep.h glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/sysdep.h +--- glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/sysdep.h 2014-05-29 13:58:25.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/powerpc/powerpc64/sysdep.h 2014-05-29 13:58:25.000000000 -0500 +@@ -74,6 +74,8 @@ + #endif + .endm + ++#if _CALL_ELF != 2 ++ + /* Macro to prepare for calling via a function pointer. */ + .macro PPC64_LOAD_FUNCPTR PTR + ld r12,0(\PTR) +@@ -115,13 +117,37 @@ + .size name,.-BODY_LABEL(name); \ + .size BODY_LABEL(name),.-BODY_LABEL(name); + #endif ++#define LOCALENTRY(name) ++ ++#else /* _CALL_ELF */ ++ ++/* Macro to prepare for calling via a function pointer. */ ++ .macro PPC64_LOAD_FUNCPTR PTR ++ mr r12,\PTR ++ mtctr r12 ++ .endm ++ ++#define DOT_LABEL(X) X ++#define BODY_LABEL(X) X ++#define ENTRY_2(name) \ ++ .globl name; \ ++ .type name,@function; ++#define END_2(name) \ ++ .size name,.-name; ++#define LOCALENTRY(name) \ ++1: addis r2,r12,.TOC.-1b@ha; \ ++ addi r2,r2,.TOC.-1b@l; \ ++ .localentry name,.-name; ++ ++#endif /* _CALL_ELF */ + + #define ENTRY(name) \ + .section ".text"; \ + ENTRY_2(name) \ + .align ALIGNARG(2); \ + BODY_LABEL(name): \ +- cfi_startproc; ++ cfi_startproc; \ ++ LOCALENTRY(name) + + #define EALIGN_W_0 /* No words to insert. */ + #define EALIGN_W_1 nop +@@ -140,7 +166,8 @@ + .align ALIGNARG(alignt); \ + EALIGN_W_##words; \ + BODY_LABEL(name): \ +- cfi_startproc; ++ cfi_startproc; \ ++ LOCALENTRY(name) + + /* Local labels stripped out by the linker. */ + #undef L +@@ -295,6 +322,8 @@ + + #else /* !__ASSEMBLER__ */ + ++#if _CALL_ELF != 2 ++ + #define PPC64_LOAD_FUNCPTR(ptr) \ + "ld 12,0(" #ptr ");\n" \ + "ld 2,8(" #ptr ");\n" \ +@@ -335,5 +364,26 @@ + ".size " #name ",.-" BODY_PREFIX #name ";\n" \ + ".size " BODY_PREFIX #name ",.-" BODY_PREFIX #name ";" + #endif ++#define LOCALENTRY(name) ++ ++#else /* _CALL_ELF */ ++ ++#define PPC64_LOAD_FUNCPTR(ptr) \ ++ "mr 12," #ptr ";\n" \ ++ "mtctr 12;" ++ ++#define DOT_PREFIX "" ++#define BODY_PREFIX "" ++#define ENTRY_2(name) \ ++ ".type " #name ",@function;\n" \ ++ ".globl " #name ";" ++#define END_2(name) \ ++ ".size " #name ",.-" #name ";" ++#define LOCALENTRY(name) \ ++ "1: addis 2,12,.TOC.-1b@ha;\n" \ ++ "addi 2,2,.TOC.-1b@l;\n" \ ++ ".localentry " #name ",.-" #name ";" ++ ++#endif /* _CALL_ELF */ + + #endif /* __ASSEMBLER__ */ +diff -urN glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/ldsodefs.h glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/ldsodefs.h +--- glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/ldsodefs.h 2014-05-29 13:58:24.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/ldsodefs.h 2014-05-29 13:58:25.000000000 -0500 +@@ -23,6 +23,8 @@ + + /* Now define our stuff. */ + ++#if _CALL_ELF != 2 ++ + static __always_inline bool + _dl_ppc64_is_opd_sym (const struct link_map *l, const ElfW(Sym) *sym) + { +@@ -73,4 +75,6 @@ + #define DL_ADDR_SYM_MATCH(L, SYM, MATCHSYM, ADDR) \ + _dl_ppc64_addr_sym_match (L, SYM, MATCHSYM, ADDR) + ++#endif ++ + #endif /* ldsodefs.h */ +diff -urN glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/makecontext.S glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/makecontext.S +--- glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/makecontext.S 2014-05-29 13:58:24.000000000 -0500 ++++ glibc-2.17-c758a686/sysdeps/unix/sysv/linux/powerpc/powerpc64/makecontext.S 2014-05-29 13:58:25.000000000 -0500 +@@ -111,6 +111,7 @@ + + L(noparms): + ++#if _CALL_ELF != 2 + /* Load the function address and TOC from the function descriptor + and store them in the ucontext as NIP and r2. Store the 3rd + field of the function descriptor into the ucontext as r11 in case +@@ -121,6 +122,12 @@ + std r0,(SIGCONTEXT_GP_REGS+(PT_NIP*8))(r3) + std r10,(SIGCONTEXT_GP_REGS+(PT_R2*8))(r3) + std r9,(SIGCONTEXT_GP_REGS+(PT_R11*8))(r3) ++#else ++ /* In the ELFv2 ABI, the function pointer is already the address. ++ Store it as NIP and r12 as required by the ABI. */ ++ std r4,(SIGCONTEXT_GP_REGS+(PT_NIP*8))(r3) ++ std r4,(SIGCONTEXT_GP_REGS+(PT_R12*8))(r3) ++#endif + + /* If the target function returns we need to do some cleanup. We use a + code trick to get the address of our cleanup function into the link |