diff options
-rw-r--r-- | Makefile | 19 | ||||
-rw-r--r-- | parse-events.c | 34 | ||||
-rw-r--r-- | parse-events.h | 2 | ||||
-rw-r--r-- | plugin_kmem.c | 56 | ||||
-rw-r--r-- | trace-ftrace.c | 22 |
5 files changed, 113 insertions, 20 deletions
@@ -18,8 +18,11 @@ CFLAGS = -g -Wall $(CONFIG_FLAGS) | |||
18 | %.o: %.c | 18 | %.o: %.c |
19 | $(CC) -c $(CFLAGS) $(EXT) $(INCLUDES) $< -o $@ | 19 | $(CC) -c $(CFLAGS) $(EXT) $(INCLUDES) $< -o $@ |
20 | 20 | ||
21 | TARGETS = libparsevent.a libtracecmd.a trace-cmd plugin_hrtimer.so plugin_mac80211.so \ | 21 | PLUGINS = plugin_hrtimer.so plugin_mac80211.so plugin_sched_switch.so \ |
22 | plugin_sched_switch.so trace-graph trace-view kernelshark | 22 | plugin_kmem.so |
23 | |||
24 | TARGETS = libparsevent.a libtracecmd.a trace-cmd $(PLUGINS) \ | ||
25 | trace-graph trace-view kernelshark | ||
23 | 26 | ||
24 | all: $(TARGETS) | 27 | all: $(TARGETS) |
25 | 28 | ||
@@ -99,19 +102,25 @@ libtracecmd.so: $(TCMD_LIB_OBJS) | |||
99 | libtracecmd.a: $(TCMD_LIB_OBJS) | 102 | libtracecmd.a: $(TCMD_LIB_OBJS) |
100 | $(RM) $@; $(AR) rcs $@ $^ | 103 | $(RM) $@; $(AR) rcs $@ $^ |
101 | 104 | ||
102 | plugin_hrtimer.o: plugin_hrtimer.c parse-events.h | 105 | plugin_hrtimer.o: plugin_hrtimer.c parse-events.h trace-cmd.h |
103 | $(CC) -c $(CFLAGS) -fPIC -o $@ $< | 106 | $(CC) -c $(CFLAGS) -fPIC -o $@ $< |
104 | 107 | ||
105 | plugin_hrtimer.so: plugin_hrtimer.o | 108 | plugin_hrtimer.so: plugin_hrtimer.o |
106 | $(CC) -shared -nostartfiles -o $@ $< | 109 | $(CC) -shared -nostartfiles -o $@ $< |
107 | 110 | ||
108 | plugin_sched_switch.o: plugin_sched_switch.c parse-events.h | 111 | plugin_kmem.o: plugin_kmem.c parse-events.h trace-cmd.h |
112 | $(CC) -c $(CFLAGS) -fPIC -o $@ $< | ||
113 | |||
114 | plugin_kmem.so: plugin_kmem.o | ||
115 | $(CC) -shared -nostartfiles -o $@ $< | ||
116 | |||
117 | plugin_sched_switch.o: plugin_sched_switch.c parse-events.h trace-cmd.h | ||
109 | $(CC) -c $(CFLAGS) -fPIC -o $@ $< | 118 | $(CC) -c $(CFLAGS) -fPIC -o $@ $< |
110 | 119 | ||
111 | plugin_sched_switch.so: plugin_sched_switch.o | 120 | plugin_sched_switch.so: plugin_sched_switch.o |
112 | $(CC) -shared -nostartfiles -o $@ $< | 121 | $(CC) -shared -nostartfiles -o $@ $< |
113 | 122 | ||
114 | plugin_mac80211.o: plugin_mac80211.c parse-events.h | 123 | plugin_mac80211.o: plugin_mac80211.c parse-events.h trace-cmd.h |
115 | $(CC) -c $(CFLAGS) -fPIC -o $@ $< | 124 | $(CC) -c $(CFLAGS) -fPIC -o $@ $< |
116 | 125 | ||
117 | plugin_mac80211.so: plugin_mac80211.o | 126 | plugin_mac80211.so: plugin_mac80211.o |
diff --git a/parse-events.c b/parse-events.c index 53aad3e..406b28f 100644 --- a/parse-events.c +++ b/parse-events.c | |||
@@ -348,6 +348,27 @@ const char *pevent_find_function(struct pevent *pevent, unsigned long long addr) | |||
348 | } | 348 | } |
349 | 349 | ||
350 | /** | 350 | /** |
351 | * pevent_find_function_address - find a function address by a given address | ||
352 | * @pevent: handle for the pevent | ||
353 | * @addr: the address to find the function with | ||
354 | * | ||
355 | * Returns the address the function starts at. This can be used in | ||
356 | * conjunction with pevent_find_function to print both the function | ||
357 | * name and the function offset. | ||
358 | */ | ||
359 | unsigned long long | ||
360 | pevent_find_function_address(struct pevent *pevent, unsigned long long addr) | ||
361 | { | ||
362 | struct func_map *map; | ||
363 | |||
364 | map = find_func(pevent, addr); | ||
365 | if (!map) | ||
366 | return 0; | ||
367 | |||
368 | return map->addr; | ||
369 | } | ||
370 | |||
371 | /** | ||
351 | * pevent_register_function - register a function with a given address | 372 | * pevent_register_function - register a function with a given address |
352 | * @pevent: handle for the pevent | 373 | * @pevent: handle for the pevent |
353 | * @function: the function name to register | 374 | * @function: the function name to register |
@@ -3324,9 +3345,12 @@ const char *pevent_data_comm_from_pid(struct pevent *pevent, int pid) | |||
3324 | void pevent_event_info(struct trace_seq *s, struct event_format *event, | 3345 | void pevent_event_info(struct trace_seq *s, struct event_format *event, |
3325 | struct record *record) | 3346 | struct record *record) |
3326 | { | 3347 | { |
3348 | int print_pretty = 1; | ||
3349 | |||
3327 | if (event->handler) | 3350 | if (event->handler) |
3328 | event->handler(s, record, event); | 3351 | print_pretty = event->handler(s, record, event); |
3329 | else | 3352 | |
3353 | if (print_pretty) | ||
3330 | pretty_print(s, record->data, record->size, event); | 3354 | pretty_print(s, record->data, record->size, event); |
3331 | 3355 | ||
3332 | trace_seq_terminate(s); | 3356 | trace_seq_terminate(s); |
@@ -3342,6 +3366,7 @@ void pevent_print_event(struct pevent *pevent, struct trace_seq *s, | |||
3342 | const char *comm; | 3366 | const char *comm; |
3343 | void *data = record->data; | 3367 | void *data = record->data; |
3344 | int size = record->size; | 3368 | int size = record->size; |
3369 | int print_pretty = 1; | ||
3345 | int type; | 3370 | int type; |
3346 | int pid; | 3371 | int pid; |
3347 | int len; | 3372 | int len; |
@@ -3376,8 +3401,9 @@ void pevent_print_event(struct pevent *pevent, struct trace_seq *s, | |||
3376 | trace_seq_printf(s, "%.*s", 20 - len, spaces); | 3401 | trace_seq_printf(s, "%.*s", 20 - len, spaces); |
3377 | 3402 | ||
3378 | if (event->handler) | 3403 | if (event->handler) |
3379 | event->handler(s, record, event); | 3404 | print_pretty = event->handler(s, record, event); |
3380 | else | 3405 | |
3406 | if (print_pretty) | ||
3381 | pretty_print(s, data, size, event); | 3407 | pretty_print(s, data, size, event); |
3382 | 3408 | ||
3383 | trace_seq_terminate(s); | 3409 | trace_seq_terminate(s); |
diff --git a/parse-events.h b/parse-events.h index bfbba5c..e148e7f 100644 --- a/parse-events.h +++ b/parse-events.h | |||
@@ -366,6 +366,8 @@ struct format_field *pevent_find_field(struct event_format *event, const char *n | |||
366 | struct format_field *pevent_find_any_field(struct event_format *event, const char *name); | 366 | struct format_field *pevent_find_any_field(struct event_format *event, const char *name); |
367 | 367 | ||
368 | const char *pevent_find_function(struct pevent *pevent, unsigned long long addr); | 368 | const char *pevent_find_function(struct pevent *pevent, unsigned long long addr); |
369 | unsigned long long | ||
370 | pevent_find_function_address(struct pevent *pevent, unsigned long long addr); | ||
369 | unsigned long long pevent_read_number(struct pevent *pevent, const void *ptr, int size); | 371 | unsigned long long pevent_read_number(struct pevent *pevent, const void *ptr, int size); |
370 | int pevent_read_number_field(struct format_field *field, const void *data, | 372 | int pevent_read_number_field(struct format_field *field, const void *data, |
371 | unsigned long long *value); | 373 | unsigned long long *value); |
diff --git a/plugin_kmem.c b/plugin_kmem.c new file mode 100644 index 0000000..d707bf2 --- /dev/null +++ b/plugin_kmem.c | |||
@@ -0,0 +1,56 @@ | |||
1 | #include <stdio.h> | ||
2 | #include <stdlib.h> | ||
3 | #include <string.h> | ||
4 | |||
5 | #include "trace-cmd.h" | ||
6 | |||
7 | static int call_site_handler(struct trace_seq *s, struct record *record, | ||
8 | struct event_format *event) | ||
9 | { | ||
10 | struct format_field *field; | ||
11 | unsigned long long val, addr; | ||
12 | void *data = record->data; | ||
13 | const char *func; | ||
14 | |||
15 | field = pevent_find_field(event, "call_site"); | ||
16 | if (!field) | ||
17 | return 1; | ||
18 | |||
19 | if (pevent_read_number_field(field, data, &val)) | ||
20 | return 1; | ||
21 | |||
22 | func = pevent_find_function(event->pevent, val); | ||
23 | if (!func) | ||
24 | return 1; | ||
25 | addr = pevent_find_function_address(event->pevent, val); | ||
26 | |||
27 | trace_seq_printf(s, "(%s+0x%x) ", func, (int)(val - addr)); | ||
28 | |||
29 | return 1; | ||
30 | } | ||
31 | |||
32 | int PEVENT_PLUGIN_LOADER(struct pevent *pevent) | ||
33 | { | ||
34 | pevent_register_event_handler(pevent, -1, "kmem", "kfree", | ||
35 | call_site_handler); | ||
36 | |||
37 | pevent_register_event_handler(pevent, -1, "kmem", "kmalloc", | ||
38 | call_site_handler); | ||
39 | |||
40 | pevent_register_event_handler(pevent, -1, "kmem", "kmalloc_node", | ||
41 | call_site_handler); | ||
42 | |||
43 | pevent_register_event_handler(pevent, -1, "kmem", "kmem_cache_alloc", | ||
44 | call_site_handler); | ||
45 | |||
46 | pevent_register_event_handler(pevent, -1, "kmem", "kmem_cache_alloc_node", | ||
47 | call_site_handler); | ||
48 | |||
49 | pevent_register_event_handler(pevent, -1, "kmem", "kfree", | ||
50 | call_site_handler); | ||
51 | |||
52 | pevent_register_event_handler(pevent, -1, "kmem", "kmem_cache_free", | ||
53 | call_site_handler); | ||
54 | |||
55 | return 0; | ||
56 | } | ||
diff --git a/trace-ftrace.c b/trace-ftrace.c index 1b79ec7..8b0646b 100644 --- a/trace-ftrace.c +++ b/trace-ftrace.c | |||
@@ -229,7 +229,6 @@ fgraph_ent_handler(struct trace_seq *s, struct record *record, | |||
229 | void *data = record->data; | 229 | void *data = record->data; |
230 | int size = record->size; | 230 | int size = record->size; |
231 | int cpu = record->cpu; | 231 | int cpu = record->cpu; |
232 | int ret; | ||
233 | 232 | ||
234 | if (get_field_val(s, data, event, "common_pid", &pid)) | 233 | if (get_field_val(s, data, event, "common_pid", &pid)) |
235 | return trace_seq_putc(s, '!'); | 234 | return trace_seq_putc(s, '!'); |
@@ -257,15 +256,15 @@ fgraph_ent_handler(struct trace_seq *s, struct record *record, | |||
257 | * We also do a new peek on this CPU to update the | 256 | * We also do a new peek on this CPU to update the |
258 | * record cache. | 257 | * record cache. |
259 | */ | 258 | */ |
260 | ret = print_graph_entry_leaf(s, event, data, rec); | 259 | print_graph_entry_leaf(s, event, data, rec); |
261 | free_record(rec); | 260 | free_record(rec); |
262 | tracecmd_peek_data(tracecmd_curr_thread_handle, cpu); | 261 | tracecmd_peek_data(tracecmd_curr_thread_handle, cpu); |
263 | } else | 262 | } else |
264 | ret = print_graph_nested(s, event, data); | 263 | print_graph_nested(s, event, data); |
265 | 264 | ||
266 | free(data); | 265 | free(data); |
267 | 266 | ||
268 | return ret; | 267 | return 0; |
269 | } | 268 | } |
270 | 269 | ||
271 | static int | 270 | static int |
@@ -298,7 +297,9 @@ fgraph_ret_handler(struct trace_seq *s, struct record *record, | |||
298 | for (i = 0; i < (int)(depth * TRACE_GRAPH_INDENT); i++) | 297 | for (i = 0; i < (int)(depth * TRACE_GRAPH_INDENT); i++) |
299 | trace_seq_putc(s, ' '); | 298 | trace_seq_putc(s, ' '); |
300 | 299 | ||
301 | return trace_seq_putc(s, '}'); | 300 | trace_seq_putc(s, '}'); |
301 | |||
302 | return 0; | ||
302 | } | 303 | } |
303 | 304 | ||
304 | static int | 305 | static int |
@@ -309,16 +310,15 @@ trace_stack_handler(struct trace_seq *s, struct record *record, | |||
309 | unsigned long long addr; | 310 | unsigned long long addr; |
310 | const char *func; | 311 | const char *func; |
311 | void *data = record->data; | 312 | void *data = record->data; |
312 | int ret; | ||
313 | int i; | 313 | int i; |
314 | 314 | ||
315 | field = pevent_find_any_field(event, "caller"); | 315 | field = pevent_find_any_field(event, "caller"); |
316 | if (!field) { | 316 | if (!field) { |
317 | trace_seq_printf(s, "<CANT FIND FIELD %s>", "caller"); | 317 | trace_seq_printf(s, "<CANT FIND FIELD %s>", "caller"); |
318 | return -1; | 318 | return 0; |
319 | } | 319 | } |
320 | 320 | ||
321 | ret = trace_seq_puts(s, "<stack trace>\n"); | 321 | trace_seq_puts(s, "<stack trace>\n"); |
322 | 322 | ||
323 | for (i = 0; i < field->size; i += long_size) { | 323 | for (i = 0; i < field->size; i += long_size) { |
324 | addr = pevent_read_number(event->pevent, | 324 | addr = pevent_read_number(event->pevent, |
@@ -330,12 +330,12 @@ trace_stack_handler(struct trace_seq *s, struct record *record, | |||
330 | 330 | ||
331 | func = pevent_find_function(event->pevent, addr); | 331 | func = pevent_find_function(event->pevent, addr); |
332 | if (func) | 332 | if (func) |
333 | ret = trace_seq_printf(s, "=> %s (%llx)\n", func, addr); | 333 | trace_seq_printf(s, "=> %s (%llx)\n", func, addr); |
334 | else | 334 | else |
335 | ret = trace_seq_printf(s, "=> %llx\n", addr); | 335 | trace_seq_printf(s, "=> %llx\n", addr); |
336 | } | 336 | } |
337 | 337 | ||
338 | return ret; | 338 | return 0; |
339 | } | 339 | } |
340 | 340 | ||
341 | int tracecmd_ftrace_overrides(struct tracecmd_input *handle) | 341 | int tracecmd_ftrace_overrides(struct tracecmd_input *handle) |