diff options
Diffstat (limited to 'tools/perf/util/probe-event.c')
| -rw-r--r-- | tools/perf/util/probe-event.c | 401 |
1 files changed, 224 insertions, 177 deletions
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index 0c24bc7afbca..710e4620923e 100644 --- a/tools/perf/util/probe-event.c +++ b/tools/perf/util/probe-event.c @@ -11,6 +11,7 @@ #include <sys/stat.h> #include <fcntl.h> #include <errno.h> +#include <libgen.h> #include <stdio.h> #include <unistd.h> #include <stdlib.h> @@ -39,6 +40,7 @@ #include "session.h" #include "string2.h" #include "strbuf.h" +#include "parse-events.h" #include <subcmd/pager.h> #include <linux/ctype.h> @@ -50,9 +52,14 @@ #define PERFPROBE_GROUP "probe" +/* Defined in kernel/trace/trace.h */ +#define MAX_EVENT_NAME_LEN 64 + bool probe_event_dry_run; /* Dry run flag */ struct probe_conf probe_conf = { .magic_num = DEFAULT_PROBE_MAGIC_NUM }; +static char *synthesize_perf_probe_point(struct perf_probe_point *pp); + #define semantic_error(msg ...) pr_err("Semantic error :" msg) int e_snprintf(char *str, size_t size, const char *format, ...) @@ -68,13 +75,14 @@ int e_snprintf(char *str, size_t size, const char *format, ...) } static struct machine *host_machine; +static struct perf_env host_env; /* Initialize symbol maps and path of vmlinux/modules */ int init_probe_symbol_maps(bool user_only) { int ret; - symbol_conf.sort_by_name = true; + perf_env__init(&host_env); symbol_conf.allow_aliases = true; ret = symbol__init(NULL); if (ret < 0) { @@ -88,7 +96,7 @@ int init_probe_symbol_maps(bool user_only) if (symbol_conf.vmlinux_name) pr_debug("Use vmlinux: %s\n", symbol_conf.vmlinux_name); - host_machine = machine__new_host(); + host_machine = machine__new_host(&host_env); if (!host_machine) { pr_debug("machine__new_host() failed.\n"); symbol__exit(); @@ -105,6 +113,7 @@ void exit_probe_symbol_maps(void) machine__delete(host_machine); host_machine = NULL; symbol__exit(); + perf_env__exit(&host_env); } static struct ref_reloc_sym *kernel_get_ref_reloc_sym(struct map **pmap) @@ -135,42 +144,59 @@ static int kernel_get_symbol_address_by_name(const char *name, u64 *addr, /* ref_reloc_sym is just a label. Need a special fix*/ reloc_sym = kernel_get_ref_reloc_sym(&map); if (reloc_sym && strcmp(name, reloc_sym->name) == 0) - *addr = (!map->reloc || reloc) ? reloc_sym->addr : + *addr = (!map__reloc(map) || reloc) ? reloc_sym->addr : reloc_sym->unrelocated_addr; else { sym = machine__find_kernel_symbol_by_name(host_machine, name, &map); if (!sym) return -ENOENT; - *addr = map->unmap_ip(map, sym->start) - - ((reloc) ? 0 : map->reloc) - - ((reladdr) ? map->start : 0); + *addr = map__unmap_ip(map, sym->start) - + ((reloc) ? 0 : map__reloc(map)) - + ((reladdr) ? map__start(map) : 0); + } + return 0; +} + +struct kernel_get_module_map_cb_args { + const char *module; + struct map *result; +}; + +static int kernel_get_module_map_cb(struct map *map, void *data) +{ + struct kernel_get_module_map_cb_args *args = data; + struct dso *dso = map__dso(map); + const char *short_name = dso__short_name(dso); + u16 short_name_len = dso__short_name_len(dso); + + if (strncmp(short_name + 1, args->module, short_name_len - 2) == 0 && + args->module[short_name_len - 2] == '\0') { + args->result = map__get(map); + return 1; } return 0; } static struct map *kernel_get_module_map(const char *module) { - struct maps *maps = machine__kernel_maps(host_machine); - struct map *pos; + struct kernel_get_module_map_cb_args args = { + .module = module, + .result = NULL, + }; /* A file path -- this is an offline module */ if (module && strchr(module, '/')) return dso__new_map(module); if (!module) { - pos = machine__kernel_map(host_machine); - return map__get(pos); - } + struct map *map = machine__kernel_map(host_machine); - maps__for_each_entry(maps, pos) { - /* short_name is "[module]" */ - if (strncmp(pos->dso->short_name + 1, module, - pos->dso->short_name_len - 2) == 0 && - module[pos->dso->short_name_len - 2] == '\0') { - return map__get(pos); - } + return map__get(map); } - return NULL; + + maps__for_each_map(machine__kernel_maps(host_machine), kernel_get_module_map_cb, &args); + + return args.result; } struct map *get_target_map(const char *target, struct nsinfo *nsi, bool user) @@ -178,13 +204,14 @@ struct map *get_target_map(const char *target, struct nsinfo *nsi, bool user) /* Init maps of given executable or kernel */ if (user) { struct map *map; + struct dso *dso; map = dso__new_map(target); - if (map && map->dso) { - mutex_lock(&map->dso->lock); - nsinfo__put(map->dso->nsinfo); - map->dso->nsinfo = nsinfo__get(nsi); - mutex_unlock(&map->dso->lock); + dso = map ? map__dso(map) : NULL; + if (dso) { + mutex_lock(dso__lock(dso)); + dso__set_nsinfo(dso, nsinfo__get(nsi)); + mutex_unlock(dso__lock(dso)); } return map; } else { @@ -215,7 +242,7 @@ static int convert_exec_to_group(const char *exec, char **result) } } - ret = e_snprintf(buf, 64, "%s_%s", PERFPROBE_GROUP, ptr1); + ret = e_snprintf(buf, sizeof(buf), "%s_%s", PERFPROBE_GROUP, ptr1); if (ret < 0) goto out; @@ -250,7 +277,7 @@ static bool kprobe_warn_out_range(const char *symbol, u64 address) map = kernel_get_module_map(NULL); if (map) { - ret = address <= map->start || map->end < address; + ret = address <= map__start(map) || map__end(map) < address; if (ret) pr_warning("%s is out of .text, skip it.\n", symbol); map__put(map); @@ -322,7 +349,7 @@ elf_err: return mod_name; } -#ifdef HAVE_DWARF_SUPPORT +#ifdef HAVE_LIBDW_SUPPORT static int kernel_get_module_dso(const char *module, struct dso **pdso) { @@ -337,7 +364,8 @@ static int kernel_get_module_dso(const char *module, struct dso **pdso) snprintf(module_name, sizeof(module_name), "[%s]", module); map = maps__find_by_name(machine__kernel_maps(host_machine), module_name); if (map) { - dso = map->dso; + dso = map__dso(map); + map__put(map); goto found; } pr_debug("Failed to find module %s.\n", module); @@ -345,12 +373,12 @@ static int kernel_get_module_dso(const char *module, struct dso **pdso) } map = machine__kernel_map(host_machine); - dso = map->dso; - if (!dso->has_build_id) + dso = map__dso(map); + if (!dso__has_build_id(dso)) dso__read_running_kernel_build_id(dso, host_machine); vmlinux_name = symbol_conf.vmlinux_name; - dso->load_errno = 0; + *dso__load_errno(dso) = 0; if (vmlinux_name) ret = dso__load_vmlinux(dso, map, vmlinux_name, false); else @@ -375,6 +403,7 @@ static int find_alternative_probe_point(struct debuginfo *dinfo, struct symbol *sym; u64 address = 0; int ret = -ENOENT; + size_t idx; /* This can work only for function-name based one */ if (!pp->function || pp->file) @@ -385,7 +414,7 @@ static int find_alternative_probe_point(struct debuginfo *dinfo, return -EINVAL; /* Find the address of given function */ - map__for_each_symbol_by_name(map, pp->function, sym) { + map__for_each_symbol_by_name(map, pp->function, sym, idx) { if (uprobes) { address = sym->start; if (sym->type == STT_GNU_IFUNC) @@ -393,7 +422,7 @@ static int find_alternative_probe_point(struct debuginfo *dinfo, "Consider identifying the final function used at run time and set the probe directly on that.\n", pp->function); } else - address = map->unmap_ip(map, sym->start) - map->reloc; + address = map__unmap_ip(map, sym->start) - map__reloc(map); break; } if (!address) { @@ -476,7 +505,7 @@ static struct debuginfo *open_from_debuginfod(struct dso *dso, struct nsinfo *ns if (!c) return NULL; - build_id__sprintf(&dso->bid, sbuild_id); + build_id__snprintf(dso__bid(dso), sbuild_id, sizeof(sbuild_id)); fd = debuginfod_find_debuginfo(c, (const unsigned char *)sbuild_id, 0, &path); if (fd >= 0) @@ -519,7 +548,7 @@ static struct debuginfo *open_debuginfo(const char *module, struct nsinfo *nsi, if (!module || !strchr(module, '/')) { err = kernel_get_module_dso(module, &dso); if (err < 0) { - if (!dso || dso->load_errno == 0) { + if (!dso || *dso__load_errno(dso) == 0) { if (!str_error_r(-err, reason, STRERR_BUFSIZE)) strcpy(reason, "(unknown)"); } else @@ -536,7 +565,7 @@ static struct debuginfo *open_debuginfo(const char *module, struct nsinfo *nsi, } return NULL; } - path = dso->long_name; + path = dso__long_name(dso); } nsinfo__mountns_enter(nsi, &nsc); ret = debuginfo__new(path); @@ -859,7 +888,7 @@ post_process_kernel_probe_trace_events(struct probe_trace_event *tevs, free(tevs[i].point.symbol); tevs[i].point.symbol = tmp; tevs[i].point.offset = tevs[i].point.address - - (map->reloc ? reloc_sym->unrelocated_addr : + (map__reloc(map) ? reloc_sym->unrelocated_addr : reloc_sym->addr); } return skipped; @@ -917,7 +946,7 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev, dinfo = open_debuginfo(pev->target, pev->nsi, !need_dwarf); if (!dinfo) { if (need_dwarf) - return -ENOENT; + return -ENODATA; pr_debug("Could not open debuginfo. Try to use symbols.\n"); return 0; } @@ -954,9 +983,10 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev, debuginfo__delete(dinfo); if (ntevs == 0) { /* No error but failed to find probe point. */ - pr_warning("Probe point '%s' not found.\n", - synthesize_perf_probe_point(&pev->point)); - return -ENOENT; + char *probe_point = synthesize_perf_probe_point(&pev->point); + pr_warning("Probe point '%s' not found.\n", probe_point); + free(probe_point); + return -ENODEV; } else if (ntevs < 0) { /* Error path : ntevs < 0 */ pr_debug("An error occurred in debuginfo analysis (%d).\n", ntevs); @@ -1013,6 +1043,17 @@ static int _show_one_line(FILE *fp, int l, bool skip, bool show_num) return rv; } +static int sprint_line_description(char *sbuf, size_t size, struct line_range *lr) +{ + if (!lr->function) + return snprintf(sbuf, size, "file: %s, line: %d", lr->file, lr->start); + + if (lr->file) + return snprintf(sbuf, size, "function: %s, file:%s, line: %d", lr->function, lr->file, lr->start); + + return snprintf(sbuf, size, "function: %s, line:%d", lr->function, lr->start); +} + #define show_one_line_with_num(f,l) _show_one_line(f,l,false,true) #define show_one_line(f,l) _show_one_line(f,l,false,false) #define skip_one_line(f,l) _show_one_line(f,l,true,false) @@ -1025,7 +1066,6 @@ static int _show_one_line(FILE *fp, int l, bool skip, bool show_num) static int __show_line_range(struct line_range *lr, const char *module, bool user) { - struct build_id bid; int l = 1; struct int_node *ln; struct debuginfo *dinfo; @@ -1042,17 +1082,23 @@ static int __show_line_range(struct line_range *lr, const char *module, ret = debuginfo__find_line_range(dinfo, lr); if (!ret) { /* Not found, retry with an alternative */ + pr_debug2("Failed to find line range in debuginfo. Fallback to alternative\n"); ret = get_alternative_line_range(dinfo, lr, module, user); if (!ret) ret = debuginfo__find_line_range(dinfo, lr); + else /* Ignore error, we just failed to find it. */ + ret = -ENOENT; } if (dinfo->build_id) { + struct build_id bid; + build_id__init(&bid, dinfo->build_id, BUILD_ID_SIZE); - build_id__sprintf(&bid, sbuild_id); + build_id__snprintf(&bid, sbuild_id, sizeof(sbuild_id)); } debuginfo__delete(dinfo); if (ret == 0 || ret == -ENOENT) { - pr_warning("Specified source line is not found.\n"); + sprint_line_description(sbuf, sizeof(sbuf), lr); + pr_warning("Specified source line(%s) is not found.\n", sbuf); return -ENOENT; } else if (ret < 0) { pr_warning("Debuginfo analysis failed.\n"); @@ -1227,7 +1273,7 @@ out: return ret; } -#else /* !HAVE_DWARF_SUPPORT */ +#else /* !HAVE_LIBDW_SUPPORT */ static void debuginfo_cache__exit(void) { @@ -1320,32 +1366,41 @@ static bool is_c_func_name(const char *name) * * SRC[:SLN[+NUM|-ELN]] * FNC[@SRC][:SLN[+NUM|-ELN]] + * + * FNC@SRC accepts `FNC@*` which forcibly specify FNC as function name. + * SRC and FUNC can be quoted by double/single quotes. */ int parse_line_range_desc(const char *arg, struct line_range *lr) { - char *range, *file, *name = strdup(arg); - int err; + char *buf = strdup(arg); + char *p; + int err = 0; - if (!name) + if (!buf) return -ENOMEM; lr->start = 0; lr->end = INT_MAX; - range = strchr(name, ':'); - if (range) { - *range++ = '\0'; + p = strpbrk_esq(buf, ":"); + if (p) { + if (p == buf) { + semantic_error("No file/function name in '%s'.\n", p); + err = -EINVAL; + goto out; + } + *(p++) = '\0'; - err = parse_line_num(&range, &lr->start, "start line"); + err = parse_line_num(&p, &lr->start, "start line"); if (err) - goto err; + goto out; - if (*range == '+' || *range == '-') { - const char c = *range++; + if (*p == '+' || *p == '-') { + const char c = *(p++); - err = parse_line_num(&range, &lr->end, "end line"); + err = parse_line_num(&p, &lr->end, "end line"); if (err) - goto err; + goto out; if (c == '+') { lr->end += lr->start; @@ -1365,36 +1420,43 @@ int parse_line_range_desc(const char *arg, struct line_range *lr) if (lr->start > lr->end) { semantic_error("Start line must be smaller" " than end line.\n"); - goto err; + goto out; } - if (*range != '\0') { - semantic_error("Tailing with invalid str '%s'.\n", range); - goto err; + if (*p != '\0') { + semantic_error("Tailing with invalid str '%s'.\n", p); + goto out; } } - file = strchr(name, '@'); - if (file) { - *file = '\0'; - lr->file = strdup(++file); - if (lr->file == NULL) { - err = -ENOMEM; - goto err; + p = strpbrk_esq(buf, "@"); + if (p) { + *p++ = '\0'; + if (strcmp(p, "*")) { + lr->file = strdup_esq(p); + if (lr->file == NULL) { + err = -ENOMEM; + goto out; + } + } + if (*buf != '\0') + lr->function = strdup_esq(buf); + if (!lr->function && !lr->file) { + semantic_error("Only '@*' is not allowed.\n"); + err = -EINVAL; + goto out; } - lr->function = name; - } else if (strchr(name, '/') || strchr(name, '.')) - lr->file = name; - else if (is_c_func_name(name))/* We reuse it for checking funcname */ - lr->function = name; + } else if (strpbrk_esq(buf, "/.")) + lr->file = strdup_esq(buf); + else if (is_c_func_name(buf))/* We reuse it for checking funcname */ + lr->function = strdup_esq(buf); else { /* Invalid name */ - semantic_error("'%s' is not a valid function name.\n", name); + semantic_error("'%s' is not a valid function name.\n", buf); err = -EINVAL; - goto err; + goto out; } - return 0; -err: - free(name); +out: + free(buf); return err; } @@ -1402,19 +1464,19 @@ static int parse_perf_probe_event_name(char **arg, struct perf_probe_event *pev) { char *ptr; - ptr = strpbrk_esc(*arg, ":"); + ptr = strpbrk_esq(*arg, ":"); if (ptr) { *ptr = '\0'; if (!pev->sdt && !is_c_func_name(*arg)) goto ng_name; - pev->group = strdup_esc(*arg); + pev->group = strdup_esq(*arg); if (!pev->group) return -ENOMEM; *arg = ptr + 1; } else pev->group = NULL; - pev->event = strdup_esc(*arg); + pev->event = strdup_esq(*arg); if (pev->event == NULL) return -ENOMEM; @@ -1453,7 +1515,7 @@ static int parse_perf_probe_point(char *arg, struct perf_probe_event *pev) arg++; } - ptr = strpbrk_esc(arg, ";=@+%"); + ptr = strpbrk_esq(arg, ";=@+%"); if (pev->sdt) { if (ptr) { if (*ptr != '@') { @@ -1467,7 +1529,7 @@ static int parse_perf_probe_point(char *arg, struct perf_probe_event *pev) pev->target = build_id_cache__origname(tmp); free(tmp); } else - pev->target = strdup_esc(ptr + 1); + pev->target = strdup_esq(ptr + 1); if (!pev->target) return -ENOMEM; *ptr = '\0'; @@ -1508,7 +1570,7 @@ static int parse_perf_probe_point(char *arg, struct perf_probe_event *pev) file_spec = true; } - ptr = strpbrk_esc(arg, ";:+@%"); + ptr = strpbrk_esq(arg, ";:+@%"); if (ptr) { nc = *ptr; *ptr++ = '\0'; @@ -1517,7 +1579,7 @@ static int parse_perf_probe_point(char *arg, struct perf_probe_event *pev) if (arg[0] == '\0') tmp = NULL; else { - tmp = strdup_esc(arg); + tmp = strdup_esq(arg); if (tmp == NULL) return -ENOMEM; } @@ -1555,7 +1617,7 @@ static int parse_perf_probe_point(char *arg, struct perf_probe_event *pev) return -ENOMEM; break; } - ptr = strpbrk_esc(arg, ";:+@%"); + ptr = strpbrk_esq(arg, ";:+@%"); if (ptr) { nc = *ptr; *ptr++ = '\0'; @@ -1582,7 +1644,9 @@ static int parse_perf_probe_point(char *arg, struct perf_probe_event *pev) semantic_error("SRC@SRC is not allowed.\n"); return -EINVAL; } - pp->file = strdup_esc(arg); + if (!strcmp(arg, "*")) + break; + pp->file = strdup_esq(arg); if (pp->file == NULL) return -ENOMEM; break; @@ -2002,7 +2066,7 @@ out: } /* Compose only probe point (not argument) */ -char *synthesize_perf_probe_point(struct perf_probe_point *pp) +static char *synthesize_perf_probe_point(struct perf_probe_point *pp) { struct strbuf buf; char *tmp, *ret = NULL; @@ -2055,14 +2119,18 @@ char *synthesize_perf_probe_command(struct perf_probe_event *pev) goto out; tmp = synthesize_perf_probe_point(&pev->point); - if (!tmp || strbuf_addstr(&buf, tmp) < 0) + if (!tmp || strbuf_addstr(&buf, tmp) < 0) { + free(tmp); goto out; + } free(tmp); for (i = 0; i < pev->nargs; i++) { tmp = synthesize_perf_probe_arg(pev->args + i); - if (!tmp || strbuf_addf(&buf, " %s", tmp) < 0) + if (!tmp || strbuf_addf(&buf, " %s", tmp) < 0) { + free(tmp); goto out; + } free(tmp); } @@ -2242,14 +2310,12 @@ static int find_perf_probe_point_from_map(struct probe_trace_point *tp, goto out; pp->retprobe = tp->retprobe; - pp->offset = addr - map->unmap_ip(map, sym->start); + pp->offset = addr - map__unmap_ip(map, sym->start); pp->function = strdup(sym->name); ret = pp->function ? 0 : -ENOMEM; out: - if (map && !is_kprobe) { - map__put(map); - } + map__put(map); return ret; } @@ -2353,6 +2419,7 @@ void clear_perf_probe_event(struct perf_probe_event *pev) } pev->nargs = 0; zfree(&pev->args); + nsinfo__zput(pev->nsi); } #define strdup_or_goto(str, label) \ @@ -2713,7 +2780,7 @@ int show_perf_probe_events(struct strfilter *filter) static int get_new_event_name(char *buf, size_t len, const char *base, struct strlist *namelist, bool ret_event, - bool allow_suffix) + bool allow_suffix, bool not_C_symname) { int i, ret; char *p, *nbase; @@ -2724,15 +2791,32 @@ static int get_new_event_name(char *buf, size_t len, const char *base, if (!nbase) return -ENOMEM; - /* Cut off the dot suffixes (e.g. .const, .isra) and version suffixes */ - p = strpbrk(nbase, ".@"); - if (p && p != nbase) - *p = '\0'; + if (not_C_symname) { + /* Replace non-alnum with '_' */ + char *s, *d; + + s = d = nbase; + do { + if (*s && !isalnum(*s)) { + if (d != nbase && *(d - 1) != '_') + *d++ = '_'; + } else + *d++ = *s; + } while (*s++); + } else { + /* Cut off the dot suffixes (e.g. .const, .isra) and version suffixes */ + p = strpbrk(nbase, ".@"); + if (p && p != nbase) + *p = '\0'; + } /* Try no suffix number */ ret = e_snprintf(buf, len, "%s%s", nbase, ret_event ? "__return" : ""); if (ret < 0) { - pr_debug("snprintf() failed: %d\n", ret); + pr_warning("snprintf() failed: %d; the event name '%s' is too long\n" + " Hint: Set a shorter event with syntax \"EVENT=PROBEDEF\"\n" + " EVENT: Event name (max length: %d bytes).\n", + ret, nbase, MAX_EVENT_NAME_LEN); goto out; } if (!strlist__has_entry(namelist, buf)) @@ -2752,7 +2836,10 @@ static int get_new_event_name(char *buf, size_t len, const char *base, for (i = 1; i < MAX_EVENT_INDEX; i++) { ret = e_snprintf(buf, len, "%s_%d", nbase, i); if (ret < 0) { - pr_debug("snprintf() failed: %d\n", ret); + pr_warning("Add suffix failed: %d; the event name '%s' is too long\n" + " Hint: Set a shorter event with syntax \"EVENT=PROBEDEF\"\n" + " EVENT: Event name (max length: %d bytes).\n", + ret, nbase, MAX_EVENT_NAME_LEN); goto out; } if (!strlist__has_entry(namelist, buf)) @@ -2793,13 +2880,18 @@ static void warn_uprobe_event_compat(struct probe_trace_event *tev) if (!tev->uprobes || tev->nargs == 0 || !buf) goto out; - for (i = 0; i < tev->nargs; i++) - if (strglobmatch(tev->args[i].value, "[$@+-]*")) { - pr_warning("Please upgrade your kernel to at least " - "3.14 to have access to feature %s\n", + for (i = 0; i < tev->nargs; i++) { + if (strchr(tev->args[i].value, '@')) { + pr_warning("%s accesses a variable by symbol name, but that is not supported for user application probe.\n", tev->args[i].value); break; } + if (strglobmatch(tev->args[i].value, "[$+-]*")) { + pr_warning("Please upgrade your kernel to at least 3.14 to have access to feature %s\n", + tev->args[i].value); + break; + } + } out: free(buf); } @@ -2811,7 +2903,8 @@ static int probe_trace_event__set_name(struct probe_trace_event *tev, bool allow_suffix) { const char *event, *group; - char buf[64]; + bool not_C_symname = true; + char buf[MAX_EVENT_NAME_LEN]; int ret; /* If probe_event or trace_event already have the name, reuse it */ @@ -2825,8 +2918,10 @@ static int probe_trace_event__set_name(struct probe_trace_event *tev, (strncmp(pev->point.function, "0x", 2) != 0) && !strisglob(pev->point.function)) event = pev->point.function; - else + else { event = tev->point.realname; + not_C_symname = !is_known_C_lang(tev->lang); + } } if (pev->group && !pev->sdt) group = pev->group; @@ -2835,9 +2930,16 @@ static int probe_trace_event__set_name(struct probe_trace_event *tev, else group = PERFPROBE_GROUP; + if (strlen(group) >= MAX_EVENT_NAME_LEN) { + pr_err("Probe group string='%s' is too long (>= %d bytes)\n", + group, MAX_EVENT_NAME_LEN); + return -ENOMEM; + } + /* Get an unused new event name */ - ret = get_new_event_name(buf, 64, event, namelist, - tev->point.retprobe, allow_suffix); + ret = get_new_event_name(buf, sizeof(buf), event, namelist, + tev->point.retprobe, allow_suffix, + not_C_symname); if (ret < 0) return ret; @@ -3116,7 +3218,7 @@ static int find_probe_trace_events_from_map(struct perf_probe_event *pev, goto err_out; } /* Add one probe point */ - tp->address = map->unmap_ip(map, sym->start) + pp->offset; + tp->address = map__unmap_ip(map, sym->start) + pp->offset; /* Check the kprobe (not in module) is within .text */ if (!pev->uprobes && !pev->target && @@ -3666,73 +3768,19 @@ void cleanup_perf_probe_events(struct perf_probe_event *pevs, int npevs) /* Loop 3: cleanup and free trace events */ for (i = 0; i < npevs; i++) { pev = &pevs[i]; - for (j = 0; j < pevs[i].ntevs; j++) - clear_probe_trace_event(&pevs[i].tevs[j]); - zfree(&pevs[i].tevs); - pevs[i].ntevs = 0; - nsinfo__zput(pev->nsi); - clear_perf_probe_event(&pevs[i]); - } -} - -int add_perf_probe_events(struct perf_probe_event *pevs, int npevs) -{ - int ret; - - ret = init_probe_symbol_maps(pevs->uprobes); - if (ret < 0) - return ret; - - ret = convert_perf_probe_events(pevs, npevs); - if (ret == 0) - ret = apply_perf_probe_events(pevs, npevs); - - cleanup_perf_probe_events(pevs, npevs); - - exit_probe_symbol_maps(); - return ret; -} - -int del_perf_probe_events(struct strfilter *filter) -{ - int ret, ret2, ufd = -1, kfd = -1; - char *str = strfilter__string(filter); - - if (!str) - return -EINVAL; - - /* Get current event names */ - ret = probe_file__open_both(&kfd, &ufd, PF_FL_RW); - if (ret < 0) - goto out; - - ret = probe_file__del_events(kfd, filter); - if (ret < 0 && ret != -ENOENT) - goto error; - - ret2 = probe_file__del_events(ufd, filter); - if (ret2 < 0 && ret2 != -ENOENT) { - ret = ret2; - goto error; + for (j = 0; j < pev->ntevs; j++) + clear_probe_trace_event(&pev->tevs[j]); + zfree(&pev->tevs); + pev->ntevs = 0; + clear_perf_probe_event(pev); } - ret = 0; - -error: - if (kfd >= 0) - close(kfd); - if (ufd >= 0) - close(ufd); -out: - free(str); - - return ret; } int show_available_funcs(const char *target, struct nsinfo *nsi, struct strfilter *_filter, bool user) { - struct rb_node *nd; struct map *map; + struct dso *dso; int ret; ret = init_probe_symbol_maps(user); @@ -3758,18 +3806,17 @@ int show_available_funcs(const char *target, struct nsinfo *nsi, (target) ? : "kernel"); goto end; } - if (!dso__sorted_by_name(map->dso)) - dso__sort_by_name(map->dso); + dso = map__dso(map); + dso__sort_by_name(dso); /* Show all (filtered) symbols */ setup_pager(); - for (nd = rb_first_cached(&map->dso->symbol_names); nd; - nd = rb_next(nd)) { - struct symbol_name_rb_node *pos = rb_entry(nd, struct symbol_name_rb_node, rb_node); + for (size_t i = 0; i < dso__symbol_names_len(dso); i++) { + struct symbol *pos = dso__symbol_names(dso)[i]; - if (strfilter__compare(_filter, pos->sym.name)) - printf("%s\n", pos->sym.name); + if (strfilter__compare(_filter, pos->name)) + printf("%s\n", pos->name); } end: map__put(map); |
