diff gcc/ada/sigtramp-ios.c @ 111:04ced10e8804

gcc 7
author kono
date Fri, 27 Oct 2017 22:46:09 +0900
parents
children 84e7813d76e9
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gcc/ada/sigtramp-ios.c	Fri Oct 27 22:46:09 2017 +0900
@@ -0,0 +1,233 @@
+/****************************************************************************
+ *                                                                          *
+ *                         GNAT COMPILER COMPONENTS                         *
+ *                                                                          *
+ *                             S I G T R A M P                              *
+ *                                                                          *
+ *                         Asm Implementation File                          *
+ *                                                                          *
+ *           Copyright (C) 2015, Free Software Foundation, Inc.             *
+ *                                                                          *
+ * GNAT is free software;  you can  redistribute it  and/or modify it under *
+ * terms of the  GNU General Public License as published  by the Free Soft- *
+ * ware  Foundation;  either version 3,  or (at your option) any later ver- *
+ * sion.  GNAT is distributed in the hope that it will be useful, but WITH- *
+ * OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY *
+ * or FITNESS FOR A PARTICULAR PURPOSE.                                     *
+ *                                                                          *
+ * As a special exception under Section 7 of GPL version 3, you are granted *
+ * additional permissions described in the GCC Runtime Library Exception,   *
+ * version 3.1, as published by the Free Software Foundation.               *
+ *                                                                          *
+ * In particular,  you can freely  distribute your programs  built with the *
+ * GNAT Pro compiler, including any required library run-time units,  using *
+ * any licensing terms  of your choosing.  See the AdaCore Software License *
+ * for full details.                                                        *
+ *                                                                          *
+ * GNAT was originally developed  by the GNAT team at  New York University. *
+ * Extensive contributions were provided by Ada Core Technologies Inc.      *
+ *                                                                          *
+ ****************************************************************************/
+
+/****************************************************
+ * ARM64/IOS version of the __gnat_sigtramp service *
+ ****************************************************/
+
+#include <sys/ucontext.h>
+
+#include "sigtramp.h"
+/* See sigtramp.h for a general explanation of functionality.  */
+
+/* ----------------------
+   -- General comments --
+   ----------------------
+
+   Unfortunately the libunwind library used on this platform comes with severe
+   limitations that make the implementation convoluted:
+
+     1. At each step, the stack pointer register SP is restored with the CFA.
+	This makes it impossible to set the CFA to an arbitrary value, for
+	example to the address of the context saved on the stack, which means
+	that the simple CFI directives cannot be used for the registers.
+
+     2. For the ARM64 architecture (and only it), DWARF expressions are not
+	supported to compute the CFA.  Only DW_CFA_def_cfa is supported, which
+	means that the CFA (modulo offset) must be loaded into a register.
+
+     3. The return column cannot be changed (30 for the ARM64 architecture).
+	Since column 30 is that of the LR register, this makes it impossible
+	to restore both the LR register and the PC.
+
+   Therefore we need 2 distinct call-saved registers in the trampoline and
+   we resort to manual encoding of CFI byte sequences.  */
+
+/* -----------------------------------------
+   -- Protypes for our internal asm stubs --
+   -----------------------------------------
+
+   Even though our symbols will remain local, the prototype claims "extern"
+   and not "static" to prevent compiler complaints about a symbol used but
+   never defined.  */
+
+/* sigtramp stub providing unwind info for common registers.  */
+
+extern void __gnat_sigtramp_common
+  (int signo, void *siginfo, void *sigcontext,
+   __sigtramphandler_t * handler);
+
+void __gnat_sigtramp (int signo, void *si, void *ucontext,
+                      __sigtramphandler_t * handler)
+     __attribute__((optimize(2)));
+
+void __gnat_sigtramp (int signo, void *si, void *ucontext,
+                      __sigtramphandler_t * handler)
+{
+  mcontext_t mcontext = ((ucontext_t *) ucontext)->uc_mcontext;
+
+  __gnat_sigtramp_common (signo, si, mcontext, handler);
+}
+
+/* asm string construction helpers.  */
+
+#define STR(TEXT) #TEXT
+/* stringify expanded TEXT, surrounding it with double quotes.  */
+
+#define S(E) STR(E)
+/* stringify E, which will resolve as text but may contain macros
+   still to be expanded.  */
+
+/* asm (TEXT) outputs <tab>TEXT. These facilitate the output of
+   multiline contents:  */
+#define TAB(S) "\t" S
+#define CR(S)  S "\n"
+
+#undef TCR
+#define TCR(S) TAB(CR(S))
+
+/* Offset in uc_mcontext of the __ss structure containing the registers.  */
+#define UC_MCONTEXT_SS 16
+
+#define CFA_REG  19
+#define BASE_REG 20
+
+#define DW_CFA_def_cfa    0x0c
+#define DW_CFA_expression 0x10
+
+#define DW_OP_breg(n)     0x70+(n)
+
+#define REG_REGNO_GR(n)   n
+#define REG_REGNO_PC      30
+
+/* The first byte of the SLEB128 value of the offset.  */
+#define REG_OFFSET_GR(n)         (UC_MCONTEXT_SS + n * 8)
+#define REG_OFFSET_LONG_GR(n)    (UC_MCONTEXT_SS + n * 8 + 128)
+#define REG_OFFSET_LONG128_GR(n) (UC_MCONTEXT_SS + (n - 16) * 8 + 128)
+#define REG_OFFSET_LONG256_GR(n) (UC_MCONTEXT_SS + (n - 32) * 8 + 128)
+
+#define REG_OFFSET_LONG256_PC    REG_OFFSET_LONG256_GR(32)
+
+#define CFI_DEF_CFA \
+  TCR(".cfi_def_cfa " S(CFA_REG) ", 0")
+
+/* We need 4 variants depending on the offset: 0+, 64+, 128+, 256+.  */
+#define COMMON_CFI(REG) \
+  ".cfi_escape " S(DW_CFA_expression) "," S(REG_REGNO_##REG) ",2," \
+  S(DW_OP_breg(BASE_REG)) "," S(REG_OFFSET_##REG)
+
+#define COMMON_LONG_CFI(REG) \
+  ".cfi_escape " S(DW_CFA_expression) "," S(REG_REGNO_##REG) ",3," \
+  S(DW_OP_breg(BASE_REG)) "," S(REG_OFFSET_LONG_##REG) ",0"
+
+#define COMMON_LONG128_CFI(REG) \
+  ".cfi_escape " S(DW_CFA_expression) "," S(REG_REGNO_##REG) ",3," \
+  S(DW_OP_breg(BASE_REG)) "," S(REG_OFFSET_LONG128_##REG) ",1"
+
+#define COMMON_LONG256_CFI(REG) \
+  ".cfi_escape " S(DW_CFA_expression) "," S(REG_REGNO_##REG) ",3," \
+  S(DW_OP_breg(BASE_REG)) "," S(REG_OFFSET_LONG256_##REG) ",2"
+
+#define CFI_COMMON_REGS \
+  CR("# CFI for common registers\n") \
+  TCR(COMMON_CFI(GR(0)))  \
+  TCR(COMMON_CFI(GR(1)))  \
+  TCR(COMMON_CFI(GR(2)))  \
+  TCR(COMMON_CFI(GR(3)))  \
+  TCR(COMMON_CFI(GR(4)))  \
+  TCR(COMMON_CFI(GR(5)))  \
+  TCR(COMMON_LONG_CFI(GR(6)))  \
+  TCR(COMMON_LONG_CFI(GR(7)))  \
+  TCR(COMMON_LONG_CFI(GR(8)))  \
+  TCR(COMMON_LONG_CFI(GR(9)))  \
+  TCR(COMMON_LONG_CFI(GR(10))) \
+  TCR(COMMON_LONG_CFI(GR(11))) \
+  TCR(COMMON_LONG_CFI(GR(12))) \
+  TCR(COMMON_LONG_CFI(GR(13))) \
+  TCR(COMMON_LONG128_CFI(GR(14))) \
+  TCR(COMMON_LONG128_CFI(GR(15))) \
+  TCR(COMMON_LONG128_CFI(GR(16))) \
+  TCR(COMMON_LONG128_CFI(GR(17))) \
+  TCR(COMMON_LONG128_CFI(GR(18))) \
+  TCR(COMMON_LONG128_CFI(GR(19))) \
+  TCR(COMMON_LONG128_CFI(GR(20))) \
+  TCR(COMMON_LONG128_CFI(GR(21))) \
+  TCR(COMMON_LONG128_CFI(GR(22))) \
+  TCR(COMMON_LONG128_CFI(GR(23))) \
+  TCR(COMMON_LONG128_CFI(GR(24))) \
+  TCR(COMMON_LONG128_CFI(GR(25))) \
+  TCR(COMMON_LONG128_CFI(GR(26))) \
+  TCR(COMMON_LONG128_CFI(GR(27))) \
+  TCR(COMMON_LONG128_CFI(GR(28))) \
+  TCR(COMMON_LONG128_CFI(GR(29))) \
+  TCR(COMMON_LONG256_CFI(PC))
+
+/* Trampoline body block
+   ---------------------  */
+
+#define SIGTRAMP_BODY \
+  TCR("stp fp, lr, [sp, #-32]!") \
+  TCR("stp x" S(CFA_REG) ", x" S(BASE_REG) ", [sp, #16]") \
+  TCR("mov fp, sp") \
+  TCR("# Load the saved value of the stack pointer as CFA") \
+  TCR("ldr x" S(CFA_REG) ", [x2, #" S(REG_OFFSET_GR(31)) "]") \
+  TCR("# Use x" S(BASE_REG) " as base register for the CFI") \
+  TCR("mov x" S(BASE_REG) ", x2") \
+  TCR("# Call the handler") \
+  TCR("blr x3") \
+  TCR("# Release our frame and return (should never get here!).") \
+  TCR("ldp x" S(CFA_REG) ", x" S(BASE_REG)" , [sp, #16]") \
+  TCR("ldp fp, lr, [sp], 32") \
+  TCR("ret")
+
+/* -----------------------------
+   -- Symbol definition block --
+   ----------------------------- */
+
+#define SIGTRAMP_START(SYM) \
+  CR("# " S(SYM) " signal trampoline") \
+  CR(S(SYM) ":") \
+  TCR(".cfi_startproc") \
+  TCR(".cfi_signal_frame")
+
+/* ------------------------------
+   -- Symbol termination block --
+   ------------------------------ */
+
+#define SIGTRAMP_END(SYM) \
+  TCR(".cfi_endproc")
+
+/*----------------------------
+  -- And now, the real code --
+  ---------------------------- */
+
+asm(".text\n"
+    TCR(".align 2"));
+
+/* sigtramp stub for common registers.  */
+
+#define TRAMP_COMMON ___gnat_sigtramp_common
+
+asm (SIGTRAMP_START(TRAMP_COMMON));
+asm (CFI_DEF_CFA);
+asm (CFI_COMMON_REGS);
+asm (SIGTRAMP_BODY);
+asm (SIGTRAMP_END(TRAMP_COMMON));