diff options
author | charlet <charlet@138bc75d-0d04-0410-961f-82ee72b054a4> | 2015-11-13 13:11:30 +0000 |
---|---|---|
committer | charlet <charlet@138bc75d-0d04-0410-961f-82ee72b054a4> | 2015-11-13 13:11:30 +0000 |
commit | 4d7ab124210339f865472a69b01dbd1a514c45c2 (patch) | |
tree | b2c0b873dc782dd0985edac23610f821beb0f0c5 /gcc/ada/sigtramp-ios.c | |
parent | fbc5a5a6242362d342ec531db9eabd2852d2266f (diff) | |
download | gcc-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.c | 233 |
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)); |