1 /* Get previous frame state for an existing frame state.
2 Copyright (C) 2013 Red Hat, Inc.
3 This file is part of elfutils.
5 This file is free software; you can redistribute it and/or modify
6 it under the terms of either
8 * the GNU Lesser General Public License as published by the Free
9 Software Foundation; either version 3 of the License, or (at
10 your option) any later version
14 * the GNU General Public License as published by the Free
15 Software Foundation; either version 2 of the License, or (at
16 your option) any later version
18 or both in parallel, as here.
20 elfutils is distributed in the hope that it will be useful, but
21 WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 General Public License for more details.
25 You should have received copies of the GNU General Public License and
26 the GNU Lesser General Public License along with this program. If
27 not, see <http://www.gnu.org/licenses/>. */
37 #include "libebl_CPU.h"
39 /* s390/s390x do not annotate signal handler frame by CFI. It would be also
40 difficult as PC points into a stub built on stack. Function below is called
41 only if unwinder could not find CFI. Function then verifies the register
42 state for this frame really belongs to a signal frame. In such case it
43 fetches original registers saved by the signal frame. */
46 s390_unwind (Ebl *ebl, Dwarf_Addr pc, ebl_tid_registers_t *setfunc,
47 ebl_tid_registers_get_t *getfunc, ebl_pid_memory_read_t *readfunc,
48 void *arg, bool *signal_framep)
50 /* Caller already assumed caller adjustment but S390 instructions are 4 bytes
52 if ((pc & 0x3) != 0x3)
55 /* We can assume big-endian read here. */
57 if (! readfunc (pc, &instr, arg))
59 /* Fetch only the very first two bytes. */
60 instr = (instr >> (ebl->class == ELFCLASS64 ? 48 : 16)) & 0xffff;
61 /* See GDB s390_sigtramp_frame_sniffer. */
62 /* Check for 'svc' as the first instruction. */
63 if (((instr >> 8) & 0xff) != 0x0a)
65 /* Check for 'sigreturn' or 'rt_sigreturn' as the second instruction. */
66 if ((instr & 0xff) != 119 && (instr & 0xff) != 173)
68 /* See GDB s390_sigtramp_frame_unwind_cache. */
70 if (! getfunc (0 + 15, 1, &this_sp, arg))
72 unsigned word_size = ebl->class == ELFCLASS64 ? 8 : 4;
73 Dwarf_Addr next_cfa = this_sp + 16 * word_size + 32;
74 /* "New-style RT frame" is not supported,
75 assuming "Old-style RT frame and all non-RT frames".
76 Pointer to the array of saved registers is at NEXT_CFA + 8. */
77 Dwarf_Word sigreg_ptr;
78 if (! readfunc (next_cfa + 8, &sigreg_ptr, arg))
81 sigreg_ptr += word_size;
82 /* Read PSW address. */
84 if (! readfunc (sigreg_ptr, &val, arg))
86 if (! setfunc (-1, 1, &val, arg))
88 sigreg_ptr += word_size;
91 for (int i = 0; i < 16; i++)
93 if (! readfunc (sigreg_ptr, &gprs[i], arg))
95 sigreg_ptr += word_size;
97 /* Then the ACRs. Skip them, they are not used in CFI. */
98 for (int i = 0; i < 16; i++)
100 /* The floating-point control word. */
102 /* And finally the FPRs. */
104 for (int i = 0; i < 16; i++)
106 if (! readfunc (sigreg_ptr, &val, arg))
108 if (ebl->class == ELFCLASS32)
111 if (! readfunc (sigreg_ptr + 4, &val_low, arg))
113 val = (val << 32) | val_low;
118 /* If we have them, the GPR upper halves are appended at the end. */
119 if (ebl->class == ELFCLASS32)
121 /* Skip signal number. */
123 for (int i = 0; i < 16; i++)
125 if (! readfunc (sigreg_ptr, &val, arg))
127 Dwarf_Word val_low = gprs[i];
128 val = (val << 32) | val_low;
133 if (! setfunc (0, 16, gprs, arg))
135 if (! setfunc (16, 16, fprs, arg))
137 *signal_framep = true;