aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteven Rostedt <srostedt@redhat.com>2010-07-14 10:25:19 -0400
committerSteven Rostedt <rostedt@goodmis.org>2010-07-14 14:35:29 -0400
commitfa8ded4b3e6587d6dc5d65d5998cf2c624005a72 (patch)
treeae6fa45cf56cce663207b91f4a323565475ae901
parentf0e369a8213555b9ceec134bc5fe9f293417f835 (diff)
trace-cmd: Fix trace-cmd function graph handling of its events
The function graph needs to store the function graph return event for later use. This patch changes the function graph callbacks to use the context to store this information and initialize it when first referenced. The event data is now stored on the tracecmd_input handle, that allows more than one tracecmd_input handle to work with this code in one utility. Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
-rw-r--r--trace-cmd.h9
-rw-r--r--trace-ftrace.c86
-rw-r--r--trace-input.c4
3 files changed, 73 insertions, 26 deletions
diff --git a/trace-cmd.h b/trace-cmd.h
index 901a843..dda4d0b 100644
--- a/trace-cmd.h
+++ b/trace-cmd.h
@@ -77,6 +77,13 @@ enum {
77 TRACECMD_OPTION_DONE, 77 TRACECMD_OPTION_DONE,
78}; 78};
79 79
80struct tracecmd_ftrace {
81 struct tracecmd_input *handle;
82 struct event_format *fgraph_ret_event;
83 int fgraph_ret_id;
84 int long_size;
85};
86
80struct tracecmd_input *tracecmd_alloc(const char *file); 87struct tracecmd_input *tracecmd_alloc(const char *file);
81struct tracecmd_input *tracecmd_alloc_fd(int fd); 88struct tracecmd_input *tracecmd_alloc_fd(int fd);
82struct tracecmd_input *tracecmd_open(const char *file); 89struct tracecmd_input *tracecmd_open(const char *file);
@@ -138,7 +145,7 @@ int tracecmd_set_cursor(struct tracecmd_input *handle,
138unsigned long long 145unsigned long long
139tracecmd_get_cursor(struct tracecmd_input *handle, int cpu); 146tracecmd_get_cursor(struct tracecmd_input *handle, int cpu);
140 147
141int tracecmd_ftrace_overrides(struct tracecmd_input *handle); 148int tracecmd_ftrace_overrides(struct tracecmd_input *handle, struct tracecmd_ftrace *finfo);
142struct pevent *tracecmd_get_pevent(struct tracecmd_input *handle); 149struct pevent *tracecmd_get_pevent(struct tracecmd_input *handle);
143 150
144#ifndef SWIG 151#ifndef SWIG
diff --git a/trace-ftrace.c b/trace-ftrace.c
index f12b221..f11fb6f 100644
--- a/trace-ftrace.c
+++ b/trace-ftrace.c
@@ -25,9 +25,36 @@
25 25
26#include "trace-cmd.h" 26#include "trace-cmd.h"
27 27
28static struct event_format *fgraph_ret_event; 28static void find_long_size(struct tracecmd_ftrace *finfo)
29static int fgraph_ret_id; 29{
30static int long_size; 30 finfo->long_size = tracecmd_long_size(finfo->handle);
31}
32
33#define long_size_check(handle) \
34 do { \
35 if (!finfo->long_size) \
36 find_long_size(finfo); \
37 } while (0)
38
39static int find_ret_event(struct tracecmd_ftrace *finfo, struct pevent *pevent)
40{
41 struct event_format *event;
42
43 /* Store the func ret id and event for later use */
44 event = pevent_find_event_by_name(pevent, "ftrace", "funcgraph_exit");
45 if (!event)
46 return -1;
47
48 finfo->fgraph_ret_id = event->id;
49 finfo->fgraph_ret_event = event;
50 return 0;
51}
52
53#define ret_event_check(finfo, pevent) \
54 do { \
55 if (!finfo->fgraph_ret_event && find_ret_event(finfo, pevent) < 0) \
56 return -1; \
57 } while (0)
31 58
32static int function_handler(struct trace_seq *s, struct record *record, 59static int function_handler(struct trace_seq *s, struct record *record,
33 struct event_format *event, void *context) 60 struct event_format *event, void *context)
@@ -61,27 +88,28 @@ static int function_handler(struct trace_seq *s, struct record *record,
61 88
62static struct record * 89static struct record *
63get_return_for_leaf(struct trace_seq *s, int cpu, int cur_pid, 90get_return_for_leaf(struct trace_seq *s, int cpu, int cur_pid,
64 unsigned long long cur_func, struct record *next) 91 unsigned long long cur_func, struct record *next,
92 struct tracecmd_ftrace *finfo)
65{ 93{
66 unsigned long long val; 94 unsigned long long val;
67 unsigned long long type; 95 unsigned long long type;
68 unsigned long long pid; 96 unsigned long long pid;
69 97
70 /* Searching a common field, can use any event */ 98 /* Searching a common field, can use any event */
71 if (pevent_get_common_field_val(s, fgraph_ret_event, "common_type", next, &type, 1)) 99 if (pevent_get_common_field_val(s, finfo->fgraph_ret_event, "common_type", next, &type, 1))
72 return NULL; 100 return NULL;
73 101
74 if (type != fgraph_ret_id) 102 if (type != finfo->fgraph_ret_id)
75 return NULL; 103 return NULL;
76 104
77 if (pevent_get_common_field_val(s, fgraph_ret_event, "common_pid", next, &pid, 1)) 105 if (pevent_get_common_field_val(s, finfo->fgraph_ret_event, "common_pid", next, &pid, 1))
78 return NULL; 106 return NULL;
79 107
80 if (cur_pid != pid) 108 if (cur_pid != pid)
81 return NULL; 109 return NULL;
82 110
83 /* We aleady know this is a funcgraph_ret_event */ 111 /* We aleady know this is a funcgraph_ret_event */
84 if (pevent_get_field_val(s, fgraph_ret_event, "func", next, &val, 1)) 112 if (pevent_get_field_val(s, finfo->fgraph_ret_event, "func", next, &val, 1))
85 return NULL; 113 return NULL;
86 114
87 if (cur_func != val) 115 if (cur_func != val)
@@ -146,7 +174,8 @@ static void print_graph_duration(struct trace_seq *s, unsigned long long duratio
146static int 174static int
147print_graph_entry_leaf(struct trace_seq *s, 175print_graph_entry_leaf(struct trace_seq *s,
148 struct event_format *event, 176 struct event_format *event,
149 struct record *record, struct record *ret_rec) 177 struct record *record, struct record *ret_rec,
178 struct tracecmd_ftrace *finfo)
150{ 179{
151 struct pevent *pevent = event->pevent; 180 struct pevent *pevent = event->pevent;
152 unsigned long long rettime, calltime; 181 unsigned long long rettime, calltime;
@@ -155,11 +184,10 @@ print_graph_entry_leaf(struct trace_seq *s,
155 const char *func; 184 const char *func;
156 int i; 185 int i;
157 186
158 187 if (pevent_get_field_val(s, finfo->fgraph_ret_event, "rettime", ret_rec, &rettime, 1))
159 if (pevent_get_field_val(s, fgraph_ret_event, "rettime", ret_rec, &rettime, 1))
160 return trace_seq_putc(s, '!'); 188 return trace_seq_putc(s, '!');
161 189
162 if (pevent_get_field_val(s, fgraph_ret_event, "calltime", ret_rec, &calltime, 1)) 190 if (pevent_get_field_val(s, finfo->fgraph_ret_event, "calltime", ret_rec, &calltime, 1))
163 return trace_seq_putc(s, '!'); 191 return trace_seq_putc(s, '!');
164 192
165 duration = rettime - calltime; 193 duration = rettime - calltime;
@@ -225,10 +253,13 @@ static int
225fgraph_ent_handler(struct trace_seq *s, struct record *record, 253fgraph_ent_handler(struct trace_seq *s, struct record *record,
226 struct event_format *event, void *context) 254 struct event_format *event, void *context)
227{ 255{
256 struct tracecmd_ftrace *finfo = context;
228 struct record *rec; 257 struct record *rec;
229 unsigned long long val, pid; 258 unsigned long long val, pid;
230 int cpu = record->cpu; 259 int cpu = record->cpu;
231 260
261 ret_event_check(finfo, event->pevent);
262
232 if (pevent_get_common_field_val(s, event, "common_pid", record, &pid, 1)) 263 if (pevent_get_common_field_val(s, event, "common_pid", record, &pid, 1))
233 return trace_seq_putc(s, '!'); 264 return trace_seq_putc(s, '!');
234 265
@@ -237,14 +268,14 @@ fgraph_ent_handler(struct trace_seq *s, struct record *record,
237 268
238 rec = tracecmd_peek_data(tracecmd_curr_thread_handle, cpu); 269 rec = tracecmd_peek_data(tracecmd_curr_thread_handle, cpu);
239 if (rec) 270 if (rec)
240 rec = get_return_for_leaf(s, cpu, pid, val, rec); 271 rec = get_return_for_leaf(s, cpu, pid, val, rec, finfo);
241 272
242 if (rec) { 273 if (rec) {
243 /* 274 /*
244 * If this is a leaf function, then get_return_for_leaf 275 * If this is a leaf function, then get_return_for_leaf
245 * returns the return of the function 276 * returns the return of the function
246 */ 277 */
247 print_graph_entry_leaf(s, event, record, rec); 278 print_graph_entry_leaf(s, event, record, rec, finfo);
248 free_record(rec); 279 free_record(rec);
249 } else 280 } else
250 print_graph_nested(s, event, record); 281 print_graph_nested(s, event, record);
@@ -256,10 +287,13 @@ static int
256fgraph_ret_handler(struct trace_seq *s, struct record *record, 287fgraph_ret_handler(struct trace_seq *s, struct record *record,
257 struct event_format *event, void *context) 288 struct event_format *event, void *context)
258{ 289{
290 struct tracecmd_ftrace *finfo = context;
259 unsigned long long rettime, calltime; 291 unsigned long long rettime, calltime;
260 unsigned long long duration, depth; 292 unsigned long long duration, depth;
261 int i; 293 int i;
262 294
295 ret_event_check(finfo, event->pevent);
296
263 if (pevent_get_field_val(s, event, "rettime", record, &rettime, 1)) 297 if (pevent_get_field_val(s, event, "rettime", record, &rettime, 1))
264 return trace_seq_putc(s, '!'); 298 return trace_seq_putc(s, '!');
265 299
@@ -290,6 +324,7 @@ static int
290trace_stack_handler(struct trace_seq *s, struct record *record, 324trace_stack_handler(struct trace_seq *s, struct record *record,
291 struct event_format *event, void *context) 325 struct event_format *event, void *context)
292{ 326{
327 struct tracecmd_ftrace *finfo = context;
293 struct format_field *field; 328 struct format_field *field;
294 unsigned long long addr; 329 unsigned long long addr;
295 const char *func; 330 const char *func;
@@ -304,11 +339,13 @@ trace_stack_handler(struct trace_seq *s, struct record *record,
304 339
305 trace_seq_puts(s, "<stack trace>\n"); 340 trace_seq_puts(s, "<stack trace>\n");
306 341
307 for (i = 0; i < field->size; i += long_size) { 342 long_size_check(finfo);
343
344 for (i = 0; i < field->size; i += finfo->long_size) {
308 addr = pevent_read_number(event->pevent, 345 addr = pevent_read_number(event->pevent,
309 data + field->offset + i, long_size); 346 data + field->offset + i, finfo->long_size);
310 347
311 if ((long_size == 8 && addr == (unsigned long long)-1) || 348 if ((finfo->long_size == 8 && addr == (unsigned long long)-1) ||
312 ((int)addr == -1)) 349 ((int)addr == -1))
313 break; 350 break;
314 351
@@ -322,7 +359,8 @@ trace_stack_handler(struct trace_seq *s, struct record *record,
322 return 0; 359 return 0;
323} 360}
324 361
325int tracecmd_ftrace_overrides(struct tracecmd_input *handle) 362int tracecmd_ftrace_overrides(struct tracecmd_input *handle,
363 struct tracecmd_ftrace *finfo)
326{ 364{
327 struct pevent *pevent; 365 struct pevent *pevent;
328 struct event_format *event; 366 struct event_format *event;
@@ -333,23 +371,23 @@ int tracecmd_ftrace_overrides(struct tracecmd_input *handle)
333 function_handler, NULL); 371 function_handler, NULL);
334 372
335 pevent_register_event_handler(pevent, -1, "ftrace", "funcgraph_entry", 373 pevent_register_event_handler(pevent, -1, "ftrace", "funcgraph_entry",
336 fgraph_ent_handler, NULL); 374 fgraph_ent_handler, finfo);
337 375
338 pevent_register_event_handler(pevent, -1, "ftrace", "funcgraph_exit", 376 pevent_register_event_handler(pevent, -1, "ftrace", "funcgraph_exit",
339 fgraph_ret_handler, NULL); 377 fgraph_ret_handler, finfo);
340 378
341 pevent_register_event_handler(pevent, -1, "ftrace", "kernel_stack", 379 pevent_register_event_handler(pevent, -1, "ftrace", "kernel_stack",
342 trace_stack_handler, NULL); 380 trace_stack_handler, finfo);
343 381
344 /* Store the func ret id and event for later use */ 382 /* Store the func ret id and event for later use */
345 event = pevent_find_event_by_name(pevent, "ftrace", "funcgraph_exit"); 383 event = pevent_find_event_by_name(pevent, "ftrace", "funcgraph_exit");
346 if (!event) 384 if (!event)
347 return 0; 385 return 0;
348 386
349 long_size = tracecmd_long_size(handle); 387 finfo->long_size = tracecmd_long_size(handle);
350 388
351 fgraph_ret_id = event->id; 389 finfo->fgraph_ret_id = event->id;
352 fgraph_ret_event = event; 390 finfo->fgraph_ret_event = event;
353 391
354 return 0; 392 return 0;
355} 393}
diff --git a/trace-input.c b/trace-input.c
index 398d0f9..b3dbca3 100644
--- a/trace-input.c
+++ b/trace-input.c
@@ -82,6 +82,8 @@ struct tracecmd_input {
82 int ref; 82 int ref;
83 struct cpu_data *cpu_data; 83 struct cpu_data *cpu_data;
84 84
85 struct tracecmd_ftrace finfo;
86
85 /* file information */ 87 /* file information */
86 size_t header_files_start; 88 size_t header_files_start;
87 size_t ftrace_files_start; 89 size_t ftrace_files_start;
@@ -1976,7 +1978,7 @@ struct tracecmd_input *tracecmd_alloc_fd(int fd)
1976 goto failed_read; 1978 goto failed_read;
1977 1979
1978 /* register default ftrace functions first */ 1980 /* register default ftrace functions first */
1979 tracecmd_ftrace_overrides(handle); 1981 tracecmd_ftrace_overrides(handle, &handle->finfo);
1980 1982
1981 handle->plugin_list = tracecmd_load_plugins(handle->pevent); 1983 handle->plugin_list = tracecmd_load_plugins(handle->pevent);
1982 1984