aboutsummaryrefslogtreecommitdiffstats
path: root/trace-ftrace.c
diff options
context:
space:
mode:
Diffstat (limited to 'trace-ftrace.c')
-rw-r--r--trace-ftrace.c88
1 files changed, 64 insertions, 24 deletions
diff --git a/trace-ftrace.c b/trace-ftrace.c
index f12b221..193e85d 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,34 +359,37 @@ 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;
329 367
368 finfo->handle = handle;
369
330 pevent = tracecmd_get_pevent(handle); 370 pevent = tracecmd_get_pevent(handle);
331 371
332 pevent_register_event_handler(pevent, -1, "ftrace", "function", 372 pevent_register_event_handler(pevent, -1, "ftrace", "function",
333 function_handler, NULL); 373 function_handler, NULL);
334 374
335 pevent_register_event_handler(pevent, -1, "ftrace", "funcgraph_entry", 375 pevent_register_event_handler(pevent, -1, "ftrace", "funcgraph_entry",
336 fgraph_ent_handler, NULL); 376 fgraph_ent_handler, finfo);
337 377
338 pevent_register_event_handler(pevent, -1, "ftrace", "funcgraph_exit", 378 pevent_register_event_handler(pevent, -1, "ftrace", "funcgraph_exit",
339 fgraph_ret_handler, NULL); 379 fgraph_ret_handler, finfo);
340 380
341 pevent_register_event_handler(pevent, -1, "ftrace", "kernel_stack", 381 pevent_register_event_handler(pevent, -1, "ftrace", "kernel_stack",
342 trace_stack_handler, NULL); 382 trace_stack_handler, finfo);
343 383
344 /* Store the func ret id and event for later use */ 384 /* Store the func ret id and event for later use */
345 event = pevent_find_event_by_name(pevent, "ftrace", "funcgraph_exit"); 385 event = pevent_find_event_by_name(pevent, "ftrace", "funcgraph_exit");
346 if (!event) 386 if (!event)
347 return 0; 387 return 0;
348 388
349 long_size = tracecmd_long_size(handle); 389 finfo->long_size = tracecmd_long_size(handle);
350 390
351 fgraph_ret_id = event->id; 391 finfo->fgraph_ret_id = event->id;
352 fgraph_ret_event = event; 392 finfo->fgraph_ret_event = event;
353 393
354 return 0; 394 return 0;
355} 395}