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 (®s[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