summaryrefslogtreecommitdiffstats
path: root/runtime/stack-i386.c
diff options
context:
space:
mode:
authorMartin Hunt <hunt@monkey.(none)>2008-04-15 21:10:34 -0400
committerMartin Hunt <hunt@monkey.(none)>2008-04-15 21:10:34 -0400
commit4f7a75f2cb3394290d1093a031546aa848ace929 (patch)
tree081546c0cd685ed58bc90c4903a7d954415300bf /runtime/stack-i386.c
parent8558d3925ee2931b654a19f243bfa8b3be0bfc12 (diff)
downloadsystemtap-steved-4f7a75f2cb3394290d1093a031546aa848ace929.tar.gz
systemtap-steved-4f7a75f2cb3394290d1093a031546aa848ace929.tar.xz
systemtap-steved-4f7a75f2cb3394290d1093a031546aa848ace929.zip
2.6.25 fixes and stack level limits.
Diffstat (limited to 'runtime/stack-i386.c')
-rw-r--r--runtime/stack-i386.c50
1 files changed, 23 insertions, 27 deletions
diff --git a/runtime/stack-i386.c b/runtime/stack-i386.c
index 78f89b0d..ad101889 100644
--- a/runtime/stack-i386.c
+++ b/runtime/stack-i386.c
@@ -14,65 +14,61 @@ static int _stp_valid_stack_ptr(unsigned long context, unsigned long p)
}
/* DWARF unwinder failed. Just dump intereting addresses on kernel stack. */
-static void _stp_stack_print_fallback(unsigned long context, unsigned long stack, int verbose)
+static void _stp_stack_print_fallback(unsigned long context, unsigned long stack, int verbose, int levels)
{
unsigned long addr;
- while (_stp_valid_stack_ptr(context, stack) &&
- !_stp_pbuf_full()) {
+ while (levels && _stp_valid_stack_ptr(context, stack)) {
if (unlikely(_stp_read_address(addr, (unsigned long *)stack, KERNEL_DS))) {
/* cannot access stack. give up. */
return;
}
- _stp_func_print(addr, verbose, 0);
+ if (_stp_func_print(addr, verbose, 0))
+ levels--;
stack++;
}
}
static void __stp_stack_print (struct pt_regs *regs, int verbose, int levels)
{
- unsigned long *stack = (unsigned long *)&REG_SP(regs);
- unsigned long context = (unsigned long)stack & ~(THREAD_SIZE - 1);
+ unsigned long context = (unsigned long)&REG_SP(regs) & ~(THREAD_SIZE - 1);
#ifdef STP_USE_FRAME_POINTER
- /* FIXME: need to use _stp_func_print() and safe copy */
unsigned long addr;
-
-#ifdef STAPCONF_X86_UNIREGS
- unsigned long ebp = regs->bp;
-#else
- unsigned long ebp = regs->ebp;
-#endif /* STAPCONF_X86_UNIREGS */
-
- while (_stp_valid_stack_ptr(context, (unsigned long)ebp) &&
- !_stp_pbuf_full()) {
- if (unlikely(_stp_read_address(addr, (unsigned long *)(ebp + 4), KERNEL_DS))) {
+ unsigned long next_fp, fp = REG_FP(regs);
+
+ while (levels && _stp_valid_stack_ptr(context, (unsigned long)fp)) {
+ if (unlikely(_stp_read_address(addr, (unsigned long *)(fp + 4), KERNEL_DS))) {
/* cannot access stack. give up. */
return;
}
- if (verbose) {
- _stp_print_char(' ');
- _stp_symbol_print (addr);
- _stp_print_char('\n');
- } else
- _stp_printf ("0x%08lx ", addr);
- ebp = *(unsigned long *)ebp;
+ _stp_func_print(addr, verbose, 1);
+ if (unlikely(_stp_read_address(next_fp, (unsigned long *)fp, KERNEL_DS))) {
+ /* cannot access stack. give up. */
+ return;
+ }
+ levels--;
+
+ /* frame pointers move upwards */
+ if (next_fp <= fp)
+ break;
+ fp = next_fp;
}
#else
struct unwind_frame_info info;
arch_unw_init_frame_info(&info, regs);
- while (!arch_unw_user_mode(&info) &&
- !_stp_pbuf_full ()) {
+ while (levels && !arch_unw_user_mode(&info)) {
int ret = unwind(&info);
dbug_unwind(1, "ret=%d PC=%lx SP=%lx\n", ret, UNW_PC(&info), UNW_SP(&info));
if (ret == 0) {
_stp_func_print(UNW_PC(&info), verbose, 1);
+ levels--;
continue;
}
/* If an error happened or we hit a kretprobe trampoline, use fallback backtrace */
/* FIXME: is there a way to unwind across kretprobe trampolines? */
if (ret < 0 || (ret > 0 && UNW_PC(&info) == _stp_kretprobe_trampoline))
- _stp_stack_print_fallback(context, UNW_SP(&info), verbose);
+ _stp_stack_print_fallback(context, UNW_SP(&info), verbose, levels);
break;
}
#endif /* STP_USE_FRAME_POINTER */