• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "remote.h"
31 #include <signal.h>
32 
33 /* This definition originates in /usr/include/asm-ppc64/ptrace.h, but is
34    defined there only when __KERNEL__ is defined.  We reproduce it here for
35    our use at the user level in order to locate the ucontext record, which
36    appears to be at this offset relative to the stack pointer when in the
37    context of the signal handler return trampoline code -
38    __kernel_sigtramp_rt64.  */
39 #define __SIGNAL_FRAMESIZE 128
40 
41 /* This definition comes from the document "64-bit PowerPC ELF Application
42    Binary Interface Supplement 1.9", section 3.2.2.
43    http://www.linux-foundation.org/spec/ELF/ppc64/PPC-elf64abi-1.9.html#STACK */
44 
45 typedef struct
46 {
47   long unsigned back_chain;
48   long unsigned cr_save;
49   long unsigned lr_save;
50   /* many more fields here, but they are unused by this code */
51 } stack_frame_t;
52 
53 
54 int
unw_step(unw_cursor_t * cursor)55 unw_step (unw_cursor_t * cursor)
56 {
57   struct cursor *c = (struct cursor *) cursor;
58   stack_frame_t dummy;
59   unw_word_t back_chain_offset, lr_save_offset, v_regs_ptr;
60   struct dwarf_loc back_chain_loc, lr_save_loc, sp_loc, ip_loc, v_regs_loc;
61   int ret, i;
62 
63   Debug (1, "(cursor=%p, ip=0x%016lx)\n", c, (unsigned long) c->dwarf.ip);
64 
65   /* Try DWARF-based unwinding... */
66 
67   ret = dwarf_step (&c->dwarf);
68 
69   if (ret < 0 && ret != -UNW_ENOINFO)
70     {
71       Debug (2, "returning %d\n", ret);
72       return ret;
73     }
74 
75   if (unlikely (ret < 0))
76     {
77       if (likely (unw_is_signal_frame (cursor) <= 0))
78         {
79           /* DWARF unwinding failed.  As of 09/26/2006, gcc in 64-bit mode
80              produces the mandatory level of traceback record in the code, but
81              I get the impression that this is transitory, that eventually gcc
82              will not produce any traceback records at all.  So, for now, we
83              won't bother to try to find and use these records.
84 
85              We can, however, attempt to unwind the frame by using the callback
86              chain.  This is very crude, however, and won't be able to unwind
87              any registers besides the IP, SP, and LR . */
88 
89           back_chain_offset = ((void *) &dummy.back_chain - (void *) &dummy);
90           lr_save_offset = ((void *) &dummy.lr_save - (void *) &dummy);
91 
92           back_chain_loc = DWARF_LOC (c->dwarf.cfa + back_chain_offset, 0);
93 
94           if ((ret =
95                dwarf_get (&c->dwarf, back_chain_loc, &c->dwarf.cfa)) < 0)
96             {
97               Debug (2,
98                  "Unable to retrieve CFA from back chain in stack frame - %d\n",
99                  ret);
100               return ret;
101             }
102           if (c->dwarf.cfa == 0)
103             /* Unless the cursor or stack is corrupt or uninitialized we've most
104                likely hit the top of the stack */
105             return 0;
106 
107           lr_save_loc = DWARF_LOC (c->dwarf.cfa + lr_save_offset, 0);
108 
109           if ((ret = dwarf_get (&c->dwarf, lr_save_loc, &c->dwarf.ip)) < 0)
110             {
111               Debug (2,
112                  "Unable to retrieve IP from lr save in stack frame - %d\n",
113                  ret);
114               return ret;
115             }
116 
117           /* Mark all registers unsaved */
118           for (i = 0; i < DWARF_NUM_PRESERVED_REGS; ++i)
119             c->dwarf.loc[i] = DWARF_NULL_LOC;
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_NIP), 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_PPC64_R0] =
163             DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R0, 0);
164           c->dwarf.loc[UNW_PPC64_R1] =
165             DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R1, 0);
166           c->dwarf.loc[UNW_PPC64_R2] =
167             DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R2, 0);
168           c->dwarf.loc[UNW_PPC64_R3] =
169             DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R3, 0);
170           c->dwarf.loc[UNW_PPC64_R4] =
171             DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R4, 0);
172           c->dwarf.loc[UNW_PPC64_R5] =
173             DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R5, 0);
174           c->dwarf.loc[UNW_PPC64_R6] =
175             DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R6, 0);
176           c->dwarf.loc[UNW_PPC64_R7] =
177             DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R7, 0);
178           c->dwarf.loc[UNW_PPC64_R8] =
179             DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R8, 0);
180           c->dwarf.loc[UNW_PPC64_R9] =
181             DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R9, 0);
182           c->dwarf.loc[UNW_PPC64_R10] =
183             DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R10, 0);
184           c->dwarf.loc[UNW_PPC64_R11] =
185             DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R11, 0);
186           c->dwarf.loc[UNW_PPC64_R12] =
187             DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R12, 0);
188           c->dwarf.loc[UNW_PPC64_R13] =
189             DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R13, 0);
190           c->dwarf.loc[UNW_PPC64_R14] =
191             DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R14, 0);
192           c->dwarf.loc[UNW_PPC64_R15] =
193             DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R15, 0);
194           c->dwarf.loc[UNW_PPC64_R16] =
195             DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R16, 0);
196           c->dwarf.loc[UNW_PPC64_R17] =
197             DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R17, 0);
198           c->dwarf.loc[UNW_PPC64_R18] =
199             DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R18, 0);
200           c->dwarf.loc[UNW_PPC64_R19] =
201             DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R19, 0);
202           c->dwarf.loc[UNW_PPC64_R20] =
203             DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R20, 0);
204           c->dwarf.loc[UNW_PPC64_R21] =
205             DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R21, 0);
206           c->dwarf.loc[UNW_PPC64_R22] =
207             DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R22, 0);
208           c->dwarf.loc[UNW_PPC64_R23] =
209             DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R23, 0);
210           c->dwarf.loc[UNW_PPC64_R24] =
211             DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R24, 0);
212           c->dwarf.loc[UNW_PPC64_R25] =
213             DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R25, 0);
214           c->dwarf.loc[UNW_PPC64_R26] =
215             DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R26, 0);
216           c->dwarf.loc[UNW_PPC64_R27] =
217             DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R27, 0);
218           c->dwarf.loc[UNW_PPC64_R28] =
219             DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R28, 0);
220           c->dwarf.loc[UNW_PPC64_R29] =
221             DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R29, 0);
222           c->dwarf.loc[UNW_PPC64_R30] =
223             DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R30, 0);
224           c->dwarf.loc[UNW_PPC64_R31] =
225             DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_R31, 0);
226 
227           c->dwarf.loc[UNW_PPC64_LR] =
228             DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_LINK, 0);
229           c->dwarf.loc[UNW_PPC64_CTR] =
230             DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_CTR, 0);
231           /* This CR0 assignment is probably wrong.  There are 8 dwarf columns
232              assigned to the CR registers, but only one CR register in the
233              mcontext structure */
234           c->dwarf.loc[UNW_PPC64_CR0] =
235             DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_CCR, 0);
236           c->dwarf.loc[UNW_PPC64_XER] =
237             DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_XER, 0);
238           c->dwarf.loc[UNW_PPC64_NIP] =
239             DWARF_LOC (ucontext + UC_MCONTEXT_GREGS_NIP, 0);
240 
241           /* TODO: Is there a way of obtaining the value of the
242              pseudo frame pointer (which is sp + some fixed offset, I
243              assume), based on the contents of the ucontext record
244              structure?  For now, set this loc to null. */
245           c->dwarf.loc[UNW_PPC64_FRAME_POINTER] = DWARF_NULL_LOC;
246 
247           c->dwarf.loc[UNW_PPC64_F0] =
248             DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R0, 0);
249           c->dwarf.loc[UNW_PPC64_F1] =
250             DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R1, 0);
251           c->dwarf.loc[UNW_PPC64_F2] =
252             DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R2, 0);
253           c->dwarf.loc[UNW_PPC64_F3] =
254             DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R3, 0);
255           c->dwarf.loc[UNW_PPC64_F4] =
256             DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R4, 0);
257           c->dwarf.loc[UNW_PPC64_F5] =
258             DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R5, 0);
259           c->dwarf.loc[UNW_PPC64_F6] =
260             DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R6, 0);
261           c->dwarf.loc[UNW_PPC64_F7] =
262             DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R7, 0);
263           c->dwarf.loc[UNW_PPC64_F8] =
264             DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R8, 0);
265           c->dwarf.loc[UNW_PPC64_F9] =
266             DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R9, 0);
267           c->dwarf.loc[UNW_PPC64_F10] =
268             DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R10, 0);
269           c->dwarf.loc[UNW_PPC64_F11] =
270             DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R11, 0);
271           c->dwarf.loc[UNW_PPC64_F12] =
272             DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R12, 0);
273           c->dwarf.loc[UNW_PPC64_F13] =
274             DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R13, 0);
275           c->dwarf.loc[UNW_PPC64_F14] =
276             DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R14, 0);
277           c->dwarf.loc[UNW_PPC64_F15] =
278             DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R15, 0);
279           c->dwarf.loc[UNW_PPC64_F16] =
280             DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R16, 0);
281           c->dwarf.loc[UNW_PPC64_F17] =
282             DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R17, 0);
283           c->dwarf.loc[UNW_PPC64_F18] =
284             DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R18, 0);
285           c->dwarf.loc[UNW_PPC64_F19] =
286             DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R19, 0);
287           c->dwarf.loc[UNW_PPC64_F20] =
288             DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R20, 0);
289           c->dwarf.loc[UNW_PPC64_F21] =
290             DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R21, 0);
291           c->dwarf.loc[UNW_PPC64_F22] =
292             DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R22, 0);
293           c->dwarf.loc[UNW_PPC64_F23] =
294             DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R23, 0);
295           c->dwarf.loc[UNW_PPC64_F24] =
296             DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R24, 0);
297           c->dwarf.loc[UNW_PPC64_F25] =
298             DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R25, 0);
299           c->dwarf.loc[UNW_PPC64_F26] =
300             DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R26, 0);
301           c->dwarf.loc[UNW_PPC64_F27] =
302             DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R27, 0);
303           c->dwarf.loc[UNW_PPC64_F28] =
304             DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R28, 0);
305           c->dwarf.loc[UNW_PPC64_F29] =
306             DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R29, 0);
307           c->dwarf.loc[UNW_PPC64_F30] =
308             DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R30, 0);
309           c->dwarf.loc[UNW_PPC64_F31] =
310             DWARF_LOC (ucontext + UC_MCONTEXT_FREGS_R31, 0);
311           /* Note that there is no .eh_section register column for the
312              FPSCR register.  I don't know why this is.  */
313 
314 #if defined(__linux__)
315           v_regs_loc = DWARF_LOC (ucontext + UC_MCONTEXT_V_REGS, 0);
316           ret = dwarf_get (&c->dwarf, v_regs_loc, &v_regs_ptr);
317 #elif defined(__FreeBSD__)
318           /* Offset into main structure. */
319           v_regs_ptr = (ucontext + UC_MCONTEXT_V_REGS);
320           ret = 0;
321 #endif
322 
323           if (ret < 0)
324             {
325               Debug (2, "returning %d\n", ret);
326               return ret;
327             }
328           if (v_regs_ptr != 0)
329             {
330               /* The v_regs_ptr is not null.  Set all of the AltiVec locs */
331 
332               c->dwarf.loc[UNW_PPC64_V0] =
333                 DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R0, 0);
334               c->dwarf.loc[UNW_PPC64_V1] =
335                 DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R1, 0);
336               c->dwarf.loc[UNW_PPC64_V2] =
337                 DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R2, 0);
338               c->dwarf.loc[UNW_PPC64_V3] =
339                 DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R3, 0);
340               c->dwarf.loc[UNW_PPC64_V4] =
341                 DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R4, 0);
342               c->dwarf.loc[UNW_PPC64_V5] =
343                 DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R5, 0);
344               c->dwarf.loc[UNW_PPC64_V6] =
345                 DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R6, 0);
346               c->dwarf.loc[UNW_PPC64_V7] =
347                 DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R7, 0);
348               c->dwarf.loc[UNW_PPC64_V8] =
349                 DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R8, 0);
350               c->dwarf.loc[UNW_PPC64_V9] =
351                 DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R9, 0);
352               c->dwarf.loc[UNW_PPC64_V10] =
353                 DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R10, 0);
354               c->dwarf.loc[UNW_PPC64_V11] =
355                 DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R11, 0);
356               c->dwarf.loc[UNW_PPC64_V12] =
357                 DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R12, 0);
358               c->dwarf.loc[UNW_PPC64_V13] =
359                 DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R13, 0);
360               c->dwarf.loc[UNW_PPC64_V14] =
361                 DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R14, 0);
362               c->dwarf.loc[UNW_PPC64_V15] =
363                 DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R15, 0);
364               c->dwarf.loc[UNW_PPC64_V16] =
365                 DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R16, 0);
366               c->dwarf.loc[UNW_PPC64_V17] =
367                 DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R17, 0);
368               c->dwarf.loc[UNW_PPC64_V18] =
369                 DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R18, 0);
370               c->dwarf.loc[UNW_PPC64_V19] =
371                 DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R19, 0);
372               c->dwarf.loc[UNW_PPC64_V20] =
373                 DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R20, 0);
374               c->dwarf.loc[UNW_PPC64_V21] =
375                 DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R21, 0);
376               c->dwarf.loc[UNW_PPC64_V22] =
377                 DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R22, 0);
378               c->dwarf.loc[UNW_PPC64_V23] =
379                 DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R23, 0);
380               c->dwarf.loc[UNW_PPC64_V24] =
381                 DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R24, 0);
382               c->dwarf.loc[UNW_PPC64_V25] =
383                 DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R25, 0);
384               c->dwarf.loc[UNW_PPC64_V26] =
385                 DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R26, 0);
386               c->dwarf.loc[UNW_PPC64_V27] =
387                 DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R27, 0);
388               c->dwarf.loc[UNW_PPC64_V28] =
389                 DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R28, 0);
390               c->dwarf.loc[UNW_PPC64_V29] =
391                 DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R29, 0);
392               c->dwarf.loc[UNW_PPC64_V30] =
393                 DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R30, 0);
394               c->dwarf.loc[UNW_PPC64_V31] =
395                 DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_R31, 0);
396               c->dwarf.loc[UNW_PPC64_VRSAVE] =
397                 DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_VRSAVE, 0);
398               c->dwarf.loc[UNW_PPC64_VSCR] =
399                 DWARF_LOC (v_regs_ptr + UC_MCONTEXT_VREGS_VSCR, 0);
400             }
401           else
402             {
403               c->dwarf.loc[UNW_PPC64_V0] = DWARF_NULL_LOC;
404               c->dwarf.loc[UNW_PPC64_V1] = DWARF_NULL_LOC;
405               c->dwarf.loc[UNW_PPC64_V2] = DWARF_NULL_LOC;
406               c->dwarf.loc[UNW_PPC64_V3] = DWARF_NULL_LOC;
407               c->dwarf.loc[UNW_PPC64_V4] = DWARF_NULL_LOC;
408               c->dwarf.loc[UNW_PPC64_V5] = DWARF_NULL_LOC;
409               c->dwarf.loc[UNW_PPC64_V6] = DWARF_NULL_LOC;
410               c->dwarf.loc[UNW_PPC64_V7] = DWARF_NULL_LOC;
411               c->dwarf.loc[UNW_PPC64_V8] = DWARF_NULL_LOC;
412               c->dwarf.loc[UNW_PPC64_V9] = DWARF_NULL_LOC;
413               c->dwarf.loc[UNW_PPC64_V10] = DWARF_NULL_LOC;
414               c->dwarf.loc[UNW_PPC64_V11] = DWARF_NULL_LOC;
415               c->dwarf.loc[UNW_PPC64_V12] = DWARF_NULL_LOC;
416               c->dwarf.loc[UNW_PPC64_V13] = DWARF_NULL_LOC;
417               c->dwarf.loc[UNW_PPC64_V14] = DWARF_NULL_LOC;
418               c->dwarf.loc[UNW_PPC64_V15] = DWARF_NULL_LOC;
419               c->dwarf.loc[UNW_PPC64_V16] = DWARF_NULL_LOC;
420               c->dwarf.loc[UNW_PPC64_V17] = DWARF_NULL_LOC;
421               c->dwarf.loc[UNW_PPC64_V18] = DWARF_NULL_LOC;
422               c->dwarf.loc[UNW_PPC64_V19] = DWARF_NULL_LOC;
423               c->dwarf.loc[UNW_PPC64_V20] = DWARF_NULL_LOC;
424               c->dwarf.loc[UNW_PPC64_V21] = DWARF_NULL_LOC;
425               c->dwarf.loc[UNW_PPC64_V22] = DWARF_NULL_LOC;
426               c->dwarf.loc[UNW_PPC64_V23] = DWARF_NULL_LOC;
427               c->dwarf.loc[UNW_PPC64_V24] = DWARF_NULL_LOC;
428               c->dwarf.loc[UNW_PPC64_V25] = DWARF_NULL_LOC;
429               c->dwarf.loc[UNW_PPC64_V26] = DWARF_NULL_LOC;
430               c->dwarf.loc[UNW_PPC64_V27] = DWARF_NULL_LOC;
431               c->dwarf.loc[UNW_PPC64_V28] = DWARF_NULL_LOC;
432               c->dwarf.loc[UNW_PPC64_V29] = DWARF_NULL_LOC;
433               c->dwarf.loc[UNW_PPC64_V30] = DWARF_NULL_LOC;
434               c->dwarf.loc[UNW_PPC64_V31] = DWARF_NULL_LOC;
435               c->dwarf.loc[UNW_PPC64_VRSAVE] = DWARF_NULL_LOC;
436               c->dwarf.loc[UNW_PPC64_VSCR] = DWARF_NULL_LOC;
437             }
438           ret = 1;
439         }
440     }
441 
442   if (c->dwarf.ip == 0)
443     {
444       /* Unless the cursor or stack is corrupt or uninitialized,
445          we've most likely hit the top of the stack */
446       Debug (2, "returning 0\n");
447       return 0;
448     }
449 
450   // on ppc64, R2 register is used as pointer to TOC
451   // section which is used for symbol lookup in PIC code
452   // ppc64 linker generates "ld r2, 40(r1)" (ELFv1) or
453   // "ld r2, 24(r1)" (ELFv2) instruction after each
454   // @plt call. We need restore R2, but only for @plt calls
455   {
456     unw_word_t ip = c->dwarf.ip;
457     unw_addr_space_t as = c->dwarf.as;
458     unw_accessors_t *a = unw_get_accessors_int (as);
459     void *arg = c->dwarf.as_arg;
460     uint32_t toc_save = (as->abi == UNW_PPC64_ABI_ELFv2)? 24 : 40;
461     int32_t inst;
462 
463     if (fetch32 (as, a, &ip, &inst, arg) >= 0
464 	&& (uint32_t)inst == (0xE8410000U + toc_save))
465       {
466 	// @plt call, restoring R2 from CFA+toc_save
467 	c->dwarf.loc[UNW_PPC64_R2] = DWARF_LOC(c->dwarf.cfa + toc_save, 0);
468       }
469   }
470 
471   Debug (2, "returning %d with last return statement\n", ret);
472   return ret;
473 }
474