diff options
| author | Steven Rostedt <srostedt@redhat.com> | 2009-12-31 17:16:18 -0500 |
|---|---|---|
| committer | Steven Rostedt <rostedt@goodmis.org> | 2009-12-31 17:20:52 -0500 |
| commit | 05e0559ecaff29d65a478e85addef12cf9d1a81b (patch) | |
| tree | 70a7d5751d197849a9c7a6fce15d7b8e09caa09d | |
| parent | 4fe3fea9f09815461b40427c3c68f9cd62ef538c (diff) | |
trace-cmd: Add plugin_kmem for showing function names of call sites
The kmem events only show a useless hex symbol for the call site name.
This adds a plugin to do a lookup of the function name and still
print the rest of the event format.
Also adds pevent_find_function_address() to let the plugin show the
offset into the function as well.
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
| -rw-r--r-- | Makefile | 18 | ||||
| -rw-r--r-- | parse-events.c | 21 | ||||
| -rw-r--r-- | parse-events.h | 2 | ||||
| -rw-r--r-- | plugin_kmem.c | 56 |
4 files changed, 92 insertions, 5 deletions
| @@ -9,8 +9,10 @@ LIBS = -L. -ltracecmd -ldl | |||
| 9 | %.o: %.c | 9 | %.o: %.c |
| 10 | $(CC) -c $(CFLAGS) $(EXT) $(INCLUDES) $< -o $@ | 10 | $(CC) -c $(CFLAGS) $(EXT) $(INCLUDES) $< -o $@ |
| 11 | 11 | ||
| 12 | TARGETS = libparsevent.a libtracecmd.a trace-cmd plugin_hrtimer.so plugin_mac80211.so \ | 12 | PLUGINS = plugin_hrtimer.so plugin_mac80211.so plugin_sched_switch.so \ |
| 13 | plugin_sched_switch.so | 13 | plugin_kmem.so |
| 14 | |||
| 15 | TARGETS = libparsevent.a libtracecmd.a trace-cmd $(PLUGINS) | ||
| 14 | 16 | ||
| 15 | all: $(TARGETS) | 17 | all: $(TARGETS) |
| 16 | 18 | ||
| @@ -65,19 +67,25 @@ libtracecmd.so: $(TCMD_LIB_OBJS) | |||
| 65 | libtracecmd.a: $(TCMD_LIB_OBJS) | 67 | libtracecmd.a: $(TCMD_LIB_OBJS) |
| 66 | $(RM) $@; $(AR) rcs $@ $^ | 68 | $(RM) $@; $(AR) rcs $@ $^ |
| 67 | 69 | ||
| 68 | plugin_hrtimer.o: plugin_hrtimer.c parse-events.h | 70 | plugin_hrtimer.o: plugin_hrtimer.c parse-events.h trace-cmd.h |
| 69 | $(CC) -c $(CFLAGS) -fPIC -o $@ $< | 71 | $(CC) -c $(CFLAGS) -fPIC -o $@ $< |
| 70 | 72 | ||
| 71 | plugin_hrtimer.so: plugin_hrtimer.o | 73 | plugin_hrtimer.so: plugin_hrtimer.o |
| 72 | $(CC) -shared -nostartfiles -o $@ $< | 74 | $(CC) -shared -nostartfiles -o $@ $< |
| 73 | 75 | ||
| 74 | plugin_sched_switch.o: plugin_sched_switch.c parse-events.h | 76 | plugin_kmem.o: plugin_kmem.c parse-events.h trace-cmd.h |
| 77 | $(CC) -c $(CFLAGS) -fPIC -o $@ $< | ||
| 78 | |||
| 79 | plugin_kmem.so: plugin_kmem.o | ||
| 80 | $(CC) -shared -nostartfiles -o $@ $< | ||
| 81 | |||
| 82 | plugin_sched_switch.o: plugin_sched_switch.c parse-events.h trace-cmd.h | ||
| 75 | $(CC) -c $(CFLAGS) -fPIC -o $@ $< | 83 | $(CC) -c $(CFLAGS) -fPIC -o $@ $< |
| 76 | 84 | ||
| 77 | plugin_sched_switch.so: plugin_sched_switch.o | 85 | plugin_sched_switch.so: plugin_sched_switch.o |
| 78 | $(CC) -shared -nostartfiles -o $@ $< | 86 | $(CC) -shared -nostartfiles -o $@ $< |
| 79 | 87 | ||
| 80 | plugin_mac80211.o: plugin_mac80211.c parse-events.h | 88 | plugin_mac80211.o: plugin_mac80211.c parse-events.h trace-cmd.h |
| 81 | $(CC) -c $(CFLAGS) -fPIC -o $@ $< | 89 | $(CC) -c $(CFLAGS) -fPIC -o $@ $< |
| 82 | 90 | ||
| 83 | plugin_mac80211.so: plugin_mac80211.o | 91 | plugin_mac80211.so: plugin_mac80211.o |
diff --git a/parse-events.c b/parse-events.c index d2d7e0a..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 |
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 | } | ||
