summaryrefslogtreecommitdiff
path: root/gcc/ada/sigtramp-ios.c
diff options
context:
space:
mode:
authorcharlet <charlet@138bc75d-0d04-0410-961f-82ee72b054a4>2015-11-13 13:11:30 +0000
committercharlet <charlet@138bc75d-0d04-0410-961f-82ee72b054a4>2015-11-13 13:11:30 +0000
commit4d7ab124210339f865472a69b01dbd1a514c45c2 (patch)
treeb2c0b873dc782dd0985edac23610f821beb0f0c5 /gcc/ada/sigtramp-ios.c
parentfbc5a5a6242362d342ec531db9eabd2852d2266f (diff)
downloadgcc-4d7ab124210339f865472a69b01dbd1a514c45c2.tar.gz
2015-11-13 Bob Duff <duff@adacore.com>
* sem_ch6.adb (Check_Private_Overriding): Change name of Parent_Is_Private to be Overrides_Private_Part_Op, and use Unit_Declaration_Node. 2015-11-13 Bob Duff <duff@adacore.com> * sinfo.ads: Minor comment fix. * sem_ch6.adb: Minor reformatting. 2015-11-13 Jerome Lambourg <lambourg@adacore.com> * tracebak.c: Do not use the GCC Unwinder to retrieve traceback for x86_64-vx7. 2015-11-13 Eric Botcazou <ebotcazou@adacore.com> * init.c [Darwin/arm64]: Fix typo. * sigtramp-armios.c: Remove. * sigtramp-ios.c: New file. 2015-11-13 Doug Rupp <rupp@adacore.com> * s-stchop-vxworks.adb (Set_Stack_Limit_For_Current_Task): Set stack limit to 12000 decimal vice 12000 hexadecimal. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@230315 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/ada/sigtramp-ios.c')
-rw-r--r--gcc/ada/sigtramp-ios.c233
1 files changed, 233 insertions, 0 deletions
diff --git a/gcc/ada/sigtramp-ios.c b/gcc/ada/sigtramp-ios.c
new file mode 100644
index 00000000000..36c4f871791
--- /dev/null
+++ b/gcc/ada/sigtramp-ios.c
@@ -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));