• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <stddef.h>
27 #include "dwarf_i.h"
28 #include "libunwind_i.h"
29 
30 #define alloc_reg_state()	(mempool_alloc (&dwarf_reg_state_pool))
31 #define free_reg_state(rs)	(mempool_free (&dwarf_reg_state_pool, rs))
32 
33 static inline int
read_regnum(unw_addr_space_t as,unw_accessors_t * a,unw_word_t * addr,unw_word_t * valp,void * arg)34 read_regnum (unw_addr_space_t as, unw_accessors_t *a, unw_word_t *addr,
35 	     unw_word_t *valp, void *arg)
36 {
37   int ret;
38 
39   if ((ret = dwarf_read_uleb128 (as, a, addr, valp, arg)) < 0)
40     return ret;
41 
42   if (*valp >= DWARF_NUM_PRESERVED_REGS)
43     {
44       Debug (1, "Invalid register number %u\n", (unsigned int) *valp);
45       return -UNW_EBADREG;
46     }
47   return 0;
48 }
49 
50 static inline void
set_reg(dwarf_state_record_t * sr,unw_word_t regnum,dwarf_where_t where,unw_word_t val)51 set_reg (dwarf_state_record_t *sr, unw_word_t regnum, dwarf_where_t where,
52 	 unw_word_t val)
53 {
54   sr->rs_current.reg[regnum].where = where;
55   sr->rs_current.reg[regnum].val = val;
56 }
57 
58 /* Run a CFI program to update the register state.  */
59 static int
run_cfi_program(struct dwarf_cursor * c,dwarf_state_record_t * sr,unw_word_t ip,unw_word_t * addr,unw_word_t end_addr,struct dwarf_cie_info * dci)60 run_cfi_program (struct dwarf_cursor *c, dwarf_state_record_t *sr,
61 		 unw_word_t ip, unw_word_t *addr, unw_word_t end_addr,
62 		 struct dwarf_cie_info *dci)
63 {
64   unw_word_t curr_ip, operand = 0, regnum, val, len, fde_encoding;
65   dwarf_reg_state_t *rs_stack = NULL, *new_rs, *old_rs;
66   unw_addr_space_t as;
67   unw_accessors_t *a;
68   uint8_t u8, op;
69   uint16_t u16;
70   uint32_t u32;
71   void *arg;
72   int ret;
73 
74   as = c->as;
75   arg = c->as_arg;
76   if (c->pi.flags & UNW_PI_FLAG_DEBUG_FRAME)
77     {
78       /* .debug_frame CFI is stored in local address space.  */
79       as = unw_local_addr_space;
80       arg = NULL;
81     }
82   a = unw_get_accessors (as);
83   curr_ip = c->pi.start_ip;
84 
85   /* Process everything up to and including the current 'ip',
86      including all the DW_CFA_advance_loc instructions.  See
87      'c->use_prev_instr' use in 'fetch_proc_info' for details. */
88   while (curr_ip <= ip && *addr < end_addr)
89     {
90       if ((ret = dwarf_readu8 (as, a, addr, &op, arg)) < 0)
91 	return ret;
92 
93       if (op & DWARF_CFA_OPCODE_MASK)
94 	{
95 	  operand = op & DWARF_CFA_OPERAND_MASK;
96 	  op &= ~DWARF_CFA_OPERAND_MASK;
97 	}
98       switch ((dwarf_cfa_t) op)
99 	{
100 	case DW_CFA_advance_loc:
101 	  curr_ip += operand * dci->code_align;
102 	  Debug (15, "CFA_advance_loc to 0x%lx\n", (long) curr_ip);
103 	  break;
104 
105 	case DW_CFA_advance_loc1:
106 	  if ((ret = dwarf_readu8 (as, a, addr, &u8, arg)) < 0)
107 	    goto fail;
108 	  curr_ip += u8 * dci->code_align;
109 	  Debug (15, "CFA_advance_loc1 to 0x%lx\n", (long) curr_ip);
110 	  break;
111 
112 	case DW_CFA_advance_loc2:
113 	  if ((ret = dwarf_readu16 (as, a, addr, &u16, arg)) < 0)
114 	    goto fail;
115 	  curr_ip += u16 * dci->code_align;
116 	  Debug (15, "CFA_advance_loc2 to 0x%lx\n", (long) curr_ip);
117 	  break;
118 
119 	case DW_CFA_advance_loc4:
120 	  if ((ret = dwarf_readu32 (as, a, addr, &u32, arg)) < 0)
121 	    goto fail;
122 	  curr_ip += u32 * dci->code_align;
123 	  Debug (15, "CFA_advance_loc4 to 0x%lx\n", (long) curr_ip);
124 	  break;
125 
126 	case DW_CFA_MIPS_advance_loc8:
127 #ifdef UNW_TARGET_MIPS
128 	  {
129 	    uint64_t u64;
130 
131 	    if ((ret = dwarf_readu64 (as, a, addr, &u64, arg)) < 0)
132 	      goto fail;
133 	    curr_ip += u64 * dci->code_align;
134 	    Debug (15, "CFA_MIPS_advance_loc8\n");
135 	    break;
136 	  }
137 #else
138 	  Debug (1, "DW_CFA_MIPS_advance_loc8 on non-MIPS target\n");
139 	  ret = -UNW_EINVAL;
140 	  goto fail;
141 #endif
142 
143 	case DW_CFA_offset:
144 	  regnum = operand;
145 	  if (regnum >= DWARF_NUM_PRESERVED_REGS)
146 	    {
147 	      Debug (1, "Invalid register number %u in DW_cfa_OFFSET\n",
148 		     (unsigned int) regnum);
149 	      ret = -UNW_EBADREG;
150 	      goto fail;
151 	    }
152 	  if ((ret = dwarf_read_uleb128 (as, a, addr, &val, arg)) < 0)
153 	    goto fail;
154 	  set_reg (sr, regnum, DWARF_WHERE_CFAREL, val * dci->data_align);
155 	  Debug (15, "CFA_offset r%lu at cfa+0x%lx\n",
156 		 (long) regnum, (long) (val * dci->data_align));
157 	  break;
158 
159 	case DW_CFA_offset_extended:
160 	  if (((ret = read_regnum (as, a, addr, &regnum, arg)) < 0)
161 	      || ((ret = dwarf_read_uleb128 (as, a, addr, &val, arg)) < 0))
162 	    goto fail;
163 	  set_reg (sr, regnum, DWARF_WHERE_CFAREL, val * dci->data_align);
164 	  Debug (15, "CFA_offset_extended r%lu at cf+0x%lx\n",
165 		 (long) regnum, (long) (val * dci->data_align));
166 	  break;
167 
168 	case DW_CFA_offset_extended_sf:
169 	  if (((ret = read_regnum (as, a, addr, &regnum, arg)) < 0)
170 	      || ((ret = dwarf_read_sleb128 (as, a, addr, &val, arg)) < 0))
171 	    goto fail;
172 	  set_reg (sr, regnum, DWARF_WHERE_CFAREL, val * dci->data_align);
173 	  Debug (15, "CFA_offset_extended_sf r%lu at cf+0x%lx\n",
174 		 (long) regnum, (long) (val * dci->data_align));
175 	  break;
176 
177 	case DW_CFA_restore:
178 	  regnum = operand;
179 	  if (regnum >= DWARF_NUM_PRESERVED_REGS)
180 	    {
181 	      Debug (1, "Invalid register number %u in DW_CFA_restore\n",
182 		     (unsigned int) regnum);
183 	      ret = -UNW_EINVAL;
184 	      goto fail;
185 	    }
186 	  sr->rs_current.reg[regnum] = sr->rs_initial.reg[regnum];
187 	  Debug (15, "CFA_restore r%lu\n", (long) regnum);
188 	  break;
189 
190 	case DW_CFA_restore_extended:
191 	  if ((ret = dwarf_read_uleb128 (as, a, addr, &regnum, arg)) < 0)
192 	    goto fail;
193 	  if (regnum >= DWARF_NUM_PRESERVED_REGS)
194 	    {
195 	      Debug (1, "Invalid register number %u in "
196 		     "DW_CFA_restore_extended\n", (unsigned int) regnum);
197 	      ret = -UNW_EINVAL;
198 	      goto fail;
199 	    }
200 	  sr->rs_current.reg[regnum] = sr->rs_initial.reg[regnum];
201 	  Debug (15, "CFA_restore_extended r%lu\n", (long) regnum);
202 	  break;
203 
204 	case DW_CFA_nop:
205 	  break;
206 
207 	case DW_CFA_set_loc:
208 	  fde_encoding = dci->fde_encoding;
209 	  if ((ret = dwarf_read_encoded_pointer (as, a, addr, fde_encoding,
210 						 &c->pi, &curr_ip,
211 						 arg)) < 0)
212 	    goto fail;
213 	  Debug (15, "CFA_set_loc to 0x%lx\n", (long) curr_ip);
214 	  break;
215 
216 	case DW_CFA_undefined:
217 	  if ((ret = read_regnum (as, a, addr, &regnum, arg)) < 0)
218 	    goto fail;
219 	  set_reg (sr, regnum, DWARF_WHERE_UNDEF, 0);
220 	  Debug (15, "CFA_undefined r%lu\n", (long) regnum);
221 	  break;
222 
223 	case DW_CFA_same_value:
224 	  if ((ret = read_regnum (as, a, addr, &regnum, arg)) < 0)
225 	    goto fail;
226 	  set_reg (sr, regnum, DWARF_WHERE_SAME, 0);
227 	  Debug (15, "CFA_same_value r%lu\n", (long) regnum);
228 	  break;
229 
230 	case DW_CFA_register:
231 	  if (((ret = read_regnum (as, a, addr, &regnum, arg)) < 0)
232 	      || ((ret = dwarf_read_uleb128 (as, a, addr, &val, arg)) < 0))
233 	    goto fail;
234 	  set_reg (sr, regnum, DWARF_WHERE_REG, val);
235 	  Debug (15, "CFA_register r%lu to r%lu\n", (long) regnum, (long) val);
236 	  break;
237 
238 	case DW_CFA_remember_state:
239 	  new_rs = alloc_reg_state ();
240 	  if (!new_rs)
241 	    {
242 	      Debug (1, "Out of memory in DW_CFA_remember_state\n");
243 	      ret = -UNW_ENOMEM;
244 	      goto fail;
245 	    }
246 
247 	  memcpy (new_rs->reg, sr->rs_current.reg, sizeof (new_rs->reg));
248 	  new_rs->next = rs_stack;
249 	  rs_stack = new_rs;
250 	  Debug (15, "CFA_remember_state\n");
251 	  break;
252 
253 	case DW_CFA_restore_state:
254 	  if (!rs_stack)
255 	    {
256 	      Debug (1, "register-state stack underflow\n");
257 	      ret = -UNW_EINVAL;
258 	      goto fail;
259 	    }
260 	  memcpy (&sr->rs_current.reg, &rs_stack->reg, sizeof (rs_stack->reg));
261 	  old_rs = rs_stack;
262 	  rs_stack = rs_stack->next;
263 	  free_reg_state (old_rs);
264 	  Debug (15, "CFA_restore_state\n");
265 	  break;
266 
267 	case DW_CFA_def_cfa:
268 	  if (((ret = read_regnum (as, a, addr, &regnum, arg)) < 0)
269 	      || ((ret = dwarf_read_uleb128 (as, a, addr, &val, arg)) < 0))
270 	    goto fail;
271 	  set_reg (sr, DWARF_CFA_REG_COLUMN, DWARF_WHERE_REG, regnum);
272 	  set_reg (sr, DWARF_CFA_OFF_COLUMN, 0, val);	/* NOT factored! */
273 	  Debug (15, "CFA_def_cfa r%lu+0x%lx\n", (long) regnum, (long) val);
274 	  break;
275 
276 	case DW_CFA_def_cfa_sf:
277 	  if (((ret = read_regnum (as, a, addr, &regnum, arg)) < 0)
278 	      || ((ret = dwarf_read_sleb128 (as, a, addr, &val, arg)) < 0))
279 	    goto fail;
280 	  set_reg (sr, DWARF_CFA_REG_COLUMN, DWARF_WHERE_REG, regnum);
281 	  set_reg (sr, DWARF_CFA_OFF_COLUMN, 0,
282 		   val * dci->data_align);		/* factored! */
283 	  Debug (15, "CFA_def_cfa_sf r%lu+0x%lx\n",
284 		 (long) regnum, (long) (val * dci->data_align));
285 	  break;
286 
287 	case DW_CFA_def_cfa_register:
288 	  if ((ret = read_regnum (as, a, addr, &regnum, arg)) < 0)
289 	    goto fail;
290 	  set_reg (sr, DWARF_CFA_REG_COLUMN, DWARF_WHERE_REG, regnum);
291 	  Debug (15, "CFA_def_cfa_register r%lu\n", (long) regnum);
292 	  break;
293 
294 	case DW_CFA_def_cfa_offset:
295 	  if ((ret = dwarf_read_uleb128 (as, a, addr, &val, arg)) < 0)
296 	    goto fail;
297 	  set_reg (sr, DWARF_CFA_OFF_COLUMN, 0, val);	/* NOT factored! */
298 	  Debug (15, "CFA_def_cfa_offset 0x%lx\n", (long) val);
299 	  break;
300 
301 	case DW_CFA_def_cfa_offset_sf:
302 	  if ((ret = dwarf_read_sleb128 (as, a, addr, &val, arg)) < 0)
303 	    goto fail;
304 	  set_reg (sr, DWARF_CFA_OFF_COLUMN, 0,
305 		   val * dci->data_align);	/* factored! */
306 	  Debug (15, "CFA_def_cfa_offset_sf 0x%lx\n",
307 		 (long) (val * dci->data_align));
308 	  break;
309 
310 	case DW_CFA_def_cfa_expression:
311 	  /* Save the address of the DW_FORM_block for later evaluation. */
312 	  set_reg (sr, DWARF_CFA_REG_COLUMN, DWARF_WHERE_EXPR, *addr);
313 
314 	  if ((ret = dwarf_read_uleb128 (as, a, addr, &len, arg)) < 0)
315 	    goto fail;
316 
317 	  Debug (15, "CFA_def_cfa_expr @ 0x%lx [%lu bytes]\n",
318 		 (long) *addr, (long) len);
319 	  *addr += len;
320 	  break;
321 
322 	case DW_CFA_expression:
323 	  if ((ret = read_regnum (as, a, addr, &regnum, arg)) < 0)
324 	    goto fail;
325 
326 	  /* Save the address of the DW_FORM_block for later evaluation. */
327 	  set_reg (sr, regnum, DWARF_WHERE_EXPR, *addr);
328 
329 	  if ((ret = dwarf_read_uleb128 (as, a, addr, &len, arg)) < 0)
330 	    goto fail;
331 
332 	  Debug (15, "CFA_expression r%lu @ 0x%lx [%lu bytes]\n",
333 		 (long) regnum, (long) addr, (long) len);
334 	  *addr += len;
335 	  break;
336 
337 	case DW_CFA_GNU_args_size:
338 	  if ((ret = dwarf_read_uleb128 (as, a, addr, &val, arg)) < 0)
339 	    goto fail;
340 	  sr->args_size = val;
341 	  Debug (15, "CFA_GNU_args_size %lu\n", (long) val);
342 	  break;
343 
344 	case DW_CFA_GNU_negative_offset_extended:
345 	  /* A comment in GCC says that this is obsoleted by
346 	     DW_CFA_offset_extended_sf, but that it's used by older
347 	     PowerPC code.  */
348 	  if (((ret = read_regnum (as, a, addr, &regnum, arg)) < 0)
349 	      || ((ret = dwarf_read_uleb128 (as, a, addr, &val, arg)) < 0))
350 	    goto fail;
351 	  set_reg (sr, regnum, DWARF_WHERE_CFAREL, -(val * dci->data_align));
352 	  Debug (15, "CFA_GNU_negative_offset_extended cfa+0x%lx\n",
353 		 (long) -(val * dci->data_align));
354 	  break;
355 
356 	case DW_CFA_GNU_window_save:
357 #ifdef UNW_TARGET_SPARC
358 	  /* This is a special CFA to handle all 16 windowed registers
359 	     on SPARC.  */
360 	  for (regnum = 16; regnum < 32; ++regnum)
361 	    set_reg (sr, regnum, DWARF_WHERE_CFAREL,
362 		     (regnum - 16) * sizeof (unw_word_t));
363 	  Debug (15, "CFA_GNU_window_save\n");
364 	  break;
365 #else
366 	  /* FALL THROUGH */
367 #endif
368 	case DW_CFA_lo_user:
369 	case DW_CFA_hi_user:
370 	  Debug (1, "Unexpected CFA opcode 0x%x\n", op);
371 	  ret = -UNW_EINVAL;
372 	  goto fail;
373 	}
374     }
375   ret = 0;
376 
377  fail:
378   /* Free the register-state stack, if not empty already.  */
379   while (rs_stack)
380     {
381       old_rs = rs_stack;
382       rs_stack = rs_stack->next;
383       free_reg_state (old_rs);
384     }
385   return ret;
386 }
387 
388 static int
fetch_proc_info(struct dwarf_cursor * c,unw_word_t ip,int need_unwind_info)389 fetch_proc_info (struct dwarf_cursor *c, unw_word_t ip, int need_unwind_info)
390 {
391   int ret, dynamic = 1;
392 
393   /* The 'ip' can point either to the previous or next instruction
394      depending on what type of frame we have: normal call or a place
395      to resume execution (e.g. after signal frame).
396 
397      For a normal call frame we need to back up so we point within the
398      call itself; this is important because a) the call might be the
399      very last instruction of the function and the edge of the FDE,
400      and b) so that run_cfi_program() runs locations up to the call
401      but not more.
402 
403      For execution resume, we need to do the exact opposite and look
404      up using the current 'ip' value.  That is where execution will
405      continue, and it's important we get this right, as 'ip' could be
406      right at the function entry and hence FDE edge, or at instruction
407      that manipulates CFA (push/pop). */
408   if (c->use_prev_instr)
409     --ip;
410 
411   if (c->pi_valid && !need_unwind_info)
412     return 0;
413 
414   memset (&c->pi, 0, sizeof (c->pi));
415 
416   /* check dynamic info first --- it overrides everything else */
417   ret = unwi_find_dynamic_proc_info (c->as, ip, &c->pi, need_unwind_info,
418 				     c->as_arg);
419   if (ret == -UNW_ENOINFO)
420     {
421       dynamic = 0;
422       if ((ret = tdep_find_proc_info (c, ip, need_unwind_info)) < 0)
423 	return ret;
424     }
425 
426   if (c->pi.format != UNW_INFO_FORMAT_DYNAMIC
427       && c->pi.format != UNW_INFO_FORMAT_TABLE
428       && c->pi.format != UNW_INFO_FORMAT_REMOTE_TABLE)
429     return -UNW_ENOINFO;
430 
431   c->pi_valid = 1;
432   c->pi_is_dynamic = dynamic;
433 
434   /* Let system/machine-dependent code determine frame-specific attributes. */
435   if (ret >= 0)
436     tdep_fetch_frame (c, ip, need_unwind_info);
437 
438   /* Update use_prev_instr for the next frame. */
439   if (need_unwind_info)
440   {
441     assert(c->pi.unwind_info);
442     struct dwarf_cie_info *dci = c->pi.unwind_info;
443     c->use_prev_instr = ! dci->signal_frame;
444   }
445 
446   return ret;
447 }
448 
449 static int
parse_dynamic(struct dwarf_cursor * c,unw_word_t ip,dwarf_state_record_t * sr)450 parse_dynamic (struct dwarf_cursor *c, unw_word_t ip, dwarf_state_record_t *sr)
451 {
452   Debug (1, "Not yet implemented\n");
453 #if 0
454   /* Don't forget to set the ret_addr_column!  */
455   c->ret_addr_column = XXX;
456 #endif
457   return -UNW_ENOINFO;
458 }
459 
460 static inline void
put_unwind_info(struct dwarf_cursor * c,unw_proc_info_t * pi)461 put_unwind_info (struct dwarf_cursor *c, unw_proc_info_t *pi)
462 {
463   if (c->pi_is_dynamic)
464     unwi_put_dynamic_unwind_info (c->as, pi, c->as_arg);
465   else if (pi->unwind_info && pi->format == UNW_INFO_FORMAT_TABLE)
466     {
467       mempool_free (&dwarf_cie_info_pool, pi->unwind_info);
468       pi->unwind_info = NULL;
469     }
470 }
471 
472 static inline int
parse_fde(struct dwarf_cursor * c,unw_word_t ip,dwarf_state_record_t * sr)473 parse_fde (struct dwarf_cursor *c, unw_word_t ip, dwarf_state_record_t *sr)
474 {
475   struct dwarf_cie_info *dci;
476   unw_word_t addr;
477   int ret;
478 
479   dci = c->pi.unwind_info;
480   c->ret_addr_column = dci->ret_addr_column;
481 
482   addr = dci->cie_instr_start;
483   if ((ret = run_cfi_program (c, sr, ~(unw_word_t) 0, &addr,
484 			      dci->cie_instr_end, dci)) < 0)
485     return ret;
486 
487   memcpy (&sr->rs_initial, &sr->rs_current, sizeof (sr->rs_initial));
488 
489   addr = dci->fde_instr_start;
490   if ((ret = run_cfi_program (c, sr, ip, &addr, dci->fde_instr_end, dci)) < 0)
491     return ret;
492 
493   return 0;
494 }
495 
496 static inline void
flush_rs_cache(struct dwarf_rs_cache * cache)497 flush_rs_cache (struct dwarf_rs_cache *cache)
498 {
499   int i;
500 
501   cache->lru_head = DWARF_UNW_CACHE_SIZE - 1;
502   cache->lru_tail = 0;
503 
504   for (i = 0; i < DWARF_UNW_CACHE_SIZE; ++i)
505     {
506       if (i > 0)
507 	cache->buckets[i].lru_chain = (i - 1);
508       cache->buckets[i].coll_chain = -1;
509       cache->buckets[i].ip = 0;
510       cache->buckets[i].valid = 0;
511     }
512   for (i = 0; i<DWARF_UNW_HASH_SIZE; ++i)
513     cache->hash[i] = -1;
514 }
515 
516 static inline struct dwarf_rs_cache *
get_rs_cache(unw_addr_space_t as,intrmask_t * saved_maskp)517 get_rs_cache (unw_addr_space_t as, intrmask_t *saved_maskp)
518 {
519   struct dwarf_rs_cache *cache = &as->global_cache;
520   unw_caching_policy_t caching = as->caching_policy;
521 
522   if (caching == UNW_CACHE_NONE)
523     return NULL;
524 
525   if (likely (caching == UNW_CACHE_GLOBAL))
526     {
527       Debug (16, "acquiring lock\n");
528       lock_acquire (&cache->lock, *saved_maskp);
529     }
530 
531   if (atomic_read (&as->cache_generation) != atomic_read (&cache->generation))
532     {
533       flush_rs_cache (cache);
534       cache->generation = as->cache_generation;
535     }
536 
537   return cache;
538 }
539 
540 static inline void
put_rs_cache(unw_addr_space_t as,struct dwarf_rs_cache * cache,intrmask_t * saved_maskp)541 put_rs_cache (unw_addr_space_t as, struct dwarf_rs_cache *cache,
542 		  intrmask_t *saved_maskp)
543 {
544   assert (as->caching_policy != UNW_CACHE_NONE);
545 
546   Debug (16, "unmasking signals/interrupts and releasing lock\n");
547   if (likely (as->caching_policy == UNW_CACHE_GLOBAL))
548     lock_release (&cache->lock, *saved_maskp);
549 }
550 
551 static inline unw_hash_index_t CONST_ATTR
hash(unw_word_t ip)552 hash (unw_word_t ip)
553 {
554   /* based on (sqrt(5)/2-1)*2^64 */
555 # define magic	((unw_word_t) 0x9e3779b97f4a7c16ULL)
556 
557   return ip * magic >> ((sizeof(unw_word_t) * 8) - DWARF_LOG_UNW_HASH_SIZE);
558 }
559 
560 static inline long
cache_match(dwarf_reg_state_t * rs,unw_word_t ip)561 cache_match (dwarf_reg_state_t *rs, unw_word_t ip)
562 {
563   if (rs->valid && (ip == rs->ip))
564     return 1;
565   return 0;
566 }
567 
568 static dwarf_reg_state_t *
rs_lookup(struct dwarf_rs_cache * cache,struct dwarf_cursor * c)569 rs_lookup (struct dwarf_rs_cache *cache, struct dwarf_cursor *c)
570 {
571   dwarf_reg_state_t *rs = cache->buckets + c->hint;
572   unsigned short index;
573   unw_word_t ip;
574 
575   ip = c->ip;
576 
577   if (cache_match (rs, ip))
578     return rs;
579 
580   index = cache->hash[hash (ip)];
581   if (index >= DWARF_UNW_CACHE_SIZE)
582     return NULL;
583 
584   rs = cache->buckets + index;
585   while (1)
586     {
587       if (cache_match (rs, ip))
588         {
589           /* update hint; no locking needed: single-word writes are atomic */
590           c->hint = cache->buckets[c->prev_rs].hint =
591             (rs - cache->buckets);
592           return rs;
593         }
594       if (rs->coll_chain >= DWARF_UNW_HASH_SIZE)
595         return NULL;
596       rs = cache->buckets + rs->coll_chain;
597     }
598 }
599 
600 static inline dwarf_reg_state_t *
rs_new(struct dwarf_rs_cache * cache,struct dwarf_cursor * c)601 rs_new (struct dwarf_rs_cache *cache, struct dwarf_cursor * c)
602 {
603   dwarf_reg_state_t *rs, *prev, *tmp;
604   unw_hash_index_t index;
605   unsigned short head;
606 
607   head = cache->lru_head;
608   rs = cache->buckets + head;
609   cache->lru_head = rs->lru_chain;
610 
611   /* re-insert rs at the tail of the LRU chain: */
612   cache->buckets[cache->lru_tail].lru_chain = head;
613   cache->lru_tail = head;
614 
615   /* remove the old rs from the hash table (if it's there): */
616   if (rs->ip)
617     {
618       index = hash (rs->ip);
619       tmp = cache->buckets + cache->hash[index];
620       prev = NULL;
621       while (1)
622 	{
623 	  if (tmp == rs)
624 	    {
625 	      if (prev)
626 		prev->coll_chain = tmp->coll_chain;
627 	      else
628 		cache->hash[index] = tmp->coll_chain;
629 	      break;
630 	    }
631 	  else
632 	    prev = tmp;
633 	  if (tmp->coll_chain >= DWARF_UNW_CACHE_SIZE)
634 	    /* old rs wasn't in the hash-table */
635 	    break;
636 	  tmp = cache->buckets + tmp->coll_chain;
637 	}
638     }
639 
640   /* enter new rs in the hash table */
641   index = hash (c->ip);
642   rs->coll_chain = cache->hash[index];
643   cache->hash[index] = rs - cache->buckets;
644 
645   rs->hint = 0;
646   rs->ip = c->ip;
647   rs->valid = 1;
648   rs->ret_addr_column = c->ret_addr_column;
649   rs->signal_frame = 0;
650   tdep_cache_frame (c, rs);
651 
652   return rs;
653 }
654 
655 static int
create_state_record_for(struct dwarf_cursor * c,dwarf_state_record_t * sr,unw_word_t ip)656 create_state_record_for (struct dwarf_cursor *c, dwarf_state_record_t *sr,
657 			 unw_word_t ip)
658 {
659   int i, ret;
660 
661   assert (c->pi_valid);
662 
663   memset (sr, 0, sizeof (*sr));
664   for (i = 0; i < DWARF_NUM_PRESERVED_REGS + 2; ++i)
665     set_reg (sr, i, DWARF_WHERE_SAME, 0);
666 
667   switch (c->pi.format)
668     {
669     case UNW_INFO_FORMAT_TABLE:
670     case UNW_INFO_FORMAT_REMOTE_TABLE:
671       ret = parse_fde (c, ip, sr);
672       break;
673 
674     case UNW_INFO_FORMAT_DYNAMIC:
675       ret = parse_dynamic (c, ip, sr);
676       break;
677 
678     default:
679       Debug (1, "Unexpected unwind-info format %d\n", c->pi.format);
680       ret = -UNW_EINVAL;
681     }
682   return ret;
683 }
684 
685 static inline int
eval_location_expr(struct dwarf_cursor * c,unw_addr_space_t as,unw_accessors_t * a,unw_word_t addr,dwarf_loc_t * locp,void * arg)686 eval_location_expr (struct dwarf_cursor *c, unw_addr_space_t as,
687 		    unw_accessors_t *a, unw_word_t addr,
688 		    dwarf_loc_t *locp, void *arg)
689 {
690   int ret, is_register;
691   unw_word_t len, val;
692 
693   /* read the length of the expression: */
694   if ((ret = dwarf_read_uleb128 (as, a, &addr, &len, arg)) < 0)
695     return ret;
696 
697   /* evaluate the expression: */
698   if ((ret = dwarf_eval_expr (c, &addr, len, &val, &is_register)) < 0)
699     return ret;
700 
701   if (is_register)
702     *locp = DWARF_REG_LOC (c, dwarf_to_unw_regnum (val));
703   else
704     *locp = DWARF_MEM_LOC (c, val);
705 
706   return 0;
707 }
708 
709 static int
apply_reg_state(struct dwarf_cursor * c,struct dwarf_reg_state * rs)710 apply_reg_state (struct dwarf_cursor *c, struct dwarf_reg_state *rs)
711 {
712   unw_word_t regnum, addr, cfa, ip;
713   unw_word_t prev_ip, prev_cfa;
714   unw_addr_space_t as;
715   dwarf_loc_t cfa_loc;
716   unw_accessors_t *a;
717   int i, ret;
718   void *arg;
719 
720   prev_ip = c->ip;
721   prev_cfa = c->cfa;
722 
723   as = c->as;
724   arg = c->as_arg;
725   a = unw_get_accessors (as);
726 
727   /* Evaluate the CFA first, because it may be referred to by other
728      expressions.  */
729 
730   if (rs->reg[DWARF_CFA_REG_COLUMN].where == DWARF_WHERE_REG)
731     {
732       /* CFA is equal to [reg] + offset: */
733 
734       /* As a special-case, if the stack-pointer is the CFA and the
735 	 stack-pointer wasn't saved, popping the CFA implicitly pops
736 	 the stack-pointer as well.  */
737       if ((rs->reg[DWARF_CFA_REG_COLUMN].val == UNW_TDEP_SP)
738           && (UNW_TDEP_SP < ARRAY_SIZE(rs->reg))
739 	  && (rs->reg[UNW_TDEP_SP].where == DWARF_WHERE_SAME))
740 	  cfa = c->cfa;
741       else
742 	{
743 	  regnum = dwarf_to_unw_regnum (rs->reg[DWARF_CFA_REG_COLUMN].val);
744 	  if ((ret = unw_get_reg ((unw_cursor_t *) c, regnum, &cfa)) < 0)
745 	    return ret;
746 	}
747       cfa += rs->reg[DWARF_CFA_OFF_COLUMN].val;
748     }
749   else
750     {
751       /* CFA is equal to EXPR: */
752 
753       assert (rs->reg[DWARF_CFA_REG_COLUMN].where == DWARF_WHERE_EXPR);
754 
755       addr = rs->reg[DWARF_CFA_REG_COLUMN].val;
756       if ((ret = eval_location_expr (c, as, a, addr, &cfa_loc, arg)) < 0)
757 	return ret;
758       /* the returned location better be a memory location... */
759       if (DWARF_IS_REG_LOC (cfa_loc))
760 	return -UNW_EBADFRAME;
761       cfa = DWARF_GET_LOC (cfa_loc);
762     }
763 
764   for (i = 0; i < DWARF_NUM_PRESERVED_REGS; ++i)
765     {
766       switch ((dwarf_where_t) rs->reg[i].where)
767 	{
768 	case DWARF_WHERE_UNDEF:
769 	  c->loc[i] = DWARF_NULL_LOC;
770 	  break;
771 
772 	case DWARF_WHERE_SAME:
773 	  break;
774 
775 	case DWARF_WHERE_CFAREL:
776 	  c->loc[i] = DWARF_MEM_LOC (c, cfa + rs->reg[i].val);
777 	  break;
778 
779 	case DWARF_WHERE_REG:
780 	  c->loc[i] = DWARF_REG_LOC (c, dwarf_to_unw_regnum (rs->reg[i].val));
781 	  break;
782 
783 	case DWARF_WHERE_EXPR:
784 	  addr = rs->reg[i].val;
785 	  if ((ret = eval_location_expr (c, as, a, addr, c->loc + i, arg)) < 0)
786 	    return ret;
787 	  break;
788 	}
789     }
790 
791   c->cfa = cfa;
792   /* DWARF spec says undefined return address location means end of stack. */
793   if (DWARF_IS_NULL_LOC (c->loc[c->ret_addr_column]))
794     c->ip = 0;
795   else
796   {
797     ret = dwarf_get (c, c->loc[c->ret_addr_column], &ip);
798     if (ret < 0)
799       return ret;
800     c->ip = ip;
801   }
802 
803   /* XXX: check for ip to be code_aligned */
804   if (c->ip == prev_ip && c->cfa == prev_cfa)
805     {
806       Dprintf ("%s: ip and cfa unchanged; stopping here (ip=0x%lx)\n",
807 	       __FUNCTION__, (long) c->ip);
808       return -UNW_EBADFRAME;
809     }
810 
811   if (c->stash_frames)
812     tdep_stash_frame (c, rs);
813 
814   return 0;
815 }
816 
817 static int
uncached_dwarf_find_save_locs(struct dwarf_cursor * c)818 uncached_dwarf_find_save_locs (struct dwarf_cursor *c)
819 {
820   dwarf_state_record_t sr;
821   int ret;
822 
823   if ((ret = fetch_proc_info (c, c->ip, 1)) < 0)
824     {
825       put_unwind_info (c, &c->pi);
826       return ret;
827     }
828 
829   if ((ret = create_state_record_for (c, &sr, c->ip)) < 0)
830     {
831       /* ANDROID support update. */
832       put_unwind_info (c, &c->pi);
833       /* End of ANDROID update. */
834       return ret;
835     }
836 
837   if ((ret = apply_reg_state (c, &sr.rs_current)) < 0)
838     {
839       /* ANDROID support update. */
840       put_unwind_info (c, &c->pi);
841       /* End of ANDROID update. */
842       return ret;
843     }
844 
845   put_unwind_info (c, &c->pi);
846   return 0;
847 }
848 
849 /* The function finds the saved locations and applies the register
850    state as well. */
851 HIDDEN int
dwarf_find_save_locs(struct dwarf_cursor * c)852 dwarf_find_save_locs (struct dwarf_cursor *c)
853 {
854 #if defined(CONSERVE_STACK)
855   dwarf_reg_state_t *rs_copy;
856 #else
857   dwarf_reg_state_t rs_copy_stack;
858   dwarf_reg_state_t *rs_copy = &rs_copy_stack;
859 #endif
860   dwarf_reg_state_t *rs;
861   struct dwarf_rs_cache *cache;
862   int ret = 0;
863   intrmask_t saved_mask;
864 
865   if (c->as->caching_policy == UNW_CACHE_NONE)
866     return uncached_dwarf_find_save_locs (c);
867 
868   cache = get_rs_cache(c->as, &saved_mask);
869   rs = rs_lookup(cache, c);
870 
871   if (rs)
872     {
873       c->ret_addr_column = rs->ret_addr_column;
874       c->use_prev_instr = ! rs->signal_frame;
875     }
876   else
877     {
878 #if !defined(CONSERVE_STACK)
879       dwarf_state_record_t sr_stack;
880       dwarf_state_record_t *sr = &sr_stack;
881 #else
882       dwarf_state_record_t *sr = (dwarf_state_record_t*)malloc(sizeof(dwarf_state_record_t));
883 
884       if (sr == NULL)
885         return -UNW_ENOMEM;
886 #endif
887 
888       if ((ret = fetch_proc_info (c, c->ip, 1)) < 0 ||
889 	  (ret = create_state_record_for (c, sr, c->ip)) < 0)
890 	{
891           put_rs_cache (c->as, cache, &saved_mask);
892           put_unwind_info (c, &c->pi);
893 #if defined(CONSERVE_STACK)
894           free(sr);
895 #endif
896 	  return ret;
897 	}
898 
899       rs = rs_new (cache, c);
900       memcpy(rs, &sr->rs_current, offsetof(struct dwarf_reg_state, ip));
901       cache->buckets[c->prev_rs].hint = rs - cache->buckets;
902 
903       c->hint = rs->hint;
904       c->prev_rs = rs - cache->buckets;
905 
906       put_unwind_info (c, &c->pi);
907 
908 #if defined(CONSERVE_STACK)
909       free(sr);
910 #endif
911     }
912 
913 #if defined(CONSERVE_STACK)
914   rs_copy = (dwarf_reg_state_t*)malloc(sizeof(dwarf_reg_state_t));
915   if (rs_copy == NULL)
916     return -UNW_ENOMEM;
917 #endif
918 
919   memcpy (rs_copy, rs, sizeof (*rs_copy));
920   put_rs_cache (c->as, cache, &saved_mask);
921 
922   tdep_reuse_frame (c, rs_copy);
923   ret = apply_reg_state (c, rs_copy);
924 
925 #if defined(CONSERVE_STACK)
926   free(rs_copy);
927 #endif
928 
929   return ret;
930 }
931 
932 /* The proc-info must be valid for IP before this routine can be
933    called.  */
934 HIDDEN int
dwarf_create_state_record(struct dwarf_cursor * c,dwarf_state_record_t * sr)935 dwarf_create_state_record (struct dwarf_cursor *c, dwarf_state_record_t *sr)
936 {
937   return create_state_record_for (c, sr, c->ip);
938 }
939 
940 HIDDEN int
dwarf_make_proc_info(struct dwarf_cursor * c)941 dwarf_make_proc_info (struct dwarf_cursor *c)
942 {
943 #if 0
944   if (c->as->caching_policy == UNW_CACHE_NONE
945       || get_cached_proc_info (c) < 0)
946 #endif
947     /* Lookup it up the slow way... */
948     return fetch_proc_info (c, c->ip, 0);
949   return 0;
950 }
951