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