/*
* Copyright 2000, International Business Machines Corporation and others.
* All Rights Reserved.
- *
+ *
* This software has been released under the terms of the IBM Public
* License. For details, see the LICENSE file in the top-level source
* directory or online at http://www.openafs.org/dl/license10.html
#include <afsconfig.h>
#include <afs/param.h>
-RCSID
- ("$Header$");
-
#include <stdio.h>
#include <assert.h>
-#include "lwp.h"
#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
+# include <stdlib.h>
#endif
+
+#include "lwp.h"
+
#if defined(AFS_OSF_ENV) || defined(AFS_S390_LINUX20_ENV)
extern int PRE_Block; /* used in lwp.c and process.s */
#else
#if defined(USE_UCONTEXT) && defined(HAVE_UCONTEXT_H)
afs_int32
-savecontext(char (*ep) (), struct lwp_context *savearea, char *newsp)
+savecontext(void (*ep) (void), struct lwp_context *savearea, char *newsp)
{
-#if defined(AFS_IA64_LINUX20_ENV)
- register unsigned long sp __asm__("r12");
-#elif defined(AFS_AMD64_LINUX24_ENV)
- register unsigned long sp __asm__("sp");
-#elif defined(AFS_HPUX1122_ENV)
-/* don't need anything special, will use
- * ucontext.uc_stack.ss_sp as it matches r12.
- * This should also work for Linux,
- * but dont have system to test DEE
- */
-#else
-#error "You need to update stack pointer register for this platform"
+#if defined(AFS_LINUX20_ENV)
+ /* getcontext does not export stack info */
+ int stackvar;
#endif
PRE_Block = 1;
savearea->state = 0;
getcontext(&savearea->ucontext);
-#if defined(AFS_HPUX1122_ENV)
- savearea->topstack = savearea->ucontext.uc_stack.ss_sp;
+#if defined(AFS_LINUX20_ENV)
+ savearea->topstack = (char *)&stackvar;
#else
- savearea->topstack = sp;
+ savearea->topstack = savearea->ucontext.uc_stack.ss_sp;
#endif
switch (savearea->state) {
case 0:
}
void
-returnto(savearea)
- struct lwp_context *savearea;
+returnto(struct lwp_context *savearea)
{
PRE_Block = 0;
# else
# define LWP_SP JB_SP
# endif
-#elif defined(AFS_HPUX_ENV)
+#elif defined(AFS_HPUX_ENV) || defined(AFS_PARISC_LINUX24_ENV)
#define LWP_SP 1
#elif defined(AFS_LINUX20_ENV)
#if defined(AFS_PPC_LINUX20_ENV) || defined(AFS_PPC64_LINUX20_ENV)
typedef __uint64_t jmp_buf_type;
#endif
#else
-#if defined(AFS_ALPHA_LINUX20_ENV) || defined(AFS_PPC64_LINUX20_ENV)
+#if defined(AFS_ALPHA_LINUX20_ENV) || defined(AFS_PPC64_LINUX20_ENV)
typedef long jmp_buf_type;
#else
typedef int jmp_buf_type;
#endif /*SGI*/
static jmp_buf jmp_tmp;
-static char (*EP) ();
+static void (*EP) (void);
static int rc;
static jmp_buf_type *jmpBuffer;
+/** Starting with Glibc 2.4 pointers in jmp_buf are mangled (XOR) for "protection".
+ * On Sparc ucontext functions are not implemented.
+ */
+#define ptr_mangle(x) (x)
+#ifdef AFS_LINUX20_ENV
+
+#ifdef __GLIBC__
+#if (__GLIBC__ > 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ > 3)
+
+#if defined(AFS_SPARC64_LINUX24_ENV) || defined(AFS_SPARC_LINUX24_ENV)
+/* technically we should use POINTER_GUARD
+ * ( == offsetof (tcbhead_t, pointer_guard) )
+ * instead of 0x18
+ */
+#undef ptr_mangle
+static int ptr_mangle(int p)
+{
+ register char *tls_ptr __asm__("%g7");
+ return p ^ *(int*)(tls_ptr + 0x18);
+}
+#else
+#error need ptr_mangle support or use UCONTEXT
+#endif
+
+#endif
+#endif
+#endif
+
+
afs_int32
-savecontext(ep, savearea, sp)
- char (*ep) ();
- struct lwp_context *savearea;
- char *sp;
+savecontext(void (*ep)(void), struct lwp_context *savearea, char *sp)
{
int code;
code = setjmp(savearea->setjmp_buffer);
jmpBuffer = (jmp_buf_type *) savearea->setjmp_buffer;
- savearea->topstack = (char *)jmpBuffer[LWP_SP];
+ savearea->topstack = (char *) ptr_mangle(jmpBuffer[LWP_SP]);
#if defined(DEBUG)
{
switch (rc) {
case 0:
jmpBuffer = (jmp_buf_type *) jmp_tmp;
- jmpBuffer[LWP_SP] = (jmp_buf_type) sp;
+ jmpBuffer[LWP_SP] = ptr_mangle((jmp_buf_type) sp);
#if defined(AFS_S390_LINUX20_ENV) || defined(AFS_SPARC_LINUX20_ENV) || (defined(AFS_SPARC64_LINUX20_ENV) && defined(AFS_32BIT_USR_ENV))
- jmpBuffer[LWP_FP] = (jmp_buf_type) sp;
+ jmpBuffer[LWP_FP] = ptr_mangle((jmp_buf_type) sp);
#endif
longjmp(jmp_tmp, 1);
break;
return 0;
}
-afs_int32
+void
returnto(struct lwp_context * savearea)
{
#if defined(DEBUG)
#endif
PRE_Block = 0;
longjmp(savearea->setjmp_buffer, 2);
- return 0;
+ return;
}
#endif