1 /* libunwind - a platform-independent unwind library
2 Copyright (c) 2003, 2005 Hewlett-Packard Development Company, L.P.
3 Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
4
5 This file is part of libunwind.
6
7 Permission is hereby granted, free of charge, to any person obtaining
8 a copy of this software and associated documentation files (the
9 "Software"), to deal in the Software without restriction, including
10 without limitation the rights to use, copy, modify, merge, publish,
11 distribute, sublicense, and/or sell copies of the Software, and to
12 permit persons to whom the Software is furnished to do so, subject to
13 the following conditions:
14
15 The above copyright notice and this permission notice shall be
16 included in all copies or substantial portions of the Software.
17
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
22 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
25
26 #include "dwarf_i.h"
27 #include "libunwind_i.h"
28 #include <stddef.h>
29 #include <limits.h>
30
31 #define alloc_reg_state() (mempool_alloc (&dwarf_reg_state_pool))
32 #define free_reg_state(rs) (mempool_free (&dwarf_reg_state_pool, rs))
33
34 #define DWARF_UNW_CACHE_SIZE(log_size) (1 << log_size)
35 #define DWARF_UNW_HASH_SIZE(log_size) (1 << (log_size + 1))
36
37 static inline int
read_regnum(unw_addr_space_t as,unw_accessors_t * a,unw_word_t * addr,unw_word_t * valp,void * arg)38 read_regnum (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
39 unw_word_t *valp, void *arg)
40 {
41 int ret;
42
43 if ((ret = dwarf_read_uleb128 (as, a, addr, valp, arg)) < 0)
44 return ret;
45
46 if (*valp >= DWARF_NUM_PRESERVED_REGS)
47 {
48 Debug (1, "Invalid register number %u\n", (unsigned int) *valp);
49 return -UNW_EBADREG;
50 }
51 return 0;
52 }
53
54 static inline void
set_reg(dwarf_state_record_t * sr,unw_word_t regnum,dwarf_where_t where,unw_word_t val)55 set_reg (dwarf_state_record_t *sr, unw_word_t regnum, dwarf_where_t where,
56 unw_word_t val)
57 {
58 sr->rs_current.reg.where[regnum] = where;
59 sr->rs_current.reg.val[regnum] = val;
60 }
61
62 static inline int
push_rstate_stack(dwarf_stackable_reg_state_t ** rs_stack)63 push_rstate_stack(dwarf_stackable_reg_state_t **rs_stack)
64 {
65 dwarf_stackable_reg_state_t *old_rs = *rs_stack;
66 if (NULL == (*rs_stack = alloc_reg_state ()))
67 {
68 *rs_stack = old_rs;
69 return -1;
70 }
71 (*rs_stack)->next = old_rs;
72 return 0;
73 }
74
75 static inline void
pop_rstate_stack(dwarf_stackable_reg_state_t ** rs_stack)76 pop_rstate_stack(dwarf_stackable_reg_state_t **rs_stack)
77 {
78 dwarf_stackable_reg_state_t *old_rs = *rs_stack;
79 *rs_stack = old_rs->next;
80 free_reg_state (old_rs);
81 }
82
83 static inline void
empty_rstate_stack(dwarf_stackable_reg_state_t ** rs_stack)84 empty_rstate_stack(dwarf_stackable_reg_state_t **rs_stack)
85 {
86 while (*rs_stack)
87 pop_rstate_stack(rs_stack);
88 }
89
90 #ifdef UNW_TARGET_AARCH64
91
92 static void
93 aarch64_negate_ra_sign_state(dwarf_state_record_t *sr);
94
95 #endif
96
97 /* Run a CFI program to update the register state. */
98 static int
run_cfi_program(struct dwarf_cursor * c,dwarf_state_record_t * sr,unw_word_t * ip,unw_word_t end_ip,unw_word_t * addr,unw_word_t end_addr,dwarf_stackable_reg_state_t ** rs_stack,struct dwarf_cie_info * dci)99 run_cfi_program (struct dwarf_cursor *c, dwarf_state_record_t *sr,
100 unw_word_t *ip, unw_word_t end_ip,
101 unw_word_t *addr, unw_word_t end_addr,
102 dwarf_stackable_reg_state_t **rs_stack,
103 struct dwarf_cie_info *dci)
104 {
105 unw_addr_space_t as;
106 void *arg;
107
108 if (c->pi.flags & UNW_PI_FLAG_DEBUG_FRAME)
109 {
110 /* .debug_frame CFI is stored in local address space. */
111 as = unw_local_addr_space;
112 arg = NULL;
113 }
114 else
115 {
116 as = c->as;
117 arg = c->as_arg;
118 }
119 unw_accessors_t *a = unw_get_accessors_int (as);
120 int ret = 0;
121
122 while (*ip <= end_ip && *addr < end_addr && ret >= 0)
123 {
124 unw_word_t operand = 0, regnum, val, len;
125 uint8_t u8, op;
126 uint16_t u16;
127 uint32_t u32;
128
129 if ((ret = dwarf_readu8 (as, a, addr, &op, arg)) < 0)
130 break;
131
132 if (op & DWARF_CFA_OPCODE_MASK)
133 {
134 operand = op & DWARF_CFA_OPERAND_MASK;
135 op &= ~DWARF_CFA_OPERAND_MASK;
136 }
137 switch ((dwarf_cfa_t) op)
138 {
139 case DW_CFA_advance_loc:
140 *ip += operand * dci->code_align;
141 Debug (15, "CFA_advance_loc to 0x%lx\n", (long) *ip);
142 break;
143
144 case DW_CFA_advance_loc1:
145 if ((ret = dwarf_readu8 (as, a, addr, &u8, arg)) < 0)
146 break;
147 *ip += u8 * dci->code_align;
148 Debug (15, "CFA_advance_loc1 to 0x%lx\n", (long) *ip);
149 break;
150
151 case DW_CFA_advance_loc2:
152 if ((ret = dwarf_readu16 (as, a, addr, &u16, arg)) < 0)
153 break;
154 *ip += u16 * dci->code_align;
155 Debug (15, "CFA_advance_loc2 to 0x%lx\n", (long) *ip);
156 break;
157
158 case DW_CFA_advance_loc4:
159 if ((ret = dwarf_readu32 (as, a, addr, &u32, arg)) < 0)
160 break;
161 *ip += u32 * dci->code_align;
162 Debug (15, "CFA_advance_loc4 to 0x%lx\n", (long) *ip);
163 break;
164
165 case DW_CFA_MIPS_advance_loc8:
166 #ifdef UNW_TARGET_MIPS
167 {
168 uint64_t u64 = 0;
169
170 if ((ret = dwarf_readu64 (as, a, addr, &u64, arg)) < 0)
171 break;
172 *ip += u64 * dci->code_align;
173 Debug (15, "CFA_MIPS_advance_loc8\n");
174 break;
175 }
176 #else
177 Debug (1, "DW_CFA_MIPS_advance_loc8 on non-MIPS target\n");
178 ret = -UNW_EINVAL;
179 break;
180 #endif
181
182 case DW_CFA_offset:
183 regnum = operand;
184 if (regnum >= DWARF_NUM_PRESERVED_REGS)
185 {
186 Debug (1, "Invalid register number %u in DW_cfa_OFFSET\n",
187 (unsigned int) regnum);
188 ret = -UNW_EBADREG;
189 break;
190 }
191 if ((ret = dwarf_read_uleb128 (as, a, addr, &val, arg)) < 0)
192 break;
193 set_reg (sr, regnum, DWARF_WHERE_CFAREL, val * dci->data_align);
194 Debug (15, "CFA_offset r%lu at cfa+0x%lx\n",
195 (long) regnum, (long) (val * dci->data_align));
196 break;
197
198 case DW_CFA_offset_extended:
199 if (((ret = read_regnum (as, a, addr, ®num, arg)) < 0)
200 || ((ret = dwarf_read_uleb128 (as, a, addr, &val, arg)) < 0))
201 break;
202 set_reg (sr, regnum, DWARF_WHERE_CFAREL, val * dci->data_align);
203 Debug (15, "CFA_offset_extended r%lu at cf+0x%lx\n",
204 (long) regnum, (long) (val * dci->data_align));
205 break;
206
207 case DW_CFA_offset_extended_sf:
208 if (((ret = read_regnum (as, a, addr, ®num, arg)) < 0)
209 || ((ret = dwarf_read_sleb128 (as, a, addr, &val, arg)) < 0))
210 break;
211 set_reg (sr, regnum, DWARF_WHERE_CFAREL, val * dci->data_align);
212 Debug (15, "CFA_offset_extended_sf r%lu at cf+0x%lx\n",
213 (long) regnum, (long) (val * dci->data_align));
214 break;
215
216 case DW_CFA_restore:
217 regnum = operand;
218 if (regnum >= DWARF_NUM_PRESERVED_REGS)
219 {
220 Debug (1, "Invalid register number %u in DW_CFA_restore\n",
221 (unsigned int) regnum);
222 ret = -UNW_EINVAL;
223 break;
224 }
225 sr->rs_current.reg.where[regnum] = sr->rs_initial.reg.where[regnum];
226 sr->rs_current.reg.val[regnum] = sr->rs_initial.reg.val[regnum];
227 Debug (15, "CFA_restore r%lu\n", (long) regnum);
228 break;
229
230 case DW_CFA_restore_extended:
231 if ((ret = dwarf_read_uleb128 (as, a, addr, ®num, arg)) < 0)
232 break;
233 if (regnum >= DWARF_NUM_PRESERVED_REGS)
234 {
235 Debug (1, "Invalid register number %u in "
236 "DW_CFA_restore_extended\n", (unsigned int) regnum);
237 ret = -UNW_EINVAL;
238 break;
239 }
240 sr->rs_current.reg.where[regnum] = sr->rs_initial.reg.where[regnum];
241 sr->rs_current.reg.val[regnum] = sr->rs_initial.reg.val[regnum];
242 Debug (15, "CFA_restore_extended r%lu\n", (long) regnum);
243 break;
244
245 case DW_CFA_nop:
246 break;
247
248 case DW_CFA_set_loc:
249 if ((ret = dwarf_read_encoded_pointer (as, a, addr, dci->fde_encoding,
250 &c->pi, ip,
251 arg)) < 0)
252 break;
253 Debug (15, "CFA_set_loc to 0x%lx\n", (long) *ip);
254 break;
255
256 case DW_CFA_undefined:
257 if ((ret = read_regnum (as, a, addr, ®num, arg)) < 0)
258 break;
259 set_reg (sr, regnum, DWARF_WHERE_UNDEF, 0);
260 Debug (15, "CFA_undefined r%lu\n", (long) regnum);
261 break;
262
263 case DW_CFA_same_value:
264 if ((ret = read_regnum (as, a, addr, ®num, arg)) < 0)
265 break;
266 set_reg (sr, regnum, DWARF_WHERE_SAME, 0);
267 Debug (15, "CFA_same_value r%lu\n", (long) regnum);
268 break;
269
270 case DW_CFA_register:
271 if (((ret = read_regnum (as, a, addr, ®num, arg)) < 0)
272 || ((ret = dwarf_read_uleb128 (as, a, addr, &val, arg)) < 0))
273 break;
274 set_reg (sr, regnum, DWARF_WHERE_REG, val);
275 Debug (15, "CFA_register r%lu to r%lu\n", (long) regnum, (long) val);
276 break;
277
278 case DW_CFA_remember_state:
279 if (push_rstate_stack(rs_stack) < 0)
280 {
281 Debug (1, "Out of memory in DW_CFA_remember_state\n");
282 ret = -UNW_ENOMEM;
283 break;
284 }
285 (*rs_stack)->state = sr->rs_current;
286 Debug (15, "CFA_remember_state\n");
287 break;
288
289 case DW_CFA_restore_state:
290 if (!*rs_stack)
291 {
292 Debug (1, "register-state stack underflow\n");
293 ret = -UNW_EINVAL;
294 break;
295 }
296 sr->rs_current = (*rs_stack)->state;
297 pop_rstate_stack(rs_stack);
298 Debug (15, "CFA_restore_state\n");
299 break;
300
301 case DW_CFA_def_cfa:
302 if (((ret = read_regnum (as, a, addr, ®num, arg)) < 0)
303 || ((ret = dwarf_read_uleb128 (as, a, addr, &val, arg)) < 0))
304 break;
305 set_reg (sr, DWARF_CFA_REG_COLUMN, DWARF_WHERE_REG, regnum);
306 set_reg (sr, DWARF_CFA_OFF_COLUMN, 0, val); /* NOT factored! */
307 Debug (15, "CFA_def_cfa r%lu+0x%lx\n", (long) regnum, (long) val);
308 break;
309
310 case DW_CFA_def_cfa_sf:
311 if (((ret = read_regnum (as, a, addr, ®num, arg)) < 0)
312 || ((ret = dwarf_read_sleb128 (as, a, addr, &val, arg)) < 0))
313 break;
314 set_reg (sr, DWARF_CFA_REG_COLUMN, DWARF_WHERE_REG, regnum);
315 set_reg (sr, DWARF_CFA_OFF_COLUMN, 0,
316 val * dci->data_align); /* factored! */
317 Debug (15, "CFA_def_cfa_sf r%lu+0x%lx\n",
318 (long) regnum, (long) (val * dci->data_align));
319 break;
320
321 case DW_CFA_def_cfa_register:
322 if ((ret = read_regnum (as, a, addr, ®num, arg)) < 0)
323 break;
324 set_reg (sr, DWARF_CFA_REG_COLUMN, DWARF_WHERE_REG, regnum);
325 Debug (15, "CFA_def_cfa_register r%lu\n", (long) regnum);
326 break;
327
328 case DW_CFA_def_cfa_offset:
329 if ((ret = dwarf_read_uleb128 (as, a, addr, &val, arg)) < 0)
330 break;
331 set_reg (sr, DWARF_CFA_OFF_COLUMN, 0, val); /* NOT factored! */
332 Debug (15, "CFA_def_cfa_offset 0x%lx\n", (long) val);
333 break;
334
335 case DW_CFA_def_cfa_offset_sf:
336 if ((ret = dwarf_read_sleb128 (as, a, addr, &val, arg)) < 0)
337 break;
338 set_reg (sr, DWARF_CFA_OFF_COLUMN, 0,
339 val * dci->data_align); /* factored! */
340 Debug (15, "CFA_def_cfa_offset_sf 0x%lx\n",
341 (long) (val * dci->data_align));
342 break;
343
344 case DW_CFA_val_offset:
345 if (((ret = read_regnum (as, a, addr, ®num, arg)) < 0)
346 || ((ret = dwarf_read_uleb128 (as, a, addr, &val, arg)) < 0))
347 break;
348 set_reg (sr, regnum, DWARF_WHERE_VAL, val * dci->data_align);
349 Debug (15, "CFA_offset_extended_sf r%lu at cf+0x%lx\n",
350 (long) regnum, (long) (val * dci->data_align));
351 break;
352
353 case DW_CFA_val_offset_sf:
354 if (((ret = read_regnum (as, a, addr, ®num, arg)) < 0)
355 || ((ret = dwarf_read_sleb128 (as, a, addr, &val, arg)) < 0))
356 break;
357 set_reg (sr, regnum, DWARF_WHERE_VAL, val * dci->data_align);
358 Debug (15, "CFA_offset_extended_sf r%lu at cf+0x%lx\n",
359 (long) regnum, (long) (val * dci->data_align));
360 break;
361
362 case DW_CFA_def_cfa_expression:
363 /* Save the address of the DW_FORM_block for later evaluation. */
364 set_reg (sr, DWARF_CFA_REG_COLUMN, DWARF_WHERE_EXPR, *addr);
365
366 if ((ret = dwarf_read_uleb128 (as, a, addr, &len, arg)) < 0)
367 break;
368
369 Debug (15, "CFA_def_cfa_expr @ 0x%lx [%lu bytes]\n",
370 (long) *addr, (long) len);
371 *addr += len;
372 break;
373
374 case DW_CFA_expression:
375 if ((ret = read_regnum (as, a, addr, ®num, arg)) < 0)
376 break;
377
378 /* Save the address of the DW_FORM_block for later evaluation. */
379 set_reg (sr, regnum, DWARF_WHERE_EXPR, *addr);
380
381 if ((ret = dwarf_read_uleb128 (as, a, addr, &len, arg)) < 0)
382 break;
383
384 Debug (15, "CFA_expression r%lu @ 0x%lx [%lu bytes]\n",
385 (long) regnum, (long) addr, (long) len);
386 *addr += len;
387 break;
388
389 case DW_CFA_val_expression:
390 if ((ret = read_regnum (as, a, addr, ®num, arg)) < 0)
391 break;
392
393 /* Save the address of the DW_FORM_block for later evaluation. */
394 set_reg (sr, regnum, DWARF_WHERE_VAL_EXPR, *addr);
395
396 if ((ret = dwarf_read_uleb128 (as, a, addr, &len, arg)) < 0)
397 break;
398
399 Debug (15, "CFA_val_expression r%lu @ 0x%lx [%lu bytes]\n",
400 (long) regnum, (long) addr, (long) len);
401 *addr += len;
402 break;
403
404 case DW_CFA_GNU_args_size:
405 if ((ret = dwarf_read_uleb128 (as, a, addr, &val, arg)) < 0)
406 break;
407 sr->args_size = val;
408 Debug (15, "CFA_GNU_args_size %lu\n", (long) val);
409 break;
410
411 case DW_CFA_GNU_negative_offset_extended:
412 /* A comment in GCC says that this is obsoleted by
413 DW_CFA_offset_extended_sf, but that it's used by older
414 PowerPC code. */
415 if (((ret = read_regnum (as, a, addr, ®num, arg)) < 0)
416 || ((ret = dwarf_read_uleb128 (as, a, addr, &val, arg)) < 0))
417 break;
418 set_reg (sr, regnum, DWARF_WHERE_CFAREL, ~(val * dci->data_align) + 1);
419 Debug (15, "CFA_GNU_negative_offset_extended cfa+0x%lx\n",
420 (long) (~(val * dci->data_align) + 1));
421 break;
422
423 case DW_CFA_GNU_window_save:
424 #ifdef UNW_TARGET_SPARC
425 /* This is a special CFA to handle all 16 windowed registers
426 on SPARC. */
427 for (regnum = 16; regnum < 32; ++regnum)
428 set_reg (sr, regnum, DWARF_WHERE_CFAREL,
429 (regnum - 16) * sizeof (unw_word_t));
430 Debug (15, "CFA_GNU_window_save\n");
431 break;
432 #elif UNW_TARGET_AARCH64
433 /* This is a specific opcode on aarch64, DW_CFA_AARCH64_negate_ra_state */
434 Debug (15, "DW_CFA_AARCH64_negate_ra_state\n");
435 aarch64_negate_ra_sign_state(sr);
436 break;
437 #else
438 /* FALL THROUGH */
439 #endif
440 case DW_CFA_lo_user:
441 case DW_CFA_hi_user:
442 Debug (1, "Unexpected CFA opcode 0x%x\n", op);
443 ret = -UNW_EINVAL;
444 break;
445 }
446 }
447
448 if (ret > 0)
449 ret = 0;
450 return ret;
451 }
452
453 static int
fetch_proc_info(struct dwarf_cursor * c,unw_word_t ip)454 fetch_proc_info (struct dwarf_cursor *c, unw_word_t ip)
455 {
456 int ret, dynamic = 1;
457
458 /* The 'ip' can point either to the previous or next instruction
459 depending on what type of frame we have: normal call or a place
460 to resume execution (e.g. after signal frame).
461
462 For a normal call frame we need to back up so we point within the
463 call itself; this is important because a) the call might be the
464 very last instruction of the function and the edge of the FDE,
465 and b) so that run_cfi_program() runs locations up to the call
466 but not more.
467
468 For signal frame, we need to do the exact opposite and look
469 up using the current 'ip' value. That is where execution will
470 continue, and it's important we get this right, as 'ip' could be
471 right at the function entry and hence FDE edge, or at instruction
472 that manipulates CFA (push/pop). */
473
474 if (c->use_prev_instr)
475 {
476 #if defined(__arm__)
477 /* On arm, the least bit denotes thumb/arm mode, clear it. */
478 ip &= ~(unw_word_t)0x1;
479 #endif
480 --ip;
481 }
482
483 memset (&c->pi, 0, sizeof (c->pi));
484
485 /* check dynamic info first --- it overrides everything else */
486 ret = unwi_find_dynamic_proc_info (c->as, ip, &c->pi, 1,
487 c->as_arg);
488 if (ret == -UNW_ENOINFO)
489 {
490 dynamic = 0;
491 if ((ret = tdep_find_proc_info (c, ip, 1)) < 0)
492 return ret;
493 }
494
495 if (c->pi.format != UNW_INFO_FORMAT_DYNAMIC
496 && c->pi.format != UNW_INFO_FORMAT_TABLE
497 && c->pi.format != UNW_INFO_FORMAT_REMOTE_TABLE)
498 return -UNW_ENOINFO;
499
500 c->pi_valid = 1;
501 c->pi_is_dynamic = dynamic;
502
503 /* Let system/machine-dependent code determine frame-specific attributes. */
504 if (ret >= 0)
505 tdep_fetch_frame (c, ip, 1);
506
507 return ret;
508 }
509
510 static int
parse_dynamic(struct dwarf_cursor * c,unw_word_t ip,dwarf_state_record_t * sr)511 parse_dynamic (struct dwarf_cursor *c, unw_word_t ip, dwarf_state_record_t *sr)
512 {
513 Debug (1, "Not yet implemented\n");
514 return -UNW_ENOINFO;
515 }
516
517 static inline void
put_unwind_info(struct dwarf_cursor * c,unw_proc_info_t * pi)518 put_unwind_info (struct dwarf_cursor *c, unw_proc_info_t *pi)
519 {
520 if (c->pi_is_dynamic)
521 unwi_put_dynamic_unwind_info (c->as, pi, c->as_arg);
522 else if (pi->unwind_info && pi->format == UNW_INFO_FORMAT_TABLE)
523 {
524 mempool_free (&dwarf_cie_info_pool, pi->unwind_info);
525 pi->unwind_info = NULL;
526 }
527 c->pi_valid = 0;
528 }
529
530 static inline int
setup_fde(struct dwarf_cursor * c,dwarf_state_record_t * sr)531 setup_fde (struct dwarf_cursor *c, dwarf_state_record_t *sr)
532 {
533 int i, ret;
534
535 assert (c->pi_valid);
536
537 memset (sr, 0, sizeof (*sr));
538 for (i = 0; i < DWARF_NUM_PRESERVED_REGS + 2; ++i)
539 set_reg (sr, i, DWARF_WHERE_SAME, 0);
540
541 struct dwarf_cie_info *dci = c->pi.unwind_info;
542 sr->rs_current.ret_addr_column = dci->ret_addr_column;
543 unw_word_t addr = dci->cie_instr_start;
544 unw_word_t curr_ip = 0;
545 dwarf_stackable_reg_state_t *rs_stack = NULL;
546 ret = run_cfi_program (c, sr, &curr_ip, ~(unw_word_t) 0, &addr,
547 dci->cie_instr_end,
548 &rs_stack, dci);
549 empty_rstate_stack(&rs_stack);
550 if (ret < 0)
551 return ret;
552
553 memcpy (&sr->rs_initial, &sr->rs_current, sizeof (sr->rs_initial));
554 return 0;
555 }
556
557 static inline int
parse_fde(struct dwarf_cursor * c,unw_word_t ip,dwarf_state_record_t * sr)558 parse_fde (struct dwarf_cursor *c, unw_word_t ip, dwarf_state_record_t *sr)
559 {
560 int ret;
561 struct dwarf_cie_info *dci = c->pi.unwind_info;
562 unw_word_t addr = dci->fde_instr_start;
563 unw_word_t curr_ip = c->pi.start_ip;
564 dwarf_stackable_reg_state_t *rs_stack = NULL;
565 /* Process up to current `ip` for signal frame and `ip - 1` for normal call frame
566 See `c->use_prev_instr` use in `fetch_proc_info` for details. */
567 ret = run_cfi_program (c, sr, &curr_ip, ip - c->use_prev_instr, &addr, dci->fde_instr_end,
568 &rs_stack, dci);
569 empty_rstate_stack(&rs_stack);
570 if (ret < 0)
571 return ret;
572
573 return 0;
574 }
575
576 HIDDEN int
dwarf_flush_rs_cache(struct dwarf_rs_cache * cache)577 dwarf_flush_rs_cache (struct dwarf_rs_cache *cache)
578 {
579 int i;
580
581 if (cache->log_size == DWARF_DEFAULT_LOG_UNW_CACHE_SIZE
582 || !cache->hash) {
583 cache->hash = cache->default_hash;
584 cache->buckets = cache->default_buckets;
585 cache->links = cache->default_links;
586 cache->log_size = DWARF_DEFAULT_LOG_UNW_CACHE_SIZE;
587 } else {
588 if (cache->hash && cache->hash != cache->default_hash)
589 munmap(cache->hash, DWARF_UNW_HASH_SIZE(cache->prev_log_size)
590 * sizeof (cache->hash[0]));
591 if (cache->buckets && cache->buckets != cache->default_buckets)
592 munmap(cache->buckets, DWARF_UNW_CACHE_SIZE(cache->prev_log_size)
593 * sizeof (cache->buckets[0]));
594 if (cache->links && cache->links != cache->default_links)
595 munmap(cache->links, DWARF_UNW_CACHE_SIZE(cache->prev_log_size)
596 * sizeof (cache->links[0]));
597 GET_MEMORY(cache->hash, DWARF_UNW_HASH_SIZE(cache->log_size)
598 * sizeof (cache->hash[0]));
599 GET_MEMORY(cache->buckets, DWARF_UNW_CACHE_SIZE(cache->log_size)
600 * sizeof (cache->buckets[0]));
601 GET_MEMORY(cache->links, DWARF_UNW_CACHE_SIZE(cache->log_size)
602 * sizeof (cache->links[0]));
603 if (!cache->hash || !cache->buckets || !cache->links)
604 {
605 Debug (1, "Unable to allocate cache memory");
606 return -UNW_ENOMEM;
607 }
608 cache->prev_log_size = cache->log_size;
609 }
610
611 cache->rr_head = 0;
612
613 for (i = 0; i < DWARF_UNW_CACHE_SIZE(cache->log_size); ++i)
614 {
615 cache->links[i].coll_chain = -1;
616 cache->links[i].ip = 0;
617 cache->links[i].valid = 0;
618 }
619 for (i = 0; i< DWARF_UNW_HASH_SIZE(cache->log_size); ++i)
620 cache->hash[i] = -1;
621
622 return 0;
623 }
624
625 static inline struct dwarf_rs_cache *
get_rs_cache(unw_addr_space_t as,intrmask_t * saved_maskp)626 get_rs_cache (unw_addr_space_t as, intrmask_t *saved_maskp)
627 {
628 struct dwarf_rs_cache *cache = &as->global_cache;
629 unw_caching_policy_t caching = as->caching_policy;
630
631 if (caching == UNW_CACHE_NONE)
632 return NULL;
633
634 #if defined(HAVE___CACHE_PER_THREAD) && HAVE___CACHE_PER_THREAD
635 if (likely (caching == UNW_CACHE_PER_THREAD))
636 {
637 static _Thread_local struct dwarf_rs_cache tls_cache __attribute__((tls_model("initial-exec")));
638 Debug (16, "using TLS cache\n");
639 cache = &tls_cache;
640 }
641 else
642 #else
643 if (likely (caching == UNW_CACHE_GLOBAL))
644 #endif
645 {
646 Debug (16, "acquiring lock\n");
647 lock_acquire (&cache->lock, *saved_maskp);
648 }
649
650 if ((atomic_load (&as->cache_generation) != atomic_load (&cache->generation))
651 || !cache->hash)
652 {
653 /* cache_size is only set in the global_cache, copy it over before flushing */
654 cache->log_size = as->global_cache.log_size;
655 if (dwarf_flush_rs_cache (cache) < 0)
656 return NULL;
657 atomic_store (&cache->generation, atomic_load (&as->cache_generation));
658 }
659
660 return cache;
661 }
662
663 static inline void
put_rs_cache(unw_addr_space_t as,struct dwarf_rs_cache * cache,intrmask_t * saved_maskp)664 put_rs_cache (unw_addr_space_t as, struct dwarf_rs_cache *cache,
665 intrmask_t *saved_maskp)
666 {
667 assert (as->caching_policy != UNW_CACHE_NONE);
668
669 Debug (16, "unmasking signals/interrupts and releasing lock\n");
670 if (likely (as->caching_policy == UNW_CACHE_GLOBAL))
671 lock_release (&cache->lock, *saved_maskp);
672 }
673
674 static inline unw_hash_index_t CONST_ATTR
hash(unw_word_t ip,unsigned short log_size)675 hash (unw_word_t ip, unsigned short log_size)
676 {
677 /* based on (sqrt(5)/2-1)*2^64 */
678 # define magic ((unw_word_t) 0x9e3779b97f4a7c16ULL)
679
680 return ip * magic >> ((sizeof(unw_word_t) * 8) - (log_size + 1));
681 }
682
683 static inline long
cache_match(struct dwarf_rs_cache * cache,unsigned short index,unw_word_t ip)684 cache_match (struct dwarf_rs_cache *cache, unsigned short index, unw_word_t ip)
685 {
686 return (cache->links[index].valid && (ip == cache->links[index].ip));
687 }
688
689 static dwarf_reg_state_t *
rs_lookup(struct dwarf_rs_cache * cache,struct dwarf_cursor * c)690 rs_lookup (struct dwarf_rs_cache *cache, struct dwarf_cursor *c)
691 {
692 unsigned short index;
693 unw_word_t ip = c->ip;
694
695 if (c->hint > 0)
696 {
697 index = c->hint - 1;
698 if (cache_match (cache, index, ip))
699 return &cache->buckets[index];
700 }
701
702 for (index = cache->hash[hash (ip, cache->log_size)];
703 index < DWARF_UNW_CACHE_SIZE(cache->log_size);
704 index = cache->links[index].coll_chain)
705 {
706 if (cache_match (cache, index, ip))
707 return &cache->buckets[index];
708 }
709 return NULL;
710 }
711
712 static inline dwarf_reg_state_t *
rs_new(struct dwarf_rs_cache * cache,struct dwarf_cursor * c)713 rs_new (struct dwarf_rs_cache *cache, struct dwarf_cursor * c)
714 {
715 unw_hash_index_t index;
716 unsigned short head;
717
718 head = cache->rr_head;
719 cache->rr_head = (head + 1) & (DWARF_UNW_CACHE_SIZE(cache->log_size) - 1);
720
721 /* remove the old rs from the hash table (if it's there): */
722 if (cache->links[head].ip)
723 {
724 unsigned short *pindex;
725 for (pindex = &cache->hash[hash (cache->links[head].ip, cache->log_size)];
726 *pindex < DWARF_UNW_CACHE_SIZE(cache->log_size);
727 pindex = &cache->links[*pindex].coll_chain)
728 {
729 if (*pindex == head)
730 {
731 *pindex = cache->links[*pindex].coll_chain;
732 break;
733 }
734 }
735 }
736
737 /* enter new rs in the hash table */
738 index = hash (c->ip, cache->log_size);
739 cache->links[head].coll_chain = cache->hash[index];
740 cache->hash[index] = head;
741
742 cache->links[head].ip = c->ip;
743 cache->links[head].valid = 1;
744 cache->links[head].signal_frame = tdep_cache_frame(c);
745 return cache->buckets + head;
746 }
747
748 static int
create_state_record_for(struct dwarf_cursor * c,dwarf_state_record_t * sr,unw_word_t ip)749 create_state_record_for (struct dwarf_cursor *c, dwarf_state_record_t *sr,
750 unw_word_t ip)
751 {
752 int ret;
753 switch (c->pi.format)
754 {
755 case UNW_INFO_FORMAT_TABLE:
756 case UNW_INFO_FORMAT_REMOTE_TABLE:
757 if ((ret = setup_fde(c, sr)) < 0)
758 return ret;
759 ret = parse_fde (c, ip, sr);
760 break;
761
762 case UNW_INFO_FORMAT_DYNAMIC:
763 ret = parse_dynamic (c, ip, sr);
764 break;
765
766 default:
767 Debug (1, "Unexpected unwind-info format %d\n", c->pi.format);
768 ret = -UNW_EINVAL;
769 }
770 return ret;
771 }
772
773 static inline int
eval_location_expr(struct dwarf_cursor * c,unw_word_t stack_val,unw_addr_space_t as,unw_accessors_t * a,unw_word_t addr,dwarf_loc_t * locp,void * arg)774 eval_location_expr (struct dwarf_cursor *c, unw_word_t stack_val, unw_addr_space_t as,
775 unw_accessors_t *a, unw_word_t addr,
776 dwarf_loc_t *locp, void *arg)
777 {
778 int ret, is_register;
779 unw_word_t len, val;
780
781 /* read the length of the expression: */
782 if ((ret = dwarf_read_uleb128 (as, a, &addr, &len, arg)) < 0)
783 return ret;
784
785 /* evaluate the expression: */
786 if ((ret = dwarf_eval_expr (c, stack_val, &addr, len, &val, &is_register)) < 0)
787 return ret;
788
789 if (is_register)
790 *locp = DWARF_REG_LOC (c, dwarf_to_unw_regnum (val));
791 else
792 *locp = DWARF_MEM_LOC (c, val);
793
794 return 0;
795 }
796
797
798 #ifdef UNW_TARGET_AARCH64
799 #include "libunwind-aarch64.h"
800
801 static void
aarch64_negate_ra_sign_state(dwarf_state_record_t * sr)802 aarch64_negate_ra_sign_state(dwarf_state_record_t *sr)
803 {
804 unw_word_t ra_sign_state = sr->rs_current.reg.val[UNW_AARCH64_RA_SIGN_STATE];
805 ra_sign_state ^= 0x1;
806 set_reg(sr, UNW_AARCH64_RA_SIGN_STATE, DWARF_WHERE_SAME, ra_sign_state);
807 }
808
809 static unw_word_t
aarch64_strip_pac_remote(unw_accessors_t * a,unw_addr_space_t as,void * arg,unw_word_t old_ip)810 aarch64_strip_pac_remote(unw_accessors_t *a, unw_addr_space_t as, void *arg, unw_word_t old_ip)
811 {
812 if (a->ptrauth_insn_mask)
813 {
814 unw_word_t ip, insn_mask;
815
816 insn_mask = a->ptrauth_insn_mask(as, arg);
817 ip = old_ip & (~insn_mask);
818
819 Debug(15, "stripping pac from address, before: %lx, after: %lx\n", old_ip, ip);
820 return ip;
821 }
822 else
823 {
824 unw_word_t insn_mask = 0xFFFFFF8000000000; // mask all bits from [63:40];
825 unw_word_t ip = old_ip & (~insn_mask);
826 Debug(15, "return address %lx might be signed, use 0xFFFFFF8000000000 as default mask\n", old_ip);
827 return ip;
828 }
829 }
830
831 static unw_word_t
aarch64_strip_pac_local(unw_word_t in_addr)832 aarch64_strip_pac_local(unw_word_t in_addr)
833 {
834 unw_word_t out_addr = in_addr;
835
836 #ifdef __aarch64__
837 // Strip the PAC with XPACLRI instruction
838 register unsigned long long x30 __asm__("x30") = in_addr;
839 __asm__("hint 0x7" : "+r" (x30));
840 out_addr = x30;
841 #endif
842
843 return out_addr;
844 }
845
846 static unw_word_t
aarch64_get_ra_sign_state(struct dwarf_reg_state * rs)847 aarch64_get_ra_sign_state(struct dwarf_reg_state *rs)
848 {
849 return rs->reg.val[UNW_AARCH64_RA_SIGN_STATE];
850 }
851
852 #endif
853
854 static int
apply_reg_state(struct dwarf_cursor * c,struct dwarf_reg_state * rs)855 apply_reg_state (struct dwarf_cursor *c, struct dwarf_reg_state *rs)
856 {
857 unw_word_t regnum, addr, cfa, ip;
858 unw_word_t prev_ip, prev_cfa;
859 unw_addr_space_t as;
860 dwarf_loc_t cfa_loc;
861 unw_accessors_t *a;
862 int i, ret;
863 void *arg;
864
865 /* In the case that we have incorrect CFI, the return address column may be
866 * outside the valid range of data and will read invalid data. Protect
867 * against the errant read and indicate that we have a bad frame. */
868 if (rs->ret_addr_column >= DWARF_NUM_PRESERVED_REGS) {
869 Dprintf ("%s: return address entry %zu is outside of range of CIE",
870 __FUNCTION__, rs->ret_addr_column);
871 return -UNW_EBADFRAME;
872 }
873
874 prev_ip = c->ip;
875 prev_cfa = c->cfa;
876
877 as = c->as;
878 arg = c->as_arg;
879 a = unw_get_accessors_int (as);
880
881 /* Evaluate the CFA first, because it may be referred to by other
882 expressions. */
883
884 if (rs->reg.where[DWARF_CFA_REG_COLUMN] == DWARF_WHERE_REG)
885 {
886 /* CFA is equal to [reg] + offset: */
887
888 /* As a special-case, if the stack-pointer is the CFA and the
889 stack-pointer wasn't saved, popping the CFA implicitly pops
890 the stack-pointer as well. */
891 if ((rs->reg.val[DWARF_CFA_REG_COLUMN] == UNW_TDEP_SP)
892 && (UNW_TDEP_SP < ARRAY_SIZE(rs->reg.val))
893 && (rs->reg.where[UNW_TDEP_SP] == DWARF_WHERE_SAME))
894 cfa = c->cfa;
895 else
896 {
897 regnum = dwarf_to_unw_regnum (rs->reg.val[DWARF_CFA_REG_COLUMN]);
898 if ((ret = unw_get_reg ((unw_cursor_t *) c, regnum, &cfa)) < 0)
899 return ret;
900 }
901 cfa += rs->reg.val[DWARF_CFA_OFF_COLUMN];
902 }
903 else
904 {
905 /* CFA is equal to EXPR: */
906
907 assert (rs->reg.where[DWARF_CFA_REG_COLUMN] == DWARF_WHERE_EXPR);
908
909 addr = rs->reg.val[DWARF_CFA_REG_COLUMN];
910 /* The dwarf standard doesn't specify an initial value to be pushed on */
911 /* the stack before DW_CFA_def_cfa_expression evaluation. We push on a */
912 /* dummy value (0) to keep the eval_location_expr function consistent. */
913 if ((ret = eval_location_expr (c, 0, as, a, addr, &cfa_loc, arg)) < 0)
914 return ret;
915 /* the returned location better be a memory location... */
916 if (DWARF_IS_REG_LOC (cfa_loc))
917 return -UNW_EBADFRAME;
918 cfa = DWARF_GET_LOC (cfa_loc);
919 }
920
921 #ifdef ONLY_RECOVER_GENERAL_REGS
922 const int32_t regCount = 33;
923 #else
924 const int32_t regCount = DWARF_NUM_PRESERVED_REGS;
925 #endif
926
927 dwarf_loc_t new_loc[DWARF_NUM_PRESERVED_REGS];
928 memcpy(new_loc, c->loc, sizeof(new_loc));
929
930 for (i = 0; i < regCount; ++i)
931 {
932 switch ((dwarf_where_t) rs->reg.where[i])
933 {
934 case DWARF_WHERE_UNDEF:
935 new_loc[i] = DWARF_NULL_LOC;
936 break;
937
938 case DWARF_WHERE_SAME:
939 break;
940
941 case DWARF_WHERE_CFAREL:
942 new_loc[i] = DWARF_MEM_LOC (c, cfa + rs->reg.val[i]);
943 break;
944
945 case DWARF_WHERE_REG:
946 #ifdef __s390x__
947 /* GPRs can be saved in FPRs on s390x */
948 if (unw_is_fpreg (dwarf_to_unw_regnum (rs->reg.val[i])))
949 {
950 new_loc[i] = DWARF_FPREG_LOC (c, dwarf_to_unw_regnum (rs->reg.val[i]));
951 break;
952 }
953 #endif
954 new_loc[i] = new_loc[rs->reg.val[i]];
955 break;
956
957 case DWARF_WHERE_EXPR:
958 addr = rs->reg.val[i];
959 /* The dwarf standard requires the current CFA to be pushed on the */
960 /* stack before DW_CFA_expression evaluation. */
961 if ((ret = eval_location_expr (c, cfa, as, a, addr, new_loc + i, arg)) < 0)
962 return ret;
963 break;
964
965 case DWARF_WHERE_VAL_EXPR:
966 addr = rs->reg.val[i];
967 /* The dwarf standard requires the current CFA to be pushed on the */
968 /* stack before DW_CFA_val_expression evaluation. */
969 if ((ret = eval_location_expr (c, cfa, as, a, addr, new_loc + i, arg)) < 0)
970 return ret;
971 new_loc[i] = DWARF_VAL_LOC (c, DWARF_GET_LOC (new_loc[i]));
972 break;
973
974 case DWARF_WHERE_VAL:
975 new_loc[i] = DWARF_VAL_LOC (c, DWARF_GET_LOC (new_loc[i]));
976 Debug (16, "%s(%d), where[%d]=0x%x, new_loc.val=0x%x\n",
977 __FILE__, __LINE__, i, rs->reg.where[i], new_loc[i].val);
978 break;
979 }
980 }
981
982 memcpy(c->loc, new_loc, sizeof(new_loc));
983
984 c->cfa = cfa;
985 /* DWARF spec says undefined return address location means end of stack. */
986 if (DWARF_IS_NULL_LOC (c->loc[rs->ret_addr_column]))
987 {
988 c->ip = 0;
989 ret = 0;
990 }
991 else
992 {
993 ret = dwarf_get (c, c->loc[rs->ret_addr_column], &ip);
994 if (ret < 0)
995 return ret;
996 #ifdef UNW_TARGET_AARCH64
997 if (aarch64_get_ra_sign_state(rs))
998 {
999 if (c->as != NULL && c->as->pid == -1)
1000 {
1001 ip = aarch64_strip_pac_local(ip);
1002 }
1003 else
1004 {
1005 ip = aarch64_strip_pac_remote(a, as, arg, ip);
1006 }
1007 }
1008 #endif
1009 c->ip = ip;
1010 ret = 1;
1011 }
1012
1013 /* XXX: check for ip to be code_aligned */
1014 if (c->ip == prev_ip && c->cfa == prev_cfa)
1015 {
1016 Dprintf ("%s: ip and cfa unchanged; stopping here (ip=0x%lx)\n",
1017 __FUNCTION__, (long) c->ip);
1018 return -UNW_EBADFRAME;
1019 }
1020
1021 if (c->stash_frames)
1022 tdep_stash_frame (c, rs);
1023
1024 return ret;
1025 }
1026
1027 /* Find the saved locations. */
1028 static int
find_reg_state(struct dwarf_cursor * c,dwarf_state_record_t * sr)1029 find_reg_state (struct dwarf_cursor *c, dwarf_state_record_t *sr)
1030 {
1031 dwarf_reg_state_t *rs = NULL;
1032 struct dwarf_rs_cache *cache;
1033 int ret = 0;
1034 intrmask_t saved_mask;
1035
1036 if ((cache = get_rs_cache(c->as, &saved_mask)) &&
1037 (rs = rs_lookup(cache, c)))
1038 {
1039 /* update hint; no locking needed: single-word writes are atomic */
1040 unsigned short index = rs - cache->buckets;
1041 c->use_prev_instr = ! cache->links[index].signal_frame;
1042 memcpy (&sr->rs_current, rs, sizeof (*rs));
1043 }
1044 else
1045 {
1046 ret = fetch_proc_info (c, c->ip);
1047 int next_use_prev_instr = c->use_prev_instr;
1048 if (ret >= 0)
1049 {
1050 /* Update use_prev_instr for the next frame. */
1051 assert(c->pi.unwind_info);
1052 struct dwarf_cie_info *dci = c->pi.unwind_info;
1053 next_use_prev_instr = ! dci->signal_frame;
1054 ret = create_state_record_for (c, sr, c->ip);
1055 }
1056 put_unwind_info (c, &c->pi);
1057 c->use_prev_instr = next_use_prev_instr;
1058
1059 if (cache && ret >= 0)
1060 {
1061 rs = rs_new (cache, c);
1062 cache->links[rs - cache->buckets].hint = 0;
1063 memcpy(rs, &sr->rs_current, sizeof(*rs));
1064 }
1065 }
1066
1067 unsigned short index = -1;
1068 if (cache)
1069 {
1070 if (rs)
1071 {
1072 index = rs - cache->buckets;
1073 c->hint = cache->links[index].hint;
1074 cache->links[c->prev_rs].hint = index + 1;
1075 c->prev_rs = index;
1076 }
1077 if (ret >= 0)
1078 tdep_reuse_frame (c, cache->links[index].signal_frame);
1079 put_rs_cache (c->as, cache, &saved_mask);
1080 }
1081 return ret;
1082 }
1083
1084 /* The function finds the saved locations and applies the register
1085 state as well. */
1086 HIDDEN int
dwarf_step(struct dwarf_cursor * c)1087 dwarf_step (struct dwarf_cursor *c)
1088 {
1089 int ret;
1090 dwarf_state_record_t sr;
1091 if ((ret = find_reg_state (c, &sr)) < 0)
1092 return ret;
1093 return apply_reg_state (c, &sr.rs_current);
1094 }
1095
1096 HIDDEN int
dwarf_make_proc_info(struct dwarf_cursor * c)1097 dwarf_make_proc_info (struct dwarf_cursor *c)
1098 {
1099 #if 0
1100 if (c->as->caching_policy == UNW_CACHE_NONE
1101 || get_cached_proc_info (c) < 0)
1102 #endif
1103 /* Need to check if current frame contains
1104 args_size, and set cursor appropriately. Only
1105 needed for unw_resume */
1106 dwarf_state_record_t sr;
1107 sr.args_size = 0;
1108 int ret;
1109
1110 /* Lookup it up the slow way... */
1111 ret = fetch_proc_info (c, c->ip);
1112 if (ret >= 0)
1113 ret = create_state_record_for (c, &sr, c->ip);
1114 put_unwind_info (c, &c->pi);
1115 if (ret < 0)
1116 return ret;
1117 c->args_size = sr.args_size;
1118
1119 return 0;
1120 }
1121
1122 static int
dwarf_reg_states_dynamic_iterate(struct dwarf_cursor * c,unw_reg_states_callback cb,void * token)1123 dwarf_reg_states_dynamic_iterate(struct dwarf_cursor *c,
1124 unw_reg_states_callback cb,
1125 void *token)
1126 {
1127 Debug (1, "Not yet implemented\n");
1128 return -UNW_ENOINFO;
1129 }
1130
1131 static int
dwarf_reg_states_table_iterate(struct dwarf_cursor * c,unw_reg_states_callback cb,void * token)1132 dwarf_reg_states_table_iterate(struct dwarf_cursor *c,
1133 unw_reg_states_callback cb,
1134 void *token)
1135 {
1136 dwarf_state_record_t sr;
1137 int ret = setup_fde(c, &sr);
1138 struct dwarf_cie_info *dci = c->pi.unwind_info;
1139 unw_word_t addr = dci->fde_instr_start;
1140 unw_word_t curr_ip = c->pi.start_ip;
1141 dwarf_stackable_reg_state_t *rs_stack = NULL;
1142 while (ret >= 0 && curr_ip < c->pi.end_ip && addr < dci->fde_instr_end)
1143 {
1144 unw_word_t prev_ip = curr_ip;
1145 ret = run_cfi_program (c, &sr, &curr_ip, prev_ip, &addr, dci->fde_instr_end,
1146 &rs_stack, dci);
1147 if (ret >= 0 && prev_ip < curr_ip)
1148 ret = cb(token, &sr.rs_current, sizeof(sr.rs_current), prev_ip, curr_ip);
1149 }
1150 empty_rstate_stack(&rs_stack);
1151 #if defined(NEED_LAST_IP)
1152 if (ret >= 0 && curr_ip < c->pi.last_ip)
1153 /* report the dead zone after the procedure ends */
1154 ret = cb(token, &sr.rs_current, sizeof(sr.rs_current), curr_ip, c->pi.last_ip);
1155 #else
1156 if (ret >= 0 && curr_ip < c->pi.end_ip)
1157 /* report for whatever is left before procedure end */
1158 ret = cb(token, &sr.rs_current, sizeof(sr.rs_current), curr_ip, c->pi.end_ip);
1159 #endif
1160 return ret;
1161 }
1162
1163 HIDDEN int
dwarf_reg_states_iterate(struct dwarf_cursor * c,unw_reg_states_callback cb,void * token)1164 dwarf_reg_states_iterate(struct dwarf_cursor *c,
1165 unw_reg_states_callback cb,
1166 void *token)
1167 {
1168 int ret = fetch_proc_info (c, c->ip);
1169 int next_use_prev_instr = c->use_prev_instr;
1170 if (ret >= 0)
1171 {
1172 /* Update use_prev_instr for the next frame. */
1173 assert(c->pi.unwind_info);
1174 struct dwarf_cie_info *dci = c->pi.unwind_info;
1175 next_use_prev_instr = ! dci->signal_frame;
1176 switch (c->pi.format)
1177 {
1178 case UNW_INFO_FORMAT_TABLE:
1179 case UNW_INFO_FORMAT_REMOTE_TABLE:
1180 ret = dwarf_reg_states_table_iterate(c, cb, token);
1181 break;
1182
1183 case UNW_INFO_FORMAT_DYNAMIC:
1184 ret = dwarf_reg_states_dynamic_iterate (c, cb, token);
1185 break;
1186
1187 default:
1188 Debug (1, "Unexpected unwind-info format %d\n", c->pi.format);
1189 ret = -UNW_EINVAL;
1190 }
1191 }
1192 put_unwind_info (c, &c->pi);
1193 c->use_prev_instr = next_use_prev_instr;
1194 return ret;
1195 }
1196
1197 HIDDEN int
dwarf_apply_reg_state(struct dwarf_cursor * c,struct dwarf_reg_state * rs)1198 dwarf_apply_reg_state (struct dwarf_cursor *c, struct dwarf_reg_state *rs)
1199 {
1200 return apply_reg_state(c, rs);
1201 }
1202