2 * kernel stack unwinding
3 * Copyright (C) 2008-2009 Red Hat Inc.
5 * Based on old kernel code that is
6 * Copyright (C) 2002-2006 Novell, Inc.
7 * Jan Beulich <jbeulich@novell.com>
9 * This code is released under version 2 of the GNU GPL.
11 * This code currently does stack unwinding in the kernel and modules.
12 * It has been extended to handle userspace unwinding using systemtap
16 #include "unwind/unwind.h"
18 #ifdef STP_USE_DWARF_UNWINDER
20 struct eh_frame_hdr_table_entry
{
21 unsigned long start
, fde
;
24 static int cmp_eh_frame_hdr_table_entries(const void *p1
, const void *p2
)
26 const struct eh_frame_hdr_table_entry
*e1
= p1
;
27 const struct eh_frame_hdr_table_entry
*e2
= p2
;
28 return (e1
->start
> e2
->start
) - (e1
->start
< e2
->start
);
31 static void swap_eh_frame_hdr_table_entries(void *p1
, void *p2
, int size
)
33 struct eh_frame_hdr_table_entry
*e1
= p1
;
34 struct eh_frame_hdr_table_entry
*e2
= p2
;
38 e1
->start
= e2
->start
;
45 static uleb128_t
get_uleb128(const u8
**pcur
, const u8
*end
)
47 const u8
*cur
= *pcur
;
51 for (shift
= 0; cur
< end
; shift
+= 7) {
52 if (shift
+ 7 > 8 * sizeof(value
)
53 && (*cur
& 0x7fU
) >= (1U << (8 * sizeof(value
) - shift
))) {
57 value
|= (uleb128_t
)(*cur
& 0x7f) << shift
;
66 static sleb128_t
get_sleb128(const u8
**pcur
, const u8
*end
)
68 const u8
*cur
= *pcur
;
72 for (shift
= 0; cur
< end
; shift
+= 7) {
73 if (shift
+ 7 > 8 * sizeof(value
)
74 && (*cur
& 0x7fU
) >= (1U << (8 * sizeof(value
) - shift
))) {
78 value
|= (sleb128_t
)(*cur
& 0x7f) << shift
;
80 value
|= -(*cur
++ & 0x40) << shift
;
89 /* given an FDE, find its CIE */
90 static const u32
*cie_for_fde(const u32
*fde
, void *unwind_data
,
91 uint32_t table_len
, int is_ehframe
)
95 /* check that length is proper */
96 if (!*fde
|| (*fde
& (sizeof(*fde
) - 1)))
99 /* CIE id for eh_frame is 0, otherwise 0xffffffff */
100 if (is_ehframe
&& fde
[1] == 0)
102 else if (fde
[1] == 0xffffffff)
105 /* OK, must be an FDE. Now find its CIE. */
107 /* CIE_pointer must be a proper offset */
108 if ((fde
[1] & (sizeof(*fde
) - 1)) || fde
[1] > (unsigned long)(fde
+ 1) - (unsigned long)unwind_data
) {
109 dbug_unwind(1, "fde[1]=%lx fde+1=%lx, unwind_data=%lx %lx\n",
110 (unsigned long)fde
[1], (unsigned long)(fde
+ 1),
111 (unsigned long)unwind_data
, (unsigned long)(fde
+ 1) - (unsigned long)unwind_data
);
112 return NULL
; /* this is not a valid FDE */
115 /* cie pointer field is different in eh_frame vs debug_frame */
117 cie
= fde
+ 1 - fde
[1] / sizeof(*fde
);
119 cie
= unwind_data
+ fde
[1];
121 /* Make sure address falls in the table */
122 if (((void *)cie
) < ((void*)unwind_data
)
123 || ((void*)cie
) > ((void*)(unwind_data
+ table_len
)))
126 if (*cie
<= sizeof(*cie
) + 4 || *cie
>= fde
[1] - sizeof(*fde
)
127 || (*cie
& (sizeof(*cie
) - 1))
128 || (cie
[1] != 0xffffffff && cie
[1] != 0)) {
129 dbug_unwind(1, "cie is not valid %lx %x %x %x\n", (unsigned long)cie
, *cie
, fde
[1], cie
[1]);
130 return NULL
; /* this is not a (valid) CIE */
136 /* read an encoded pointer */
137 static unsigned long read_pointer(const u8
**pLoc
, const void *end
, signed ptrType
)
139 unsigned long value
= 0;
146 const unsigned long *pul
;
149 if (ptrType
< 0 || ptrType
== DW_EH_PE_omit
)
153 switch (ptrType
& DW_EH_PE_FORM
) {
155 if (end
< (const void *)(ptr
.p16u
+ 1))
157 if (ptrType
& DW_EH_PE_signed
)
158 value
= _stp_get_unaligned(ptr
.p16s
++);
160 value
= _stp_get_unaligned(ptr
.p16u
++);
164 if (end
< (const void *)(ptr
.p32u
+ 1))
166 if (ptrType
& DW_EH_PE_signed
)
167 value
= _stp_get_unaligned(ptr
.p32s
++);
169 value
= _stp_get_unaligned(ptr
.p32u
++);
172 BUILD_BUG_ON(sizeof(u64
) != sizeof(value
));
174 BUILD_BUG_ON(sizeof(u32
) != sizeof(value
));
176 case DW_EH_PE_absptr
:
177 if (end
< (const void *)(ptr
.pul
+ 1))
179 value
= _stp_get_unaligned(ptr
.pul
++);
181 case DW_EH_PE_leb128
:
182 BUILD_BUG_ON(sizeof(uleb128_t
) > sizeof(value
));
183 value
= ptrType
& DW_EH_PE_signed
? get_sleb128(&ptr
.p8
, end
)
184 : get_uleb128(&ptr
.p8
, end
);
185 if ((const void *)ptr
.p8
> end
)
191 switch (ptrType
& DW_EH_PE_ADJUST
) {
192 case DW_EH_PE_absptr
:
195 value
+= (unsigned long)*pLoc
;
200 if ((ptrType
& DW_EH_PE_indirect
)
201 && _stp_read_address(value
, (unsigned long *)value
, KERNEL_DS
))
208 static signed fde_pointer_type(const u32
*cie
, void *unwind_data
,
211 const u8
*ptr
= (const u8
*)(cie
+ 2);
212 unsigned version
= *ptr
;
215 return -1; /* unsupported */
218 const u8
*end
= (const u8
*)(cie
+ 1) + *cie
;
221 /* end of cie should fall within unwind table. */
222 if (((void*)end
) < ((void *)unwind_data
)
223 || ((void *)end
) > ((void *)(unwind_data
+ table_len
)))
226 /* check if augmentation size is first (and thus present) */
229 /* check if augmentation string is nul-terminated */
230 if ((ptr
= memchr(aug
= (const void *)ptr
, 0, end
- ptr
)) == NULL
)
232 ++ptr
; /* skip terminator */
233 get_uleb128(&ptr
, end
); /* skip code alignment */
234 get_sleb128(&ptr
, end
); /* skip data alignment */
235 /* skip return address column */
236 version
<= 1 ? (void)++ptr
: (void)get_uleb128(&ptr
, end
);
237 len
= get_uleb128(&ptr
, end
); /* augmentation length */
238 if (ptr
+ len
< ptr
|| ptr
+ len
> end
)
249 signed ptrType
= *ptr
++;
251 if (!read_pointer(&ptr
, end
, ptrType
) || ptr
> end
)
262 return DW_EH_PE_absptr
;
265 static int advance_loc(unsigned long delta
, struct unwind_state
*state
)
267 state
->loc
+= delta
* state
->codeAlign
;
268 dbug_unwind(1, "state->loc=%lx\n", state
->loc
);
272 static void set_rule(uleb128_t reg
, enum item_location where
, uleb128_t value
, struct unwind_state
*state
)
274 dbug_unwind(1, "reg=%lx, where=%d, value=%lx\n", reg
, where
, value
);
275 if (reg
< ARRAY_SIZE(state
->regs
)) {
276 state
->regs
[reg
].where
= where
;
277 state
->regs
[reg
].value
= value
;
281 static int processCFI(const u8
*start
, const u8
*end
, unsigned long targetLoc
, signed ptrType
, struct unwind_state
*state
)
290 dbug_unwind(1, "targetLoc=%lx state->loc=%lx\n", targetLoc
, state
->loc
);
291 if (start
!= state
->cieStart
) {
292 state
->loc
= state
->org
;
293 result
= processCFI(state
->cieStart
, state
->cieEnd
, 0, ptrType
, state
);
294 if (targetLoc
== 0 && state
->label
== NULL
)
298 for (ptr
.p8
= start
; result
&& ptr
.p8
< end
;) {
299 switch (*ptr
.p8
>> 6) {
304 dbug_unwind(1, "DW_CFA_nop\n");
307 if ((state
->loc
= read_pointer(&ptr
.p8
, end
, ptrType
)) == 0)
309 dbug_unwind(1, "DW_CFA_set_loc %lx (result=%d)\n", state
->loc
, result
);
311 case DW_CFA_advance_loc1
:
312 result
= ptr
.p8
< end
&& advance_loc(*ptr
.p8
++, state
);
313 dbug_unwind(1, "DW_CFA_advance_loc1 %d\n", result
);
315 case DW_CFA_advance_loc2
:
316 result
= ptr
.p8
<= end
+ 2 && advance_loc(*ptr
.p16
++, state
);
317 dbug_unwind(1, "DW_CFA_advance_loc2 %d\n", result
);
319 case DW_CFA_advance_loc4
:
320 result
= ptr
.p8
<= end
+ 4 && advance_loc(*ptr
.p32
++, state
);
321 dbug_unwind(1, "DW_CFA_advance_loc4 %d\n", result
);
323 case DW_CFA_offset_extended
:
324 value
= get_uleb128(&ptr
.p8
, end
);
325 set_rule(value
, Memory
, get_uleb128(&ptr
.p8
, end
), state
);
326 dbug_unwind(1, "DW_CFA_offset_extended\n");
328 case DW_CFA_val_offset
:
329 value
= get_uleb128(&ptr
.p8
, end
);
330 set_rule(value
, Value
, get_uleb128(&ptr
.p8
, end
), state
);
331 dbug_unwind(1, "DW_CFA_val_offset\n");
333 case DW_CFA_offset_extended_sf
:
334 value
= get_uleb128(&ptr
.p8
, end
);
335 set_rule(value
, Memory
, get_sleb128(&ptr
.p8
, end
), state
);
336 dbug_unwind(1, "DW_CFA_offset_extended_sf\n");
338 case DW_CFA_val_offset_sf
:
339 value
= get_uleb128(&ptr
.p8
, end
);
340 set_rule(value
, Value
, get_sleb128(&ptr
.p8
, end
), state
);
341 dbug_unwind(1, "DW_CFA_val_offset_sf\n");
343 case DW_CFA_restore_extended
:
344 case DW_CFA_undefined
:
345 case DW_CFA_same_value
:
346 set_rule(get_uleb128(&ptr
.p8
, end
), Nowhere
, 0, state
);
347 dbug_unwind(1, "DW_CFA_undefined\n");
349 case DW_CFA_register
:
350 value
= get_uleb128(&ptr
.p8
, end
);
351 set_rule(value
, Register
, get_uleb128(&ptr
.p8
, end
), state
);
352 dbug_unwind(1, "DW_CFA_register\n");
354 case DW_CFA_remember_state
:
355 dbug_unwind(1, "DW_CFA_remember_state\n");
356 if (ptr
.p8
== state
->label
) {
360 if (state
->stackDepth
>= STP_MAX_STACK_DEPTH
)
362 state
->stack
[state
->stackDepth
++] = ptr
.p8
;
364 case DW_CFA_restore_state
:
365 dbug_unwind(1, "DW_CFA_restore_state\n");
366 if (state
->stackDepth
) {
367 const uleb128_t loc
= state
->loc
;
368 const u8
*label
= state
->label
;
370 state
->label
= state
->stack
[state
->stackDepth
- 1];
371 memcpy(&state
->cfa
, &badCFA
, sizeof(state
->cfa
));
372 memset(state
->regs
, 0, sizeof(state
->regs
));
373 state
->stackDepth
= 0;
374 result
= processCFI(start
, end
, 0, ptrType
, state
);
376 state
->label
= label
;
381 state
->cfa
.reg
= get_uleb128(&ptr
.p8
, end
);
382 dbug_unwind(1, "DW_CFA_def_cfa reg=%ld\n", state
->cfa
.reg
);
384 case DW_CFA_def_cfa_offset
:
385 state
->cfa
.offs
= get_uleb128(&ptr
.p8
, end
);
386 dbug_unwind(1, "DW_CFA_def_cfa_offset offs=%lx\n", state
->cfa
.offs
);
388 case DW_CFA_def_cfa_sf
:
389 state
->cfa
.reg
= get_uleb128(&ptr
.p8
, end
);
390 dbug_unwind(1, "DW_CFA_def_cfa_sf reg=%ld\n", state
->cfa
.reg
);
392 case DW_CFA_def_cfa_offset_sf
:
393 state
->cfa
.offs
= get_sleb128(&ptr
.p8
, end
) * state
->dataAlign
;
394 dbug_unwind(1, "DW_CFA_def_cfa_offset_sf offs=%lx\n", state
->cfa
.offs
);
396 case DW_CFA_def_cfa_register
:
397 state
->cfa
.reg
= get_uleb128(&ptr
.p8
, end
);
398 dbug_unwind(1, "DW_CFA_def_cfa_register reg=%ld\n", state
->cfa
.reg
);
400 /*todo case DW_CFA_def_cfa_expression: */
401 /*todo case DW_CFA_expression: */
402 /*todo case DW_CFA_val_expression: */
403 case DW_CFA_GNU_args_size
:
404 get_uleb128(&ptr
.p8
, end
);
405 dbug_unwind(1, "DW_CFA_GNU_args_size\n");
407 case DW_CFA_GNU_negative_offset_extended
:
408 value
= get_uleb128(&ptr
.p8
, end
);
409 set_rule(value
, Memory
, (uleb128_t
)0 - get_uleb128(&ptr
.p8
, end
), state
);
410 dbug_unwind(1, "DW_CFA_GNU_negative_offset_extended\n");
412 case DW_CFA_GNU_window_save
:
414 dbug_unwind(1, "unimplemented call frame instruction: 0x%x\n", *(ptr
.p8
- 1));
420 result
= advance_loc(*ptr
.p8
++ & 0x3f, state
);
421 dbug_unwind(1, "case 1\n");
424 value
= *ptr
.p8
++ & 0x3f;
425 set_rule(value
, Memory
, get_uleb128(&ptr
.p8
, end
), state
);
426 dbug_unwind(1, "case 2\n");
429 set_rule(*ptr
.p8
++ & 0x3f, Nowhere
, 0, state
);
430 dbug_unwind(1, "case 3\n");
433 dbug_unwind(1, "targetLoc=%lx state->loc=%lx\n", targetLoc
, state
->loc
);
436 if (result
&& targetLoc
!= 0 && targetLoc
< state
->loc
)
439 return result
&& ptr
.p8
== end
&& (targetLoc
== 0 || state
->label
== NULL
);
443 static const char *_stp_enc_hi_name
[] = {
451 static const char *_stp_enc_lo_name
[] = {
462 static char *_stp_eh_enc_name(signed type
)
466 if (type
== DW_EH_PE_omit
)
467 return "DW_EH_PE_omit";
469 hi
= (type
& DW_EH_PE_ADJUST
) >> 4;
470 low
= type
& DW_EH_PE_FORM
;
471 if (hi
> 5 || low
> 4 || (low
== 0 && (type
& DW_EH_PE_signed
))) {
472 sprintf(buf
, "ERROR:encoding=0x%x", type
);
477 if (type
& DW_EH_PE_indirect
)
478 strlcpy(buf
, "DW_EH_PE_indirect|", sizeof(buf
));
479 strlcat(buf
, _stp_enc_hi_name
[hi
], sizeof(buf
));
481 if (type
& DW_EH_PE_signed
)
483 strlcat(buf
, _stp_enc_lo_name
[low
], sizeof(buf
));
486 #endif /* DEBUG_UNWIND */
488 // If this is an address inside a module, adjust for section relocation
489 // and the elfutils base relocation done during loading of the .dwarf_frame
492 adjustStartLoc (unsigned long startLoc
,
493 struct _stp_module
*m
,
494 struct _stp_section
*s
,
495 unsigned ptrType
, int is_ehframe
)
497 /* XXX - some, or all, of this should really be done by
498 _stp_module_relocate and/or read_pointer. */
499 dbug_unwind(2, "adjustStartLoc=%lx, ptrType=%s, m=%s, s=%s eh=%d\n",
500 startLoc
, _stp_eh_enc_name(ptrType
), m
->name
, s
->name
, is_ehframe
);
502 || strcmp (m
->name
, "kernel") == 0
503 || (strcmp (s
->name
, ".absolute") == 0 && !is_ehframe
))
506 /* eh_frame data has been loaded in the kernel, so readjust offset. */
508 dbug_unwind(2, "eh_frame=%lx, eh_frame_addr=%lx\n", (unsigned long) m
->eh_frame
, m
->eh_frame_addr
);
509 if ((ptrType
& DW_EH_PE_ADJUST
) == DW_EH_PE_pcrel
) {
510 startLoc
-= (unsigned long) m
->eh_frame
;
511 startLoc
+= m
->eh_frame_addr
;
513 if (strcmp (s
->name
, ".absolute") == 0)
517 if (strcmp (s
->name
, ".dynamic") == 0)
518 return startLoc
+ s
->addr
;
520 startLoc
= _stp_module_relocate (m
->name
, s
->name
, startLoc
);
521 startLoc
-= m
->dwarf_module_base
;
525 /* If we previously created an unwind header, then use it now to binary search */
526 /* for the FDE corresponding to pc. XXX FIXME not currently supported. */
528 static u32
*_stp_search_unwind_hdr(unsigned long pc
,
529 struct _stp_module
*m
,
530 struct _stp_section
*s
)
532 const u8
*ptr
, *end
, *hdr
= m
->unwind_hdr
;
533 unsigned long startLoc
;
535 unsigned num
, tableSize
, t2
;
537 if (hdr
== NULL
|| hdr
[0] != 1)
540 dbug_unwind(1, "search for %lx", pc
);
543 switch (hdr
[3] & DW_EH_PE_FORM
) {
544 case DW_EH_PE_absptr
:
545 tableSize
= sizeof(unsigned long);
557 dbug_unwind(1, "bad table encoding");
561 end
= hdr
+ m
->unwind_hdr_len
;
563 if (read_pointer(&ptr
, end
, hdr
[1]) != (unsigned long)m
->debug_frame
) {
564 dbug_unwind(1, "eh_frame_ptr not valid");
568 num
= read_pointer(&ptr
, end
, hdr
[2]);
569 if (num
== 0 || num
!= (end
- ptr
) / (2 * tableSize
) || (end
- ptr
) % (2 * tableSize
)) {
570 dbug_unwind(1, "Bad num=%d end-ptr=%ld 2*tableSize=%d", num
, (long)(end
- ptr
), 2 * tableSize
);
575 const u8
*cur
= ptr
+ (num
/ 2) * (2 * tableSize
);
576 startLoc
= read_pointer(&cur
, cur
+ tableSize
, hdr
[3]);
577 startLoc
= adjustStartLoc(startLoc
, m
, s
, hdr
[3], 1);
581 ptr
= cur
- tableSize
;
584 } while (startLoc
&& num
> 1);
586 if (num
== 1 && (startLoc
= adjustStartLoc(read_pointer(&ptr
, ptr
+ tableSize
, hdr
[3]), m
, s
, hdr
[3], 1)) != 0 && pc
>= startLoc
)
587 fde
= (void *)read_pointer(&ptr
, ptr
+ tableSize
, hdr
[3]);
589 dbug_unwind(1, "returning fde=%lx startLoc=%lx", (unsigned long) fde
, startLoc
);
593 /* Unwind to previous to frame. Returns 0 if successful, negative
594 * number in case of an error. A positive return means unwinding is finished;
595 * don't try to fallback to dumping addresses on the stack. */
596 static int unwind_frame(struct unwind_frame_info
*frame
,
597 struct _stp_module
*m
, struct _stp_section
*s
,
598 void *table
, uint32_t table_len
, int is_ehframe
)
600 #define FRAME_REG(r, t) (((t *)frame)[reg_info[r].offs])
601 const u32
*fde
, *cie
= NULL
;
602 const u8
*ptr
= NULL
, *end
= NULL
;
603 unsigned long pc
= UNW_PC(frame
) - frame
->call_frame
;
604 unsigned long tableSize
, startLoc
= 0, endLoc
= 0, cfa
;
607 uleb128_t retAddrReg
= 0;
608 struct unwind_state state
;
610 if (unlikely(table_len
== 0 || table_len
& (sizeof(*fde
) - 1))) {
611 dbug_unwind(1, "Module %s: frame_len=%d", m
->name
, table_len
);
615 fde
= _stp_search_unwind_hdr(pc
, m
, s
);
616 dbug_unwind(1, "%s: fde=%lx\n", m
->name
, (unsigned long) fde
);
618 /* found the fde, now set startLoc and endLoc */
620 cie
= cie_for_fde(fde
, table
, table_len
, is_ehframe
);
621 if (likely(cie
!= NULL
&& cie
!= &bad_cie
&& cie
!= ¬_fde
)) {
622 ptr
= (const u8
*)(fde
+ 2);
623 ptrType
= fde_pointer_type(cie
, table
, table_len
);
624 startLoc
= read_pointer(&ptr
, (const u8
*)(fde
+ 1) + *fde
, ptrType
);
625 startLoc
= adjustStartLoc(startLoc
, m
, s
, ptrType
, is_ehframe
);
627 dbug_unwind(2, "startLoc=%lx, ptrType=%s\n", startLoc
, _stp_eh_enc_name(ptrType
));
628 if (!(ptrType
& DW_EH_PE_indirect
))
629 ptrType
&= DW_EH_PE_FORM
| DW_EH_PE_signed
;
630 endLoc
= startLoc
+ read_pointer(&ptr
, (const u8
*)(fde
+ 1) + *fde
, ptrType
);
632 dbug_unwind(1, "pc (%lx) > endLoc(%lx)\n", pc
, endLoc
);
636 dbug_unwind(1, "fde found in header, but cie is bad!\n");
641 /* did not a good fde find with binary search, so do slow linear search */
643 for (fde
= table
, tableSize
= table_len
; cie
= NULL
, tableSize
> sizeof(*fde
)
644 && tableSize
- sizeof(*fde
) >= *fde
; tableSize
-= sizeof(*fde
) + *fde
, fde
+= 1 + *fde
/ sizeof(*fde
)) {
645 dbug_unwind(3, "fde=%lx tableSize=%d\n", (long)*fde
, (int)tableSize
);
646 cie
= cie_for_fde(fde
, table
, table_len
, is_ehframe
);
647 if (cie
== &bad_cie
) {
651 if (cie
== NULL
|| cie
== ¬_fde
|| (ptrType
= fde_pointer_type(cie
, table
, table_len
)) < 0)
654 ptr
= (const u8
*)(fde
+ 2);
655 startLoc
= read_pointer(&ptr
, (const u8
*)(fde
+ 1) + *fde
, ptrType
);
656 startLoc
= adjustStartLoc(startLoc
, m
, s
, ptrType
, is_ehframe
);
657 dbug_unwind(2, "startLoc=%lx, ptrType=%s\n", startLoc
, _stp_eh_enc_name(ptrType
));
660 if (!(ptrType
& DW_EH_PE_indirect
))
661 ptrType
&= DW_EH_PE_FORM
| DW_EH_PE_signed
;
662 endLoc
= startLoc
+ read_pointer(&ptr
, (const u8
*)(fde
+ 1) + *fde
, ptrType
);
663 dbug_unwind(3, "endLoc=%lx\n", endLoc
);
664 if (pc
>= startLoc
&& pc
< endLoc
)
669 dbug_unwind(1, "cie=%lx fde=%lx startLoc=%lx endLoc=%lx, pc=%lx\n",
670 (unsigned long) cie
, (unsigned long)fde
, (unsigned long) startLoc
, (unsigned long) endLoc
, pc
);
671 if (cie
== NULL
|| fde
== NULL
)
674 /* found the CIE and FDE */
676 memset(&state
, 0, sizeof(state
));
677 state
.cieEnd
= ptr
; /* keep here temporarily */
678 ptr
= (const u8
*)(cie
+ 2);
679 end
= (const u8
*)(cie
+ 1) + *cie
;
680 frame
->call_frame
= 1;
681 if ((state
.version
= *ptr
) != 1) {
682 dbug_unwind(1, "CIE version number is %d. 1 is supported.\n", state
.version
);
683 goto err
; /* unsupported version */
686 /* check if augmentation size is first (and thus present) */
688 while (++ptr
< end
&& *ptr
) {
690 /* check for ignorable (or already handled)
691 * nul-terminated augmentation string */
697 dbug_unwind(1, "This is a signal frame\n");
698 frame
->call_frame
= 0;
706 if (ptr
>= end
|| *ptr
) {
707 dbug_unwind(1, "Problem parsing the augmentation string.\n");
713 /* get code aligment factor */
714 state
.codeAlign
= get_uleb128(&ptr
, end
);
715 /* get data aligment factor */
716 state
.dataAlign
= get_sleb128(&ptr
, end
);
717 if (state
.codeAlign
== 0 || state
.dataAlign
== 0 || ptr
>= end
)
720 retAddrReg
= state
.version
<= 1 ? *ptr
++ : get_uleb128(&ptr
, end
);
722 /* skip augmentation */
723 if (((const char *)(cie
+ 2))[1] == 'z') {
724 uleb128_t augSize
= get_uleb128(&ptr
, end
);
727 if (ptr
> end
|| retAddrReg
>= ARRAY_SIZE(reg_info
)
728 || REG_INVALID(retAddrReg
)
729 || reg_info
[retAddrReg
].width
!= sizeof(unsigned long))
732 state
.cieStart
= ptr
;
735 end
= (const u8
*)(fde
+ 1) + *fde
;
737 /* skip augmentation */
738 if (((const char *)(cie
+ 2))[1] == 'z') {
739 uleb128_t augSize
= get_uleb128(&ptr
, end
);
740 if ((ptr
+= augSize
) > end
)
744 state
.org
= startLoc
;
745 memcpy(&state
.cfa
, &badCFA
, sizeof(state
.cfa
));
746 /* process instructions */
747 if (!processCFI(ptr
, end
, pc
, ptrType
, &state
)
748 || state
.loc
> endLoc
|| state
.regs
[retAddrReg
].where
== Nowhere
|| state
.cfa
.reg
>= ARRAY_SIZE(reg_info
)
749 || reg_info
[state
.cfa
.reg
].width
!= sizeof(unsigned long)
750 || state
.cfa
.offs
% sizeof(unsigned long))
754 #ifndef CONFIG_AS_CFI_SIGNAL_FRAME
755 if (frame
->call_frame
&& !UNW_DEFAULT_RA(state
.regs
[retAddrReg
], state
.dataAlign
))
756 frame
->call_frame
= 0;
758 cfa
= FRAME_REG(state
.cfa
.reg
, unsigned long) + state
.cfa
.offs
;
759 startLoc
= min((unsigned long)UNW_SP(frame
), cfa
);
760 endLoc
= max((unsigned long)UNW_SP(frame
), cfa
);
761 dbug_unwind(1, "cfa=%lx startLoc=%lx, endLoc=%lx\n", cfa
, startLoc
, endLoc
);
762 if (STACK_LIMIT(startLoc
) != STACK_LIMIT(endLoc
)) {
763 startLoc
= min(STACK_LIMIT(cfa
), cfa
);
764 endLoc
= max(STACK_LIMIT(cfa
), cfa
);
765 dbug_unwind(1, "cfa startLoc=%lx, endLoc=%lx\n",
766 (unsigned long)startLoc
, (unsigned long)endLoc
);
769 # define CASES CASE(8); CASE(16); CASE(32)
771 # define CASES CASE(8); CASE(16); CASE(32); CASE(64)
773 dbug_unwind(1, "cie=%lx fde=%lx\n", (unsigned long) cie
, (unsigned long) fde
);
774 for (i
= 0; i
< ARRAY_SIZE(state
.regs
); ++i
) {
775 if (REG_INVALID(i
)) {
776 if (state
.regs
[i
].where
== Nowhere
)
778 dbug_unwind(2, "REG_INVALID %d\n", i
);
781 dbug_unwind(2, "register %d. where=%d\n", i
, state
.regs
[i
].where
);
782 switch (state
.regs
[i
].where
) {
786 if (state
.regs
[i
].value
>= ARRAY_SIZE(reg_info
)
787 || REG_INVALID(state
.regs
[i
].value
)
788 || reg_info
[i
].width
> reg_info
[state
.regs
[i
].value
].width
) {
789 dbug_unwind(2, "case Register bad\n");
792 switch (reg_info
[state
.regs
[i
].value
].width
) {
795 state.regs[i].value = FRAME_REG(state.regs[i].value, \
801 dbug_unwind(2, "default\n");
807 for (i
= 0; i
< ARRAY_SIZE(state
.regs
); ++i
) {
808 dbug_unwind(2, "register %d. invalid=%d\n", i
, REG_INVALID(i
));
811 dbug_unwind(2, "register %d. where=%d\n", i
, state
.regs
[i
].where
);
812 switch (state
.regs
[i
].where
) {
814 if (reg_info
[i
].width
!= sizeof(UNW_SP(frame
))
815 || &FRAME_REG(i
, __typeof__(UNW_SP(frame
)))
821 switch (reg_info
[i
].width
) {
822 #define CASE(n) case sizeof(u##n): \
823 FRAME_REG(i, u##n) = state.regs[i].value; \
828 dbug_unwind(2, "default\n");
833 if (reg_info
[i
].width
!= sizeof(unsigned long)) {
834 dbug_unwind(2, "Value\n");
837 FRAME_REG(i
, unsigned long) = cfa
+ state
.regs
[i
].value
* state
.dataAlign
;
840 unsigned long addr
= cfa
+ state
.regs
[i
].value
* state
.dataAlign
;
841 dbug_unwind(2, "addr=%lx width=%d\n", addr
, reg_info
[i
].width
);
842 switch (reg_info
[i
].width
) {
843 #define CASE(n) case sizeof(u##n): \
844 if (unlikely(_stp_read_address(FRAME_REG(i, u##n), (u##n *)addr, KERNEL_DS))) \
846 dbug_unwind(1, "set register %d to %lx\n", i, (long)FRAME_REG(i,u##n));\
851 dbug_unwind(2, "default\n");
858 dbug_unwind(1, "returning 0 (%lx)\n", UNW_PC(frame
));
862 dbug_unwind(1, "_stp_read_address failed to access memory\n");
867 /* PC was in a range convered by a module but no unwind info */
868 /* found for the specific PC. This seems to happen only for kretprobe */
869 /* trampolines and at the end of interrupt backtraces. */
875 static int unwind(struct unwind_frame_info
*frame
, struct task_struct
*tsk
)
877 struct _stp_module
*m
;
878 struct _stp_section
*s
= NULL
;
879 unsigned long pc
= UNW_PC(frame
) - frame
->call_frame
;
882 dbug_unwind(1, "pc=%lx, %lx", pc
, UNW_PC(frame
));
884 if (UNW_PC(frame
) == 0)
887 m
= _stp_mod_sec_lookup (pc
, tsk
, &s
);
888 if (unlikely(m
== NULL
)) {
889 dbug_unwind(1, "No module found for pc=%lx", pc
);
893 dbug_unwind(1, "trying debug_frame\n");
894 res
= unwind_frame (frame
, m
, s
, m
->debug_frame
,
895 m
->debug_frame_len
, 0);
897 dbug_unwind(1, "debug_frame failed: %d, trying eh_frame\n", res
);
898 res
= unwind_frame (frame
, m
, s
, m
->eh_frame
,
905 #endif /* STP_USE_DWARF_UNWINDER */