aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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