2 * eventdef.c - ktap eventdef parser
4 * This file is part of ktap by Jovi Zhangwei.
6 * Copyright (C) 2012-2013 Jovi Zhangwei <jovi.zhangwei@gmail.com>.
8 * ktap is free software; you can redistribute it and/or modify it
9 * under the terms and conditions of the GNU General Public License,
10 * version 2, as published by the Free Software Foundation.
12 * ktap is distributed in the hope it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17 * You should have received a copy of the GNU General Public License along with
18 * this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
29 #include "../include/ktap_types.h"
30 #include "../include/ktap_opcodes.h"
34 #define TRACING_EVENTS_DIR "/sys/kernel/debug/tracing/events"
37 static int idmap_size = 1024; /* set init size */
40 static int idmap_init(void)
42 idmap = malloc(idmap_size);
46 memset(idmap, 0, idmap_size);
50 static void idmap_free(void)
55 static inline int idmap_is_set(int id)
57 return idmap[id / 8] & (1 << (id % 8));
60 static void idmap_set(int id)
62 if (id >= idmap_size * 8) {
63 int newsize = id + 100; /* allocate extra 800 id */
64 idmap = realloc(idmap, newsize);
65 memset(idmap + idmap_size, 0, newsize - idmap_size);
69 if (!idmap_is_set(id))
72 idmap[id / 8] = idmap[id / 8] | (1 << (id % 8));
75 static void idmap_clear(int id)
78 idmap[id / 8] = idmap[id / 8] & ~ (1 << (id % 8));
81 static int idmap_get_max_id(void)
83 return idmap_size * 8;
86 static int *get_id_array()
91 id_array = malloc(sizeof(int) * id_nr);
95 for (i = 0; i < idmap_get_max_id(); i++) {
103 static int add_event(char *evtid_path)
108 fd = open(evtid_path, O_RDONLY);
111 * some tracepoint doesn't have id file, like ftrace,
112 * return success in here, and don't print error.
114 verbose_printf("warning: cannot open file %s\n", evtid_path);
118 if (read(fd, id_buf, sizeof(id_buf)) < 0) {
119 fprintf(stderr, "read file error %s\n", evtid_path);
132 static int add_tracepoint(char *sys_name, char *evt_name)
134 char evtid_path[PATH_MAX] = {0};
137 snprintf(evtid_path, PATH_MAX, "%s/%s/%s/id", TRACING_EVENTS_DIR,
139 return add_event(evtid_path);
142 static int add_tracepoint_multi_event(char *sys_name, char *evt_name)
144 char evt_path[PATH_MAX];
145 struct dirent *evt_ent;
149 snprintf(evt_path, PATH_MAX, "%s/%s", TRACING_EVENTS_DIR, sys_name);
150 evt_dir = opendir(evt_path);
152 perror("Can't open event dir");
156 while (!ret && (evt_ent = readdir(evt_dir))) {
157 if (!strcmp(evt_ent->d_name, ".")
158 || !strcmp(evt_ent->d_name, "..")
159 || !strcmp(evt_ent->d_name, "enable")
160 || !strcmp(evt_ent->d_name, "filter"))
163 if (!strglobmatch(evt_ent->d_name, evt_name))
166 ret = add_tracepoint(sys_name, evt_ent->d_name);
173 static int add_tracepoint_event(char *sys_name, char *evt_name)
175 return strpbrk(evt_name, "*?") ?
176 add_tracepoint_multi_event(sys_name, evt_name) :
177 add_tracepoint(sys_name, evt_name);
180 static int add_tracepoint_multi_sys(char *sys_name, char *evt_name)
182 struct dirent *events_ent;
186 events_dir = opendir(TRACING_EVENTS_DIR);
188 perror("Can't open event dir");
192 while (!ret && (events_ent = readdir(events_dir))) {
193 if (!strcmp(events_ent->d_name, ".")
194 || !strcmp(events_ent->d_name, "..")
195 || !strcmp(events_ent->d_name, "enable")
196 || !strcmp(events_ent->d_name, "header_event")
197 || !strcmp(events_ent->d_name, "header_page"))
200 if (!strglobmatch(events_ent->d_name, sys_name))
203 ret = add_tracepoint_event(events_ent->d_name,
207 closedir(events_dir);
211 static int parse_events_add_tracepoint(char *sys, char *event)
213 if (strpbrk(sys, "*?"))
214 return add_tracepoint_multi_sys(sys, event);
216 return add_tracepoint_event(sys, event);
225 struct probe_list *next;
230 static struct probe_list *probe_list_head; /* for cleanup resources */
233 * Some symbol format cannot write to uprobe_events in debugfs, like:
234 * symbol "check_one_fd.part.0" in glibc.
235 * For those symbols, we change the format, get rid of invalid chars,
236 * "check_one_fd.part.0" -> "check_one_fd"
238 * This function copy is_good_name function in linux/kernel/trace/trace_probe.h
240 static char *format_symbol_name(const char *old_symbol)
242 char *new_name = strdup(old_symbol);
243 char *name = new_name;
245 if (!isalpha(*name) && *name != '_')
248 while (*++name != '\0') {
249 if (!isalpha(*name) && !isdigit(*name) && *name != '_') {
255 /* this is a good name */
260 #define KPROBE_EVENTS_PATH "/sys/kernel/debug/tracing/kprobe_events"
263 * @return 0 on success, otherwise -1
266 write_kprobe_event(int fd, int ret_probe, const char *symbol, char *fetch_args)
268 char probe_event[128] = {0};
269 char event[64] = {0};
270 struct probe_list *pl;
271 char event_id_path[128] = {0};
275 /* In case some symbols cannot write to uprobe_events debugfs file */
276 symbol_name = format_symbol_name(symbol);
282 snprintf(event, 64, "ktap_kprobes_%d/ret_%s",
283 getpid(), symbol_name);
284 snprintf(probe_event, 128, "r:%s %s %s",
285 event, symbol, fetch_args);
287 snprintf(event, 64, "ktap_kprobes_%d/%s",
288 getpid(), symbol_name);
289 snprintf(probe_event, 128, "p:%s %s %s",
290 event, symbol, fetch_args);
293 sprintf(event_id_path, "/sys/kernel/debug/tracing/events/%s/id", event);
294 /* if event id already exist, then don't write to kprobes_event again */
295 id_fd = open(event_id_path, O_RDONLY);
299 /* remember add event id to ids_array */
300 ret = add_event(event_id_path);
307 verbose_printf("write kprobe event %s\n", probe_event);
309 if (write(fd, probe_event, strlen(probe_event)) <= 0) {
310 fprintf(stderr, "Cannot write %s to %s\n", probe_event,
315 /* add to cleanup list */
316 pl = malloc(sizeof(struct probe_list));
320 pl->type = KPROBE_EVENT;
321 pl->next = probe_list_head;
322 memcpy(pl->event, event, 64);
323 probe_list_head = pl;
325 ret = add_event(event_id_path);
338 static unsigned long core_kernel_text_start;
339 static unsigned long core_kernel_text_end;
340 static unsigned long kprobes_text_start;
341 static unsigned long kprobes_text_end;
343 static void init_kprobe_prohibited_area(void)
352 core_kernel_text_start = find_kernel_symbol("_stext");
353 core_kernel_text_end = find_kernel_symbol("_etext");
354 kprobes_text_start = find_kernel_symbol("__kprobes_text_start");
355 kprobes_text_end = find_kernel_symbol("__kprobes_text_end");
358 static int check_kprobe_addr_prohibited(unsigned long addr)
360 if (addr <= core_kernel_text_start || addr >= core_kernel_text_end)
363 if (addr >= kprobes_text_start && addr <= kprobes_text_end)
369 struct probe_cb_base {
378 static int kprobe_symbol_actor(void *arg, const char *name, char type,
381 struct probe_cb_base *base = (struct probe_cb_base *)arg;
383 /* only can probe text function */
384 if (type != 't' && type != 'T')
387 if (!strglobmatch(name, base->symbol))
390 if (check_kprobe_addr_prohibited(start))
393 return write_kprobe_event(base->fd, base->ret_probe, name,
397 static int parse_events_add_kprobe(char *event)
400 struct probe_cb_base base;
403 fd = open(KPROBE_EVENTS_PATH, O_WRONLY);
405 fprintf(stderr, "Cannot open %s\n", KPROBE_EVENTS_PATH);
409 end = strpbrk(event, "% ");
411 symbol = strndup(event, end - event);
413 symbol = strdup(event);
416 base.ret_probe = !!strstr(event, "%return");
417 base.symbol = symbol;
418 base.fetch_args = strchr(event, ' ');
420 init_kprobe_prohibited_area();
422 ret = kallsyms_parse(&base, kprobe_symbol_actor);
424 fprintf(stderr, "cannot parse symbol \"%s\"\n", symbol);
432 #define UPROBE_EVENTS_PATH "/sys/kernel/debug/tracing/uprobe_events"
435 * @return 0 on success, otherwise -1
438 write_uprobe_event(int fd, int ret_probe, const char *binary,
439 const char *symbol, unsigned long addr,
442 char probe_event[128] = {0};
443 char event[64] = {0};
444 struct probe_list *pl;
445 char event_id_path[128] = {0};
449 /* In case some symbols cannot write to uprobe_events debugfs file */
450 symbol_name = format_symbol_name(symbol);
456 snprintf(event, 64, "ktap_uprobes_%d/ret_%s",
457 getpid(), symbol_name);
458 snprintf(probe_event, 128, "r:%s %s:0x%lx %s",
459 event, binary, addr, fetch_args);
461 snprintf(event, 64, "ktap_uprobes_%d/%s",
462 getpid(), symbol_name);
463 snprintf(probe_event, 128, "p:%s %s:0x%lx %s",
464 event, binary, addr, fetch_args);
467 sprintf(event_id_path, "/sys/kernel/debug/tracing/events/%s/id", event);
468 /* if event id already exist, then don't write to uprobes_event again */
469 id_fd = open(event_id_path, O_RDONLY);
473 /* remember add event id to ids_array */
474 ret = add_event(event_id_path);
481 verbose_printf("write uprobe event %s\n", probe_event);
483 if (write(fd, probe_event, strlen(probe_event)) <= 0) {
484 fprintf(stderr, "Cannot write %s to %s\n", probe_event,
489 /* add to cleanup list */
490 pl = malloc(sizeof(struct probe_list));
494 pl->type = UPROBE_EVENT;
495 pl->next = probe_list_head;
496 memcpy(pl->event, event, 64);
497 probe_list_head = pl;
499 ret = add_event(event_id_path);
513 * TODO: avoid copy-paste stuff
515 * @return 1 on success, otherwise 0
518 static int parse_events_resolve_symbol(int fd, char *event, int type)
520 char *colon, *binary, *fetch_args;
521 unsigned long symbol_address;
523 colon = strchr(event, ':');
527 symbol_address = strtol(colon + 1 /* skip ":" */, NULL, 0);
529 fetch_args = strchr(event, ' ');
532 * We already have address, no need in resolving.
534 if (symbol_address) {
537 binary = strndup(event, colon - event);
538 ret = write_uprobe_event(fd, !!strstr(event, "%return"), binary,
539 "NULL", symbol_address, fetch_args);
544 fprintf(stderr, "error: cannot resolve event \"%s\" without libelf, "
545 "please recompile ktap with NO_LIBELF disabled\n",
552 static int uprobe_symbol_actor(const char *name, vaddr_t addr, void *arg)
554 struct probe_cb_base *base = (struct probe_cb_base *)arg;
557 if (!strglobmatch(name, base->symbol))
560 verbose_printf("uprobe: binary: \"%s\" symbol \"%s\" "
561 "resolved to 0x%lx\n",
562 base->binary, base->symbol, addr);
564 ret = write_uprobe_event(base->fd, base->ret_probe, base->binary,
565 name, addr, base->fetch_args);
572 static int parse_events_resolve_symbol(int fd, char *event, int type)
575 vaddr_t symbol_address;
577 struct probe_cb_base base = {
582 colon = strchr(event, ':');
586 base.ret_probe = !!strstr(event, "%return");
587 symbol_address = strtol(colon + 1 /* skip ":" */, NULL, 0);
588 base.binary = strndup(event, colon - event);
590 base.fetch_args = strchr(event, ' ');
593 * We already have address, no need in resolving.
595 if (symbol_address) {
597 ret = write_uprobe_event(fd, base.ret_probe, base.binary,
598 "NULL", symbol_address,
604 end = strpbrk(event, "% ");
606 base.symbol = strndup(colon + 1, end - 1 - colon);
608 base.symbol = strdup(colon + 1);
610 ret = parse_dso_symbols(base.binary, type, uprobe_symbol_actor,
613 fprintf(stderr, "error: cannot find symbol %s in binary %s\n",
614 base.symbol, base.binary);
617 /* no error found when parse symbols */
628 static int parse_events_add_uprobe(char *old_event, int type)
633 fd = open(UPROBE_EVENTS_PATH, O_WRONLY);
635 fprintf(stderr, "Cannot open %s\n", UPROBE_EVENTS_PATH);
639 ret = parse_events_resolve_symbol(fd, old_event, type);
645 static int parse_events_add_probe(char *old_event)
649 separator = strchr(old_event, ':');
650 if (!separator || (separator == old_event))
651 return parse_events_add_kprobe(old_event);
653 return parse_events_add_uprobe(old_event, FIND_SYMBOL);
656 static int parse_events_add_sdt(char *old_event)
658 return parse_events_add_uprobe(old_event, FIND_STAPSDT_NOTE);
661 static void strim(char *s)
671 while (end >= s && isspace(*end))
677 static int get_sys_event_filter_str(char *start,
678 char **sys, char **event, char **filter)
680 char *separator, *separator2, *ptr, *end;
682 while (*start == ' ')
686 separator = strchr(start, ':');
687 if (!separator || (separator == start)) {
691 ptr = malloc(separator - start + 1);
695 strncpy(ptr, start, separator - start);
696 ptr[separator - start] = '\0';
701 if (!strcmp(*sys, "probe") && (*(separator + 1) == '/')) {
702 /* it's uprobe event */
703 separator2 = strchr(separator + 1, ':');
707 separator2 = separator;
710 end = start + strlen(start);
711 while (*--end == ' ') {
717 filter_start = strchr(separator2, '/');
718 if (filter_start == end)
721 ptr = malloc(end - filter_start + 2);
725 memcpy(ptr, filter_start, end - filter_start + 1);
726 ptr[end - filter_start + 1] = '\0';
737 ptr = malloc(end - separator);
741 memcpy(ptr, separator + 1, end - separator - 1);
742 ptr[end - separator - 1] = '\0';
750 static char *get_next_eventdef(char *str)
754 separator = strchr(str, ',');
756 return str + strlen(str);
759 return separator + 1;
762 ktap_eventdef_info *ktapc_parse_eventdef(const char *eventdef)
764 char *str = strdup(eventdef);
765 char *sys, *event, *filter, *next;
766 ktap_eventdef_info *evdef_info;
772 next = get_next_eventdef(str);
774 if (get_sys_event_filter_str(str, &sys, &event, &filter))
777 verbose_printf("parse_eventdef: sys[%s], event[%s], filter[%s]\n",
780 if (!strcmp(sys, "probe"))
781 ret = parse_events_add_probe(event);
782 else if (!strcmp(sys, "sdt"))
783 ret = parse_events_add_sdt(event);
785 ret = parse_events_add_tracepoint(sys, event);
790 /* don't trace ftrace:function when all tracepoints enabled */
791 if (!strcmp(sys, "*"))
795 if (filter && *next != '\0') {
796 fprintf(stderr, "Error: eventdef only can append one filter\n");
802 goto parse_next_eventdef;
804 evdef_info = malloc(sizeof(*evdef_info));
808 evdef_info->nr = id_nr;
809 evdef_info->id_arr = get_id_array();
810 evdef_info->filter = filter;
816 cleanup_event_resources();
820 void cleanup_event_resources(void)
822 struct probe_list *pl;
824 char probe_event[128] = {0};
827 for (pl = probe_list_head; pl; pl = pl->next) {
828 if (pl->type == KPROBE_EVENT)
829 path = KPROBE_EVENTS_PATH;
830 else if (pl->type == UPROBE_EVENT)
831 path = UPROBE_EVENTS_PATH;
833 fprintf(stderr, "Cannot cleanup event type %d\n",
838 snprintf(probe_event, 128, "-:%s", pl->event);
840 fd = open(path, O_WRONLY);
842 fprintf(stderr, "Cannot open %s\n", UPROBE_EVENTS_PATH);
846 ret = write(fd, probe_event, strlen(probe_event));
848 fprintf(stderr, "Cannot write %s to %s\n", probe_event,