diff options
| -rw-r--r-- | trace-cmd.h | 9 | ||||
| -rw-r--r-- | trace-ftrace.c | 86 | ||||
| -rw-r--r-- | trace-input.c | 4 |
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 | ||
| 80 | struct 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 | |||
| 80 | struct tracecmd_input *tracecmd_alloc(const char *file); | 87 | struct tracecmd_input *tracecmd_alloc(const char *file); |
| 81 | struct tracecmd_input *tracecmd_alloc_fd(int fd); | 88 | struct tracecmd_input *tracecmd_alloc_fd(int fd); |
| 82 | struct tracecmd_input *tracecmd_open(const char *file); | 89 | struct tracecmd_input *tracecmd_open(const char *file); |
| @@ -138,7 +145,7 @@ int tracecmd_set_cursor(struct tracecmd_input *handle, | |||
| 138 | unsigned long long | 145 | unsigned long long |
| 139 | tracecmd_get_cursor(struct tracecmd_input *handle, int cpu); | 146 | tracecmd_get_cursor(struct tracecmd_input *handle, int cpu); |
| 140 | 147 | ||
| 141 | int tracecmd_ftrace_overrides(struct tracecmd_input *handle); | 148 | int tracecmd_ftrace_overrides(struct tracecmd_input *handle, struct tracecmd_ftrace *finfo); |
| 142 | struct pevent *tracecmd_get_pevent(struct tracecmd_input *handle); | 149 | struct 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 | ||
| 28 | static struct event_format *fgraph_ret_event; | 28 | static void find_long_size(struct tracecmd_ftrace *finfo) |
| 29 | static int fgraph_ret_id; | 29 | { |
| 30 | static 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 | |||
| 39 | static 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 | ||
| 32 | static int function_handler(struct trace_seq *s, struct record *record, | 59 | static 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 | ||
| 62 | static struct record * | 89 | static struct record * |
| 63 | get_return_for_leaf(struct trace_seq *s, int cpu, int cur_pid, | 90 | get_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 | |||
| 146 | static int | 174 | static int |
| 147 | print_graph_entry_leaf(struct trace_seq *s, | 175 | print_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 | |||
| 225 | fgraph_ent_handler(struct trace_seq *s, struct record *record, | 253 | fgraph_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 | |||
| 256 | fgraph_ret_handler(struct trace_seq *s, struct record *record, | 287 | fgraph_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 | |||
| 290 | trace_stack_handler(struct trace_seq *s, struct record *record, | 324 | trace_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 | ||
| 325 | int tracecmd_ftrace_overrides(struct tracecmd_input *handle) | 362 | int 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 | ||
