diff options
author | Steven Rostedt <srostedt@redhat.com> | 2009-12-10 00:34:23 -0500 |
---|---|---|
committer | Steven Rostedt <rostedt@goodmis.org> | 2009-12-10 00:34:54 -0500 |
commit | 82bf45c96fcf9cfe6fd2d99d39119475c8d3b590 (patch) | |
tree | b1e79ec092f801bc2eaecbecca33a22504998a05 | |
parent | 2d802a522d04d89fc9277cd5c79dafb7af62fae4 (diff) |
Add override handler to handle kernel stack trace entry
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
-rw-r--r-- | trace-ftrace.c | 43 |
1 files changed, 43 insertions, 0 deletions
diff --git a/trace-ftrace.c b/trace-ftrace.c index 68ac7a8..b1d420d 100644 --- a/trace-ftrace.c +++ b/trace-ftrace.c | |||
@@ -6,6 +6,7 @@ | |||
6 | 6 | ||
7 | static struct event *fgraph_ret_event; | 7 | static struct event *fgraph_ret_event; |
8 | static int fgraph_ret_id; | 8 | static int fgraph_ret_id; |
9 | static int long_size; | ||
9 | 10 | ||
10 | static int get_field_val(struct trace_seq *s, void *data, | 11 | static int get_field_val(struct trace_seq *s, void *data, |
11 | struct event *event, const char *name, | 12 | struct event *event, const char *name, |
@@ -289,6 +290,43 @@ fgraph_ret_handler(struct trace_seq *s, void *data, int size, | |||
289 | return trace_seq_putc(s, '}'); | 290 | return trace_seq_putc(s, '}'); |
290 | } | 291 | } |
291 | 292 | ||
293 | static int | ||
294 | trace_stack_handler(struct trace_seq *s, void *data, int size, | ||
295 | struct event *event, int cpu, | ||
296 | unsigned long long nsecs) | ||
297 | { | ||
298 | struct format_field *field; | ||
299 | unsigned long long addr; | ||
300 | const char *func; | ||
301 | int ret; | ||
302 | int i; | ||
303 | |||
304 | field = pevent_find_any_field(event, "caller"); | ||
305 | if (!field) { | ||
306 | trace_seq_printf(s, "<CANT FIND FIELD %s>", "caller"); | ||
307 | return -1; | ||
308 | } | ||
309 | |||
310 | ret = trace_seq_puts(s, "<stack trace>\n"); | ||
311 | |||
312 | for (i = 0; i < field->size; i += long_size) { | ||
313 | addr = pevent_read_number(event->pevent, | ||
314 | data + field->offset + i, long_size); | ||
315 | |||
316 | if ((long_size == 8 && addr == (unsigned long long)-1) || | ||
317 | ((int)addr == -1)) | ||
318 | break; | ||
319 | |||
320 | func = pevent_find_function(event->pevent, addr); | ||
321 | if (func) | ||
322 | ret = trace_seq_printf(s, "=> %s (%llx)\n", func, addr); | ||
323 | else | ||
324 | ret = trace_seq_printf(s, "=> %llx\n", addr); | ||
325 | } | ||
326 | |||
327 | return ret; | ||
328 | } | ||
329 | |||
292 | int tracecmd_ftrace_overrides(struct tracecmd_input *handle) | 330 | int tracecmd_ftrace_overrides(struct tracecmd_input *handle) |
293 | { | 331 | { |
294 | struct pevent *pevent; | 332 | struct pevent *pevent; |
@@ -305,11 +343,16 @@ int tracecmd_ftrace_overrides(struct tracecmd_input *handle) | |||
305 | pevent_register_event_handler(pevent, -1, "ftrace", "funcgraph_exit", | 343 | pevent_register_event_handler(pevent, -1, "ftrace", "funcgraph_exit", |
306 | fgraph_ret_handler); | 344 | fgraph_ret_handler); |
307 | 345 | ||
346 | pevent_register_event_handler(pevent, -1, "ftrace", "kernel_stack", | ||
347 | trace_stack_handler); | ||
348 | |||
308 | /* Store the func ret id and event for later use */ | 349 | /* Store the func ret id and event for later use */ |
309 | event = pevent_find_event_by_name(pevent, "ftrace", "funcgraph_exit"); | 350 | event = pevent_find_event_by_name(pevent, "ftrace", "funcgraph_exit"); |
310 | if (!event) | 351 | if (!event) |
311 | return 0; | 352 | return 0; |
312 | 353 | ||
354 | long_size = tracecmd_long_size(handle); | ||
355 | |||
313 | fgraph_ret_id = event->id; | 356 | fgraph_ret_id = event->id; |
314 | fgraph_ret_event = event; | 357 | fgraph_ret_event = event; |
315 | 358 | ||