2 * Stack tracing functions
3 * Copyright (C) 2005-2008 Red Hat Inc.
4 * Copyright (C) 2005 Intel Corporation.
6 * This file is part of systemtap, and is free software. You can
7 * redistribute it and/or modify it under the terms of the GNU General
8 * Public License (GPL); either version 2, or (at your option) any
16 * @brief Stack Tracing Functions
19 /** @addtogroup stack Stack Tracing Functions
28 #define MAXBACKTRACE 20
30 #if defined(STAPCONF_KERNEL_STACKTRACE)
31 #include <linux/stacktrace.h>
32 #include <asm/stacktrace.h>
35 static void _stp_stack_print_fallback(unsigned long, int, int);
37 #if defined (__x86_64__)
38 #include "stack-x86_64.c"
39 #elif defined (__ia64__)
40 #include "stack-ia64.c"
41 #elif defined (__i386__)
42 #include "stack-i386.c"
43 #elif defined (__powerpc64__)
44 #include "stack-ppc64.c"
45 #elif defined (__arm__)
46 #include "stack-arm.c"
47 #elif defined (__s390__) || defined (__s390x__)
48 #include "stack-s390.c"
50 #error "Unsupported architecture"
53 #if defined(STAPCONF_KERNEL_STACKTRACE)
55 struct print_stack_data
62 static void print_stack_warning(void *data
, char *msg
)
67 print_stack_warning_symbol(void *data
, char *msg
, unsigned long symbol
)
71 static int print_stack_stack(void *data
, char *name
)
76 static void print_stack_address(void *data
, unsigned long addr
, int reliable
)
78 struct print_stack_data
*sdata
= data
;
79 if (sdata
->level
++ < sdata
->max_level
)
80 _stp_func_print(addr
,sdata
->verbose
, 0);
83 static const struct stacktrace_ops print_stack_ops
= {
84 .warning
= print_stack_warning
,
85 .warning_symbol
= print_stack_warning_symbol
,
86 .stack
= print_stack_stack
,
87 .address
= print_stack_address
,
90 static void _stp_stack_print_fallback(unsigned long stack
, int verbose
, int levels
)
92 struct print_stack_data print_data
;
93 print_data
.verbose
= verbose
;
94 print_data
.max_level
= levels
;
96 dump_trace(current
, NULL
, (long *)stack
, 0, &print_stack_ops
,
100 /** Prints the stack backtrace
101 * @param regs A pointer to the struct pt_regs.
104 static void _stp_stack_print(struct pt_regs
*regs
, int verbose
, struct kretprobe_instance
*pi
, int levels
)
107 /* print the current address */
109 _stp_print("Returning from: ");
110 _stp_symbol_print((unsigned long)_stp_probe_addr_r(pi
));
111 _stp_print("\nReturning to : ");
112 _stp_symbol_print((unsigned long)_stp_ret_addr_r(pi
));
114 _stp_print_char(' ');
115 _stp_symbol_print(REG_IP(regs
));
117 _stp_print_char('\n');
119 _stp_printf("%p %p ", (int64_t)(long)_stp_ret_addr_r(pi
), (int64_t) REG_IP(regs
));
121 _stp_printf("%p ", (int64_t) REG_IP(regs
));
123 __stp_stack_print(regs
, verbose
, levels
);
126 /** Writes stack backtrace to a string
129 * @param regs A pointer to the struct pt_regs.
132 static void _stp_stack_snprint(char *str
, int size
, struct pt_regs
*regs
, int verbose
, struct kretprobe_instance
*pi
, int levels
)
134 /* To get a string, we use a simple trick. First flush the print buffer, */
135 /* then call _stp_stack_print, then copy the result into the output string */
136 /* and clear the print buffer. */
137 _stp_pbuf
*pb
= per_cpu_ptr(Stp_pbuf
, smp_processor_id());
139 _stp_stack_print(regs
, verbose
, pi
, levels
);
140 strlcpy(str
, pb
->buf
, size
< (int)pb
->len
? size
: (int)pb
->len
);
144 /** Prints the user stack backtrace
146 * @returns Same string as was input with trace info appended,
147 * @note Currently limited to a depth of two. Works from jprobes and kprobes.
150 static void _stp_ustack_print(char *str
)
152 struct pt_regs
*nregs
= ((struct pt_regs
*)(THREAD_SIZE
+ (unsigned long)current
->thread_info
)) - 1;
153 _stp_printf("%p : [user]\n", (int64_t) REG_IP(nregs
));
155 _stp_printf("%p : [user]\n", (int64_t) (*(unsigned long *)REG_SP(nregs
)));
161 void _stp_stack_print_tsk(struct task_struct
*tsk
, int verbose
, int levels
)
163 #if defined(STAPCONF_KERNEL_STACKTRACE)
165 unsigned long backtrace
[MAXBACKTRACE
];
166 struct stack_trace trace
;
167 int maxLevels
= min(levels
, MAXBACKTRACE
);
168 memset(&trace
, 0, sizeof(trace
));
169 trace
.entries
= &backtrace
[0];
170 trace
.max_entries
= maxLevels
;
172 save_stack_trace_tsk(tsk
, &trace
);
173 for (i
= 0; i
< maxLevels
; ++i
) {
174 if (backtrace
[i
] == 0 || backtrace
[i
] == ULONG_MAX
)
176 _stp_printf("%lx ", backtrace
[i
]);
181 /** Writes a task stack backtrace to a string
184 * @param tsk A pointer to the task_struct
187 void _stp_stack_snprint_tsk(char *str
, int size
, struct task_struct
*tsk
, int verbose
, int levels
)
189 _stp_pbuf
*pb
= per_cpu_ptr(Stp_pbuf
, smp_processor_id());
191 _stp_stack_print_tsk(tsk
, verbose
, levels
);
192 strlcpy(str
, pb
->buf
, size
< (int)pb
->len
? size
: (int)pb
->len
);
195 #endif /* _STACK_C_ */