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