8506a61885ec3e77703d82edfdb9f69ddfeedf31
[platform/upstream/libunwind.git] / src / ppc32 / Gstep.c
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
7 This file is part of libunwind.
8
9 Permission is hereby granted, free of charge, to any person obtaining
10 a copy of this software and associated documentation files (the
11 "Software"), to deal in the Software without restriction, including
12 without limitation the rights to use, copy, modify, merge, publish,
13 distribute, sublicense, and/or sell copies of the Software, and to
14 permit persons to whom the Software is furnished to do so, subject to
15 the following conditions:
16
17 The above copyright notice and this permission notice shall be
18 included in all copies or substantial portions of the Software.
19
20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 WITH 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
44 typedef 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
52 PROTECTED int
53 unw_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 }