-/*
- * mono-signal-handler.h: Handle signal handler differences across platforms
+/**
+ * \file
+ * Handle signal handler differences across platforms
*
* Copyright (C) 2013 Xamarin Inc
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
*/
#ifndef __MONO_SIGNAL_HANDLER_H__
#include "config.h"
-#ifdef ENABLE_EXTENSION_MODULE
-#include "../../../mono-extensions/mono/utils/mono-signal-handler.h"
-#endif
/*
-Not all platforms support signal handlers in the same way. Some have the same concept but
-for some weird reason pass different kind of arguments.
+ * When a signal is delivered to a thread on a Krait Android device
+ * that's in the middle of skipping over an "IT" block, such as this
+ * one:
+ *
+ * 0x40184ef0 <dlfree+1308>: ldr r1, [r3, #0]
+ * 0x40184ef2 <dlfree+1310>: add.w r5, r12, r2, lsl #3
+ * 0x40184ef6 <dlfree+1314>: lsls.w r2, r0, r2
+ * 0x40184efa <dlfree+1318>: tst r2, r1
+ * ### this is the IT instruction
+ * 0x40184efc <dlfree+1320>: itt eq
+ * 0x40184efe <dlfree+1322>: orreq r2, r1
+ * ### signal arrives here
+ * 0x40184f00 <dlfree+1324>: streq r2, [r3, #0]
+ * 0x40184f02 <dlfree+1326>: beq.n 0x40184f1a <dlfree+1350>
+ * 0x40184f04 <dlfree+1328>: ldr r2, [r5, #8]
+ * 0x40184f06 <dlfree+1330>: ldr r3, [r3, #16]
+ *
+ * then the first few (at most four, one would assume) instructions of
+ * the signal handler (!) might be skipped. They happen to be the
+ * push of the frame pointer and return address, so once the signal
+ * handler has done its work, it returns into a SIGSEGV.
+ */
-All signal handler helpers should go here so they can be properly shared across the JIT,
-utils and sgen.
+#if defined (TARGET_ARM) && defined (HAVE_ARMV7) && defined (TARGET_ANDROID)
+#define KRAIT_IT_BUG_WORKAROUND 1
+#endif
-TODO: Cleanup & move mini's macros to here so they can leveraged by other parts.
+#ifdef KRAIT_IT_BUG_WORKAROUND
+#define MONO_SIGNAL_HANDLER_FUNC(access, name, arglist) \
+ static void __krait_ ## name arglist; \
+ __attribute__ ((__naked__)) access void \
+ name arglist \
+ { \
+ asm volatile ( \
+ "mov r0, r0\n\t" \
+ "mov r0, r0\n\t" \
+ "mov r0, r0\n\t" \
+ "mov r0, r0\n\t" \
+ "b __krait_" # name \
+ "\n\t"); \
+ } \
+ static __attribute__ ((__used__)) void __krait_ ## name arglist
+#endif
-*/
+/* Don't use this */
#ifndef MONO_SIGNAL_HANDLER_FUNC
#define MONO_SIGNAL_HANDLER_FUNC(access, name, arglist) access void name arglist
#endif
+/*
+ * Macros to work around signal handler differences on various platforms.
+ *
+ * To declare a signal handler function:
+ * void MONO_SIG_HANDLER_SIGNATURE (handler_func)
+ * To define a signal handler function:
+ * MONO_SIG_HANDLER_FUNC(access, name)
+ * To call another signal handler function:
+ * handler_func (MONO_SIG_HANDLER_PARAMS);
+ * To obtain the signal number:
+ * int signo = MONO_SIG_HANDLER_GET_SIGNO ();
+ * To obtain the signal context:
+ * MONO_SIG_HANDLER_GET_CONTEXT ().
+ * This will define a variable name 'ctx'.
+ */
+
+#ifdef HOST_WIN32
+#define MONO_SIG_HANDLER_SIGNATURE(ftn) ftn (int _dummy, EXCEPTION_POINTERS *_info, void *context)
+#define MONO_SIG_HANDLER_FUNC(access, ftn) MONO_SIGNAL_HANDLER_FUNC (access, ftn, (int _dummy, EXCEPTION_POINTERS *_info, void *context))
+#define MONO_SIG_HANDLER_PARAMS _dummy, _info, context
+#define MONO_SIG_HANDLER_GET_SIGNO() (_dummy)
+#define MONO_SIG_HANDLER_GET_INFO() (_info)
+#define MONO_SIG_HANDLER_INFO_TYPE EXCEPTION_POINTERS
+/* seh_vectored_exception_handler () passes in a CONTEXT* */
+#define MONO_SIG_HANDLER_GET_CONTEXT \
+ void *ctx = context;
+#else
+/* sigaction */
+#define MONO_SIG_HANDLER_SIGNATURE(ftn) ftn (int _dummy, siginfo_t *_info, void *context)
+#define MONO_SIG_HANDLER_FUNC(access, ftn) MONO_SIGNAL_HANDLER_FUNC (access, ftn, (int _dummy, siginfo_t *_info, void *context))
+#define MONO_SIG_HANDLER_PARAMS _dummy, _info, context
+#define MONO_SIG_HANDLER_GET_SIGNO() (_dummy)
+#define MONO_SIG_HANDLER_GET_INFO() (_info)
+#define MONO_SIG_HANDLER_INFO_TYPE siginfo_t
+#define MONO_SIG_HANDLER_GET_CONTEXT \
+ void *ctx = context;
+#endif
+
#endif