1/* libunwind - a platform-independent unwind library
2   Copyright (C) 2006-2007 IBM
3   Contributed by
4     Corey Ashford <cjashfor@us.ibm.com>
5     Jose Flavio Aguilar Paulino <jflavio@br.ibm.com> <joseflavio@gmail.com>
6
7This file is part of libunwind.
8
9Permission is hereby granted, free of charge, to any person obtaining
10a copy of this software and associated documentation files (the
11"Software"), to deal in the Software without restriction, including
12without limitation the rights to use, copy, modify, merge, publish,
13distribute, sublicense, and/or sell copies of the Software, and to
14permit persons to whom the Software is furnished to do so, subject to
15the following conditions:
16
17The above copyright notice and this permission notice shall be
18included in all copies or substantial portions of the Software.
19
20THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
27
28#include "unwind_i.h"
29#include "ucontext_i.h"
30#include <signal.h>
31
32/* This definition originates in /usr/include/asm-ppc64/ptrace.h, but is
33   defined there only when __KERNEL__ is defined.  We reproduce it here for
34   our use at the user level in order to locate the ucontext record, which
35   appears to be at this offset relative to the stack pointer when in the
36   context of the signal handler return trampoline code -
37   __kernel_sigtramp_rt64.  */
38#define __SIGNAL_FRAMESIZE 128
39
40/* This definition comes from the document "64-bit PowerPC ELF Application
41   Binary Interface Supplement 1.9", section 3.2.2.
42   http://www.linux-foundation.org/spec/ELF/ppc64/PPC-elf64abi-1.9.html#STACK */
43
44typedef struct
45{
46  long unsigned back_chain;
47  long unsigned lr_save;
48  /* many more fields here, but they are unused by this code */
49} stack_frame_t;
50
51
52PROTECTED int
53unw_step (unw_cursor_t * cursor)
54{
55  struct cursor *c = (struct cursor *) cursor;
56  stack_frame_t dummy;
57  unw_word_t back_chain_offset, lr_save_offset;
58  struct dwarf_loc back_chain_loc, lr_save_loc, sp_loc, ip_loc;
59  int ret;
60
61  Debug (1, "(cursor=%p, ip=0x%016lx)\n", c, (unsigned long) c->dwarf.ip);
62
63  if (c->dwarf.ip == 0)
64    {
65      /* Unless the cursor or stack is corrupt or uninitialized,
66         we've most likely hit the top of the stack */
67      return 0;
68    }
69
70  /* Try DWARF-based unwinding... */
71
72  ret = dwarf_step (&c->dwarf);
73
74  if (ret < 0 && ret != -UNW_ENOINFO)
75    {
76      Debug (2, "returning %d\n", ret);
77      return ret;
78    }
79
80  if (unlikely (ret < 0))
81    {
82      if (likely (!unw_is_signal_frame (cursor)))
83	{
84	  /* DWARF unwinding failed.  As of 09/26/2006, gcc in 64-bit mode
85	     produces the mandatory level of traceback record in the code, but
86	     I get the impression that this is transitory, that eventually gcc
87	     will not produce any traceback records at all.  So, for now, we
88	     won't bother to try to find and use these records.
89
90	     We can, however, attempt to unwind the frame by using the callback
91	     chain.  This is very crude, however, and won't be able to unwind
92	     any registers besides the IP, SP, and LR . */
93
94	  back_chain_offset = ((void *) &dummy.back_chain - (void *) &dummy);
95	  lr_save_offset = ((void *) &dummy.lr_save - (void *) &dummy);
96
97	  back_chain_loc = DWARF_LOC (c->dwarf.cfa + back_chain_offset, 0);
98
99	  if ((ret =
100	       dwarf_get (&c->dwarf, back_chain_loc, &c->dwarf.cfa)) < 0)
101	    {
102	      Debug (2,
103		 "Unable to retrieve CFA from back chain in stack frame - %d\n",
104		 ret);
105	      return ret;
106	    }
107	  if (c->dwarf.cfa == 0)
108	    /* Unless the cursor or stack is corrupt or uninitialized we've most
109	       likely hit the top of the stack */
110	    return 0;
111
112	  lr_save_loc = DWARF_LOC (c->dwarf.cfa + lr_save_offset, 0);
113
114	  if ((ret = dwarf_get (&c->dwarf, lr_save_loc, &c->dwarf.ip)) < 0)
115	    {
116	      Debug (2,
117		 "Unable to retrieve IP from lr save in stack frame - %d\n",
118		 ret);
119	      return ret;
120	    }
121	  ret = 1;
122	}
123      else
124	{
125          /* Find the sigcontext record by taking the CFA and adjusting by
126             the dummy signal frame size.
127
128             Note that there isn't any way to determined if SA_SIGINFO was
129             set in the sa_flags parameter to sigaction when the signal
130             handler was established.  If it was not set, the ucontext
131             record is not required to be on the stack, in which case the
132             following code will likely cause a seg fault or other crash
133             condition.  */
134
135	  unw_word_t ucontext = c->dwarf.cfa + __SIGNAL_FRAMESIZE;
136
137	  Debug (1, "signal frame, skip over trampoline\n");
138
139	  c->sigcontext_format = PPC_SCF_LINUX_RT_SIGFRAME;
140	  c->sigcontext_addr = ucontext;
141
142	  sp_loc = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R1, 0);
143	  ip_loc = DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_LINK, 0);
144
145	  ret = dwarf_get (&c->dwarf, sp_loc, &c->dwarf.cfa);
146	  if (ret < 0)
147	    {
148	      Debug (2, "returning %d\n", ret);
149	      return ret;
150	    }
151	  ret = dwarf_get (&c->dwarf, ip_loc, &c->dwarf.ip);
152	  if (ret < 0)
153	    {
154	      Debug (2, "returning %d\n", ret);
155	      return ret;
156	    }
157
158	  /* Instead of just restoring the non-volatile registers, do all
159	     of the registers for now.  This will incur a performance hit,
160	     but it's rare enough not to cause too much of a problem, and
161	     might be useful in some cases.  */
162	  c->dwarf.loc[UNW_PPC32_R0] =
163	    DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R0, 0);
164	  c->dwarf.loc[UNW_PPC32_R1] =
165	    DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R1, 0);
166	  c->dwarf.loc[UNW_PPC32_R2] =
167	    DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R2, 0);
168	  c->dwarf.loc[UNW_PPC32_R3] =
169	    DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R3, 0);
170	  c->dwarf.loc[UNW_PPC32_R4] =
171	    DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R4, 0);
172	  c->dwarf.loc[UNW_PPC32_R5] =
173	    DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R5, 0);
174	  c->dwarf.loc[UNW_PPC32_R6] =
175	    DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R6, 0);
176	  c->dwarf.loc[UNW_PPC32_R7] =
177	    DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R7, 0);
178	  c->dwarf.loc[UNW_PPC32_R8] =
179	    DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R8, 0);
180	  c->dwarf.loc[UNW_PPC32_R9] =
181	    DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R9, 0);
182	  c->dwarf.loc[UNW_PPC32_R10] =
183	    DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R10, 0);
184	  c->dwarf.loc[UNW_PPC32_R11] =
185	    DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R11, 0);
186	  c->dwarf.loc[UNW_PPC32_R12] =
187	    DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R12, 0);
188	  c->dwarf.loc[UNW_PPC32_R13] =
189	    DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R13, 0);
190	  c->dwarf.loc[UNW_PPC32_R14] =
191	    DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R14, 0);
192	  c->dwarf.loc[UNW_PPC32_R15] =
193	    DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R15, 0);
194	  c->dwarf.loc[UNW_PPC32_R16] =
195	    DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R16, 0);
196	  c->dwarf.loc[UNW_PPC32_R17] =
197	    DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R17, 0);
198	  c->dwarf.loc[UNW_PPC32_R18] =
199	    DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R18, 0);
200	  c->dwarf.loc[UNW_PPC32_R19] =
201	    DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R19, 0);
202	  c->dwarf.loc[UNW_PPC32_R20] =
203	    DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R20, 0);
204	  c->dwarf.loc[UNW_PPC32_R21] =
205	    DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R21, 0);
206	  c->dwarf.loc[UNW_PPC32_R22] =
207	    DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R22, 0);
208	  c->dwarf.loc[UNW_PPC32_R23] =
209	    DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R23, 0);
210	  c->dwarf.loc[UNW_PPC32_R24] =
211	    DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R24, 0);
212	  c->dwarf.loc[UNW_PPC32_R25] =
213	    DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R25, 0);
214	  c->dwarf.loc[UNW_PPC32_R26] =
215	    DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R26, 0);
216	  c->dwarf.loc[UNW_PPC32_R27] =
217	    DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R27, 0);
218	  c->dwarf.loc[UNW_PPC32_R28] =
219	    DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R28, 0);
220	  c->dwarf.loc[UNW_PPC32_R29] =
221	    DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R29, 0);
222	  c->dwarf.loc[UNW_PPC32_R30] =
223	    DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R30, 0);
224	  c->dwarf.loc[UNW_PPC32_R31] =
225	    DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R31, 0);
226
227	  c->dwarf.loc[UNW_PPC32_LR] =
228	    DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_LINK, 0);
229	  c->dwarf.loc[UNW_PPC32_CTR] =
230	    DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_CTR, 0);
231
232	  /* This CR0 assignment is probably wrong.  There are 8 dwarf columns
233	     assigned to the CR registers, but only one CR register in the
234	     mcontext structure */
235	  c->dwarf.loc[UNW_PPC32_CCR] =
236	    DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_CCR, 0);
237	  c->dwarf.loc[UNW_PPC32_XER] =
238	    DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_XER, 0);
239
240	  c->dwarf.loc[UNW_PPC32_F0] =
241	    DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R0, 0);
242	  c->dwarf.loc[UNW_PPC32_F1] =
243	    DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R1, 0);
244	  c->dwarf.loc[UNW_PPC32_F2] =
245	    DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R2, 0);
246	  c->dwarf.loc[UNW_PPC32_F3] =
247	    DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R3, 0);
248	  c->dwarf.loc[UNW_PPC32_F4] =
249	    DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R4, 0);
250	  c->dwarf.loc[UNW_PPC32_F5] =
251	    DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R5, 0);
252	  c->dwarf.loc[UNW_PPC32_F6] =
253	    DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R6, 0);
254	  c->dwarf.loc[UNW_PPC32_F7] =
255	    DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R7, 0);
256	  c->dwarf.loc[UNW_PPC32_F8] =
257	    DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R8, 0);
258	  c->dwarf.loc[UNW_PPC32_F9] =
259	    DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R9, 0);
260	  c->dwarf.loc[UNW_PPC32_F10] =
261	    DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R10, 0);
262	  c->dwarf.loc[UNW_PPC32_F11] =
263	    DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R11, 0);
264	  c->dwarf.loc[UNW_PPC32_F12] =
265	    DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R12, 0);
266	  c->dwarf.loc[UNW_PPC32_F13] =
267	    DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R13, 0);
268	  c->dwarf.loc[UNW_PPC32_F14] =
269	    DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R14, 0);
270	  c->dwarf.loc[UNW_PPC32_F15] =
271	    DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R15, 0);
272	  c->dwarf.loc[UNW_PPC32_F16] =
273	    DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R16, 0);
274	  c->dwarf.loc[UNW_PPC32_F17] =
275	    DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R17, 0);
276	  c->dwarf.loc[UNW_PPC32_F18] =
277	    DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R18, 0);
278	  c->dwarf.loc[UNW_PPC32_F19] =
279	    DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R19, 0);
280	  c->dwarf.loc[UNW_PPC32_F20] =
281	    DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R20, 0);
282	  c->dwarf.loc[UNW_PPC32_F21] =
283	    DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R21, 0);
284	  c->dwarf.loc[UNW_PPC32_F22] =
285	    DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R22, 0);
286	  c->dwarf.loc[UNW_PPC32_F23] =
287	    DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R23, 0);
288	  c->dwarf.loc[UNW_PPC32_F24] =
289	    DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R24, 0);
290	  c->dwarf.loc[UNW_PPC32_F25] =
291	    DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R25, 0);
292	  c->dwarf.loc[UNW_PPC32_F26] =
293	    DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R26, 0);
294	  c->dwarf.loc[UNW_PPC32_F27] =
295	    DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R27, 0);
296	  c->dwarf.loc[UNW_PPC32_F28] =
297	    DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R28, 0);
298	  c->dwarf.loc[UNW_PPC32_F29] =
299	    DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R29, 0);
300	  c->dwarf.loc[UNW_PPC32_F30] =
301	    DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R30, 0);
302	  c->dwarf.loc[UNW_PPC32_F31] =
303	    DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R31, 0);
304
305	  ret = 1;
306	}
307    }
308  return ret;
309}
310