diff options
Diffstat (limited to 'tools/perf/util/probe-event.c')
-rw-r--r-- | tools/perf/util/probe-event.c | 126 |
1 files changed, 89 insertions, 37 deletions
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index 28733962cd80..fcfbef07b92d 100644 --- a/tools/perf/util/probe-event.c +++ b/tools/perf/util/probe-event.c | |||
@@ -110,13 +110,12 @@ void exit_probe_symbol_maps(void) | |||
110 | static struct symbol *__find_kernel_function_by_name(const char *name, | 110 | static struct symbol *__find_kernel_function_by_name(const char *name, |
111 | struct map **mapp) | 111 | struct map **mapp) |
112 | { | 112 | { |
113 | return machine__find_kernel_function_by_name(host_machine, name, mapp, | 113 | return machine__find_kernel_function_by_name(host_machine, name, mapp); |
114 | NULL); | ||
115 | } | 114 | } |
116 | 115 | ||
117 | static struct symbol *__find_kernel_function(u64 addr, struct map **mapp) | 116 | static struct symbol *__find_kernel_function(u64 addr, struct map **mapp) |
118 | { | 117 | { |
119 | return machine__find_kernel_function(host_machine, addr, mapp, NULL); | 118 | return machine__find_kernel_function(host_machine, addr, mapp); |
120 | } | 119 | } |
121 | 120 | ||
122 | static struct ref_reloc_sym *kernel_get_ref_reloc_sym(void) | 121 | static struct ref_reloc_sym *kernel_get_ref_reloc_sym(void) |
@@ -125,7 +124,7 @@ static struct ref_reloc_sym *kernel_get_ref_reloc_sym(void) | |||
125 | struct kmap *kmap; | 124 | struct kmap *kmap; |
126 | struct map *map = machine__kernel_map(host_machine); | 125 | struct map *map = machine__kernel_map(host_machine); |
127 | 126 | ||
128 | if (map__load(map, NULL) < 0) | 127 | if (map__load(map) < 0) |
129 | return NULL; | 128 | return NULL; |
130 | 129 | ||
131 | kmap = map__kmap(map); | 130 | kmap = map__kmap(map); |
@@ -214,9 +213,13 @@ static int convert_exec_to_group(const char *exec, char **result) | |||
214 | goto out; | 213 | goto out; |
215 | } | 214 | } |
216 | 215 | ||
217 | ptr2 = strpbrk(ptr1, "-._"); | 216 | for (ptr2 = ptr1; ptr2 != '\0'; ptr2++) { |
218 | if (ptr2) | 217 | if (!isalnum(*ptr2) && *ptr2 != '_') { |
219 | *ptr2 = '\0'; | 218 | *ptr2 = '\0'; |
219 | break; | ||
220 | } | ||
221 | } | ||
222 | |||
220 | ret = e_snprintf(buf, 64, "%s_%s", PERFPROBE_GROUP, ptr1); | 223 | ret = e_snprintf(buf, 64, "%s_%s", PERFPROBE_GROUP, ptr1); |
221 | if (ret < 0) | 224 | if (ret < 0) |
222 | goto out; | 225 | goto out; |
@@ -351,9 +354,9 @@ static int kernel_get_module_dso(const char *module, struct dso **pdso) | |||
351 | vmlinux_name = symbol_conf.vmlinux_name; | 354 | vmlinux_name = symbol_conf.vmlinux_name; |
352 | dso->load_errno = 0; | 355 | dso->load_errno = 0; |
353 | if (vmlinux_name) | 356 | if (vmlinux_name) |
354 | ret = dso__load_vmlinux(dso, map, vmlinux_name, false, NULL); | 357 | ret = dso__load_vmlinux(dso, map, vmlinux_name, false); |
355 | else | 358 | else |
356 | ret = dso__load_vmlinux_path(dso, map, NULL); | 359 | ret = dso__load_vmlinux_path(dso, map); |
357 | found: | 360 | found: |
358 | *pdso = dso; | 361 | *pdso = dso; |
359 | return ret; | 362 | return ret; |
@@ -674,6 +677,10 @@ post_process_kernel_probe_trace_events(struct probe_trace_event *tevs, | |||
674 | char *tmp; | 677 | char *tmp; |
675 | int i, skipped = 0; | 678 | int i, skipped = 0; |
676 | 679 | ||
680 | /* Skip post process if the target is an offline kernel */ | ||
681 | if (symbol_conf.ignore_vmlinux_buildid) | ||
682 | return 0; | ||
683 | |||
677 | reloc_sym = kernel_get_ref_reloc_sym(); | 684 | reloc_sym = kernel_get_ref_reloc_sym(); |
678 | if (!reloc_sym) { | 685 | if (!reloc_sym) { |
679 | pr_warning("Relocated base symbol is not found!\n"); | 686 | pr_warning("Relocated base symbol is not found!\n"); |
@@ -1614,19 +1621,27 @@ out: | |||
1614 | return ret; | 1621 | return ret; |
1615 | } | 1622 | } |
1616 | 1623 | ||
1624 | /* Returns true if *any* ARG is either C variable, $params or $vars. */ | ||
1625 | bool perf_probe_with_var(struct perf_probe_event *pev) | ||
1626 | { | ||
1627 | int i = 0; | ||
1628 | |||
1629 | for (i = 0; i < pev->nargs; i++) | ||
1630 | if (is_c_varname(pev->args[i].var) || | ||
1631 | !strcmp(pev->args[i].var, PROBE_ARG_PARAMS) || | ||
1632 | !strcmp(pev->args[i].var, PROBE_ARG_VARS)) | ||
1633 | return true; | ||
1634 | return false; | ||
1635 | } | ||
1636 | |||
1617 | /* Return true if this perf_probe_event requires debuginfo */ | 1637 | /* Return true if this perf_probe_event requires debuginfo */ |
1618 | bool perf_probe_event_need_dwarf(struct perf_probe_event *pev) | 1638 | bool perf_probe_event_need_dwarf(struct perf_probe_event *pev) |
1619 | { | 1639 | { |
1620 | int i; | ||
1621 | |||
1622 | if (pev->point.file || pev->point.line || pev->point.lazy_line) | 1640 | if (pev->point.file || pev->point.line || pev->point.lazy_line) |
1623 | return true; | 1641 | return true; |
1624 | 1642 | ||
1625 | for (i = 0; i < pev->nargs; i++) | 1643 | if (perf_probe_with_var(pev)) |
1626 | if (is_c_varname(pev->args[i].var) || | 1644 | return true; |
1627 | !strcmp(pev->args[i].var, "$params") || | ||
1628 | !strcmp(pev->args[i].var, "$vars")) | ||
1629 | return true; | ||
1630 | 1645 | ||
1631 | return false; | 1646 | return false; |
1632 | } | 1647 | } |
@@ -1987,7 +2002,7 @@ static int find_perf_probe_point_from_map(struct probe_trace_point *tp, | |||
1987 | map = dso__new_map(tp->module); | 2002 | map = dso__new_map(tp->module); |
1988 | if (!map) | 2003 | if (!map) |
1989 | goto out; | 2004 | goto out; |
1990 | sym = map__find_symbol(map, addr, NULL); | 2005 | sym = map__find_symbol(map, addr); |
1991 | } else { | 2006 | } else { |
1992 | if (tp->symbol && !addr) { | 2007 | if (tp->symbol && !addr) { |
1993 | if (kernel_get_symbol_address_by_name(tp->symbol, | 2008 | if (kernel_get_symbol_address_by_name(tp->symbol, |
@@ -2692,7 +2707,7 @@ static int find_probe_functions(struct map *map, char *name, | |||
2692 | struct symbol *sym; | 2707 | struct symbol *sym; |
2693 | struct rb_node *tmp; | 2708 | struct rb_node *tmp; |
2694 | 2709 | ||
2695 | if (map__load(map, NULL) < 0) | 2710 | if (map__load(map) < 0) |
2696 | return 0; | 2711 | return 0; |
2697 | 2712 | ||
2698 | map__for_each_symbol(map, sym, tmp) { | 2713 | map__for_each_symbol(map, sym, tmp) { |
@@ -3207,6 +3222,52 @@ int convert_perf_probe_events(struct perf_probe_event *pevs, int npevs) | |||
3207 | return 0; | 3222 | return 0; |
3208 | } | 3223 | } |
3209 | 3224 | ||
3225 | static int show_probe_trace_event(struct probe_trace_event *tev) | ||
3226 | { | ||
3227 | char *buf = synthesize_probe_trace_command(tev); | ||
3228 | |||
3229 | if (!buf) { | ||
3230 | pr_debug("Failed to synthesize probe trace event.\n"); | ||
3231 | return -EINVAL; | ||
3232 | } | ||
3233 | |||
3234 | /* Showing definition always go stdout */ | ||
3235 | printf("%s\n", buf); | ||
3236 | free(buf); | ||
3237 | |||
3238 | return 0; | ||
3239 | } | ||
3240 | |||
3241 | int show_probe_trace_events(struct perf_probe_event *pevs, int npevs) | ||
3242 | { | ||
3243 | struct strlist *namelist = strlist__new(NULL, NULL); | ||
3244 | struct probe_trace_event *tev; | ||
3245 | struct perf_probe_event *pev; | ||
3246 | int i, j, ret = 0; | ||
3247 | |||
3248 | if (!namelist) | ||
3249 | return -ENOMEM; | ||
3250 | |||
3251 | for (j = 0; j < npevs && !ret; j++) { | ||
3252 | pev = &pevs[j]; | ||
3253 | for (i = 0; i < pev->ntevs && !ret; i++) { | ||
3254 | tev = &pev->tevs[i]; | ||
3255 | /* Skip if the symbol is out of .text or blacklisted */ | ||
3256 | if (!tev->point.symbol && !pev->uprobes) | ||
3257 | continue; | ||
3258 | |||
3259 | /* Set new name for tev (and update namelist) */ | ||
3260 | ret = probe_trace_event__set_name(tev, pev, | ||
3261 | namelist, true); | ||
3262 | if (!ret) | ||
3263 | ret = show_probe_trace_event(tev); | ||
3264 | } | ||
3265 | } | ||
3266 | strlist__delete(namelist); | ||
3267 | |||
3268 | return ret; | ||
3269 | } | ||
3270 | |||
3210 | int apply_perf_probe_events(struct perf_probe_event *pevs, int npevs) | 3271 | int apply_perf_probe_events(struct perf_probe_event *pevs, int npevs) |
3211 | { | 3272 | { |
3212 | int i, ret = 0; | 3273 | int i, ret = 0; |
@@ -3289,24 +3350,10 @@ out: | |||
3289 | return ret; | 3350 | return ret; |
3290 | } | 3351 | } |
3291 | 3352 | ||
3292 | /* TODO: don't use a global variable for filter ... */ | ||
3293 | static struct strfilter *available_func_filter; | ||
3294 | |||
3295 | /* | ||
3296 | * If a symbol corresponds to a function with global binding and | ||
3297 | * matches filter return 0. For all others return 1. | ||
3298 | */ | ||
3299 | static int filter_available_functions(struct map *map __maybe_unused, | ||
3300 | struct symbol *sym) | ||
3301 | { | ||
3302 | if (strfilter__compare(available_func_filter, sym->name)) | ||
3303 | return 0; | ||
3304 | return 1; | ||
3305 | } | ||
3306 | |||
3307 | int show_available_funcs(const char *target, struct strfilter *_filter, | 3353 | int show_available_funcs(const char *target, struct strfilter *_filter, |
3308 | bool user) | 3354 | bool user) |
3309 | { | 3355 | { |
3356 | struct rb_node *nd; | ||
3310 | struct map *map; | 3357 | struct map *map; |
3311 | int ret; | 3358 | int ret; |
3312 | 3359 | ||
@@ -3324,9 +3371,7 @@ int show_available_funcs(const char *target, struct strfilter *_filter, | |||
3324 | return -EINVAL; | 3371 | return -EINVAL; |
3325 | } | 3372 | } |
3326 | 3373 | ||
3327 | /* Load symbols with given filter */ | 3374 | ret = map__load(map); |
3328 | available_func_filter = _filter; | ||
3329 | ret = map__load(map, filter_available_functions); | ||
3330 | if (ret) { | 3375 | if (ret) { |
3331 | if (ret == -2) { | 3376 | if (ret == -2) { |
3332 | char *str = strfilter__string(_filter); | 3377 | char *str = strfilter__string(_filter); |
@@ -3343,7 +3388,14 @@ int show_available_funcs(const char *target, struct strfilter *_filter, | |||
3343 | 3388 | ||
3344 | /* Show all (filtered) symbols */ | 3389 | /* Show all (filtered) symbols */ |
3345 | setup_pager(); | 3390 | setup_pager(); |
3346 | dso__fprintf_symbols_by_name(map->dso, map->type, stdout); | 3391 | |
3392 | for (nd = rb_first(&map->dso->symbol_names[map->type]); nd; nd = rb_next(nd)) { | ||
3393 | struct symbol_name_rb_node *pos = rb_entry(nd, struct symbol_name_rb_node, rb_node); | ||
3394 | |||
3395 | if (strfilter__compare(_filter, pos->sym.name)) | ||
3396 | printf("%s\n", pos->sym.name); | ||
3397 | } | ||
3398 | |||
3347 | end: | 3399 | end: |
3348 | if (user) { | 3400 | if (user) { |
3349 | map__put(map); | 3401 | map__put(map); |