1169689Skan/* DWARF2 EH unwinding support for S/390 Linux. 2169689Skan Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc. 3169689Skan 4169689SkanThis file is part of GCC. 5169689Skan 6169689SkanGCC is free software; you can redistribute it and/or modify it under 7169689Skanthe terms of the GNU General Public License as published by the Free 8169689SkanSoftware Foundation; either version 2, or (at your option) any later 9169689Skanversion. 10169689Skan 11169689SkanIn addition to the permissions in the GNU General Public License, the 12169689SkanFree Software Foundation gives you unlimited permission to link the 13169689Skancompiled version of this file with other programs, and to distribute 14169689Skanthose programs without any restriction coming from the use of this 15169689Skanfile. (The General Public License restrictions do apply in other 16169689Skanrespects; for example, they cover modification of the file, and 17169689Skandistribution when not linked into another program.) 18169689Skan 19169689SkanGCC is distributed in the hope that it will be useful, but WITHOUT ANY 20169689SkanWARRANTY; without even the implied warranty of MERCHANTABILITY or 21169689SkanFITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 22169689Skanfor more details. 23169689Skan 24169689SkanYou should have received a copy of the GNU General Public License 25169689Skanalong with GCC; see the file COPYING. If not, write to the Free 26169689SkanSoftware Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 27169689Skan02110-1301, USA. */ 28169689Skan 29169689Skan/* Do code reading to identify a signal frame, and set the frame 30169689Skan state data appropriately. See unwind-dw2.c for the structs. */ 31169689Skan 32169689Skan#define MD_FALLBACK_FRAME_STATE_FOR s390_fallback_frame_state 33169689Skan 34169689Skanstatic _Unwind_Reason_Code 35169689Skans390_fallback_frame_state (struct _Unwind_Context *context, 36169689Skan _Unwind_FrameState *fs) 37169689Skan{ 38169689Skan unsigned char *pc = context->ra; 39169689Skan long new_cfa; 40169689Skan int i; 41169689Skan 42169689Skan typedef struct 43169689Skan { 44169689Skan unsigned long psw_mask; 45169689Skan unsigned long psw_addr; 46169689Skan unsigned long gprs[16]; 47169689Skan unsigned int acrs[16]; 48169689Skan unsigned int fpc; 49169689Skan unsigned int __pad; 50169689Skan double fprs[16]; 51169689Skan } __attribute__ ((__aligned__ (8))) sigregs_; 52169689Skan 53169689Skan sigregs_ *regs; 54169689Skan int *signo; 55169689Skan 56169689Skan /* svc $__NR_sigreturn or svc $__NR_rt_sigreturn */ 57169689Skan if (pc[0] != 0x0a || (pc[1] != 119 && pc[1] != 173)) 58169689Skan return _URC_END_OF_STACK; 59169689Skan 60169689Skan /* Legacy frames: 61169689Skan old signal mask (8 bytes) 62169689Skan pointer to sigregs (8 bytes) - points always to next location 63169689Skan sigregs 64169689Skan retcode 65169689Skan This frame layout was used on kernels < 2.6.9 for non-RT frames, 66169689Skan and on kernels < 2.4.13 for RT frames as well. Note that we need 67169689Skan to look at RA to detect this layout -- this means that if you use 68169689Skan sa_restorer to install a different signal restorer on a legacy 69169689Skan kernel, unwinding from signal frames will not work. */ 70169689Skan if (context->ra == context->cfa + 16 + sizeof (sigregs_)) 71169689Skan { 72169689Skan regs = (sigregs_ *)(context->cfa + 16); 73169689Skan signo = NULL; 74169689Skan } 75169689Skan 76169689Skan /* New-style RT frame: 77169689Skan retcode + alignment (8 bytes) 78169689Skan siginfo (128 bytes) 79169689Skan ucontext (contains sigregs) */ 80169689Skan else if (pc[1] == 173 /* __NR_rt_sigreturn */) 81169689Skan { 82169689Skan struct ucontext_ 83169689Skan { 84169689Skan unsigned long uc_flags; 85169689Skan struct ucontext_ *uc_link; 86169689Skan unsigned long uc_stack[3]; 87169689Skan sigregs_ uc_mcontext; 88169689Skan } *uc = context->cfa + 8 + 128; 89169689Skan 90169689Skan regs = &uc->uc_mcontext; 91169689Skan signo = context->cfa + sizeof(long); 92169689Skan } 93169689Skan 94169689Skan /* New-style non-RT frame: 95169689Skan old signal mask (8 bytes) 96169689Skan pointer to sigregs (followed by signal number) */ 97169689Skan else 98169689Skan { 99169689Skan regs = *(sigregs_ **)(context->cfa + 8); 100169689Skan signo = (int *)(regs + 1); 101169689Skan } 102169689Skan 103169689Skan new_cfa = regs->gprs[15] + 16*sizeof(long) + 32; 104169689Skan fs->cfa_how = CFA_REG_OFFSET; 105169689Skan fs->cfa_reg = 15; 106169689Skan fs->cfa_offset = 107169689Skan new_cfa - (long) context->cfa + 16*sizeof(long) + 32; 108169689Skan 109169689Skan for (i = 0; i < 16; i++) 110169689Skan { 111169689Skan fs->regs.reg[i].how = REG_SAVED_OFFSET; 112169689Skan fs->regs.reg[i].loc.offset = 113169689Skan (long)®s->gprs[i] - new_cfa; 114169689Skan } 115169689Skan for (i = 0; i < 16; i++) 116169689Skan { 117169689Skan fs->regs.reg[16+i].how = REG_SAVED_OFFSET; 118169689Skan fs->regs.reg[16+i].loc.offset = 119169689Skan (long)®s->fprs[i] - new_cfa; 120169689Skan } 121169689Skan 122169689Skan /* Load return addr from PSW into dummy register 32. */ 123169689Skan 124169689Skan fs->regs.reg[32].how = REG_SAVED_OFFSET; 125169689Skan fs->regs.reg[32].loc.offset = (long)®s->psw_addr - new_cfa; 126169689Skan fs->retaddr_column = 32; 127169689Skan /* SIGILL, SIGFPE and SIGTRAP are delivered with psw_addr 128169689Skan after the faulting instruction rather than before it. 129169689Skan Don't set FS->signal_frame in that case. */ 130169689Skan if (!signo || (*signo != 4 && *signo != 5 && *signo != 8)) 131169689Skan fs->signal_frame = 1; 132169689Skan 133169689Skan return _URC_NO_REASON; 134169689Skan} 135