• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* libunwind - a platform-independent unwind library
2    Copyright (C) 2001-2004 Hewlett-Packard Co
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 "unwind_i.h"
27 
28 /* forward declaration: */
29 static int create_state_record_for (struct cursor *c,
30 				    struct ia64_state_record *sr,
31 				    unw_word_t ip);
32 
33 typedef unsigned long unw_word;
34 
35 #define alloc_reg_state()	(mempool_alloc (&unw.reg_state_pool))
36 #define free_reg_state(rs)	(mempool_free (&unw.reg_state_pool, rs))
37 #define alloc_labeled_state()	(mempool_alloc (&unw.labeled_state_pool))
38 #define free_labeled_state(s)	(mempool_free (&unw.labeled_state_pool, s))
39 
40 /* Routines to manipulate the state stack.  */
41 
42 static inline void
push(struct ia64_state_record * sr)43 push (struct ia64_state_record *sr)
44 {
45   struct ia64_reg_state *rs;
46 
47   rs = alloc_reg_state ();
48   if (!rs)
49     {
50       print_error ("libunwind: cannot stack reg state!\n");
51       return;
52     }
53   memcpy (rs, &sr->curr, sizeof (*rs));
54   sr->curr.next = rs;
55 }
56 
57 static void
pop(struct ia64_state_record * sr)58 pop (struct ia64_state_record *sr)
59 {
60   struct ia64_reg_state *rs = sr->curr.next;
61 
62   if (!rs)
63     {
64       print_error ("libunwind: stack underflow!\n");
65       return;
66     }
67   memcpy (&sr->curr, rs, sizeof (*rs));
68   free_reg_state (rs);
69 }
70 
71 /* Make a copy of the state stack.  Non-recursive to avoid stack overflows.  */
72 static struct ia64_reg_state *
dup_state_stack(struct ia64_reg_state * rs)73 dup_state_stack (struct ia64_reg_state *rs)
74 {
75   struct ia64_reg_state *copy, *prev = NULL, *first = NULL;
76 
77   while (rs)
78     {
79       copy = alloc_reg_state ();
80       if (!copy)
81 	{
82 	  print_error ("unwind.dup_state_stack: out of memory\n");
83 	  return NULL;
84 	}
85       memcpy (copy, rs, sizeof (*copy));
86       if (first)
87 	prev->next = copy;
88       else
89 	first = copy;
90       rs = rs->next;
91       prev = copy;
92     }
93   return first;
94 }
95 
96 /* Free all stacked register states (but not RS itself).  */
97 static void
free_state_stack(struct ia64_reg_state * rs)98 free_state_stack (struct ia64_reg_state *rs)
99 {
100   struct ia64_reg_state *p, *next;
101 
102   for (p = rs->next; p != NULL; p = next)
103     {
104       next = p->next;
105       free_reg_state (p);
106     }
107   rs->next = NULL;
108 }
109 
110 /* Unwind decoder routines */
111 
112 static enum ia64_pregnum CONST_ATTR
decode_abreg(unsigned char abreg,int memory)113 decode_abreg (unsigned char abreg, int memory)
114 {
115   switch (abreg)
116     {
117     case 0x04 ... 0x07:
118       return IA64_REG_R4 + (abreg - 0x04);
119     case 0x22 ... 0x25:
120       return IA64_REG_F2 + (abreg - 0x22);
121     case 0x30 ... 0x3f:
122       return IA64_REG_F16 + (abreg - 0x30);
123     case 0x41 ... 0x45:
124       return IA64_REG_B1 + (abreg - 0x41);
125     case 0x60:
126       return IA64_REG_PR;
127     case 0x61:
128       return IA64_REG_PSP;
129     case 0x62:
130       return memory ? IA64_REG_PRI_UNAT_MEM : IA64_REG_PRI_UNAT_GR;
131     case 0x63:
132       return IA64_REG_IP;
133     case 0x64:
134       return IA64_REG_BSP;
135     case 0x65:
136       return IA64_REG_BSPSTORE;
137     case 0x66:
138       return IA64_REG_RNAT;
139     case 0x67:
140       return IA64_REG_UNAT;
141     case 0x68:
142       return IA64_REG_FPSR;
143     case 0x69:
144       return IA64_REG_PFS;
145     case 0x6a:
146       return IA64_REG_LC;
147     default:
148       break;
149     }
150   Dprintf ("libunwind: bad abreg=0x%x\n", abreg);
151   return IA64_REG_LC;
152 }
153 
154 static void
set_reg(struct ia64_reg_info * reg,enum ia64_where where,int when,unsigned long val)155 set_reg (struct ia64_reg_info *reg, enum ia64_where where, int when,
156 	 unsigned long val)
157 {
158   reg->val = val;
159   reg->where = where;
160   if (reg->when == IA64_WHEN_NEVER)
161     reg->when = when;
162 }
163 
164 static void
alloc_spill_area(unsigned long * offp,unsigned long regsize,struct ia64_reg_info * lo,struct ia64_reg_info * hi)165 alloc_spill_area (unsigned long *offp, unsigned long regsize,
166 		  struct ia64_reg_info *lo, struct ia64_reg_info *hi)
167 {
168   struct ia64_reg_info *reg;
169 
170   for (reg = hi; reg >= lo; --reg)
171     {
172       if (reg->where == IA64_WHERE_SPILL_HOME)
173 	{
174 	  reg->where = IA64_WHERE_PSPREL;
175 	  *offp -= regsize;
176 	  reg->val = *offp;
177 	}
178     }
179 }
180 
181 static inline void
spill_next_when(struct ia64_reg_info ** regp,struct ia64_reg_info * lim,unw_word t)182 spill_next_when (struct ia64_reg_info **regp, struct ia64_reg_info *lim,
183 		 unw_word t)
184 {
185   struct ia64_reg_info *reg;
186 
187   for (reg = *regp; reg <= lim; ++reg)
188     {
189       if (reg->where == IA64_WHERE_SPILL_HOME)
190 	{
191 	  reg->when = t;
192 	  *regp = reg + 1;
193 	  return;
194 	}
195     }
196   Dprintf ("libunwind: excess spill!\n");
197 }
198 
199 static inline void
finish_prologue(struct ia64_state_record * sr)200 finish_prologue (struct ia64_state_record *sr)
201 {
202   struct ia64_reg_info *reg;
203   unsigned long off;
204   int i;
205 
206   /* First, resolve implicit register save locations (see Section
207      "11.4.2.3 Rules for Using Unwind Descriptors", rule 3). */
208   for (i = 0; i < (int) ARRAY_SIZE (unw.save_order); ++i)
209     {
210       reg = sr->curr.reg + unw.save_order[i];
211       if (reg->where == IA64_WHERE_GR_SAVE)
212 	{
213 	  reg->where = IA64_WHERE_GR;
214 	  reg->val = sr->gr_save_loc++;
215 	}
216     }
217 
218   /* Next, compute when the fp, general, and branch registers get
219      saved.  This must come before alloc_spill_area() because we need
220      to know which registers are spilled to their home locations.  */
221 
222   if (sr->imask)
223     {
224       unsigned char kind, mask = 0, *cp = sr->imask;
225       unsigned long t;
226       static const unsigned char limit[3] =
227         {
228 	  IA64_REG_F31, IA64_REG_R7, IA64_REG_B5
229 	};
230       struct ia64_reg_info *(regs[3]);
231 
232       regs[0] = sr->curr.reg + IA64_REG_F2;
233       regs[1] = sr->curr.reg + IA64_REG_R4;
234       regs[2] = sr->curr.reg + IA64_REG_B1;
235 
236       for (t = 0; (int) t < sr->region_len; ++t)
237 	{
238 	  if ((t & 3) == 0)
239 	    mask = *cp++;
240 	  kind = (mask >> 2 * (3 - (t & 3))) & 3;
241 	  if (kind > 0)
242 	    spill_next_when (&regs[kind - 1], sr->curr.reg + limit[kind - 1],
243 			     sr->region_start + t);
244 	}
245     }
246 
247   /* Next, lay out the memory stack spill area.  */
248 
249   if (sr->any_spills)
250     {
251       off = sr->spill_offset;
252       alloc_spill_area (&off, 16, sr->curr.reg + IA64_REG_F2,
253 			sr->curr.reg + IA64_REG_F31);
254       alloc_spill_area (&off, 8, sr->curr.reg + IA64_REG_B1,
255 			sr->curr.reg + IA64_REG_B5);
256       alloc_spill_area (&off, 8, sr->curr.reg + IA64_REG_R4,
257 			sr->curr.reg + IA64_REG_R7);
258     }
259 }
260 
261 /* Region header descriptors.  */
262 
263 static void
desc_prologue(int body,unw_word rlen,unsigned char mask,unsigned char grsave,struct ia64_state_record * sr)264 desc_prologue (int body, unw_word rlen, unsigned char mask,
265 	       unsigned char grsave, struct ia64_state_record *sr)
266 {
267   int i, region_start;
268 
269   if (!(sr->in_body || sr->first_region))
270     finish_prologue (sr);
271   sr->first_region = 0;
272 
273   /* check if we're done: */
274   if (sr->when_target < sr->region_start + sr->region_len)
275     {
276       sr->done = 1;
277       return;
278     }
279 
280   region_start = sr->region_start + sr->region_len;
281 
282   for (i = 0; i < sr->epilogue_count; ++i)
283     pop (sr);
284   sr->epilogue_count = 0;
285   sr->when_sp_restored = IA64_WHEN_NEVER;
286 
287   sr->region_start = region_start;
288   sr->region_len = rlen;
289   sr->in_body = body;
290 
291   if (!body)
292     {
293       push (sr);
294 
295       if (mask)
296 	for (i = 0; i < 4; ++i)
297 	  {
298 	    if (mask & 0x8)
299 	      set_reg (sr->curr.reg + unw.save_order[i], IA64_WHERE_GR,
300 		       sr->region_start + sr->region_len - 1, grsave++);
301 	    mask <<= 1;
302 	  }
303       sr->gr_save_loc = grsave;
304       sr->any_spills = 0;
305       sr->imask = 0;
306       sr->spill_offset = 0x10;	/* default to psp+16 */
307     }
308 }
309 
310 /* Prologue descriptors.  */
311 
312 static inline void
desc_abi(unsigned char abi,unsigned char context,struct ia64_state_record * sr)313 desc_abi (unsigned char abi, unsigned char context,
314 	  struct ia64_state_record *sr)
315 {
316   sr->abi_marker = (abi << 8) | context;
317 }
318 
319 static inline void
desc_br_gr(unsigned char brmask,unsigned char gr,struct ia64_state_record * sr)320 desc_br_gr (unsigned char brmask, unsigned char gr,
321 	    struct ia64_state_record *sr)
322 {
323   int i;
324 
325   for (i = 0; i < 5; ++i)
326     {
327       if (brmask & 1)
328 	set_reg (sr->curr.reg + IA64_REG_B1 + i, IA64_WHERE_GR,
329 		 sr->region_start + sr->region_len - 1, gr++);
330       brmask >>= 1;
331     }
332 }
333 
334 static inline void
desc_br_mem(unsigned char brmask,struct ia64_state_record * sr)335 desc_br_mem (unsigned char brmask, struct ia64_state_record *sr)
336 {
337   int i;
338 
339   for (i = 0; i < 5; ++i)
340     {
341       if (brmask & 1)
342 	{
343 	  set_reg (sr->curr.reg + IA64_REG_B1 + i, IA64_WHERE_SPILL_HOME,
344 		   sr->region_start + sr->region_len - 1, 0);
345 	  sr->any_spills = 1;
346 	}
347       brmask >>= 1;
348     }
349 }
350 
351 static inline void
desc_frgr_mem(unsigned char grmask,unw_word frmask,struct ia64_state_record * sr)352 desc_frgr_mem (unsigned char grmask, unw_word frmask,
353 	       struct ia64_state_record *sr)
354 {
355   int i;
356 
357   for (i = 0; i < 4; ++i)
358     {
359       if ((grmask & 1) != 0)
360 	{
361 	  set_reg (sr->curr.reg + IA64_REG_R4 + i, IA64_WHERE_SPILL_HOME,
362 		   sr->region_start + sr->region_len - 1, 0);
363 	  sr->any_spills = 1;
364 	}
365       grmask >>= 1;
366     }
367   for (i = 0; i < 20; ++i)
368     {
369       if ((frmask & 1) != 0)
370 	{
371 	  int base = (i < 4) ? IA64_REG_F2 : IA64_REG_F16 - 4;
372 	  set_reg (sr->curr.reg + base + i, IA64_WHERE_SPILL_HOME,
373 		   sr->region_start + sr->region_len - 1, 0);
374 	  sr->any_spills = 1;
375 	}
376       frmask >>= 1;
377     }
378 }
379 
380 static inline void
desc_fr_mem(unsigned char frmask,struct ia64_state_record * sr)381 desc_fr_mem (unsigned char frmask, struct ia64_state_record *sr)
382 {
383   int i;
384 
385   for (i = 0; i < 4; ++i)
386     {
387       if ((frmask & 1) != 0)
388 	{
389 	  set_reg (sr->curr.reg + IA64_REG_F2 + i, IA64_WHERE_SPILL_HOME,
390 		   sr->region_start + sr->region_len - 1, 0);
391 	  sr->any_spills = 1;
392 	}
393       frmask >>= 1;
394     }
395 }
396 
397 static inline void
desc_gr_gr(unsigned char grmask,unsigned char gr,struct ia64_state_record * sr)398 desc_gr_gr (unsigned char grmask, unsigned char gr,
399 	    struct ia64_state_record *sr)
400 {
401   int i;
402 
403   for (i = 0; i < 4; ++i)
404     {
405       if ((grmask & 1) != 0)
406 	set_reg (sr->curr.reg + IA64_REG_R4 + i, IA64_WHERE_GR,
407 		 sr->region_start + sr->region_len - 1, gr++);
408       grmask >>= 1;
409     }
410 }
411 
412 static inline void
desc_gr_mem(unsigned char grmask,struct ia64_state_record * sr)413 desc_gr_mem (unsigned char grmask, struct ia64_state_record *sr)
414 {
415   int i;
416 
417   for (i = 0; i < 4; ++i)
418     {
419       if ((grmask & 1) != 0)
420 	{
421 	  set_reg (sr->curr.reg + IA64_REG_R4 + i, IA64_WHERE_SPILL_HOME,
422 		   sr->region_start + sr->region_len - 1, 0);
423 	  sr->any_spills = 1;
424 	}
425       grmask >>= 1;
426     }
427 }
428 
429 static inline void
desc_mem_stack_f(unw_word t,unw_word size,struct ia64_state_record * sr)430 desc_mem_stack_f (unw_word t, unw_word size, struct ia64_state_record *sr)
431 {
432   set_reg (sr->curr.reg + IA64_REG_PSP, IA64_WHERE_NONE,
433 	   sr->region_start + MIN ((int) t, sr->region_len - 1), 16 * size);
434 }
435 
436 static inline void
desc_mem_stack_v(unw_word t,struct ia64_state_record * sr)437 desc_mem_stack_v (unw_word t, struct ia64_state_record *sr)
438 {
439   sr->curr.reg[IA64_REG_PSP].when =
440     sr->region_start + MIN ((int) t, sr->region_len - 1);
441 }
442 
443 static inline void
desc_reg_gr(unsigned char reg,unsigned char dst,struct ia64_state_record * sr)444 desc_reg_gr (unsigned char reg, unsigned char dst,
445 	     struct ia64_state_record *sr)
446 {
447   set_reg (sr->curr.reg + reg, IA64_WHERE_GR,
448 	   sr->region_start + sr->region_len - 1, dst);
449 }
450 
451 static inline void
desc_reg_psprel(unsigned char reg,unw_word pspoff,struct ia64_state_record * sr)452 desc_reg_psprel (unsigned char reg, unw_word pspoff,
453 		 struct ia64_state_record *sr)
454 {
455   set_reg (sr->curr.reg + reg, IA64_WHERE_PSPREL,
456 	   sr->region_start + sr->region_len - 1, 0x10 - 4 * pspoff);
457 }
458 
459 static inline void
desc_reg_sprel(unsigned char reg,unw_word spoff,struct ia64_state_record * sr)460 desc_reg_sprel (unsigned char reg, unw_word spoff,
461 		struct ia64_state_record *sr)
462 {
463   set_reg (sr->curr.reg + reg, IA64_WHERE_SPREL,
464 	   sr->region_start + sr->region_len - 1, 4 * spoff);
465 }
466 
467 static inline void
desc_rp_br(unsigned char dst,struct ia64_state_record * sr)468 desc_rp_br (unsigned char dst, struct ia64_state_record *sr)
469 {
470   sr->return_link_reg = dst;
471 }
472 
473 static inline void
desc_reg_when(unsigned char regnum,unw_word t,struct ia64_state_record * sr)474 desc_reg_when (unsigned char regnum, unw_word t, struct ia64_state_record *sr)
475 {
476   struct ia64_reg_info *reg = sr->curr.reg + regnum;
477 
478   if (reg->where == IA64_WHERE_NONE)
479     reg->where = IA64_WHERE_GR_SAVE;
480   reg->when = sr->region_start + MIN ((int) t, sr->region_len - 1);
481 }
482 
483 static inline void
desc_spill_base(unw_word pspoff,struct ia64_state_record * sr)484 desc_spill_base (unw_word pspoff, struct ia64_state_record *sr)
485 {
486   sr->spill_offset = 0x10 - 4 * pspoff;
487 }
488 
489 static inline unsigned char *
desc_spill_mask(unsigned char * imaskp,struct ia64_state_record * sr)490 desc_spill_mask (unsigned char *imaskp, struct ia64_state_record *sr)
491 {
492   sr->imask = imaskp;
493   return imaskp + (2 * sr->region_len + 7) / 8;
494 }
495 
496 /* Body descriptors.  */
497 
498 static inline void
desc_epilogue(unw_word t,unw_word ecount,struct ia64_state_record * sr)499 desc_epilogue (unw_word t, unw_word ecount, struct ia64_state_record *sr)
500 {
501   sr->when_sp_restored = sr->region_start + sr->region_len - 1 - t;
502   sr->epilogue_count = ecount + 1;
503 }
504 
505 static inline void
desc_copy_state(unw_word label,struct ia64_state_record * sr)506 desc_copy_state (unw_word label, struct ia64_state_record *sr)
507 {
508   struct ia64_labeled_state *ls;
509 
510   for (ls = sr->labeled_states; ls; ls = ls->next)
511     {
512       if (ls->label == label)
513 	{
514 	  free_state_stack (&sr->curr);
515 	  memcpy (&sr->curr, &ls->saved_state, sizeof (sr->curr));
516 	  sr->curr.next = dup_state_stack (ls->saved_state.next);
517 	  return;
518 	}
519     }
520   print_error ("libunwind: failed to find labeled state\n");
521 }
522 
523 static inline void
desc_label_state(unw_word label,struct ia64_state_record * sr)524 desc_label_state (unw_word label, struct ia64_state_record *sr)
525 {
526   struct ia64_labeled_state *ls;
527 
528   ls = alloc_labeled_state ();
529   if (!ls)
530     {
531       print_error ("unwind.desc_label_state(): out of memory\n");
532       return;
533     }
534   ls->label = label;
535   memcpy (&ls->saved_state, &sr->curr, sizeof (ls->saved_state));
536   ls->saved_state.next = dup_state_stack (sr->curr.next);
537 
538   /* insert into list of labeled states: */
539   ls->next = sr->labeled_states;
540   sr->labeled_states = ls;
541 }
542 
543 /* General descriptors.  */
544 
545 static inline int
desc_is_active(unsigned char qp,unw_word t,struct ia64_state_record * sr)546 desc_is_active (unsigned char qp, unw_word t, struct ia64_state_record *sr)
547 {
548   if (sr->when_target <= sr->region_start + MIN ((int) t, sr->region_len - 1))
549     return 0;
550   if (qp > 0)
551     {
552       if ((sr->pr_val & ((unw_word_t) 1 << qp)) == 0)
553 	return 0;
554       sr->pr_mask |= ((unw_word_t) 1 << qp);
555     }
556   return 1;
557 }
558 
559 static inline void
desc_restore_p(unsigned char qp,unw_word t,unsigned char abreg,struct ia64_state_record * sr)560 desc_restore_p (unsigned char qp, unw_word t, unsigned char abreg,
561 		struct ia64_state_record *sr)
562 {
563   struct ia64_reg_info *r;
564 
565   if (!desc_is_active (qp, t, sr))
566     return;
567 
568   r = sr->curr.reg + decode_abreg (abreg, 0);
569   r->where = IA64_WHERE_NONE;
570   r->when = IA64_WHEN_NEVER;
571   r->val = 0;
572 }
573 
574 static inline void
desc_spill_reg_p(unsigned char qp,unw_word t,unsigned char abreg,unsigned char x,unsigned char ytreg,struct ia64_state_record * sr)575 desc_spill_reg_p (unsigned char qp, unw_word t, unsigned char abreg,
576 		  unsigned char x, unsigned char ytreg,
577 		  struct ia64_state_record *sr)
578 {
579   enum ia64_where where = IA64_WHERE_GR;
580   struct ia64_reg_info *r;
581 
582   if (!desc_is_active (qp, t, sr))
583     return;
584 
585   if (x)
586     where = IA64_WHERE_BR;
587   else if (ytreg & 0x80)
588     where = IA64_WHERE_FR;
589 
590   r = sr->curr.reg + decode_abreg (abreg, 0);
591   r->where = where;
592   r->when = sr->region_start + MIN ((int) t, sr->region_len - 1);
593   r->val = (ytreg & 0x7f);
594 }
595 
596 static inline void
desc_spill_psprel_p(unsigned char qp,unw_word t,unsigned char abreg,unw_word pspoff,struct ia64_state_record * sr)597 desc_spill_psprel_p (unsigned char qp, unw_word t, unsigned char abreg,
598 		     unw_word pspoff, struct ia64_state_record *sr)
599 {
600   struct ia64_reg_info *r;
601 
602   if (!desc_is_active (qp, t, sr))
603     return;
604 
605   r = sr->curr.reg + decode_abreg (abreg, 1);
606   r->where = IA64_WHERE_PSPREL;
607   r->when = sr->region_start + MIN ((int) t, sr->region_len - 1);
608   r->val = 0x10 - 4 * pspoff;
609 }
610 
611 static inline void
desc_spill_sprel_p(unsigned char qp,unw_word t,unsigned char abreg,unw_word spoff,struct ia64_state_record * sr)612 desc_spill_sprel_p (unsigned char qp, unw_word t, unsigned char abreg,
613 		    unw_word spoff, struct ia64_state_record *sr)
614 {
615   struct ia64_reg_info *r;
616 
617   if (!desc_is_active (qp, t, sr))
618     return;
619 
620   r = sr->curr.reg + decode_abreg (abreg, 1);
621   r->where = IA64_WHERE_SPREL;
622   r->when = sr->region_start + MIN ((int) t, sr->region_len - 1);
623   r->val = 4 * spoff;
624 }
625 
626 #define UNW_DEC_BAD_CODE(code)						\
627 	print_error ("libunwind: unknown code encountered\n")
628 
629 /* Register names.  */
630 #define UNW_REG_BSP		IA64_REG_BSP
631 #define UNW_REG_BSPSTORE	IA64_REG_BSPSTORE
632 #define UNW_REG_FPSR		IA64_REG_FPSR
633 #define UNW_REG_LC		IA64_REG_LC
634 #define UNW_REG_PFS		IA64_REG_PFS
635 #define UNW_REG_PR		IA64_REG_PR
636 #define UNW_REG_RNAT		IA64_REG_RNAT
637 #define UNW_REG_PSP		IA64_REG_PSP
638 #define UNW_REG_RP		IA64_REG_IP
639 #define UNW_REG_UNAT		IA64_REG_UNAT
640 
641 /* Region headers.  */
642 #define UNW_DEC_PROLOGUE_GR(fmt,r,m,gr,arg)	desc_prologue(0,r,m,gr,arg)
643 #define UNW_DEC_PROLOGUE(fmt,b,r,arg)		desc_prologue(b,r,0,32,arg)
644 
645 /* Prologue descriptors.  */
646 #define UNW_DEC_ABI(fmt,a,c,arg)		desc_abi(a,c,arg)
647 #define UNW_DEC_BR_GR(fmt,b,g,arg)		desc_br_gr(b,g,arg)
648 #define UNW_DEC_BR_MEM(fmt,b,arg)		desc_br_mem(b,arg)
649 #define UNW_DEC_FRGR_MEM(fmt,g,f,arg)		desc_frgr_mem(g,f,arg)
650 #define UNW_DEC_FR_MEM(fmt,f,arg)		desc_fr_mem(f,arg)
651 #define UNW_DEC_GR_GR(fmt,m,g,arg)		desc_gr_gr(m,g,arg)
652 #define UNW_DEC_GR_MEM(fmt,m,arg)		desc_gr_mem(m,arg)
653 #define UNW_DEC_MEM_STACK_F(fmt,t,s,arg)	desc_mem_stack_f(t,s,arg)
654 #define UNW_DEC_MEM_STACK_V(fmt,t,arg)		desc_mem_stack_v(t,arg)
655 #define UNW_DEC_REG_GR(fmt,r,d,arg)		desc_reg_gr(r,d,arg)
656 #define UNW_DEC_REG_PSPREL(fmt,r,o,arg)		desc_reg_psprel(r,o,arg)
657 #define UNW_DEC_REG_SPREL(fmt,r,o,arg)		desc_reg_sprel(r,o,arg)
658 #define UNW_DEC_REG_WHEN(fmt,r,t,arg)		desc_reg_when(r,t,arg)
659 #define UNW_DEC_PRIUNAT_WHEN_GR(fmt,t,arg) \
660 	desc_reg_when(IA64_REG_PRI_UNAT_GR,t,arg)
661 #define UNW_DEC_PRIUNAT_WHEN_MEM(fmt,t,arg) \
662 	desc_reg_when(IA64_REG_PRI_UNAT_MEM,t,arg)
663 #define UNW_DEC_PRIUNAT_GR(fmt,r,arg) \
664 	desc_reg_gr(IA64_REG_PRI_UNAT_GR,r,arg)
665 #define UNW_DEC_PRIUNAT_PSPREL(fmt,o,arg) \
666 	desc_reg_psprel(IA64_REG_PRI_UNAT_MEM,o,arg)
667 #define UNW_DEC_PRIUNAT_SPREL(fmt,o,arg) \
668 	desc_reg_sprel(IA64_REG_PRI_UNAT_MEM,o,arg)
669 #define UNW_DEC_RP_BR(fmt,d,arg)		desc_rp_br(d,arg)
670 #define UNW_DEC_SPILL_BASE(fmt,o,arg)		desc_spill_base(o,arg)
671 #define UNW_DEC_SPILL_MASK(fmt,m,arg)		(m = desc_spill_mask(m,arg))
672 
673 /* Body descriptors.  */
674 #define UNW_DEC_EPILOGUE(fmt,t,c,arg)		desc_epilogue(t,c,arg)
675 #define UNW_DEC_COPY_STATE(fmt,l,arg)		desc_copy_state(l,arg)
676 #define UNW_DEC_LABEL_STATE(fmt,l,arg)		desc_label_state(l,arg)
677 
678 /* General unwind descriptors.  */
679 #define UNW_DEC_SPILL_REG_P(f,p,t,a,x,y,arg)	desc_spill_reg_p(p,t,a,x,y,arg)
680 #define UNW_DEC_SPILL_REG(f,t,a,x,y,arg)	desc_spill_reg_p(0,t,a,x,y,arg)
681 #define UNW_DEC_SPILL_PSPREL_P(f,p,t,a,o,arg) \
682 	desc_spill_psprel_p(p,t,a,o,arg)
683 #define UNW_DEC_SPILL_PSPREL(f,t,a,o,arg) \
684 	desc_spill_psprel_p(0,t,a,o,arg)
685 #define UNW_DEC_SPILL_SPREL_P(f,p,t,a,o,arg)	desc_spill_sprel_p(p,t,a,o,arg)
686 #define UNW_DEC_SPILL_SPREL(f,t,a,o,arg)	desc_spill_sprel_p(0,t,a,o,arg)
687 #define UNW_DEC_RESTORE_P(f,p,t,a,arg)		desc_restore_p(p,t,a,arg)
688 #define UNW_DEC_RESTORE(f,t,a,arg)		desc_restore_p(0,t,a,arg)
689 
690 #include "unwind_decoder.h"
691 
692 #ifdef _U_dyn_op
693 
694 /* parse dynamic unwind info */
695 
696 static struct ia64_reg_info *
lookup_preg(int regnum,int memory,struct ia64_state_record * sr)697 lookup_preg (int regnum, int memory, struct ia64_state_record *sr)
698 {
699   int preg;
700 
701   switch (regnum)
702     {
703     case UNW_IA64_AR_BSP:		preg = IA64_REG_BSP; break;
704     case UNW_IA64_AR_BSPSTORE:		preg = IA64_REG_BSPSTORE; break;
705     case UNW_IA64_AR_FPSR:		preg = IA64_REG_FPSR; break;
706     case UNW_IA64_AR_LC:		preg = IA64_REG_LC; break;
707     case UNW_IA64_AR_PFS:		preg = IA64_REG_PFS; break;
708     case UNW_IA64_AR_RNAT:		preg = IA64_REG_RNAT; break;
709     case UNW_IA64_AR_UNAT:		preg = IA64_REG_UNAT; break;
710     case UNW_IA64_BR + 0:		preg = IA64_REG_IP; break;
711     case UNW_IA64_PR:			preg = IA64_REG_PR; break;
712     case UNW_IA64_SP:			preg = IA64_REG_PSP; break;
713 
714     case UNW_IA64_NAT:
715       if (memory)
716 	preg = IA64_REG_PRI_UNAT_MEM;
717       else
718 	preg = IA64_REG_PRI_UNAT_GR;
719       break;
720 
721     case UNW_IA64_GR + 4 ... UNW_IA64_GR + 7:
722       preg = IA64_REG_R4 + (regnum - (UNW_IA64_GR + 4));
723       break;
724 
725     case UNW_IA64_BR + 1 ... UNW_IA64_BR + 5:
726       preg = IA64_REG_B1 + (regnum - UNW_IA64_BR);
727       break;
728 
729     case UNW_IA64_FR + 2 ... UNW_IA64_FR + 5:
730       preg = IA64_REG_F2 + (regnum - (UNW_IA64_FR + 2));
731       break;
732 
733     case UNW_IA64_FR + 16 ... UNW_IA64_FR + 31:
734       preg = IA64_REG_F16 + (regnum - (UNW_IA64_FR + 16));
735       break;
736 
737     default:
738       Dprintf ("%s: invalid register number %d\n", __FUNCTION__, regnum);
739       return NULL;
740     }
741   return sr->curr.reg + preg;
742 }
743 
744 /* An alias directive inside a region of length RLEN is interpreted to
745    mean that the region behaves exactly like the first RLEN
746    instructions at the aliased IP.  RLEN=0 implies that the current
747    state matches exactly that of before the instruction at the aliased
748    IP is executed.  */
749 
750 static int
desc_alias(unw_dyn_op_t * op,struct cursor * c,struct ia64_state_record * sr)751 desc_alias (unw_dyn_op_t *op, struct cursor *c, struct ia64_state_record *sr)
752 {
753   struct ia64_state_record orig_sr = *sr;
754   int i, ret, when, rlen = sr->region_len;
755   unw_word_t new_ip;
756 
757   when = MIN (sr->when_target, rlen);
758   new_ip = op->val + ((when / 3) * 16 + (when % 3));
759 
760   if ((ret = ia64_fetch_proc_info (c, new_ip, 1)) < 0)
761     return ret;
762 
763   if ((ret = create_state_record_for (c, sr, new_ip)) < 0)
764     return ret;
765 
766   sr->first_region = orig_sr.first_region;
767   sr->done = 0;
768   sr->any_spills |= orig_sr.any_spills;
769   sr->in_body = orig_sr.in_body;
770   sr->region_start = orig_sr.region_start;
771   sr->region_len = orig_sr.region_len;
772   if (sr->when_sp_restored != IA64_WHEN_NEVER)
773     sr->when_sp_restored = op->when + MIN (orig_sr.when_sp_restored, rlen);
774   sr->epilogue_count = orig_sr.epilogue_count;
775   sr->when_target = orig_sr.when_target;
776 
777   for (i = 0; i < IA64_NUM_PREGS; ++i)
778     if (sr->curr.reg[i].when != IA64_WHEN_NEVER)
779       sr->curr.reg[i].when = op->when + MIN (sr->curr.reg[i].when, rlen);
780 
781   ia64_free_state_record (sr);
782   sr->labeled_states = orig_sr.labeled_states;
783   sr->curr.next = orig_sr.curr.next;
784   return 0;
785 }
786 
787 static inline int
parse_dynamic(struct cursor * c,struct ia64_state_record * sr)788 parse_dynamic (struct cursor *c, struct ia64_state_record *sr)
789 {
790   unw_dyn_info_t *di = c->pi.unwind_info;
791   unw_dyn_proc_info_t *proc = &di->u.pi;
792   unw_dyn_region_info_t *r;
793   struct ia64_reg_info *ri;
794   enum ia64_where where;
795   int32_t when, len;
796   unw_dyn_op_t *op;
797   unw_word_t val;
798   int memory, ret;
799   int8_t qp;
800 
801   for (r = proc->regions; r; r = r->next)
802     {
803       len = r->insn_count;
804       if (len < 0)
805 	{
806 	  if (r->next)
807 	    {
808 	      Debug (1, "negative region length allowed in last region only!");
809 	      return -UNW_EINVAL;
810 	    }
811 	  len = -len;
812 	  /* hack old region info to set the start where we need it: */
813 	  sr->region_start = (di->end_ip - di->start_ip) / 0x10 * 3 - len;
814 	  sr->region_len = 0;
815 	}
816       /* all regions are treated as prologue regions: */
817       desc_prologue (0, len, 0, 0, sr);
818 
819       if (sr->done)
820 	return 0;
821 
822       for (op = r->op; op < r->op + r->op_count; ++op)
823 	{
824 	  when = op->when;
825 	  val = op->val;
826 	  qp = op->qp;
827 
828 	  if (!desc_is_active (qp, when, sr))
829 	    continue;
830 
831 	  when = sr->region_start + MIN ((int) when, sr->region_len - 1);
832 
833 	  switch (op->tag)
834 	    {
835 	    case UNW_DYN_SAVE_REG:
836 	      memory = 0;
837 	      if ((unsigned) (val - UNW_IA64_GR) < 128)
838 		where = IA64_WHERE_GR;
839 	      else if ((unsigned) (val - UNW_IA64_FR) < 128)
840 		where = IA64_WHERE_FR;
841 	      else if ((unsigned) (val - UNW_IA64_BR) < 8)
842 		where = IA64_WHERE_BR;
843 	      else
844 		{
845 		  Dprintf ("%s: can't save to register number %d\n",
846 			   __FUNCTION__, (int) op->reg);
847 		  return -UNW_EBADREG;
848 		}
849 	      /* fall through */
850 	    update_reg_info:
851 	      ri = lookup_preg (op->reg, memory, sr);
852 	      if (!ri)
853 		return -UNW_EBADREG;
854 	      ri->where = where;
855 	      ri->when = when;
856 	      ri->val = val;
857 	      break;
858 
859 	    case UNW_DYN_SPILL_FP_REL:
860 	      memory = 1;
861 	      where = IA64_WHERE_PSPREL;
862 	      val = 0x10 - val;
863 	      goto update_reg_info;
864 
865 	    case UNW_DYN_SPILL_SP_REL:
866 	      memory = 1;
867 	      where = IA64_WHERE_SPREL;
868 	      goto update_reg_info;
869 
870 	    case UNW_DYN_ADD:
871 	      if (op->reg == UNW_IA64_SP)
872 		{
873 		  if (val & 0xf)
874 		    {
875 		      Dprintf ("%s: frame-size %ld not an integer "
876 			       "multiple of 16\n",
877 			       __FUNCTION__, (long) op->val);
878 		      return -UNW_EINVAL;
879 		    }
880 		  desc_mem_stack_f (when, -((int64_t) val / 16), sr);
881 		}
882 	      else
883 		{
884 		  Dprintf ("%s: can only ADD to stack-pointer\n",
885 			   __FUNCTION__);
886 		  return -UNW_EBADREG;
887 		}
888 	      break;
889 
890 	    case UNW_DYN_POP_FRAMES:
891 	      sr->when_sp_restored = when;
892 	      sr->epilogue_count = op->val;
893 	      break;
894 
895 	    case UNW_DYN_LABEL_STATE:
896 	      desc_label_state (op->val, sr);
897 	      break;
898 
899 	    case UNW_DYN_COPY_STATE:
900 	      desc_copy_state (op->val, sr);
901 	      break;
902 
903 	    case UNW_DYN_ALIAS:
904 	      if ((ret = desc_alias (op, c, sr)) < 0)
905 		return ret;
906 
907 	    case UNW_DYN_STOP:
908 	      goto end_of_ops;
909 	    }
910 	}
911     end_of_ops:
912       ;
913     }
914   return 0;
915 }
916 #else
917 # define parse_dynamic(c,sr)	(-UNW_EINVAL)
918 #endif /* _U_dyn_op */
919 
920 
921 HIDDEN int
ia64_fetch_proc_info(struct cursor * c,unw_word_t ip,int need_unwind_info)922 ia64_fetch_proc_info (struct cursor *c, unw_word_t ip, int need_unwind_info)
923 {
924   int ret, dynamic = 1;
925 
926   if (c->pi_valid && !need_unwind_info)
927     return 0;
928 
929   /* check dynamic info first --- it overrides everything else */
930   ret = unwi_find_dynamic_proc_info (c->as, ip, &c->pi, need_unwind_info,
931 				     c->as_arg);
932   if (ret == -UNW_ENOINFO)
933     {
934       dynamic = 0;
935       ret = ia64_find_proc_info (c, ip, need_unwind_info);
936     }
937 
938   c->pi_valid = 1;
939   c->pi_is_dynamic = dynamic;
940   return ret;
941 }
942 
943 static inline void
put_unwind_info(struct cursor * c,unw_proc_info_t * pi)944 put_unwind_info (struct cursor *c, unw_proc_info_t *pi)
945 {
946   if (!c->pi_valid)
947     return;
948 
949   if (c->pi_is_dynamic)
950     unwi_put_dynamic_unwind_info (c->as, pi, c->as_arg);
951   else
952     ia64_put_unwind_info (c, pi);
953 }
954 
955 static int
create_state_record_for(struct cursor * c,struct ia64_state_record * sr,unw_word_t ip)956 create_state_record_for (struct cursor *c, struct ia64_state_record *sr,
957 			 unw_word_t ip)
958 {
959   unw_word_t predicates = c->pr;
960   struct ia64_reg_info *r;
961   uint8_t *dp, *desc_end;
962   int ret;
963 
964   assert (c->pi_valid);
965 
966   /* build state record */
967   memset (sr, 0, sizeof (*sr));
968   for (r = sr->curr.reg; r < sr->curr.reg + IA64_NUM_PREGS; ++r)
969     r->when = IA64_WHEN_NEVER;
970   sr->pr_val = predicates;
971   sr->first_region = 1;
972 
973   if (!c->pi.unwind_info)
974     {
975       /* No info, return default unwinder (leaf proc, no mem stack, no
976          saved regs), rp in b0, pfs in ar.pfs.  */
977       Debug (1, "no unwind info for ip=0x%lx (gp=%lx)\n",
978 	     (long) ip, (long) c->pi.gp);
979       sr->curr.reg[IA64_REG_IP].where = IA64_WHERE_BR;
980       sr->curr.reg[IA64_REG_IP].when = -1;
981       sr->curr.reg[IA64_REG_IP].val = 0;
982       goto out;
983     }
984 
985   sr->when_target = (3 * ((ip & ~(unw_word_t) 0xf) - c->pi.start_ip) / 16
986 		     + (ip & 0xf));
987 
988   switch (c->pi.format)
989     {
990     case UNW_INFO_FORMAT_TABLE:
991     case UNW_INFO_FORMAT_REMOTE_TABLE:
992       dp = c->pi.unwind_info;
993       desc_end = dp + c->pi.unwind_info_size;
994       while (!sr->done && dp < desc_end)
995 	dp = unw_decode (dp, sr->in_body, sr);
996       ret = 0;
997       break;
998 
999     case UNW_INFO_FORMAT_DYNAMIC:
1000       ret = parse_dynamic (c, sr);
1001       break;
1002 
1003     default:
1004       ret = -UNW_EINVAL;
1005     }
1006 
1007   put_unwind_info (c, &c->pi);
1008 
1009   if (ret < 0)
1010     return ret;
1011 
1012   if (sr->when_target > sr->when_sp_restored)
1013     {
1014       /* sp has been restored and all values on the memory stack below
1015 	 psp also have been restored.  */
1016       sr->curr.reg[IA64_REG_PSP].val = 0;
1017       sr->curr.reg[IA64_REG_PSP].where = IA64_WHERE_NONE;
1018       sr->curr.reg[IA64_REG_PSP].when = IA64_WHEN_NEVER;
1019       for (r = sr->curr.reg; r < sr->curr.reg + IA64_NUM_PREGS; ++r)
1020 	if ((r->where == IA64_WHERE_PSPREL && r->val <= 0x10)
1021 	    || r->where == IA64_WHERE_SPREL)
1022 	  {
1023 	    r->val = 0;
1024 	    r->where = IA64_WHERE_NONE;
1025 	    r->when = IA64_WHEN_NEVER;
1026 	  }
1027     }
1028 
1029   /* If RP did't get saved, generate entry for the return link
1030      register.  */
1031   if (sr->curr.reg[IA64_REG_IP].when >= sr->when_target)
1032     {
1033       sr->curr.reg[IA64_REG_IP].where = IA64_WHERE_BR;
1034       sr->curr.reg[IA64_REG_IP].when = -1;
1035       sr->curr.reg[IA64_REG_IP].val = sr->return_link_reg;
1036     }
1037 
1038   if (sr->when_target > sr->curr.reg[IA64_REG_BSP].when
1039       && sr->when_target > sr->curr.reg[IA64_REG_BSPSTORE].when
1040       && sr->when_target > sr->curr.reg[IA64_REG_RNAT].when)
1041     {
1042       Debug (8, "func 0x%lx may switch the register-backing-store\n",
1043 	     c->pi.start_ip);
1044       c->pi.flags |= UNW_PI_FLAG_IA64_RBS_SWITCH;
1045     }
1046  out:
1047 #if UNW_DEBUG
1048   if (unwi_debug_level > 2)
1049     {
1050       Dprintf ("%s: state record for func 0x%lx, t=%u (flags=0x%lx):\n",
1051 	       __FUNCTION__,
1052 	       (long) c->pi.start_ip, sr->when_target, (long) c->pi.flags);
1053       for (r = sr->curr.reg; r < sr->curr.reg + IA64_NUM_PREGS; ++r)
1054 	{
1055 	  if (r->where != IA64_WHERE_NONE || r->when != IA64_WHEN_NEVER)
1056 	    {
1057 	      Dprintf ("  %s <- ", unw.preg_name[r - sr->curr.reg]);
1058 	      switch (r->where)
1059 		{
1060 		case IA64_WHERE_GR:
1061 		  Dprintf ("r%lu", (long) r->val);
1062 		  break;
1063 		case IA64_WHERE_FR:
1064 		  Dprintf ("f%lu", (long) r->val);
1065 		  break;
1066 		case IA64_WHERE_BR:
1067 		  Dprintf ("b%lu", (long) r->val);
1068 		  break;
1069 		case IA64_WHERE_SPREL:
1070 		  Dprintf ("[sp+0x%lx]", (long) r->val);
1071 		  break;
1072 		case IA64_WHERE_PSPREL:
1073 		  Dprintf ("[psp+0x%lx]", (long) r->val);
1074 		  break;
1075 		case IA64_WHERE_NONE:
1076 		  Dprintf ("%s+0x%lx",
1077 			   unw.preg_name[r - sr->curr.reg], (long) r->val);
1078 		  break;
1079 		default:
1080 		  Dprintf ("BADWHERE(%d)", r->where);
1081 		  break;
1082 		}
1083 	      Dprintf ("\t\t%d\n", r->when);
1084 	    }
1085 	}
1086     }
1087 #endif
1088   return 0;
1089 }
1090 
1091 /* The proc-info must be valid for IP before this routine can be
1092    called.  */
1093 HIDDEN int
ia64_create_state_record(struct cursor * c,struct ia64_state_record * sr)1094 ia64_create_state_record (struct cursor *c, struct ia64_state_record *sr)
1095 {
1096   return create_state_record_for (c, sr, c->ip);
1097 }
1098 
1099 HIDDEN int
ia64_free_state_record(struct ia64_state_record * sr)1100 ia64_free_state_record (struct ia64_state_record *sr)
1101 {
1102   struct ia64_labeled_state *ls, *next;
1103 
1104   /* free labeled register states & stack: */
1105 
1106   for (ls = sr->labeled_states; ls; ls = next)
1107     {
1108       next = ls->next;
1109       free_state_stack (&ls->saved_state);
1110       free_labeled_state (ls);
1111     }
1112   free_state_stack (&sr->curr);
1113 
1114   return 0;
1115 }
1116 
1117 HIDDEN int
ia64_make_proc_info(struct cursor * c)1118 ia64_make_proc_info (struct cursor *c)
1119 {
1120   int ret, caching = c->as->caching_policy != UNW_CACHE_NONE;
1121 
1122   if (!caching || ia64_get_cached_proc_info (c) < 0)
1123     {
1124       /* Lookup it up the slow way... */
1125       if ((ret = ia64_fetch_proc_info (c, c->ip, 0)) < 0)
1126 	return ret;
1127       if (caching)
1128 	ia64_cache_proc_info (c);
1129     }
1130   return 0;
1131 }
1132