mirror of
https://github.com/crosstool-ng/crosstool-ng.git
synced 2024-12-21 05:43:09 +00:00
86c2982568
This refreshes the line numbers, removes any fuzz (which would make any future forward ports easier) and standardizes the patch/file headers (which makes them easier to read). Signed-off-by: Alexey Neyman <stilor@att.net>
512 lines
16 KiB
Diff
512 lines
16 KiB
Diff
# 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.
|
|
#
|
|
---
|
|
# elf/elf.h | 6
|
|
# sysdeps/powerpc/powerpc64/crti.S | 2
|
|
# sysdeps/powerpc/powerpc64/dl-irel.h | 4
|
|
# sysdeps/powerpc/powerpc64/dl-machine.h | 99 ++++++++++++----
|
|
# sysdeps/powerpc/powerpc64/setjmp-common.S | 21 +--
|
|
# sysdeps/powerpc/powerpc64/sysdep.h | 54 ++++++++
|
|
# sysdeps/unix/sysv/linux/powerpc/powerpc64/ldsodefs.h | 4
|
|
# sysdeps/unix/sysv/linux/powerpc/powerpc64/makecontext.S | 7 +
|
|
# 8 files changed, 162 insertions(+), 35 deletions(-)
|
|
#
|
|
--- a/elf/elf.h
|
|
+++ b/elf/elf.h
|
|
@@ -2260,6 +2260,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)
|
|
--- a/sysdeps/powerpc/powerpc64/crti.S
|
|
+++ b/sysdeps/powerpc/powerpc64/crti.S
|
|
@@ -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)
|
|
--- a/sysdeps/powerpc/powerpc64/dl-irel.h
|
|
+++ b/sysdeps/powerpc/powerpc64/dl-irel.h
|
|
@@ -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");
|
|
--- a/sysdeps/powerpc/powerpc64/dl-machine.h
|
|
+++ b/sysdeps/powerpc/powerpc64/dl-machine.h
|
|
@@ -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));
|
|
}
|
|
|
|
--- a/sysdeps/powerpc/powerpc64/setjmp-common.S
|
|
+++ b/sysdeps/powerpc/powerpc64/setjmp-common.S
|
|
@@ -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)
|
|
--- a/sysdeps/powerpc/powerpc64/sysdep.h
|
|
+++ b/sysdeps/powerpc/powerpc64/sysdep.h
|
|
@@ -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__ */
|
|
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/ldsodefs.h
|
|
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/ldsodefs.h
|
|
@@ -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 */
|
|
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/makecontext.S
|
|
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/makecontext.S
|
|
@@ -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
|