150656eecSMasami Hiramatsu /* 20e60836bSSrikar Dronamraju * probe-event.c : perf-probe definition to probe_events format converter 350656eecSMasami Hiramatsu * 450656eecSMasami Hiramatsu * Written by Masami Hiramatsu <mhiramat@redhat.com> 550656eecSMasami Hiramatsu * 650656eecSMasami Hiramatsu * This program is free software; you can redistribute it and/or modify 750656eecSMasami Hiramatsu * it under the terms of the GNU General Public License as published by 850656eecSMasami Hiramatsu * the Free Software Foundation; either version 2 of the License, or 950656eecSMasami Hiramatsu * (at your option) any later version. 1050656eecSMasami Hiramatsu * 1150656eecSMasami Hiramatsu * This program is distributed in the hope that it will be useful, 1250656eecSMasami Hiramatsu * but WITHOUT ANY WARRANTY; without even the implied warranty of 1350656eecSMasami Hiramatsu * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1450656eecSMasami Hiramatsu * GNU General Public License for more details. 1550656eecSMasami Hiramatsu * 1650656eecSMasami Hiramatsu * You should have received a copy of the GNU General Public License 1750656eecSMasami Hiramatsu * along with this program; if not, write to the Free Software 1850656eecSMasami Hiramatsu * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 1950656eecSMasami Hiramatsu * 2050656eecSMasami Hiramatsu */ 2150656eecSMasami Hiramatsu 2250656eecSMasami Hiramatsu #define _GNU_SOURCE 2350656eecSMasami Hiramatsu #include <sys/utsname.h> 2450656eecSMasami Hiramatsu #include <sys/types.h> 2550656eecSMasami Hiramatsu #include <sys/stat.h> 2650656eecSMasami Hiramatsu #include <fcntl.h> 2750656eecSMasami Hiramatsu #include <errno.h> 2850656eecSMasami Hiramatsu #include <stdio.h> 2950656eecSMasami Hiramatsu #include <unistd.h> 3050656eecSMasami Hiramatsu #include <stdlib.h> 3150656eecSMasami Hiramatsu #include <string.h> 324de189feSMasami Hiramatsu #include <stdarg.h> 334de189feSMasami Hiramatsu #include <limits.h> 3450656eecSMasami Hiramatsu 3550656eecSMasami Hiramatsu #undef _GNU_SOURCE 3631facc5fSMasami Hiramatsu #include "util.h" 3750656eecSMasami Hiramatsu #include "event.h" 38e1c01d61SMasami Hiramatsu #include "string.h" 394de189feSMasami Hiramatsu #include "strlist.h" 4050656eecSMasami Hiramatsu #include "debug.h" 4172041334SMasami Hiramatsu #include "cache.h" 42631c9defSMasami Hiramatsu #include "color.h" 43e0faa8d3SMasami Hiramatsu #include "symbol.h" 44e0faa8d3SMasami Hiramatsu #include "thread.h" 457ca5989dSMasami Hiramatsu #include "debugfs.h" 464b4da7f7SMasami Hiramatsu #include "trace-event.h" /* For __unused */ 4750656eecSMasami Hiramatsu #include "probe-event.h" 484235b045SMasami Hiramatsu #include "probe-finder.h" 4950656eecSMasami Hiramatsu 5050656eecSMasami Hiramatsu #define MAX_CMDLEN 256 5150656eecSMasami Hiramatsu #define MAX_PROBE_ARGS 128 5250656eecSMasami Hiramatsu #define PERFPROBE_GROUP "probe" 5350656eecSMasami Hiramatsu 54f4d7da49SMasami Hiramatsu bool probe_event_dry_run; /* Dry run flag */ 55f4d7da49SMasami Hiramatsu 56146a1439SMasami Hiramatsu #define semantic_error(msg ...) pr_err("Semantic error :" msg) 5750656eecSMasami Hiramatsu 584de189feSMasami Hiramatsu /* If there is no space to write, returns -E2BIG. */ 594de189feSMasami Hiramatsu static int e_snprintf(char *str, size_t size, const char *format, ...) 6084988450SMasami Hiramatsu __attribute__((format(printf, 3, 4))); 6184988450SMasami Hiramatsu 6284988450SMasami Hiramatsu static int e_snprintf(char *str, size_t size, const char *format, ...) 634de189feSMasami Hiramatsu { 644de189feSMasami Hiramatsu int ret; 654de189feSMasami Hiramatsu va_list ap; 664de189feSMasami Hiramatsu va_start(ap, format); 674de189feSMasami Hiramatsu ret = vsnprintf(str, size, format, ap); 684de189feSMasami Hiramatsu va_end(ap); 694de189feSMasami Hiramatsu if (ret >= (int)size) 704de189feSMasami Hiramatsu ret = -E2BIG; 714de189feSMasami Hiramatsu return ret; 724de189feSMasami Hiramatsu } 734de189feSMasami Hiramatsu 744b4da7f7SMasami Hiramatsu static char *synthesize_perf_probe_point(struct perf_probe_point *pp); 75d28c6223SArnaldo Carvalho de Melo static struct machine machine; 76e0faa8d3SMasami Hiramatsu 77469b9b88SMasami Hiramatsu /* Initialize symbol maps and path of vmlinux/modules */ 78146a1439SMasami Hiramatsu static int init_vmlinux(void) 79e0faa8d3SMasami Hiramatsu { 80146a1439SMasami Hiramatsu int ret; 81146a1439SMasami Hiramatsu 82e0faa8d3SMasami Hiramatsu symbol_conf.sort_by_name = true; 83e0faa8d3SMasami Hiramatsu if (symbol_conf.vmlinux_name == NULL) 84e0faa8d3SMasami Hiramatsu symbol_conf.try_vmlinux_path = true; 85e0faa8d3SMasami Hiramatsu else 86e0faa8d3SMasami Hiramatsu pr_debug("Use vmlinux: %s\n", symbol_conf.vmlinux_name); 87146a1439SMasami Hiramatsu ret = symbol__init(); 88146a1439SMasami Hiramatsu if (ret < 0) { 89146a1439SMasami Hiramatsu pr_debug("Failed to init symbol map.\n"); 90146a1439SMasami Hiramatsu goto out; 91146a1439SMasami Hiramatsu } 92e0faa8d3SMasami Hiramatsu 93469b9b88SMasami Hiramatsu ret = machine__init(&machine, "", HOST_KERNEL_ID); 94d28c6223SArnaldo Carvalho de Melo if (ret < 0) 95d28c6223SArnaldo Carvalho de Melo goto out; 96d28c6223SArnaldo Carvalho de Melo 97469b9b88SMasami Hiramatsu if (machine__create_kernel_maps(&machine) < 0) { 980e43e5d2SMasami Hiramatsu pr_debug("machine__create_kernel_maps() failed.\n"); 99469b9b88SMasami Hiramatsu goto out; 100469b9b88SMasami Hiramatsu } 101146a1439SMasami Hiramatsu out: 102146a1439SMasami Hiramatsu if (ret < 0) 103146a1439SMasami Hiramatsu pr_warning("Failed to init vmlinux path.\n"); 104146a1439SMasami Hiramatsu return ret; 105e0faa8d3SMasami Hiramatsu } 106e0faa8d3SMasami Hiramatsu 107469b9b88SMasami Hiramatsu static struct symbol *__find_kernel_function_by_name(const char *name, 108469b9b88SMasami Hiramatsu struct map **mapp) 109e0faa8d3SMasami Hiramatsu { 110469b9b88SMasami Hiramatsu return machine__find_kernel_function_by_name(&machine, name, mapp, 111469b9b88SMasami Hiramatsu NULL); 112e0faa8d3SMasami Hiramatsu } 113469b9b88SMasami Hiramatsu 114469b9b88SMasami Hiramatsu const char *kernel_get_module_path(const char *module) 115469b9b88SMasami Hiramatsu { 116469b9b88SMasami Hiramatsu struct dso *dso; 117469b9b88SMasami Hiramatsu 118469b9b88SMasami Hiramatsu if (module) { 119469b9b88SMasami Hiramatsu list_for_each_entry(dso, &machine.kernel_dsos, node) { 120469b9b88SMasami Hiramatsu if (strncmp(dso->short_name + 1, module, 121469b9b88SMasami Hiramatsu dso->short_name_len - 2) == 0) 122469b9b88SMasami Hiramatsu goto found; 123469b9b88SMasami Hiramatsu } 124469b9b88SMasami Hiramatsu pr_debug("Failed to find module %s.\n", module); 125469b9b88SMasami Hiramatsu return NULL; 126469b9b88SMasami Hiramatsu } else { 127469b9b88SMasami Hiramatsu dso = machine.vmlinux_maps[MAP__FUNCTION]->dso; 128469b9b88SMasami Hiramatsu if (dso__load_vmlinux_path(dso, 129469b9b88SMasami Hiramatsu machine.vmlinux_maps[MAP__FUNCTION], NULL) < 0) { 130469b9b88SMasami Hiramatsu pr_debug("Failed to load kernel map.\n"); 131469b9b88SMasami Hiramatsu return NULL; 132469b9b88SMasami Hiramatsu } 133469b9b88SMasami Hiramatsu } 134469b9b88SMasami Hiramatsu found: 135469b9b88SMasami Hiramatsu return dso->long_name; 136469b9b88SMasami Hiramatsu } 137469b9b88SMasami Hiramatsu 138469b9b88SMasami Hiramatsu #ifdef DWARF_SUPPORT 139469b9b88SMasami Hiramatsu static int open_vmlinux(const char *module) 140469b9b88SMasami Hiramatsu { 141469b9b88SMasami Hiramatsu const char *path = kernel_get_module_path(module); 142469b9b88SMasami Hiramatsu if (!path) { 1430e43e5d2SMasami Hiramatsu pr_err("Failed to find path of %s module.\n", 1440e43e5d2SMasami Hiramatsu module ?: "kernel"); 145469b9b88SMasami Hiramatsu return -ENOENT; 146469b9b88SMasami Hiramatsu } 147469b9b88SMasami Hiramatsu pr_debug("Try to open %s\n", path); 148469b9b88SMasami Hiramatsu return open(path, O_RDONLY); 149e0faa8d3SMasami Hiramatsu } 1504b4da7f7SMasami Hiramatsu 1510e60836bSSrikar Dronamraju /* 1520e60836bSSrikar Dronamraju * Convert trace point to probe point with debuginfo 1530e60836bSSrikar Dronamraju * Currently only handles kprobes. 1540e60836bSSrikar Dronamraju */ 1550e60836bSSrikar Dronamraju static int kprobe_convert_to_perf_probe(struct probe_trace_point *tp, 1564b4da7f7SMasami Hiramatsu struct perf_probe_point *pp) 1574b4da7f7SMasami Hiramatsu { 1584b4da7f7SMasami Hiramatsu struct symbol *sym; 159469b9b88SMasami Hiramatsu struct map *map; 160469b9b88SMasami Hiramatsu u64 addr; 161469b9b88SMasami Hiramatsu int ret = -ENOENT; 1624b4da7f7SMasami Hiramatsu 163469b9b88SMasami Hiramatsu sym = __find_kernel_function_by_name(tp->symbol, &map); 1644b4da7f7SMasami Hiramatsu if (sym) { 165469b9b88SMasami Hiramatsu addr = map->unmap_ip(map, sym->start + tp->offset); 166469b9b88SMasami Hiramatsu pr_debug("try to find %s+%ld@%llx\n", tp->symbol, 167469b9b88SMasami Hiramatsu tp->offset, addr); 168469b9b88SMasami Hiramatsu ret = find_perf_probe_point((unsigned long)addr, pp); 169146a1439SMasami Hiramatsu } 1704b4da7f7SMasami Hiramatsu if (ret <= 0) { 171146a1439SMasami Hiramatsu pr_debug("Failed to find corresponding probes from " 172146a1439SMasami Hiramatsu "debuginfo. Use kprobe event information.\n"); 17302b95dadSMasami Hiramatsu pp->function = strdup(tp->symbol); 17402b95dadSMasami Hiramatsu if (pp->function == NULL) 17502b95dadSMasami Hiramatsu return -ENOMEM; 1764b4da7f7SMasami Hiramatsu pp->offset = tp->offset; 1774b4da7f7SMasami Hiramatsu } 1784b4da7f7SMasami Hiramatsu pp->retprobe = tp->retprobe; 179146a1439SMasami Hiramatsu 180146a1439SMasami Hiramatsu return 0; 1814b4da7f7SMasami Hiramatsu } 1824b4da7f7SMasami Hiramatsu 1834b4da7f7SMasami Hiramatsu /* Try to find perf_probe_event with debuginfo */ 1840e60836bSSrikar Dronamraju static int try_to_find_probe_trace_events(struct perf_probe_event *pev, 1850e60836bSSrikar Dronamraju struct probe_trace_event **tevs, 186469b9b88SMasami Hiramatsu int max_tevs, const char *module) 1874b4da7f7SMasami Hiramatsu { 1884b4da7f7SMasami Hiramatsu bool need_dwarf = perf_probe_event_need_dwarf(pev); 1894b4da7f7SMasami Hiramatsu int fd, ntevs; 1904b4da7f7SMasami Hiramatsu 191469b9b88SMasami Hiramatsu fd = open_vmlinux(module); 1924b4da7f7SMasami Hiramatsu if (fd < 0) { 193146a1439SMasami Hiramatsu if (need_dwarf) { 194146a1439SMasami Hiramatsu pr_warning("Failed to open debuginfo file.\n"); 195146a1439SMasami Hiramatsu return fd; 196146a1439SMasami Hiramatsu } 1974b4da7f7SMasami Hiramatsu pr_debug("Could not open vmlinux. Try to use symbols.\n"); 1984b4da7f7SMasami Hiramatsu return 0; 1994b4da7f7SMasami Hiramatsu } 2004b4da7f7SMasami Hiramatsu 2014b4da7f7SMasami Hiramatsu /* Searching trace events corresponding to probe event */ 2020e60836bSSrikar Dronamraju ntevs = find_probe_trace_events(fd, pev, tevs, max_tevs); 2034b4da7f7SMasami Hiramatsu close(fd); 2044b4da7f7SMasami Hiramatsu 205146a1439SMasami Hiramatsu if (ntevs > 0) { /* Succeeded to find trace events */ 2060e60836bSSrikar Dronamraju pr_debug("find %d probe_trace_events.\n", ntevs); 2074b4da7f7SMasami Hiramatsu return ntevs; 208146a1439SMasami Hiramatsu } 2094b4da7f7SMasami Hiramatsu 210146a1439SMasami Hiramatsu if (ntevs == 0) { /* No error but failed to find probe point. */ 211146a1439SMasami Hiramatsu pr_warning("Probe point '%s' not found.\n", 2124b4da7f7SMasami Hiramatsu synthesize_perf_probe_point(&pev->point)); 213146a1439SMasami Hiramatsu return -ENOENT; 214146a1439SMasami Hiramatsu } 215146a1439SMasami Hiramatsu /* Error path : ntevs < 0 */ 21615eca306SMasami Hiramatsu pr_debug("An error occurred in debuginfo analysis (%d).\n", ntevs); 21715eca306SMasami Hiramatsu if (ntevs == -EBADF) { 21815eca306SMasami Hiramatsu pr_warning("Warning: No dwarf info found in the vmlinux - " 21915eca306SMasami Hiramatsu "please rebuild kernel with CONFIG_DEBUG_INFO=y.\n"); 22015eca306SMasami Hiramatsu if (!need_dwarf) { 2210e43e5d2SMasami Hiramatsu pr_debug("Trying to use symbols.\n"); 2224b4da7f7SMasami Hiramatsu return 0; 2234b4da7f7SMasami Hiramatsu } 22415eca306SMasami Hiramatsu } 22515eca306SMasami Hiramatsu return ntevs; 22615eca306SMasami Hiramatsu } 2274b4da7f7SMasami Hiramatsu 2287cf0b79eSMasami Hiramatsu /* 2297cf0b79eSMasami Hiramatsu * Find a src file from a DWARF tag path. Prepend optional source path prefix 2307cf0b79eSMasami Hiramatsu * and chop off leading directories that do not exist. Result is passed back as 2317cf0b79eSMasami Hiramatsu * a newly allocated path on success. 2327cf0b79eSMasami Hiramatsu * Return 0 if file was found and readable, -errno otherwise. 2337cf0b79eSMasami Hiramatsu */ 2346a330a3cSMasami Hiramatsu static int get_real_path(const char *raw_path, const char *comp_dir, 2356a330a3cSMasami Hiramatsu char **new_path) 2367cf0b79eSMasami Hiramatsu { 2376a330a3cSMasami Hiramatsu const char *prefix = symbol_conf.source_prefix; 2386a330a3cSMasami Hiramatsu 2396a330a3cSMasami Hiramatsu if (!prefix) { 2406a330a3cSMasami Hiramatsu if (raw_path[0] != '/' && comp_dir) 2416a330a3cSMasami Hiramatsu /* If not an absolute path, try to use comp_dir */ 2426a330a3cSMasami Hiramatsu prefix = comp_dir; 2436a330a3cSMasami Hiramatsu else { 2447cf0b79eSMasami Hiramatsu if (access(raw_path, R_OK) == 0) { 2457cf0b79eSMasami Hiramatsu *new_path = strdup(raw_path); 2467cf0b79eSMasami Hiramatsu return 0; 2477cf0b79eSMasami Hiramatsu } else 2487cf0b79eSMasami Hiramatsu return -errno; 2497cf0b79eSMasami Hiramatsu } 2506a330a3cSMasami Hiramatsu } 2517cf0b79eSMasami Hiramatsu 2526a330a3cSMasami Hiramatsu *new_path = malloc((strlen(prefix) + strlen(raw_path) + 2)); 2537cf0b79eSMasami Hiramatsu if (!*new_path) 2547cf0b79eSMasami Hiramatsu return -ENOMEM; 2557cf0b79eSMasami Hiramatsu 2567cf0b79eSMasami Hiramatsu for (;;) { 2576a330a3cSMasami Hiramatsu sprintf(*new_path, "%s/%s", prefix, raw_path); 2587cf0b79eSMasami Hiramatsu 2597cf0b79eSMasami Hiramatsu if (access(*new_path, R_OK) == 0) 2607cf0b79eSMasami Hiramatsu return 0; 2617cf0b79eSMasami Hiramatsu 2626a330a3cSMasami Hiramatsu if (!symbol_conf.source_prefix) 2636a330a3cSMasami Hiramatsu /* In case of searching comp_dir, don't retry */ 2646a330a3cSMasami Hiramatsu return -errno; 2656a330a3cSMasami Hiramatsu 2667cf0b79eSMasami Hiramatsu switch (errno) { 2677cf0b79eSMasami Hiramatsu case ENAMETOOLONG: 2687cf0b79eSMasami Hiramatsu case ENOENT: 2697cf0b79eSMasami Hiramatsu case EROFS: 2707cf0b79eSMasami Hiramatsu case EFAULT: 2717cf0b79eSMasami Hiramatsu raw_path = strchr(++raw_path, '/'); 2727cf0b79eSMasami Hiramatsu if (!raw_path) { 2737cf0b79eSMasami Hiramatsu free(*new_path); 2747cf0b79eSMasami Hiramatsu *new_path = NULL; 2757cf0b79eSMasami Hiramatsu return -ENOENT; 2767cf0b79eSMasami Hiramatsu } 2777cf0b79eSMasami Hiramatsu continue; 2787cf0b79eSMasami Hiramatsu 2797cf0b79eSMasami Hiramatsu default: 2807cf0b79eSMasami Hiramatsu free(*new_path); 2817cf0b79eSMasami Hiramatsu *new_path = NULL; 2827cf0b79eSMasami Hiramatsu return -errno; 2837cf0b79eSMasami Hiramatsu } 2847cf0b79eSMasami Hiramatsu } 2857cf0b79eSMasami Hiramatsu } 2867cf0b79eSMasami Hiramatsu 2874b4da7f7SMasami Hiramatsu #define LINEBUF_SIZE 256 2884b4da7f7SMasami Hiramatsu #define NR_ADDITIONAL_LINES 2 2894b4da7f7SMasami Hiramatsu 290d3b63d7aSMasami Hiramatsu static int show_one_line(FILE *fp, int l, bool skip, bool show_num) 2914b4da7f7SMasami Hiramatsu { 2924b4da7f7SMasami Hiramatsu char buf[LINEBUF_SIZE]; 2934b4da7f7SMasami Hiramatsu const char *color = PERF_COLOR_BLUE; 2944b4da7f7SMasami Hiramatsu 2954b4da7f7SMasami Hiramatsu if (fgets(buf, LINEBUF_SIZE, fp) == NULL) 2964b4da7f7SMasami Hiramatsu goto error; 2974b4da7f7SMasami Hiramatsu if (!skip) { 2984b4da7f7SMasami Hiramatsu if (show_num) 299d3b63d7aSMasami Hiramatsu fprintf(stdout, "%7d %s", l, buf); 3004b4da7f7SMasami Hiramatsu else 3014b4da7f7SMasami Hiramatsu color_fprintf(stdout, color, " %s", buf); 3024b4da7f7SMasami Hiramatsu } 3034b4da7f7SMasami Hiramatsu 3044b4da7f7SMasami Hiramatsu while (strlen(buf) == LINEBUF_SIZE - 1 && 3054b4da7f7SMasami Hiramatsu buf[LINEBUF_SIZE - 2] != '\n') { 3064b4da7f7SMasami Hiramatsu if (fgets(buf, LINEBUF_SIZE, fp) == NULL) 3074b4da7f7SMasami Hiramatsu goto error; 3084b4da7f7SMasami Hiramatsu if (!skip) { 3094b4da7f7SMasami Hiramatsu if (show_num) 3104b4da7f7SMasami Hiramatsu fprintf(stdout, "%s", buf); 3114b4da7f7SMasami Hiramatsu else 3124b4da7f7SMasami Hiramatsu color_fprintf(stdout, color, "%s", buf); 3134b4da7f7SMasami Hiramatsu } 3144b4da7f7SMasami Hiramatsu } 315146a1439SMasami Hiramatsu 316146a1439SMasami Hiramatsu return 0; 3174b4da7f7SMasami Hiramatsu error: 3184b4da7f7SMasami Hiramatsu if (feof(fp)) 319146a1439SMasami Hiramatsu pr_warning("Source file is shorter than expected.\n"); 3204b4da7f7SMasami Hiramatsu else 321146a1439SMasami Hiramatsu pr_warning("File read error: %s\n", strerror(errno)); 322146a1439SMasami Hiramatsu 323146a1439SMasami Hiramatsu return -1; 3244b4da7f7SMasami Hiramatsu } 3254b4da7f7SMasami Hiramatsu 3264b4da7f7SMasami Hiramatsu /* 3274b4da7f7SMasami Hiramatsu * Show line-range always requires debuginfo to find source file and 3284b4da7f7SMasami Hiramatsu * line number. 3294b4da7f7SMasami Hiramatsu */ 330469b9b88SMasami Hiramatsu int show_line_range(struct line_range *lr, const char *module) 3314b4da7f7SMasami Hiramatsu { 332d3b63d7aSMasami Hiramatsu int l = 1; 3334b4da7f7SMasami Hiramatsu struct line_node *ln; 3344b4da7f7SMasami Hiramatsu FILE *fp; 3354b4da7f7SMasami Hiramatsu int fd, ret; 3367cf0b79eSMasami Hiramatsu char *tmp; 3374b4da7f7SMasami Hiramatsu 3384b4da7f7SMasami Hiramatsu /* Search a line range */ 339146a1439SMasami Hiramatsu ret = init_vmlinux(); 340146a1439SMasami Hiramatsu if (ret < 0) 341146a1439SMasami Hiramatsu return ret; 342146a1439SMasami Hiramatsu 343469b9b88SMasami Hiramatsu fd = open_vmlinux(module); 344146a1439SMasami Hiramatsu if (fd < 0) { 345146a1439SMasami Hiramatsu pr_warning("Failed to open debuginfo file.\n"); 346146a1439SMasami Hiramatsu return fd; 347146a1439SMasami Hiramatsu } 348146a1439SMasami Hiramatsu 3494b4da7f7SMasami Hiramatsu ret = find_line_range(fd, lr); 3504b4da7f7SMasami Hiramatsu close(fd); 351146a1439SMasami Hiramatsu if (ret == 0) { 352146a1439SMasami Hiramatsu pr_warning("Specified source line is not found.\n"); 353146a1439SMasami Hiramatsu return -ENOENT; 354146a1439SMasami Hiramatsu } else if (ret < 0) { 355146a1439SMasami Hiramatsu pr_warning("Debuginfo analysis failed. (%d)\n", ret); 356146a1439SMasami Hiramatsu return ret; 357146a1439SMasami Hiramatsu } 3584b4da7f7SMasami Hiramatsu 3597cf0b79eSMasami Hiramatsu /* Convert source file path */ 3607cf0b79eSMasami Hiramatsu tmp = lr->path; 3616a330a3cSMasami Hiramatsu ret = get_real_path(tmp, lr->comp_dir, &lr->path); 3627cf0b79eSMasami Hiramatsu free(tmp); /* Free old path */ 3637cf0b79eSMasami Hiramatsu if (ret < 0) { 3647cf0b79eSMasami Hiramatsu pr_warning("Failed to find source file. (%d)\n", ret); 3657cf0b79eSMasami Hiramatsu return ret; 3667cf0b79eSMasami Hiramatsu } 3677cf0b79eSMasami Hiramatsu 3684b4da7f7SMasami Hiramatsu setup_pager(); 3694b4da7f7SMasami Hiramatsu 3704b4da7f7SMasami Hiramatsu if (lr->function) 3714b4da7f7SMasami Hiramatsu fprintf(stdout, "<%s:%d>\n", lr->function, 3724b4da7f7SMasami Hiramatsu lr->start - lr->offset); 3734b4da7f7SMasami Hiramatsu else 374*62c15fc4SFranck Bui-Huu fprintf(stdout, "<%s:%d>\n", lr->path, lr->start); 3754b4da7f7SMasami Hiramatsu 3764b4da7f7SMasami Hiramatsu fp = fopen(lr->path, "r"); 377146a1439SMasami Hiramatsu if (fp == NULL) { 378146a1439SMasami Hiramatsu pr_warning("Failed to open %s: %s\n", lr->path, 379146a1439SMasami Hiramatsu strerror(errno)); 380146a1439SMasami Hiramatsu return -errno; 381146a1439SMasami Hiramatsu } 3824b4da7f7SMasami Hiramatsu /* Skip to starting line number */ 383146a1439SMasami Hiramatsu while (l < lr->start && ret >= 0) 384146a1439SMasami Hiramatsu ret = show_one_line(fp, l++, true, false); 385146a1439SMasami Hiramatsu if (ret < 0) 386146a1439SMasami Hiramatsu goto end; 3874b4da7f7SMasami Hiramatsu 3884b4da7f7SMasami Hiramatsu list_for_each_entry(ln, &lr->line_list, list) { 389146a1439SMasami Hiramatsu while (ln->line > l && ret >= 0) 390146a1439SMasami Hiramatsu ret = show_one_line(fp, (l++) - lr->offset, 391146a1439SMasami Hiramatsu false, false); 392146a1439SMasami Hiramatsu if (ret >= 0) 393146a1439SMasami Hiramatsu ret = show_one_line(fp, (l++) - lr->offset, 394146a1439SMasami Hiramatsu false, true); 395146a1439SMasami Hiramatsu if (ret < 0) 396146a1439SMasami Hiramatsu goto end; 3974b4da7f7SMasami Hiramatsu } 3984b4da7f7SMasami Hiramatsu 3994b4da7f7SMasami Hiramatsu if (lr->end == INT_MAX) 4004b4da7f7SMasami Hiramatsu lr->end = l + NR_ADDITIONAL_LINES; 401dda4ab34SMasami Hiramatsu while (l <= lr->end && !feof(fp) && ret >= 0) 402146a1439SMasami Hiramatsu ret = show_one_line(fp, (l++) - lr->offset, false, false); 403146a1439SMasami Hiramatsu end: 4044b4da7f7SMasami Hiramatsu fclose(fp); 405146a1439SMasami Hiramatsu return ret; 4064b4da7f7SMasami Hiramatsu } 4074b4da7f7SMasami Hiramatsu 408cf6eb489SMasami Hiramatsu static int show_available_vars_at(int fd, struct perf_probe_event *pev, 409fb8c5a56SMasami Hiramatsu int max_vls, bool externs) 410cf6eb489SMasami Hiramatsu { 411cf6eb489SMasami Hiramatsu char *buf; 412cf6eb489SMasami Hiramatsu int ret, i; 413cf6eb489SMasami Hiramatsu struct str_node *node; 414cf6eb489SMasami Hiramatsu struct variable_list *vls = NULL, *vl; 415cf6eb489SMasami Hiramatsu 416cf6eb489SMasami Hiramatsu buf = synthesize_perf_probe_point(&pev->point); 417cf6eb489SMasami Hiramatsu if (!buf) 418cf6eb489SMasami Hiramatsu return -EINVAL; 419cf6eb489SMasami Hiramatsu pr_debug("Searching variables at %s\n", buf); 420cf6eb489SMasami Hiramatsu 421fb8c5a56SMasami Hiramatsu ret = find_available_vars_at(fd, pev, &vls, max_vls, externs); 422cf6eb489SMasami Hiramatsu if (ret > 0) { 423cf6eb489SMasami Hiramatsu /* Some variables were found */ 424cf6eb489SMasami Hiramatsu fprintf(stdout, "Available variables at %s\n", buf); 425cf6eb489SMasami Hiramatsu for (i = 0; i < ret; i++) { 426cf6eb489SMasami Hiramatsu vl = &vls[i]; 427cf6eb489SMasami Hiramatsu /* 428cf6eb489SMasami Hiramatsu * A probe point might be converted to 429cf6eb489SMasami Hiramatsu * several trace points. 430cf6eb489SMasami Hiramatsu */ 431cf6eb489SMasami Hiramatsu fprintf(stdout, "\t@<%s+%lu>\n", vl->point.symbol, 432cf6eb489SMasami Hiramatsu vl->point.offset); 433cf6eb489SMasami Hiramatsu free(vl->point.symbol); 434cf6eb489SMasami Hiramatsu if (vl->vars) { 435cf6eb489SMasami Hiramatsu strlist__for_each(node, vl->vars) 436cf6eb489SMasami Hiramatsu fprintf(stdout, "\t\t%s\n", node->s); 437cf6eb489SMasami Hiramatsu strlist__delete(vl->vars); 438cf6eb489SMasami Hiramatsu } else 439cf6eb489SMasami Hiramatsu fprintf(stdout, "(No variables)\n"); 440cf6eb489SMasami Hiramatsu } 441cf6eb489SMasami Hiramatsu free(vls); 442cf6eb489SMasami Hiramatsu } else 443cf6eb489SMasami Hiramatsu pr_err("Failed to find variables at %s (%d)\n", buf, ret); 444cf6eb489SMasami Hiramatsu 445cf6eb489SMasami Hiramatsu free(buf); 446cf6eb489SMasami Hiramatsu return ret; 447cf6eb489SMasami Hiramatsu } 448cf6eb489SMasami Hiramatsu 449cf6eb489SMasami Hiramatsu /* Show available variables on given probe point */ 450cf6eb489SMasami Hiramatsu int show_available_vars(struct perf_probe_event *pevs, int npevs, 451469b9b88SMasami Hiramatsu int max_vls, const char *module, bool externs) 452cf6eb489SMasami Hiramatsu { 453cf6eb489SMasami Hiramatsu int i, fd, ret = 0; 454cf6eb489SMasami Hiramatsu 455cf6eb489SMasami Hiramatsu ret = init_vmlinux(); 456cf6eb489SMasami Hiramatsu if (ret < 0) 457cf6eb489SMasami Hiramatsu return ret; 458cf6eb489SMasami Hiramatsu 459469b9b88SMasami Hiramatsu fd = open_vmlinux(module); 460cf6eb489SMasami Hiramatsu if (fd < 0) { 4610e43e5d2SMasami Hiramatsu pr_warning("Failed to open debug information file.\n"); 462cf6eb489SMasami Hiramatsu return fd; 463cf6eb489SMasami Hiramatsu } 464cf6eb489SMasami Hiramatsu 465cf6eb489SMasami Hiramatsu setup_pager(); 466cf6eb489SMasami Hiramatsu 467cf6eb489SMasami Hiramatsu for (i = 0; i < npevs && ret >= 0; i++) 468fb8c5a56SMasami Hiramatsu ret = show_available_vars_at(fd, &pevs[i], max_vls, externs); 469cf6eb489SMasami Hiramatsu 470cf6eb489SMasami Hiramatsu close(fd); 471cf6eb489SMasami Hiramatsu return ret; 472cf6eb489SMasami Hiramatsu } 473cf6eb489SMasami Hiramatsu 4744b4da7f7SMasami Hiramatsu #else /* !DWARF_SUPPORT */ 4754b4da7f7SMasami Hiramatsu 4760e60836bSSrikar Dronamraju static int kprobe_convert_to_perf_probe(struct probe_trace_point *tp, 4774b4da7f7SMasami Hiramatsu struct perf_probe_point *pp) 4784b4da7f7SMasami Hiramatsu { 479469b9b88SMasami Hiramatsu struct symbol *sym; 480469b9b88SMasami Hiramatsu 481469b9b88SMasami Hiramatsu sym = __find_kernel_function_by_name(tp->symbol, NULL); 482469b9b88SMasami Hiramatsu if (!sym) { 483469b9b88SMasami Hiramatsu pr_err("Failed to find symbol %s in kernel.\n", tp->symbol); 484469b9b88SMasami Hiramatsu return -ENOENT; 485469b9b88SMasami Hiramatsu } 48602b95dadSMasami Hiramatsu pp->function = strdup(tp->symbol); 48702b95dadSMasami Hiramatsu if (pp->function == NULL) 48802b95dadSMasami Hiramatsu return -ENOMEM; 4894b4da7f7SMasami Hiramatsu pp->offset = tp->offset; 4904b4da7f7SMasami Hiramatsu pp->retprobe = tp->retprobe; 491146a1439SMasami Hiramatsu 492146a1439SMasami Hiramatsu return 0; 4934b4da7f7SMasami Hiramatsu } 4944b4da7f7SMasami Hiramatsu 4950e60836bSSrikar Dronamraju static int try_to_find_probe_trace_events(struct perf_probe_event *pev, 4960e60836bSSrikar Dronamraju struct probe_trace_event **tevs __unused, 497469b9b88SMasami Hiramatsu int max_tevs __unused, const char *mod __unused) 4984b4da7f7SMasami Hiramatsu { 499146a1439SMasami Hiramatsu if (perf_probe_event_need_dwarf(pev)) { 500146a1439SMasami Hiramatsu pr_warning("Debuginfo-analysis is not supported.\n"); 501146a1439SMasami Hiramatsu return -ENOSYS; 502146a1439SMasami Hiramatsu } 5034b4da7f7SMasami Hiramatsu return 0; 5044b4da7f7SMasami Hiramatsu } 5054b4da7f7SMasami Hiramatsu 506469b9b88SMasami Hiramatsu int show_line_range(struct line_range *lr __unused, const char *module __unused) 5074b4da7f7SMasami Hiramatsu { 508146a1439SMasami Hiramatsu pr_warning("Debuginfo-analysis is not supported.\n"); 509146a1439SMasami Hiramatsu return -ENOSYS; 5104b4da7f7SMasami Hiramatsu } 5114b4da7f7SMasami Hiramatsu 512cf6eb489SMasami Hiramatsu int show_available_vars(struct perf_probe_event *pevs __unused, 513469b9b88SMasami Hiramatsu int npevs __unused, int max_vls __unused, 514469b9b88SMasami Hiramatsu const char *module __unused, bool externs __unused) 515cf6eb489SMasami Hiramatsu { 516cf6eb489SMasami Hiramatsu pr_warning("Debuginfo-analysis is not supported.\n"); 517cf6eb489SMasami Hiramatsu return -ENOSYS; 518cf6eb489SMasami Hiramatsu } 519e0faa8d3SMasami Hiramatsu #endif 520e0faa8d3SMasami Hiramatsu 521146a1439SMasami Hiramatsu int parse_line_range_desc(const char *arg, struct line_range *lr) 522631c9defSMasami Hiramatsu { 523631c9defSMasami Hiramatsu const char *ptr; 524631c9defSMasami Hiramatsu char *tmp; 525631c9defSMasami Hiramatsu /* 526631c9defSMasami Hiramatsu * <Syntax> 527631c9defSMasami Hiramatsu * SRC:SLN[+NUM|-ELN] 528631c9defSMasami Hiramatsu * FUNC[:SLN[+NUM|-ELN]] 529631c9defSMasami Hiramatsu */ 530631c9defSMasami Hiramatsu ptr = strchr(arg, ':'); 531631c9defSMasami Hiramatsu if (ptr) { 532d3b63d7aSMasami Hiramatsu lr->start = (int)strtoul(ptr + 1, &tmp, 0); 533dda4ab34SMasami Hiramatsu if (*tmp == '+') { 534d3b63d7aSMasami Hiramatsu lr->end = lr->start + (int)strtoul(tmp + 1, &tmp, 0); 535dda4ab34SMasami Hiramatsu lr->end--; /* 536dda4ab34SMasami Hiramatsu * Adjust the number of lines here. 537dda4ab34SMasami Hiramatsu * If the number of lines == 1, the 538dda4ab34SMasami Hiramatsu * the end of line should be equal to 539dda4ab34SMasami Hiramatsu * the start of line. 540dda4ab34SMasami Hiramatsu */ 541dda4ab34SMasami Hiramatsu } else if (*tmp == '-') 542d3b63d7aSMasami Hiramatsu lr->end = (int)strtoul(tmp + 1, &tmp, 0); 543631c9defSMasami Hiramatsu else 544d3b63d7aSMasami Hiramatsu lr->end = INT_MAX; 545d3b63d7aSMasami Hiramatsu pr_debug("Line range is %d to %d\n", lr->start, lr->end); 546d3b63d7aSMasami Hiramatsu if (lr->start > lr->end) { 547631c9defSMasami Hiramatsu semantic_error("Start line must be smaller" 548146a1439SMasami Hiramatsu " than end line.\n"); 549146a1439SMasami Hiramatsu return -EINVAL; 550146a1439SMasami Hiramatsu } 551146a1439SMasami Hiramatsu if (*tmp != '\0') { 552146a1439SMasami Hiramatsu semantic_error("Tailing with invalid character '%d'.\n", 553631c9defSMasami Hiramatsu *tmp); 554146a1439SMasami Hiramatsu return -EINVAL; 555146a1439SMasami Hiramatsu } 55602b95dadSMasami Hiramatsu tmp = strndup(arg, (ptr - arg)); 557d3b63d7aSMasami Hiramatsu } else { 55802b95dadSMasami Hiramatsu tmp = strdup(arg); 559d3b63d7aSMasami Hiramatsu lr->end = INT_MAX; 560d3b63d7aSMasami Hiramatsu } 56102b95dadSMasami Hiramatsu 56202b95dadSMasami Hiramatsu if (tmp == NULL) 56302b95dadSMasami Hiramatsu return -ENOMEM; 564631c9defSMasami Hiramatsu 565631c9defSMasami Hiramatsu if (strchr(tmp, '.')) 566631c9defSMasami Hiramatsu lr->file = tmp; 567631c9defSMasami Hiramatsu else 568631c9defSMasami Hiramatsu lr->function = tmp; 569146a1439SMasami Hiramatsu 570146a1439SMasami Hiramatsu return 0; 571631c9defSMasami Hiramatsu } 572631c9defSMasami Hiramatsu 573b7702a21SMasami Hiramatsu /* Check the name is good for event/group */ 574b7702a21SMasami Hiramatsu static bool check_event_name(const char *name) 575b7702a21SMasami Hiramatsu { 576b7702a21SMasami Hiramatsu if (!isalpha(*name) && *name != '_') 577b7702a21SMasami Hiramatsu return false; 578b7702a21SMasami Hiramatsu while (*++name != '\0') { 579b7702a21SMasami Hiramatsu if (!isalpha(*name) && !isdigit(*name) && *name != '_') 580b7702a21SMasami Hiramatsu return false; 581b7702a21SMasami Hiramatsu } 582b7702a21SMasami Hiramatsu return true; 583b7702a21SMasami Hiramatsu } 584b7702a21SMasami Hiramatsu 58550656eecSMasami Hiramatsu /* Parse probepoint definition. */ 586146a1439SMasami Hiramatsu static int parse_perf_probe_point(char *arg, struct perf_probe_event *pev) 58750656eecSMasami Hiramatsu { 5884235b045SMasami Hiramatsu struct perf_probe_point *pp = &pev->point; 58950656eecSMasami Hiramatsu char *ptr, *tmp; 59050656eecSMasami Hiramatsu char c, nc = 0; 59150656eecSMasami Hiramatsu /* 59250656eecSMasami Hiramatsu * <Syntax> 5932a9c8c36SMasami Hiramatsu * perf probe [EVENT=]SRC[:LN|;PTN] 5942a9c8c36SMasami Hiramatsu * perf probe [EVENT=]FUNC[@SRC][+OFFS|%return|:LN|;PAT] 595af663d75SMasami Hiramatsu * 596af663d75SMasami Hiramatsu * TODO:Group name support 59750656eecSMasami Hiramatsu */ 59850656eecSMasami Hiramatsu 5992a9c8c36SMasami Hiramatsu ptr = strpbrk(arg, ";=@+%"); 6002a9c8c36SMasami Hiramatsu if (ptr && *ptr == '=') { /* Event name */ 601af663d75SMasami Hiramatsu *ptr = '\0'; 602af663d75SMasami Hiramatsu tmp = ptr + 1; 603146a1439SMasami Hiramatsu if (strchr(arg, ':')) { 604146a1439SMasami Hiramatsu semantic_error("Group name is not supported yet.\n"); 605146a1439SMasami Hiramatsu return -ENOTSUP; 606146a1439SMasami Hiramatsu } 607146a1439SMasami Hiramatsu if (!check_event_name(arg)) { 608b7702a21SMasami Hiramatsu semantic_error("%s is bad for event name -it must " 609146a1439SMasami Hiramatsu "follow C symbol-naming rule.\n", arg); 610146a1439SMasami Hiramatsu return -EINVAL; 611146a1439SMasami Hiramatsu } 61202b95dadSMasami Hiramatsu pev->event = strdup(arg); 61302b95dadSMasami Hiramatsu if (pev->event == NULL) 61402b95dadSMasami Hiramatsu return -ENOMEM; 6154235b045SMasami Hiramatsu pev->group = NULL; 616af663d75SMasami Hiramatsu arg = tmp; 617af663d75SMasami Hiramatsu } 618af663d75SMasami Hiramatsu 6192a9c8c36SMasami Hiramatsu ptr = strpbrk(arg, ";:+@%"); 62050656eecSMasami Hiramatsu if (ptr) { 62150656eecSMasami Hiramatsu nc = *ptr; 62250656eecSMasami Hiramatsu *ptr++ = '\0'; 62350656eecSMasami Hiramatsu } 62450656eecSMasami Hiramatsu 62502b95dadSMasami Hiramatsu tmp = strdup(arg); 62602b95dadSMasami Hiramatsu if (tmp == NULL) 62702b95dadSMasami Hiramatsu return -ENOMEM; 62802b95dadSMasami Hiramatsu 62950656eecSMasami Hiramatsu /* Check arg is function or file and copy it */ 63002b95dadSMasami Hiramatsu if (strchr(tmp, '.')) /* File */ 63102b95dadSMasami Hiramatsu pp->file = tmp; 63250656eecSMasami Hiramatsu else /* Function */ 63302b95dadSMasami Hiramatsu pp->function = tmp; 63450656eecSMasami Hiramatsu 63550656eecSMasami Hiramatsu /* Parse other options */ 63650656eecSMasami Hiramatsu while (ptr) { 63750656eecSMasami Hiramatsu arg = ptr; 63850656eecSMasami Hiramatsu c = nc; 6392a9c8c36SMasami Hiramatsu if (c == ';') { /* Lazy pattern must be the last part */ 64002b95dadSMasami Hiramatsu pp->lazy_line = strdup(arg); 64102b95dadSMasami Hiramatsu if (pp->lazy_line == NULL) 64202b95dadSMasami Hiramatsu return -ENOMEM; 6432a9c8c36SMasami Hiramatsu break; 6442a9c8c36SMasami Hiramatsu } 6452a9c8c36SMasami Hiramatsu ptr = strpbrk(arg, ";:+@%"); 64650656eecSMasami Hiramatsu if (ptr) { 64750656eecSMasami Hiramatsu nc = *ptr; 64850656eecSMasami Hiramatsu *ptr++ = '\0'; 64950656eecSMasami Hiramatsu } 65050656eecSMasami Hiramatsu switch (c) { 65150656eecSMasami Hiramatsu case ':': /* Line number */ 65250656eecSMasami Hiramatsu pp->line = strtoul(arg, &tmp, 0); 653146a1439SMasami Hiramatsu if (*tmp != '\0') { 6542a9c8c36SMasami Hiramatsu semantic_error("There is non-digit char" 655146a1439SMasami Hiramatsu " in line number.\n"); 656146a1439SMasami Hiramatsu return -EINVAL; 657146a1439SMasami Hiramatsu } 65850656eecSMasami Hiramatsu break; 65950656eecSMasami Hiramatsu case '+': /* Byte offset from a symbol */ 66050656eecSMasami Hiramatsu pp->offset = strtoul(arg, &tmp, 0); 661146a1439SMasami Hiramatsu if (*tmp != '\0') { 6622a9c8c36SMasami Hiramatsu semantic_error("There is non-digit character" 663146a1439SMasami Hiramatsu " in offset.\n"); 664146a1439SMasami Hiramatsu return -EINVAL; 665146a1439SMasami Hiramatsu } 66650656eecSMasami Hiramatsu break; 66750656eecSMasami Hiramatsu case '@': /* File name */ 668146a1439SMasami Hiramatsu if (pp->file) { 669146a1439SMasami Hiramatsu semantic_error("SRC@SRC is not allowed.\n"); 670146a1439SMasami Hiramatsu return -EINVAL; 671146a1439SMasami Hiramatsu } 67202b95dadSMasami Hiramatsu pp->file = strdup(arg); 67302b95dadSMasami Hiramatsu if (pp->file == NULL) 67402b95dadSMasami Hiramatsu return -ENOMEM; 67550656eecSMasami Hiramatsu break; 67650656eecSMasami Hiramatsu case '%': /* Probe places */ 67750656eecSMasami Hiramatsu if (strcmp(arg, "return") == 0) { 67850656eecSMasami Hiramatsu pp->retprobe = 1; 679146a1439SMasami Hiramatsu } else { /* Others not supported yet */ 680146a1439SMasami Hiramatsu semantic_error("%%%s is not supported.\n", arg); 681146a1439SMasami Hiramatsu return -ENOTSUP; 682146a1439SMasami Hiramatsu } 68350656eecSMasami Hiramatsu break; 684146a1439SMasami Hiramatsu default: /* Buggy case */ 685146a1439SMasami Hiramatsu pr_err("This program has a bug at %s:%d.\n", 686146a1439SMasami Hiramatsu __FILE__, __LINE__); 687146a1439SMasami Hiramatsu return -ENOTSUP; 68850656eecSMasami Hiramatsu break; 68950656eecSMasami Hiramatsu } 69050656eecSMasami Hiramatsu } 69150656eecSMasami Hiramatsu 69250656eecSMasami Hiramatsu /* Exclusion check */ 693146a1439SMasami Hiramatsu if (pp->lazy_line && pp->line) { 6940e43e5d2SMasami Hiramatsu semantic_error("Lazy pattern can't be used with" 6950e43e5d2SMasami Hiramatsu " line number.\n"); 696146a1439SMasami Hiramatsu return -EINVAL; 697146a1439SMasami Hiramatsu } 6982a9c8c36SMasami Hiramatsu 699146a1439SMasami Hiramatsu if (pp->lazy_line && pp->offset) { 7000e43e5d2SMasami Hiramatsu semantic_error("Lazy pattern can't be used with offset.\n"); 701146a1439SMasami Hiramatsu return -EINVAL; 702146a1439SMasami Hiramatsu } 7032a9c8c36SMasami Hiramatsu 704146a1439SMasami Hiramatsu if (pp->line && pp->offset) { 7050e43e5d2SMasami Hiramatsu semantic_error("Offset can't be used with line number.\n"); 706146a1439SMasami Hiramatsu return -EINVAL; 707146a1439SMasami Hiramatsu } 70850656eecSMasami Hiramatsu 709146a1439SMasami Hiramatsu if (!pp->line && !pp->lazy_line && pp->file && !pp->function) { 7102a9c8c36SMasami Hiramatsu semantic_error("File always requires line number or " 7110e43e5d2SMasami Hiramatsu "lazy pattern.\n"); 712146a1439SMasami Hiramatsu return -EINVAL; 713146a1439SMasami Hiramatsu } 71450656eecSMasami Hiramatsu 715146a1439SMasami Hiramatsu if (pp->offset && !pp->function) { 7160e43e5d2SMasami Hiramatsu semantic_error("Offset requires an entry function.\n"); 717146a1439SMasami Hiramatsu return -EINVAL; 718146a1439SMasami Hiramatsu } 71950656eecSMasami Hiramatsu 720146a1439SMasami Hiramatsu if (pp->retprobe && !pp->function) { 7210e43e5d2SMasami Hiramatsu semantic_error("Return probe requires an entry function.\n"); 722146a1439SMasami Hiramatsu return -EINVAL; 723146a1439SMasami Hiramatsu } 72450656eecSMasami Hiramatsu 725146a1439SMasami Hiramatsu if ((pp->offset || pp->line || pp->lazy_line) && pp->retprobe) { 7262a9c8c36SMasami Hiramatsu semantic_error("Offset/Line/Lazy pattern can't be used with " 7270e43e5d2SMasami Hiramatsu "return probe.\n"); 728146a1439SMasami Hiramatsu return -EINVAL; 729146a1439SMasami Hiramatsu } 73050656eecSMasami Hiramatsu 7314235b045SMasami Hiramatsu pr_debug("symbol:%s file:%s line:%d offset:%lu return:%d lazy:%s\n", 7322a9c8c36SMasami Hiramatsu pp->function, pp->file, pp->line, pp->offset, pp->retprobe, 7332a9c8c36SMasami Hiramatsu pp->lazy_line); 734146a1439SMasami Hiramatsu return 0; 73550656eecSMasami Hiramatsu } 73650656eecSMasami Hiramatsu 7377df2f329SMasami Hiramatsu /* Parse perf-probe event argument */ 738146a1439SMasami Hiramatsu static int parse_perf_probe_arg(char *str, struct perf_probe_arg *arg) 7397df2f329SMasami Hiramatsu { 740b2a3c12bSMasami Hiramatsu char *tmp, *goodname; 7417df2f329SMasami Hiramatsu struct perf_probe_arg_field **fieldp; 7427df2f329SMasami Hiramatsu 7437df2f329SMasami Hiramatsu pr_debug("parsing arg: %s into ", str); 7447df2f329SMasami Hiramatsu 74548481938SMasami Hiramatsu tmp = strchr(str, '='); 74648481938SMasami Hiramatsu if (tmp) { 74702b95dadSMasami Hiramatsu arg->name = strndup(str, tmp - str); 74802b95dadSMasami Hiramatsu if (arg->name == NULL) 74902b95dadSMasami Hiramatsu return -ENOMEM; 75011a1ca35SMasami Hiramatsu pr_debug("name:%s ", arg->name); 75148481938SMasami Hiramatsu str = tmp + 1; 75248481938SMasami Hiramatsu } 75348481938SMasami Hiramatsu 75411a1ca35SMasami Hiramatsu tmp = strchr(str, ':'); 75511a1ca35SMasami Hiramatsu if (tmp) { /* Type setting */ 75611a1ca35SMasami Hiramatsu *tmp = '\0'; 75702b95dadSMasami Hiramatsu arg->type = strdup(tmp + 1); 75802b95dadSMasami Hiramatsu if (arg->type == NULL) 75902b95dadSMasami Hiramatsu return -ENOMEM; 76011a1ca35SMasami Hiramatsu pr_debug("type:%s ", arg->type); 76111a1ca35SMasami Hiramatsu } 76211a1ca35SMasami Hiramatsu 763b2a3c12bSMasami Hiramatsu tmp = strpbrk(str, "-.["); 7647df2f329SMasami Hiramatsu if (!is_c_varname(str) || !tmp) { 7657df2f329SMasami Hiramatsu /* A variable, register, symbol or special value */ 76602b95dadSMasami Hiramatsu arg->var = strdup(str); 76702b95dadSMasami Hiramatsu if (arg->var == NULL) 76802b95dadSMasami Hiramatsu return -ENOMEM; 76948481938SMasami Hiramatsu pr_debug("%s\n", arg->var); 770146a1439SMasami Hiramatsu return 0; 7717df2f329SMasami Hiramatsu } 7727df2f329SMasami Hiramatsu 773b2a3c12bSMasami Hiramatsu /* Structure fields or array element */ 77402b95dadSMasami Hiramatsu arg->var = strndup(str, tmp - str); 77502b95dadSMasami Hiramatsu if (arg->var == NULL) 77602b95dadSMasami Hiramatsu return -ENOMEM; 777b2a3c12bSMasami Hiramatsu goodname = arg->var; 77848481938SMasami Hiramatsu pr_debug("%s, ", arg->var); 7797df2f329SMasami Hiramatsu fieldp = &arg->field; 7807df2f329SMasami Hiramatsu 7817df2f329SMasami Hiramatsu do { 782e334016fSMasami Hiramatsu *fieldp = zalloc(sizeof(struct perf_probe_arg_field)); 783e334016fSMasami Hiramatsu if (*fieldp == NULL) 784e334016fSMasami Hiramatsu return -ENOMEM; 785b2a3c12bSMasami Hiramatsu if (*tmp == '[') { /* Array */ 786b2a3c12bSMasami Hiramatsu str = tmp; 787b2a3c12bSMasami Hiramatsu (*fieldp)->index = strtol(str + 1, &tmp, 0); 788b2a3c12bSMasami Hiramatsu (*fieldp)->ref = true; 789b2a3c12bSMasami Hiramatsu if (*tmp != ']' || tmp == str + 1) { 790b2a3c12bSMasami Hiramatsu semantic_error("Array index must be a" 791b2a3c12bSMasami Hiramatsu " number.\n"); 792b2a3c12bSMasami Hiramatsu return -EINVAL; 793b2a3c12bSMasami Hiramatsu } 794b2a3c12bSMasami Hiramatsu tmp++; 795b2a3c12bSMasami Hiramatsu if (*tmp == '\0') 796b2a3c12bSMasami Hiramatsu tmp = NULL; 797b2a3c12bSMasami Hiramatsu } else { /* Structure */ 7987df2f329SMasami Hiramatsu if (*tmp == '.') { 7997df2f329SMasami Hiramatsu str = tmp + 1; 8007df2f329SMasami Hiramatsu (*fieldp)->ref = false; 8017df2f329SMasami Hiramatsu } else if (tmp[1] == '>') { 8027df2f329SMasami Hiramatsu str = tmp + 2; 8037df2f329SMasami Hiramatsu (*fieldp)->ref = true; 804146a1439SMasami Hiramatsu } else { 805b2a3c12bSMasami Hiramatsu semantic_error("Argument parse error: %s\n", 806b2a3c12bSMasami Hiramatsu str); 807146a1439SMasami Hiramatsu return -EINVAL; 808146a1439SMasami Hiramatsu } 809b2a3c12bSMasami Hiramatsu tmp = strpbrk(str, "-.["); 810b2a3c12bSMasami Hiramatsu } 8117df2f329SMasami Hiramatsu if (tmp) { 81202b95dadSMasami Hiramatsu (*fieldp)->name = strndup(str, tmp - str); 81302b95dadSMasami Hiramatsu if ((*fieldp)->name == NULL) 81402b95dadSMasami Hiramatsu return -ENOMEM; 815b2a3c12bSMasami Hiramatsu if (*str != '[') 816b2a3c12bSMasami Hiramatsu goodname = (*fieldp)->name; 8177df2f329SMasami Hiramatsu pr_debug("%s(%d), ", (*fieldp)->name, (*fieldp)->ref); 8187df2f329SMasami Hiramatsu fieldp = &(*fieldp)->next; 8197df2f329SMasami Hiramatsu } 8207df2f329SMasami Hiramatsu } while (tmp); 82102b95dadSMasami Hiramatsu (*fieldp)->name = strdup(str); 82202b95dadSMasami Hiramatsu if ((*fieldp)->name == NULL) 82302b95dadSMasami Hiramatsu return -ENOMEM; 824b2a3c12bSMasami Hiramatsu if (*str != '[') 825b2a3c12bSMasami Hiramatsu goodname = (*fieldp)->name; 8267df2f329SMasami Hiramatsu pr_debug("%s(%d)\n", (*fieldp)->name, (*fieldp)->ref); 827df0faf4bSMasami Hiramatsu 828b2a3c12bSMasami Hiramatsu /* If no name is specified, set the last field name (not array index)*/ 82902b95dadSMasami Hiramatsu if (!arg->name) { 830b2a3c12bSMasami Hiramatsu arg->name = strdup(goodname); 83102b95dadSMasami Hiramatsu if (arg->name == NULL) 83202b95dadSMasami Hiramatsu return -ENOMEM; 83302b95dadSMasami Hiramatsu } 834146a1439SMasami Hiramatsu return 0; 8357df2f329SMasami Hiramatsu } 8367df2f329SMasami Hiramatsu 8374235b045SMasami Hiramatsu /* Parse perf-probe event command */ 838146a1439SMasami Hiramatsu int parse_perf_probe_command(const char *cmd, struct perf_probe_event *pev) 83950656eecSMasami Hiramatsu { 840e1c01d61SMasami Hiramatsu char **argv; 841146a1439SMasami Hiramatsu int argc, i, ret = 0; 842fac13fd5SMasami Hiramatsu 8434235b045SMasami Hiramatsu argv = argv_split(cmd, &argc); 844146a1439SMasami Hiramatsu if (!argv) { 845146a1439SMasami Hiramatsu pr_debug("Failed to split arguments.\n"); 846146a1439SMasami Hiramatsu return -ENOMEM; 847146a1439SMasami Hiramatsu } 848146a1439SMasami Hiramatsu if (argc - 1 > MAX_PROBE_ARGS) { 849146a1439SMasami Hiramatsu semantic_error("Too many probe arguments (%d).\n", argc - 1); 850146a1439SMasami Hiramatsu ret = -ERANGE; 851146a1439SMasami Hiramatsu goto out; 852146a1439SMasami Hiramatsu } 85350656eecSMasami Hiramatsu /* Parse probe point */ 854146a1439SMasami Hiramatsu ret = parse_perf_probe_point(argv[0], pev); 855146a1439SMasami Hiramatsu if (ret < 0) 856146a1439SMasami Hiramatsu goto out; 85750656eecSMasami Hiramatsu 858e1c01d61SMasami Hiramatsu /* Copy arguments and ensure return probe has no C argument */ 8594235b045SMasami Hiramatsu pev->nargs = argc - 1; 860e334016fSMasami Hiramatsu pev->args = zalloc(sizeof(struct perf_probe_arg) * pev->nargs); 861e334016fSMasami Hiramatsu if (pev->args == NULL) { 862e334016fSMasami Hiramatsu ret = -ENOMEM; 863e334016fSMasami Hiramatsu goto out; 864e334016fSMasami Hiramatsu } 865146a1439SMasami Hiramatsu for (i = 0; i < pev->nargs && ret >= 0; i++) { 866146a1439SMasami Hiramatsu ret = parse_perf_probe_arg(argv[i + 1], &pev->args[i]); 867146a1439SMasami Hiramatsu if (ret >= 0 && 868146a1439SMasami Hiramatsu is_c_varname(pev->args[i].var) && pev->point.retprobe) { 8694235b045SMasami Hiramatsu semantic_error("You can't specify local variable for" 870146a1439SMasami Hiramatsu " kretprobe.\n"); 871146a1439SMasami Hiramatsu ret = -EINVAL; 872e1c01d61SMasami Hiramatsu } 873146a1439SMasami Hiramatsu } 874146a1439SMasami Hiramatsu out: 875e1c01d61SMasami Hiramatsu argv_free(argv); 876146a1439SMasami Hiramatsu 877146a1439SMasami Hiramatsu return ret; 87850656eecSMasami Hiramatsu } 87950656eecSMasami Hiramatsu 8804235b045SMasami Hiramatsu /* Return true if this perf_probe_event requires debuginfo */ 8814235b045SMasami Hiramatsu bool perf_probe_event_need_dwarf(struct perf_probe_event *pev) 8824de189feSMasami Hiramatsu { 8834235b045SMasami Hiramatsu int i; 8844235b045SMasami Hiramatsu 8854235b045SMasami Hiramatsu if (pev->point.file || pev->point.line || pev->point.lazy_line) 8864235b045SMasami Hiramatsu return true; 8874235b045SMasami Hiramatsu 8884235b045SMasami Hiramatsu for (i = 0; i < pev->nargs; i++) 88948481938SMasami Hiramatsu if (is_c_varname(pev->args[i].var)) 8904235b045SMasami Hiramatsu return true; 8914235b045SMasami Hiramatsu 8924235b045SMasami Hiramatsu return false; 8934235b045SMasami Hiramatsu } 8944235b045SMasami Hiramatsu 8950e60836bSSrikar Dronamraju /* Parse probe_events event into struct probe_point */ 8960e60836bSSrikar Dronamraju static int parse_probe_trace_command(const char *cmd, 8970e60836bSSrikar Dronamraju struct probe_trace_event *tev) 8984235b045SMasami Hiramatsu { 8990e60836bSSrikar Dronamraju struct probe_trace_point *tp = &tev->point; 9004de189feSMasami Hiramatsu char pr; 9014de189feSMasami Hiramatsu char *p; 9024de189feSMasami Hiramatsu int ret, i, argc; 9034de189feSMasami Hiramatsu char **argv; 9044de189feSMasami Hiramatsu 9050e60836bSSrikar Dronamraju pr_debug("Parsing probe_events: %s\n", cmd); 9064235b045SMasami Hiramatsu argv = argv_split(cmd, &argc); 907146a1439SMasami Hiramatsu if (!argv) { 908146a1439SMasami Hiramatsu pr_debug("Failed to split arguments.\n"); 909146a1439SMasami Hiramatsu return -ENOMEM; 910146a1439SMasami Hiramatsu } 911146a1439SMasami Hiramatsu if (argc < 2) { 912146a1439SMasami Hiramatsu semantic_error("Too few probe arguments.\n"); 913146a1439SMasami Hiramatsu ret = -ERANGE; 914146a1439SMasami Hiramatsu goto out; 915146a1439SMasami Hiramatsu } 9164de189feSMasami Hiramatsu 9174de189feSMasami Hiramatsu /* Scan event and group name. */ 91893aaa45aSLiming Wang ret = sscanf(argv[0], "%c:%a[^/ \t]/%a[^ \t]", 9194235b045SMasami Hiramatsu &pr, (float *)(void *)&tev->group, 9204235b045SMasami Hiramatsu (float *)(void *)&tev->event); 921146a1439SMasami Hiramatsu if (ret != 3) { 922146a1439SMasami Hiramatsu semantic_error("Failed to parse event name: %s\n", argv[0]); 923146a1439SMasami Hiramatsu ret = -EINVAL; 924146a1439SMasami Hiramatsu goto out; 925146a1439SMasami Hiramatsu } 9264235b045SMasami Hiramatsu pr_debug("Group:%s Event:%s probe:%c\n", tev->group, tev->event, pr); 9274de189feSMasami Hiramatsu 9284235b045SMasami Hiramatsu tp->retprobe = (pr == 'r'); 9294de189feSMasami Hiramatsu 9304de189feSMasami Hiramatsu /* Scan function name and offset */ 9314235b045SMasami Hiramatsu ret = sscanf(argv[1], "%a[^+]+%lu", (float *)(void *)&tp->symbol, 9324235b045SMasami Hiramatsu &tp->offset); 9334de189feSMasami Hiramatsu if (ret == 1) 9344235b045SMasami Hiramatsu tp->offset = 0; 9354de189feSMasami Hiramatsu 9364235b045SMasami Hiramatsu tev->nargs = argc - 2; 9370e60836bSSrikar Dronamraju tev->args = zalloc(sizeof(struct probe_trace_arg) * tev->nargs); 938e334016fSMasami Hiramatsu if (tev->args == NULL) { 939e334016fSMasami Hiramatsu ret = -ENOMEM; 940e334016fSMasami Hiramatsu goto out; 941e334016fSMasami Hiramatsu } 9424235b045SMasami Hiramatsu for (i = 0; i < tev->nargs; i++) { 9434de189feSMasami Hiramatsu p = strchr(argv[i + 2], '='); 9444de189feSMasami Hiramatsu if (p) /* We don't need which register is assigned. */ 9454235b045SMasami Hiramatsu *p++ = '\0'; 9464235b045SMasami Hiramatsu else 9474235b045SMasami Hiramatsu p = argv[i + 2]; 94802b95dadSMasami Hiramatsu tev->args[i].name = strdup(argv[i + 2]); 9494235b045SMasami Hiramatsu /* TODO: parse regs and offset */ 95002b95dadSMasami Hiramatsu tev->args[i].value = strdup(p); 95102b95dadSMasami Hiramatsu if (tev->args[i].name == NULL || tev->args[i].value == NULL) { 95202b95dadSMasami Hiramatsu ret = -ENOMEM; 95302b95dadSMasami Hiramatsu goto out; 95402b95dadSMasami Hiramatsu } 9554de189feSMasami Hiramatsu } 956146a1439SMasami Hiramatsu ret = 0; 957146a1439SMasami Hiramatsu out: 9584de189feSMasami Hiramatsu argv_free(argv); 959146a1439SMasami Hiramatsu return ret; 9604de189feSMasami Hiramatsu } 9614de189feSMasami Hiramatsu 9627df2f329SMasami Hiramatsu /* Compose only probe arg */ 9637df2f329SMasami Hiramatsu int synthesize_perf_probe_arg(struct perf_probe_arg *pa, char *buf, size_t len) 9647df2f329SMasami Hiramatsu { 9657df2f329SMasami Hiramatsu struct perf_probe_arg_field *field = pa->field; 9667df2f329SMasami Hiramatsu int ret; 9677df2f329SMasami Hiramatsu char *tmp = buf; 9687df2f329SMasami Hiramatsu 96948481938SMasami Hiramatsu if (pa->name && pa->var) 97048481938SMasami Hiramatsu ret = e_snprintf(tmp, len, "%s=%s", pa->name, pa->var); 97148481938SMasami Hiramatsu else 97248481938SMasami Hiramatsu ret = e_snprintf(tmp, len, "%s", pa->name ? pa->name : pa->var); 9737df2f329SMasami Hiramatsu if (ret <= 0) 9747df2f329SMasami Hiramatsu goto error; 9757df2f329SMasami Hiramatsu tmp += ret; 9767df2f329SMasami Hiramatsu len -= ret; 9777df2f329SMasami Hiramatsu 9787df2f329SMasami Hiramatsu while (field) { 979b2a3c12bSMasami Hiramatsu if (field->name[0] == '[') 980b2a3c12bSMasami Hiramatsu ret = e_snprintf(tmp, len, "%s", field->name); 981b2a3c12bSMasami Hiramatsu else 982b2a3c12bSMasami Hiramatsu ret = e_snprintf(tmp, len, "%s%s", 983b2a3c12bSMasami Hiramatsu field->ref ? "->" : ".", field->name); 9847df2f329SMasami Hiramatsu if (ret <= 0) 9857df2f329SMasami Hiramatsu goto error; 9867df2f329SMasami Hiramatsu tmp += ret; 9877df2f329SMasami Hiramatsu len -= ret; 9887df2f329SMasami Hiramatsu field = field->next; 9897df2f329SMasami Hiramatsu } 99011a1ca35SMasami Hiramatsu 99111a1ca35SMasami Hiramatsu if (pa->type) { 99211a1ca35SMasami Hiramatsu ret = e_snprintf(tmp, len, ":%s", pa->type); 99311a1ca35SMasami Hiramatsu if (ret <= 0) 99411a1ca35SMasami Hiramatsu goto error; 99511a1ca35SMasami Hiramatsu tmp += ret; 99611a1ca35SMasami Hiramatsu len -= ret; 99711a1ca35SMasami Hiramatsu } 99811a1ca35SMasami Hiramatsu 9997df2f329SMasami Hiramatsu return tmp - buf; 10007df2f329SMasami Hiramatsu error: 10010e43e5d2SMasami Hiramatsu pr_debug("Failed to synthesize perf probe argument: %s\n", 1002146a1439SMasami Hiramatsu strerror(-ret)); 1003146a1439SMasami Hiramatsu return ret; 10047df2f329SMasami Hiramatsu } 10057df2f329SMasami Hiramatsu 10064235b045SMasami Hiramatsu /* Compose only probe point (not argument) */ 10074235b045SMasami Hiramatsu static char *synthesize_perf_probe_point(struct perf_probe_point *pp) 100850656eecSMasami Hiramatsu { 1009fb1587d8SMasami Hiramatsu char *buf, *tmp; 1010fb1587d8SMasami Hiramatsu char offs[32] = "", line[32] = "", file[32] = ""; 1011fb1587d8SMasami Hiramatsu int ret, len; 101250656eecSMasami Hiramatsu 1013e334016fSMasami Hiramatsu buf = zalloc(MAX_CMDLEN); 1014e334016fSMasami Hiramatsu if (buf == NULL) { 1015e334016fSMasami Hiramatsu ret = -ENOMEM; 1016e334016fSMasami Hiramatsu goto error; 1017e334016fSMasami Hiramatsu } 10184de189feSMasami Hiramatsu if (pp->offset) { 1019fb1587d8SMasami Hiramatsu ret = e_snprintf(offs, 32, "+%lu", pp->offset); 10204de189feSMasami Hiramatsu if (ret <= 0) 10214de189feSMasami Hiramatsu goto error; 10224de189feSMasami Hiramatsu } 10234de189feSMasami Hiramatsu if (pp->line) { 1024fb1587d8SMasami Hiramatsu ret = e_snprintf(line, 32, ":%d", pp->line); 1025fb1587d8SMasami Hiramatsu if (ret <= 0) 1026fb1587d8SMasami Hiramatsu goto error; 1027fb1587d8SMasami Hiramatsu } 1028fb1587d8SMasami Hiramatsu if (pp->file) { 1029dd259c5dSMasami Hiramatsu len = strlen(pp->file) - 31; 1030fb1587d8SMasami Hiramatsu if (len < 0) 1031fb1587d8SMasami Hiramatsu len = 0; 1032fb1587d8SMasami Hiramatsu tmp = strchr(pp->file + len, '/'); 1033fb1587d8SMasami Hiramatsu if (!tmp) 1034dd259c5dSMasami Hiramatsu tmp = pp->file + len; 1035fb1587d8SMasami Hiramatsu ret = e_snprintf(file, 32, "@%s", tmp + 1); 10364de189feSMasami Hiramatsu if (ret <= 0) 10374de189feSMasami Hiramatsu goto error; 10384de189feSMasami Hiramatsu } 10394de189feSMasami Hiramatsu 10404de189feSMasami Hiramatsu if (pp->function) 1041fb1587d8SMasami Hiramatsu ret = e_snprintf(buf, MAX_CMDLEN, "%s%s%s%s%s", pp->function, 1042fb1587d8SMasami Hiramatsu offs, pp->retprobe ? "%return" : "", line, 1043fb1587d8SMasami Hiramatsu file); 10444de189feSMasami Hiramatsu else 1045fb1587d8SMasami Hiramatsu ret = e_snprintf(buf, MAX_CMDLEN, "%s%s", file, line); 10464235b045SMasami Hiramatsu if (ret <= 0) 10474235b045SMasami Hiramatsu goto error; 10484235b045SMasami Hiramatsu 10494235b045SMasami Hiramatsu return buf; 10504235b045SMasami Hiramatsu error: 10510e43e5d2SMasami Hiramatsu pr_debug("Failed to synthesize perf probe point: %s\n", 1052146a1439SMasami Hiramatsu strerror(-ret)); 1053e334016fSMasami Hiramatsu if (buf) 1054146a1439SMasami Hiramatsu free(buf); 1055146a1439SMasami Hiramatsu return NULL; 10564235b045SMasami Hiramatsu } 10574235b045SMasami Hiramatsu 10584235b045SMasami Hiramatsu #if 0 10594235b045SMasami Hiramatsu char *synthesize_perf_probe_command(struct perf_probe_event *pev) 10604235b045SMasami Hiramatsu { 10614235b045SMasami Hiramatsu char *buf; 10624235b045SMasami Hiramatsu int i, len, ret; 10634235b045SMasami Hiramatsu 10644235b045SMasami Hiramatsu buf = synthesize_perf_probe_point(&pev->point); 10654235b045SMasami Hiramatsu if (!buf) 10664235b045SMasami Hiramatsu return NULL; 10674235b045SMasami Hiramatsu 10684235b045SMasami Hiramatsu len = strlen(buf); 10694235b045SMasami Hiramatsu for (i = 0; i < pev->nargs; i++) { 10704235b045SMasami Hiramatsu ret = e_snprintf(&buf[len], MAX_CMDLEN - len, " %s", 10714235b045SMasami Hiramatsu pev->args[i].name); 10727ef17aafSMasami Hiramatsu if (ret <= 0) { 10734235b045SMasami Hiramatsu free(buf); 10744235b045SMasami Hiramatsu return NULL; 10757ef17aafSMasami Hiramatsu } 10764235b045SMasami Hiramatsu len += ret; 10777ef17aafSMasami Hiramatsu } 107850656eecSMasami Hiramatsu 10794235b045SMasami Hiramatsu return buf; 10804235b045SMasami Hiramatsu } 10814235b045SMasami Hiramatsu #endif 10824235b045SMasami Hiramatsu 10830e60836bSSrikar Dronamraju static int __synthesize_probe_trace_arg_ref(struct probe_trace_arg_ref *ref, 10844235b045SMasami Hiramatsu char **buf, size_t *buflen, 10854235b045SMasami Hiramatsu int depth) 10867ef17aafSMasami Hiramatsu { 10874235b045SMasami Hiramatsu int ret; 10884235b045SMasami Hiramatsu if (ref->next) { 10890e60836bSSrikar Dronamraju depth = __synthesize_probe_trace_arg_ref(ref->next, buf, 10904235b045SMasami Hiramatsu buflen, depth + 1); 10914235b045SMasami Hiramatsu if (depth < 0) 10924235b045SMasami Hiramatsu goto out; 10934235b045SMasami Hiramatsu } 10944235b045SMasami Hiramatsu 10954235b045SMasami Hiramatsu ret = e_snprintf(*buf, *buflen, "%+ld(", ref->offset); 10964235b045SMasami Hiramatsu if (ret < 0) 10974235b045SMasami Hiramatsu depth = ret; 10984235b045SMasami Hiramatsu else { 10994235b045SMasami Hiramatsu *buf += ret; 11004235b045SMasami Hiramatsu *buflen -= ret; 11014235b045SMasami Hiramatsu } 11024235b045SMasami Hiramatsu out: 11034235b045SMasami Hiramatsu return depth; 11044235b045SMasami Hiramatsu 11054235b045SMasami Hiramatsu } 11064235b045SMasami Hiramatsu 11070e60836bSSrikar Dronamraju static int synthesize_probe_trace_arg(struct probe_trace_arg *arg, 11084235b045SMasami Hiramatsu char *buf, size_t buflen) 11094235b045SMasami Hiramatsu { 11100e60836bSSrikar Dronamraju struct probe_trace_arg_ref *ref = arg->ref; 11114235b045SMasami Hiramatsu int ret, depth = 0; 11124235b045SMasami Hiramatsu char *tmp = buf; 11134235b045SMasami Hiramatsu 11144235b045SMasami Hiramatsu /* Argument name or separator */ 11154235b045SMasami Hiramatsu if (arg->name) 11164235b045SMasami Hiramatsu ret = e_snprintf(buf, buflen, " %s=", arg->name); 11174235b045SMasami Hiramatsu else 11184235b045SMasami Hiramatsu ret = e_snprintf(buf, buflen, " "); 11194235b045SMasami Hiramatsu if (ret < 0) 11204235b045SMasami Hiramatsu return ret; 11214235b045SMasami Hiramatsu buf += ret; 11224235b045SMasami Hiramatsu buflen -= ret; 11234235b045SMasami Hiramatsu 1124b7dcb857SMasami Hiramatsu /* Special case: @XXX */ 1125b7dcb857SMasami Hiramatsu if (arg->value[0] == '@' && arg->ref) 1126b7dcb857SMasami Hiramatsu ref = ref->next; 1127b7dcb857SMasami Hiramatsu 11284235b045SMasami Hiramatsu /* Dereferencing arguments */ 1129b7dcb857SMasami Hiramatsu if (ref) { 11300e60836bSSrikar Dronamraju depth = __synthesize_probe_trace_arg_ref(ref, &buf, 11314235b045SMasami Hiramatsu &buflen, 1); 11324235b045SMasami Hiramatsu if (depth < 0) 11334235b045SMasami Hiramatsu return depth; 11344235b045SMasami Hiramatsu } 11354235b045SMasami Hiramatsu 11364235b045SMasami Hiramatsu /* Print argument value */ 1137b7dcb857SMasami Hiramatsu if (arg->value[0] == '@' && arg->ref) 1138b7dcb857SMasami Hiramatsu ret = e_snprintf(buf, buflen, "%s%+ld", arg->value, 1139b7dcb857SMasami Hiramatsu arg->ref->offset); 1140b7dcb857SMasami Hiramatsu else 11414235b045SMasami Hiramatsu ret = e_snprintf(buf, buflen, "%s", arg->value); 11424235b045SMasami Hiramatsu if (ret < 0) 11434235b045SMasami Hiramatsu return ret; 11444235b045SMasami Hiramatsu buf += ret; 11454235b045SMasami Hiramatsu buflen -= ret; 11464235b045SMasami Hiramatsu 11474235b045SMasami Hiramatsu /* Closing */ 11484235b045SMasami Hiramatsu while (depth--) { 11494235b045SMasami Hiramatsu ret = e_snprintf(buf, buflen, ")"); 11504235b045SMasami Hiramatsu if (ret < 0) 11514235b045SMasami Hiramatsu return ret; 11524235b045SMasami Hiramatsu buf += ret; 11534235b045SMasami Hiramatsu buflen -= ret; 11544235b045SMasami Hiramatsu } 11554984912eSMasami Hiramatsu /* Print argument type */ 11564984912eSMasami Hiramatsu if (arg->type) { 11574984912eSMasami Hiramatsu ret = e_snprintf(buf, buflen, ":%s", arg->type); 11584984912eSMasami Hiramatsu if (ret <= 0) 11594984912eSMasami Hiramatsu return ret; 11604984912eSMasami Hiramatsu buf += ret; 11614984912eSMasami Hiramatsu } 11624235b045SMasami Hiramatsu 11634235b045SMasami Hiramatsu return buf - tmp; 11644235b045SMasami Hiramatsu } 11654235b045SMasami Hiramatsu 11660e60836bSSrikar Dronamraju char *synthesize_probe_trace_command(struct probe_trace_event *tev) 11674235b045SMasami Hiramatsu { 11680e60836bSSrikar Dronamraju struct probe_trace_point *tp = &tev->point; 11697ef17aafSMasami Hiramatsu char *buf; 11707ef17aafSMasami Hiramatsu int i, len, ret; 11717ef17aafSMasami Hiramatsu 1172e334016fSMasami Hiramatsu buf = zalloc(MAX_CMDLEN); 1173e334016fSMasami Hiramatsu if (buf == NULL) 1174e334016fSMasami Hiramatsu return NULL; 1175e334016fSMasami Hiramatsu 11764235b045SMasami Hiramatsu len = e_snprintf(buf, MAX_CMDLEN, "%c:%s/%s %s+%lu", 11774235b045SMasami Hiramatsu tp->retprobe ? 'r' : 'p', 11784235b045SMasami Hiramatsu tev->group, tev->event, 11794235b045SMasami Hiramatsu tp->symbol, tp->offset); 11804235b045SMasami Hiramatsu if (len <= 0) 11814235b045SMasami Hiramatsu goto error; 11827ef17aafSMasami Hiramatsu 11834235b045SMasami Hiramatsu for (i = 0; i < tev->nargs; i++) { 11840e60836bSSrikar Dronamraju ret = synthesize_probe_trace_arg(&tev->args[i], buf + len, 11854235b045SMasami Hiramatsu MAX_CMDLEN - len); 11864de189feSMasami Hiramatsu if (ret <= 0) 118750656eecSMasami Hiramatsu goto error; 118850656eecSMasami Hiramatsu len += ret; 118950656eecSMasami Hiramatsu } 119050656eecSMasami Hiramatsu 11914235b045SMasami Hiramatsu return buf; 119250656eecSMasami Hiramatsu error: 11934235b045SMasami Hiramatsu free(buf); 11944235b045SMasami Hiramatsu return NULL; 119550656eecSMasami Hiramatsu } 119650656eecSMasami Hiramatsu 11970e60836bSSrikar Dronamraju static int convert_to_perf_probe_event(struct probe_trace_event *tev, 11984235b045SMasami Hiramatsu struct perf_probe_event *pev) 11994de189feSMasami Hiramatsu { 120002b95dadSMasami Hiramatsu char buf[64] = ""; 1201146a1439SMasami Hiramatsu int i, ret; 12024de189feSMasami Hiramatsu 12034b4da7f7SMasami Hiramatsu /* Convert event/group name */ 120402b95dadSMasami Hiramatsu pev->event = strdup(tev->event); 120502b95dadSMasami Hiramatsu pev->group = strdup(tev->group); 120602b95dadSMasami Hiramatsu if (pev->event == NULL || pev->group == NULL) 120702b95dadSMasami Hiramatsu return -ENOMEM; 1208fb1587d8SMasami Hiramatsu 12094b4da7f7SMasami Hiramatsu /* Convert trace_point to probe_point */ 12100e60836bSSrikar Dronamraju ret = kprobe_convert_to_perf_probe(&tev->point, &pev->point); 1211146a1439SMasami Hiramatsu if (ret < 0) 1212146a1439SMasami Hiramatsu return ret; 12134b4da7f7SMasami Hiramatsu 12144235b045SMasami Hiramatsu /* Convert trace_arg to probe_arg */ 12154235b045SMasami Hiramatsu pev->nargs = tev->nargs; 1216e334016fSMasami Hiramatsu pev->args = zalloc(sizeof(struct perf_probe_arg) * pev->nargs); 1217e334016fSMasami Hiramatsu if (pev->args == NULL) 1218e334016fSMasami Hiramatsu return -ENOMEM; 121902b95dadSMasami Hiramatsu for (i = 0; i < tev->nargs && ret >= 0; i++) { 12204235b045SMasami Hiramatsu if (tev->args[i].name) 122102b95dadSMasami Hiramatsu pev->args[i].name = strdup(tev->args[i].name); 12224235b045SMasami Hiramatsu else { 12230e60836bSSrikar Dronamraju ret = synthesize_probe_trace_arg(&tev->args[i], 1224146a1439SMasami Hiramatsu buf, 64); 122502b95dadSMasami Hiramatsu pev->args[i].name = strdup(buf); 122602b95dadSMasami Hiramatsu } 122702b95dadSMasami Hiramatsu if (pev->args[i].name == NULL && ret >= 0) 122802b95dadSMasami Hiramatsu ret = -ENOMEM; 12294de189feSMasami Hiramatsu } 1230146a1439SMasami Hiramatsu 1231146a1439SMasami Hiramatsu if (ret < 0) 1232146a1439SMasami Hiramatsu clear_perf_probe_event(pev); 1233146a1439SMasami Hiramatsu 1234146a1439SMasami Hiramatsu return ret; 12354235b045SMasami Hiramatsu } 12364de189feSMasami Hiramatsu 12374235b045SMasami Hiramatsu void clear_perf_probe_event(struct perf_probe_event *pev) 12384235b045SMasami Hiramatsu { 12394235b045SMasami Hiramatsu struct perf_probe_point *pp = &pev->point; 12407df2f329SMasami Hiramatsu struct perf_probe_arg_field *field, *next; 12414235b045SMasami Hiramatsu int i; 12424de189feSMasami Hiramatsu 12434235b045SMasami Hiramatsu if (pev->event) 12444235b045SMasami Hiramatsu free(pev->event); 12454235b045SMasami Hiramatsu if (pev->group) 12464235b045SMasami Hiramatsu free(pev->group); 12474235b045SMasami Hiramatsu if (pp->file) 12484235b045SMasami Hiramatsu free(pp->file); 12494235b045SMasami Hiramatsu if (pp->function) 12504235b045SMasami Hiramatsu free(pp->function); 12514235b045SMasami Hiramatsu if (pp->lazy_line) 12524235b045SMasami Hiramatsu free(pp->lazy_line); 12537df2f329SMasami Hiramatsu for (i = 0; i < pev->nargs; i++) { 12544235b045SMasami Hiramatsu if (pev->args[i].name) 12554235b045SMasami Hiramatsu free(pev->args[i].name); 125648481938SMasami Hiramatsu if (pev->args[i].var) 125748481938SMasami Hiramatsu free(pev->args[i].var); 125811a1ca35SMasami Hiramatsu if (pev->args[i].type) 125911a1ca35SMasami Hiramatsu free(pev->args[i].type); 12607df2f329SMasami Hiramatsu field = pev->args[i].field; 12617df2f329SMasami Hiramatsu while (field) { 12627df2f329SMasami Hiramatsu next = field->next; 12637df2f329SMasami Hiramatsu if (field->name) 12647df2f329SMasami Hiramatsu free(field->name); 12657df2f329SMasami Hiramatsu free(field); 12667df2f329SMasami Hiramatsu field = next; 12677df2f329SMasami Hiramatsu } 12687df2f329SMasami Hiramatsu } 12694235b045SMasami Hiramatsu if (pev->args) 12704235b045SMasami Hiramatsu free(pev->args); 12714235b045SMasami Hiramatsu memset(pev, 0, sizeof(*pev)); 12724235b045SMasami Hiramatsu } 12734235b045SMasami Hiramatsu 12740e60836bSSrikar Dronamraju static void clear_probe_trace_event(struct probe_trace_event *tev) 12754235b045SMasami Hiramatsu { 12760e60836bSSrikar Dronamraju struct probe_trace_arg_ref *ref, *next; 12774235b045SMasami Hiramatsu int i; 12784235b045SMasami Hiramatsu 12794235b045SMasami Hiramatsu if (tev->event) 12804235b045SMasami Hiramatsu free(tev->event); 12814235b045SMasami Hiramatsu if (tev->group) 12824235b045SMasami Hiramatsu free(tev->group); 12834235b045SMasami Hiramatsu if (tev->point.symbol) 12844235b045SMasami Hiramatsu free(tev->point.symbol); 12854235b045SMasami Hiramatsu for (i = 0; i < tev->nargs; i++) { 12864235b045SMasami Hiramatsu if (tev->args[i].name) 12874235b045SMasami Hiramatsu free(tev->args[i].name); 12884235b045SMasami Hiramatsu if (tev->args[i].value) 12894235b045SMasami Hiramatsu free(tev->args[i].value); 12904984912eSMasami Hiramatsu if (tev->args[i].type) 12914984912eSMasami Hiramatsu free(tev->args[i].type); 12924235b045SMasami Hiramatsu ref = tev->args[i].ref; 12934235b045SMasami Hiramatsu while (ref) { 12944235b045SMasami Hiramatsu next = ref->next; 12954235b045SMasami Hiramatsu free(ref); 12964235b045SMasami Hiramatsu ref = next; 12974235b045SMasami Hiramatsu } 12984235b045SMasami Hiramatsu } 12994235b045SMasami Hiramatsu if (tev->args) 13004235b045SMasami Hiramatsu free(tev->args); 13014235b045SMasami Hiramatsu memset(tev, 0, sizeof(*tev)); 13024de189feSMasami Hiramatsu } 13034de189feSMasami Hiramatsu 1304f4d7da49SMasami Hiramatsu static int open_kprobe_events(bool readwrite) 13054de189feSMasami Hiramatsu { 13064de189feSMasami Hiramatsu char buf[PATH_MAX]; 13077ca5989dSMasami Hiramatsu const char *__debugfs; 13084de189feSMasami Hiramatsu int ret; 13094de189feSMasami Hiramatsu 13107ca5989dSMasami Hiramatsu __debugfs = debugfs_find_mountpoint(); 13117ca5989dSMasami Hiramatsu if (__debugfs == NULL) { 13127ca5989dSMasami Hiramatsu pr_warning("Debugfs is not mounted.\n"); 13137ca5989dSMasami Hiramatsu return -ENOENT; 13147ca5989dSMasami Hiramatsu } 13157ca5989dSMasami Hiramatsu 13167ca5989dSMasami Hiramatsu ret = e_snprintf(buf, PATH_MAX, "%stracing/kprobe_events", __debugfs); 1317146a1439SMasami Hiramatsu if (ret >= 0) { 13187ca5989dSMasami Hiramatsu pr_debug("Opening %s write=%d\n", buf, readwrite); 1319f4d7da49SMasami Hiramatsu if (readwrite && !probe_event_dry_run) 1320f4d7da49SMasami Hiramatsu ret = open(buf, O_RDWR, O_APPEND); 1321f4d7da49SMasami Hiramatsu else 1322f4d7da49SMasami Hiramatsu ret = open(buf, O_RDONLY, 0); 1323146a1439SMasami Hiramatsu } 1324f4d7da49SMasami Hiramatsu 13254de189feSMasami Hiramatsu if (ret < 0) { 13264de189feSMasami Hiramatsu if (errno == ENOENT) 1327146a1439SMasami Hiramatsu pr_warning("kprobe_events file does not exist - please" 1328146a1439SMasami Hiramatsu " rebuild kernel with CONFIG_KPROBE_EVENT.\n"); 13294de189feSMasami Hiramatsu else 1330146a1439SMasami Hiramatsu pr_warning("Failed to open kprobe_events file: %s\n", 13314de189feSMasami Hiramatsu strerror(errno)); 13324de189feSMasami Hiramatsu } 13334de189feSMasami Hiramatsu return ret; 13344de189feSMasami Hiramatsu } 13354de189feSMasami Hiramatsu 13364de189feSMasami Hiramatsu /* Get raw string list of current kprobe_events */ 13370e60836bSSrikar Dronamraju static struct strlist *get_probe_trace_command_rawlist(int fd) 13384de189feSMasami Hiramatsu { 13394de189feSMasami Hiramatsu int ret, idx; 13404de189feSMasami Hiramatsu FILE *fp; 13414de189feSMasami Hiramatsu char buf[MAX_CMDLEN]; 13424de189feSMasami Hiramatsu char *p; 13434de189feSMasami Hiramatsu struct strlist *sl; 13444de189feSMasami Hiramatsu 13454de189feSMasami Hiramatsu sl = strlist__new(true, NULL); 13464de189feSMasami Hiramatsu 13474de189feSMasami Hiramatsu fp = fdopen(dup(fd), "r"); 13484de189feSMasami Hiramatsu while (!feof(fp)) { 13494de189feSMasami Hiramatsu p = fgets(buf, MAX_CMDLEN, fp); 13504de189feSMasami Hiramatsu if (!p) 13514de189feSMasami Hiramatsu break; 13524de189feSMasami Hiramatsu 13534de189feSMasami Hiramatsu idx = strlen(p) - 1; 13544de189feSMasami Hiramatsu if (p[idx] == '\n') 13554de189feSMasami Hiramatsu p[idx] = '\0'; 13564de189feSMasami Hiramatsu ret = strlist__add(sl, buf); 1357146a1439SMasami Hiramatsu if (ret < 0) { 1358146a1439SMasami Hiramatsu pr_debug("strlist__add failed: %s\n", strerror(-ret)); 1359146a1439SMasami Hiramatsu strlist__delete(sl); 1360146a1439SMasami Hiramatsu return NULL; 1361146a1439SMasami Hiramatsu } 13624de189feSMasami Hiramatsu } 13634de189feSMasami Hiramatsu fclose(fp); 13644de189feSMasami Hiramatsu 13654de189feSMasami Hiramatsu return sl; 13664de189feSMasami Hiramatsu } 13674de189feSMasami Hiramatsu 1368278498d4SMasami Hiramatsu /* Show an event */ 1369146a1439SMasami Hiramatsu static int show_perf_probe_event(struct perf_probe_event *pev) 1370278498d4SMasami Hiramatsu { 13717e990a51SMasami Hiramatsu int i, ret; 1372278498d4SMasami Hiramatsu char buf[128]; 13734235b045SMasami Hiramatsu char *place; 1374278498d4SMasami Hiramatsu 13754235b045SMasami Hiramatsu /* Synthesize only event probe point */ 13764235b045SMasami Hiramatsu place = synthesize_perf_probe_point(&pev->point); 1377146a1439SMasami Hiramatsu if (!place) 1378146a1439SMasami Hiramatsu return -EINVAL; 13794235b045SMasami Hiramatsu 13804235b045SMasami Hiramatsu ret = e_snprintf(buf, 128, "%s:%s", pev->group, pev->event); 13817e990a51SMasami Hiramatsu if (ret < 0) 1382146a1439SMasami Hiramatsu return ret; 1383146a1439SMasami Hiramatsu 1384fb1587d8SMasami Hiramatsu printf(" %-20s (on %s", buf, place); 1385278498d4SMasami Hiramatsu 13864235b045SMasami Hiramatsu if (pev->nargs > 0) { 1387278498d4SMasami Hiramatsu printf(" with"); 13887df2f329SMasami Hiramatsu for (i = 0; i < pev->nargs; i++) { 1389146a1439SMasami Hiramatsu ret = synthesize_perf_probe_arg(&pev->args[i], 1390146a1439SMasami Hiramatsu buf, 128); 1391146a1439SMasami Hiramatsu if (ret < 0) 1392146a1439SMasami Hiramatsu break; 13937df2f329SMasami Hiramatsu printf(" %s", buf); 13947df2f329SMasami Hiramatsu } 1395278498d4SMasami Hiramatsu } 1396278498d4SMasami Hiramatsu printf(")\n"); 13974235b045SMasami Hiramatsu free(place); 1398146a1439SMasami Hiramatsu return ret; 1399278498d4SMasami Hiramatsu } 1400278498d4SMasami Hiramatsu 14014de189feSMasami Hiramatsu /* List up current perf-probe events */ 1402146a1439SMasami Hiramatsu int show_perf_probe_events(void) 14034de189feSMasami Hiramatsu { 1404146a1439SMasami Hiramatsu int fd, ret; 14050e60836bSSrikar Dronamraju struct probe_trace_event tev; 14064235b045SMasami Hiramatsu struct perf_probe_event pev; 14074de189feSMasami Hiramatsu struct strlist *rawlist; 14084de189feSMasami Hiramatsu struct str_node *ent; 14094de189feSMasami Hiramatsu 141072041334SMasami Hiramatsu setup_pager(); 1411146a1439SMasami Hiramatsu ret = init_vmlinux(); 1412146a1439SMasami Hiramatsu if (ret < 0) 1413146a1439SMasami Hiramatsu return ret; 14144235b045SMasami Hiramatsu 14154235b045SMasami Hiramatsu memset(&tev, 0, sizeof(tev)); 14164235b045SMasami Hiramatsu memset(&pev, 0, sizeof(pev)); 141772041334SMasami Hiramatsu 1418f4d7da49SMasami Hiramatsu fd = open_kprobe_events(false); 1419146a1439SMasami Hiramatsu if (fd < 0) 1420146a1439SMasami Hiramatsu return fd; 1421146a1439SMasami Hiramatsu 14220e60836bSSrikar Dronamraju rawlist = get_probe_trace_command_rawlist(fd); 14234de189feSMasami Hiramatsu close(fd); 1424146a1439SMasami Hiramatsu if (!rawlist) 1425146a1439SMasami Hiramatsu return -ENOENT; 14264de189feSMasami Hiramatsu 1427adf365f4SMasami Hiramatsu strlist__for_each(ent, rawlist) { 14280e60836bSSrikar Dronamraju ret = parse_probe_trace_command(ent->s, &tev); 1429146a1439SMasami Hiramatsu if (ret >= 0) { 1430146a1439SMasami Hiramatsu ret = convert_to_perf_probe_event(&tev, &pev); 1431146a1439SMasami Hiramatsu if (ret >= 0) 1432146a1439SMasami Hiramatsu ret = show_perf_probe_event(&pev); 1433146a1439SMasami Hiramatsu } 14344235b045SMasami Hiramatsu clear_perf_probe_event(&pev); 14350e60836bSSrikar Dronamraju clear_probe_trace_event(&tev); 1436146a1439SMasami Hiramatsu if (ret < 0) 1437146a1439SMasami Hiramatsu break; 14384de189feSMasami Hiramatsu } 14394de189feSMasami Hiramatsu strlist__delete(rawlist); 1440146a1439SMasami Hiramatsu 1441146a1439SMasami Hiramatsu return ret; 14424de189feSMasami Hiramatsu } 14434de189feSMasami Hiramatsu 1444b498ce1fSMasami Hiramatsu /* Get current perf-probe event names */ 14450e60836bSSrikar Dronamraju static struct strlist *get_probe_trace_event_names(int fd, bool include_group) 1446b498ce1fSMasami Hiramatsu { 1447fa28244dSMasami Hiramatsu char buf[128]; 1448b498ce1fSMasami Hiramatsu struct strlist *sl, *rawlist; 1449b498ce1fSMasami Hiramatsu struct str_node *ent; 14500e60836bSSrikar Dronamraju struct probe_trace_event tev; 1451146a1439SMasami Hiramatsu int ret = 0; 1452b498ce1fSMasami Hiramatsu 14534235b045SMasami Hiramatsu memset(&tev, 0, sizeof(tev)); 14540e60836bSSrikar Dronamraju rawlist = get_probe_trace_command_rawlist(fd); 1455e1d2017bSMasami Hiramatsu sl = strlist__new(true, NULL); 1456adf365f4SMasami Hiramatsu strlist__for_each(ent, rawlist) { 14570e60836bSSrikar Dronamraju ret = parse_probe_trace_command(ent->s, &tev); 1458146a1439SMasami Hiramatsu if (ret < 0) 1459146a1439SMasami Hiramatsu break; 1460fa28244dSMasami Hiramatsu if (include_group) { 1461146a1439SMasami Hiramatsu ret = e_snprintf(buf, 128, "%s:%s", tev.group, 1462146a1439SMasami Hiramatsu tev.event); 1463146a1439SMasami Hiramatsu if (ret >= 0) 1464146a1439SMasami Hiramatsu ret = strlist__add(sl, buf); 1465fa28244dSMasami Hiramatsu } else 1466146a1439SMasami Hiramatsu ret = strlist__add(sl, tev.event); 14670e60836bSSrikar Dronamraju clear_probe_trace_event(&tev); 1468146a1439SMasami Hiramatsu if (ret < 0) 1469146a1439SMasami Hiramatsu break; 1470b498ce1fSMasami Hiramatsu } 1471b498ce1fSMasami Hiramatsu strlist__delete(rawlist); 1472b498ce1fSMasami Hiramatsu 1473146a1439SMasami Hiramatsu if (ret < 0) { 1474146a1439SMasami Hiramatsu strlist__delete(sl); 1475146a1439SMasami Hiramatsu return NULL; 1476146a1439SMasami Hiramatsu } 1477b498ce1fSMasami Hiramatsu return sl; 1478b498ce1fSMasami Hiramatsu } 1479b498ce1fSMasami Hiramatsu 14800e60836bSSrikar Dronamraju static int write_probe_trace_event(int fd, struct probe_trace_event *tev) 148150656eecSMasami Hiramatsu { 14826eca8cc3SFrederic Weisbecker int ret = 0; 14830e60836bSSrikar Dronamraju char *buf = synthesize_probe_trace_command(tev); 148450656eecSMasami Hiramatsu 1485146a1439SMasami Hiramatsu if (!buf) { 14860e60836bSSrikar Dronamraju pr_debug("Failed to synthesize probe trace event.\n"); 1487146a1439SMasami Hiramatsu return -EINVAL; 1488146a1439SMasami Hiramatsu } 1489146a1439SMasami Hiramatsu 1490fa28244dSMasami Hiramatsu pr_debug("Writing event: %s\n", buf); 1491f4d7da49SMasami Hiramatsu if (!probe_event_dry_run) { 149250656eecSMasami Hiramatsu ret = write(fd, buf, strlen(buf)); 149350656eecSMasami Hiramatsu if (ret <= 0) 1494146a1439SMasami Hiramatsu pr_warning("Failed to write event: %s\n", 1495146a1439SMasami Hiramatsu strerror(errno)); 149650656eecSMasami Hiramatsu } 14974235b045SMasami Hiramatsu free(buf); 1498146a1439SMasami Hiramatsu return ret; 1499f4d7da49SMasami Hiramatsu } 150050656eecSMasami Hiramatsu 1501146a1439SMasami Hiramatsu static int get_new_event_name(char *buf, size_t len, const char *base, 1502d761b08bSMasami Hiramatsu struct strlist *namelist, bool allow_suffix) 1503b498ce1fSMasami Hiramatsu { 1504b498ce1fSMasami Hiramatsu int i, ret; 150517f88fcdSMasami Hiramatsu 150617f88fcdSMasami Hiramatsu /* Try no suffix */ 150717f88fcdSMasami Hiramatsu ret = e_snprintf(buf, len, "%s", base); 1508146a1439SMasami Hiramatsu if (ret < 0) { 1509146a1439SMasami Hiramatsu pr_debug("snprintf() failed: %s\n", strerror(-ret)); 1510146a1439SMasami Hiramatsu return ret; 1511146a1439SMasami Hiramatsu } 151217f88fcdSMasami Hiramatsu if (!strlist__has_entry(namelist, buf)) 1513146a1439SMasami Hiramatsu return 0; 151417f88fcdSMasami Hiramatsu 1515d761b08bSMasami Hiramatsu if (!allow_suffix) { 1516d761b08bSMasami Hiramatsu pr_warning("Error: event \"%s\" already exists. " 1517d761b08bSMasami Hiramatsu "(Use -f to force duplicates.)\n", base); 1518146a1439SMasami Hiramatsu return -EEXIST; 1519d761b08bSMasami Hiramatsu } 1520d761b08bSMasami Hiramatsu 152117f88fcdSMasami Hiramatsu /* Try to add suffix */ 152217f88fcdSMasami Hiramatsu for (i = 1; i < MAX_EVENT_INDEX; i++) { 1523b498ce1fSMasami Hiramatsu ret = e_snprintf(buf, len, "%s_%d", base, i); 1524146a1439SMasami Hiramatsu if (ret < 0) { 1525146a1439SMasami Hiramatsu pr_debug("snprintf() failed: %s\n", strerror(-ret)); 1526146a1439SMasami Hiramatsu return ret; 1527146a1439SMasami Hiramatsu } 1528b498ce1fSMasami Hiramatsu if (!strlist__has_entry(namelist, buf)) 1529b498ce1fSMasami Hiramatsu break; 1530b498ce1fSMasami Hiramatsu } 1531146a1439SMasami Hiramatsu if (i == MAX_EVENT_INDEX) { 1532146a1439SMasami Hiramatsu pr_warning("Too many events are on the same function.\n"); 1533146a1439SMasami Hiramatsu ret = -ERANGE; 1534b498ce1fSMasami Hiramatsu } 1535b498ce1fSMasami Hiramatsu 1536146a1439SMasami Hiramatsu return ret; 1537146a1439SMasami Hiramatsu } 1538146a1439SMasami Hiramatsu 15390e60836bSSrikar Dronamraju static int __add_probe_trace_events(struct perf_probe_event *pev, 15400e60836bSSrikar Dronamraju struct probe_trace_event *tevs, 15414235b045SMasami Hiramatsu int ntevs, bool allow_suffix) 154250656eecSMasami Hiramatsu { 1543146a1439SMasami Hiramatsu int i, fd, ret; 15440e60836bSSrikar Dronamraju struct probe_trace_event *tev = NULL; 15454235b045SMasami Hiramatsu char buf[64]; 15464235b045SMasami Hiramatsu const char *event, *group; 1547b498ce1fSMasami Hiramatsu struct strlist *namelist; 154850656eecSMasami Hiramatsu 1549f4d7da49SMasami Hiramatsu fd = open_kprobe_events(true); 1550146a1439SMasami Hiramatsu if (fd < 0) 1551146a1439SMasami Hiramatsu return fd; 1552b498ce1fSMasami Hiramatsu /* Get current event names */ 15530e60836bSSrikar Dronamraju namelist = get_probe_trace_event_names(fd, false); 1554146a1439SMasami Hiramatsu if (!namelist) { 1555146a1439SMasami Hiramatsu pr_debug("Failed to get current event list.\n"); 1556146a1439SMasami Hiramatsu return -EIO; 1557146a1439SMasami Hiramatsu } 155850656eecSMasami Hiramatsu 1559146a1439SMasami Hiramatsu ret = 0; 15604235b045SMasami Hiramatsu printf("Add new event%s\n", (ntevs > 1) ? "s:" : ":"); 156102b95dadSMasami Hiramatsu for (i = 0; i < ntevs; i++) { 15624235b045SMasami Hiramatsu tev = &tevs[i]; 15634235b045SMasami Hiramatsu if (pev->event) 15644235b045SMasami Hiramatsu event = pev->event; 15654235b045SMasami Hiramatsu else 15664235b045SMasami Hiramatsu if (pev->point.function) 15674235b045SMasami Hiramatsu event = pev->point.function; 15684235b045SMasami Hiramatsu else 15694235b045SMasami Hiramatsu event = tev->point.symbol; 15704235b045SMasami Hiramatsu if (pev->group) 15714235b045SMasami Hiramatsu group = pev->group; 15724235b045SMasami Hiramatsu else 15734235b045SMasami Hiramatsu group = PERFPROBE_GROUP; 15744235b045SMasami Hiramatsu 1575b498ce1fSMasami Hiramatsu /* Get an unused new event name */ 1576146a1439SMasami Hiramatsu ret = get_new_event_name(buf, 64, event, 1577146a1439SMasami Hiramatsu namelist, allow_suffix); 1578146a1439SMasami Hiramatsu if (ret < 0) 1579146a1439SMasami Hiramatsu break; 15804235b045SMasami Hiramatsu event = buf; 15814235b045SMasami Hiramatsu 158202b95dadSMasami Hiramatsu tev->event = strdup(event); 158302b95dadSMasami Hiramatsu tev->group = strdup(group); 158402b95dadSMasami Hiramatsu if (tev->event == NULL || tev->group == NULL) { 158502b95dadSMasami Hiramatsu ret = -ENOMEM; 158602b95dadSMasami Hiramatsu break; 158702b95dadSMasami Hiramatsu } 15880e60836bSSrikar Dronamraju ret = write_probe_trace_event(fd, tev); 1589146a1439SMasami Hiramatsu if (ret < 0) 1590146a1439SMasami Hiramatsu break; 1591b498ce1fSMasami Hiramatsu /* Add added event name to namelist */ 1592b498ce1fSMasami Hiramatsu strlist__add(namelist, event); 15934235b045SMasami Hiramatsu 15944235b045SMasami Hiramatsu /* Trick here - save current event/group */ 15954235b045SMasami Hiramatsu event = pev->event; 15964235b045SMasami Hiramatsu group = pev->group; 15974235b045SMasami Hiramatsu pev->event = tev->event; 15984235b045SMasami Hiramatsu pev->group = tev->group; 15994235b045SMasami Hiramatsu show_perf_probe_event(pev); 16004235b045SMasami Hiramatsu /* Trick here - restore current event/group */ 16014235b045SMasami Hiramatsu pev->event = (char *)event; 16024235b045SMasami Hiramatsu pev->group = (char *)group; 16034235b045SMasami Hiramatsu 1604d761b08bSMasami Hiramatsu /* 1605d761b08bSMasami Hiramatsu * Probes after the first probe which comes from same 1606d761b08bSMasami Hiramatsu * user input are always allowed to add suffix, because 1607d761b08bSMasami Hiramatsu * there might be several addresses corresponding to 1608d761b08bSMasami Hiramatsu * one code line. 1609d761b08bSMasami Hiramatsu */ 1610d761b08bSMasami Hiramatsu allow_suffix = true; 161150656eecSMasami Hiramatsu } 1612146a1439SMasami Hiramatsu 1613146a1439SMasami Hiramatsu if (ret >= 0) { 1614a9b495b0SMasami Hiramatsu /* Show how to use the event. */ 1615a9b495b0SMasami Hiramatsu printf("\nYou can now use it on all perf tools, such as:\n\n"); 1616146a1439SMasami Hiramatsu printf("\tperf record -e %s:%s -aR sleep 1\n\n", tev->group, 1617146a1439SMasami Hiramatsu tev->event); 1618146a1439SMasami Hiramatsu } 1619a9b495b0SMasami Hiramatsu 1620e1d2017bSMasami Hiramatsu strlist__delete(namelist); 162150656eecSMasami Hiramatsu close(fd); 1622146a1439SMasami Hiramatsu return ret; 162350656eecSMasami Hiramatsu } 1624fa28244dSMasami Hiramatsu 16250e60836bSSrikar Dronamraju static int convert_to_probe_trace_events(struct perf_probe_event *pev, 16260e60836bSSrikar Dronamraju struct probe_trace_event **tevs, 1627469b9b88SMasami Hiramatsu int max_tevs, const char *module) 1628e0faa8d3SMasami Hiramatsu { 1629e0faa8d3SMasami Hiramatsu struct symbol *sym; 1630e334016fSMasami Hiramatsu int ret = 0, i; 16310e60836bSSrikar Dronamraju struct probe_trace_event *tev; 16324235b045SMasami Hiramatsu 16334b4da7f7SMasami Hiramatsu /* Convert perf_probe_event with debuginfo */ 1634469b9b88SMasami Hiramatsu ret = try_to_find_probe_trace_events(pev, tevs, max_tevs, module); 1635e334016fSMasami Hiramatsu if (ret != 0) 1636e334016fSMasami Hiramatsu return ret; 1637e0faa8d3SMasami Hiramatsu 16384235b045SMasami Hiramatsu /* Allocate trace event buffer */ 16390e60836bSSrikar Dronamraju tev = *tevs = zalloc(sizeof(struct probe_trace_event)); 1640e334016fSMasami Hiramatsu if (tev == NULL) 1641e334016fSMasami Hiramatsu return -ENOMEM; 1642e0faa8d3SMasami Hiramatsu 16434235b045SMasami Hiramatsu /* Copy parameters */ 164402b95dadSMasami Hiramatsu tev->point.symbol = strdup(pev->point.function); 164502b95dadSMasami Hiramatsu if (tev->point.symbol == NULL) { 164602b95dadSMasami Hiramatsu ret = -ENOMEM; 164702b95dadSMasami Hiramatsu goto error; 164802b95dadSMasami Hiramatsu } 16494235b045SMasami Hiramatsu tev->point.offset = pev->point.offset; 165004ddd04bSMasami Hiramatsu tev->point.retprobe = pev->point.retprobe; 16514235b045SMasami Hiramatsu tev->nargs = pev->nargs; 16524235b045SMasami Hiramatsu if (tev->nargs) { 16530e60836bSSrikar Dronamraju tev->args = zalloc(sizeof(struct probe_trace_arg) 16544235b045SMasami Hiramatsu * tev->nargs); 1655e334016fSMasami Hiramatsu if (tev->args == NULL) { 165602b95dadSMasami Hiramatsu ret = -ENOMEM; 165702b95dadSMasami Hiramatsu goto error; 1658e334016fSMasami Hiramatsu } 165948481938SMasami Hiramatsu for (i = 0; i < tev->nargs; i++) { 166002b95dadSMasami Hiramatsu if (pev->args[i].name) { 166102b95dadSMasami Hiramatsu tev->args[i].name = strdup(pev->args[i].name); 166202b95dadSMasami Hiramatsu if (tev->args[i].name == NULL) { 166302b95dadSMasami Hiramatsu ret = -ENOMEM; 166402b95dadSMasami Hiramatsu goto error; 166502b95dadSMasami Hiramatsu } 166602b95dadSMasami Hiramatsu } 166702b95dadSMasami Hiramatsu tev->args[i].value = strdup(pev->args[i].var); 166802b95dadSMasami Hiramatsu if (tev->args[i].value == NULL) { 166902b95dadSMasami Hiramatsu ret = -ENOMEM; 167002b95dadSMasami Hiramatsu goto error; 167102b95dadSMasami Hiramatsu } 167202b95dadSMasami Hiramatsu if (pev->args[i].type) { 167302b95dadSMasami Hiramatsu tev->args[i].type = strdup(pev->args[i].type); 167402b95dadSMasami Hiramatsu if (tev->args[i].type == NULL) { 167502b95dadSMasami Hiramatsu ret = -ENOMEM; 167602b95dadSMasami Hiramatsu goto error; 167702b95dadSMasami Hiramatsu } 167802b95dadSMasami Hiramatsu } 167948481938SMasami Hiramatsu } 1680e0faa8d3SMasami Hiramatsu } 1681e0faa8d3SMasami Hiramatsu 16824235b045SMasami Hiramatsu /* Currently just checking function name from symbol map */ 1683469b9b88SMasami Hiramatsu sym = __find_kernel_function_by_name(tev->point.symbol, NULL); 1684146a1439SMasami Hiramatsu if (!sym) { 1685146a1439SMasami Hiramatsu pr_warning("Kernel symbol \'%s\' not found.\n", 16864235b045SMasami Hiramatsu tev->point.symbol); 168702b95dadSMasami Hiramatsu ret = -ENOENT; 168802b95dadSMasami Hiramatsu goto error; 168902b95dadSMasami Hiramatsu } 169002b95dadSMasami Hiramatsu 169102b95dadSMasami Hiramatsu return 1; 169202b95dadSMasami Hiramatsu error: 16930e60836bSSrikar Dronamraju clear_probe_trace_event(tev); 1694e334016fSMasami Hiramatsu free(tev); 1695e334016fSMasami Hiramatsu *tevs = NULL; 1696e334016fSMasami Hiramatsu return ret; 16974235b045SMasami Hiramatsu } 16984235b045SMasami Hiramatsu 16994235b045SMasami Hiramatsu struct __event_package { 17004235b045SMasami Hiramatsu struct perf_probe_event *pev; 17010e60836bSSrikar Dronamraju struct probe_trace_event *tevs; 17024235b045SMasami Hiramatsu int ntevs; 17034235b045SMasami Hiramatsu }; 17044235b045SMasami Hiramatsu 1705146a1439SMasami Hiramatsu int add_perf_probe_events(struct perf_probe_event *pevs, int npevs, 1706469b9b88SMasami Hiramatsu int max_tevs, const char *module, bool force_add) 17074235b045SMasami Hiramatsu { 1708146a1439SMasami Hiramatsu int i, j, ret; 17094235b045SMasami Hiramatsu struct __event_package *pkgs; 17104235b045SMasami Hiramatsu 1711e334016fSMasami Hiramatsu pkgs = zalloc(sizeof(struct __event_package) * npevs); 1712e334016fSMasami Hiramatsu if (pkgs == NULL) 1713e334016fSMasami Hiramatsu return -ENOMEM; 17144235b045SMasami Hiramatsu 17154235b045SMasami Hiramatsu /* Init vmlinux path */ 1716146a1439SMasami Hiramatsu ret = init_vmlinux(); 1717449e5b24SMasami Hiramatsu if (ret < 0) { 1718449e5b24SMasami Hiramatsu free(pkgs); 1719146a1439SMasami Hiramatsu return ret; 1720449e5b24SMasami Hiramatsu } 17214235b045SMasami Hiramatsu 17224235b045SMasami Hiramatsu /* Loop 1: convert all events */ 17234235b045SMasami Hiramatsu for (i = 0; i < npevs; i++) { 17244235b045SMasami Hiramatsu pkgs[i].pev = &pevs[i]; 17254235b045SMasami Hiramatsu /* Convert with or without debuginfo */ 17260e60836bSSrikar Dronamraju ret = convert_to_probe_trace_events(pkgs[i].pev, 1727469b9b88SMasami Hiramatsu &pkgs[i].tevs, 1728469b9b88SMasami Hiramatsu max_tevs, 1729469b9b88SMasami Hiramatsu module); 1730146a1439SMasami Hiramatsu if (ret < 0) 1731146a1439SMasami Hiramatsu goto end; 1732146a1439SMasami Hiramatsu pkgs[i].ntevs = ret; 17334235b045SMasami Hiramatsu } 17344235b045SMasami Hiramatsu 17354235b045SMasami Hiramatsu /* Loop 2: add all events */ 1736146a1439SMasami Hiramatsu for (i = 0; i < npevs && ret >= 0; i++) 17370e60836bSSrikar Dronamraju ret = __add_probe_trace_events(pkgs[i].pev, pkgs[i].tevs, 17384235b045SMasami Hiramatsu pkgs[i].ntevs, force_add); 1739146a1439SMasami Hiramatsu end: 1740449e5b24SMasami Hiramatsu /* Loop 3: cleanup and free trace events */ 1741449e5b24SMasami Hiramatsu for (i = 0; i < npevs; i++) { 1742146a1439SMasami Hiramatsu for (j = 0; j < pkgs[i].ntevs; j++) 17430e60836bSSrikar Dronamraju clear_probe_trace_event(&pkgs[i].tevs[j]); 1744449e5b24SMasami Hiramatsu free(pkgs[i].tevs); 1745449e5b24SMasami Hiramatsu } 1746449e5b24SMasami Hiramatsu free(pkgs); 1747146a1439SMasami Hiramatsu 1748146a1439SMasami Hiramatsu return ret; 1749e0faa8d3SMasami Hiramatsu } 1750e0faa8d3SMasami Hiramatsu 17510e60836bSSrikar Dronamraju static int __del_trace_probe_event(int fd, struct str_node *ent) 1752bbbb521bSMasami Hiramatsu { 1753bbbb521bSMasami Hiramatsu char *p; 1754bbbb521bSMasami Hiramatsu char buf[128]; 17554235b045SMasami Hiramatsu int ret; 1756bbbb521bSMasami Hiramatsu 17570e60836bSSrikar Dronamraju /* Convert from perf-probe event to trace-probe event */ 1758146a1439SMasami Hiramatsu ret = e_snprintf(buf, 128, "-:%s", ent->s); 1759146a1439SMasami Hiramatsu if (ret < 0) 1760146a1439SMasami Hiramatsu goto error; 1761146a1439SMasami Hiramatsu 1762bbbb521bSMasami Hiramatsu p = strchr(buf + 2, ':'); 1763146a1439SMasami Hiramatsu if (!p) { 1764146a1439SMasami Hiramatsu pr_debug("Internal error: %s should have ':' but not.\n", 1765146a1439SMasami Hiramatsu ent->s); 1766146a1439SMasami Hiramatsu ret = -ENOTSUP; 1767146a1439SMasami Hiramatsu goto error; 1768146a1439SMasami Hiramatsu } 1769bbbb521bSMasami Hiramatsu *p = '/'; 1770bbbb521bSMasami Hiramatsu 17714235b045SMasami Hiramatsu pr_debug("Writing event: %s\n", buf); 17724235b045SMasami Hiramatsu ret = write(fd, buf, strlen(buf)); 1773146a1439SMasami Hiramatsu if (ret < 0) 1774146a1439SMasami Hiramatsu goto error; 1775146a1439SMasami Hiramatsu 1776bbbb521bSMasami Hiramatsu printf("Remove event: %s\n", ent->s); 1777146a1439SMasami Hiramatsu return 0; 1778146a1439SMasami Hiramatsu error: 1779146a1439SMasami Hiramatsu pr_warning("Failed to delete event: %s\n", strerror(-ret)); 1780146a1439SMasami Hiramatsu return ret; 1781bbbb521bSMasami Hiramatsu } 1782bbbb521bSMasami Hiramatsu 17830e60836bSSrikar Dronamraju static int del_trace_probe_event(int fd, const char *group, 1784fa28244dSMasami Hiramatsu const char *event, struct strlist *namelist) 1785fa28244dSMasami Hiramatsu { 1786fa28244dSMasami Hiramatsu char buf[128]; 1787bbbb521bSMasami Hiramatsu struct str_node *ent, *n; 1788146a1439SMasami Hiramatsu int found = 0, ret = 0; 1789fa28244dSMasami Hiramatsu 1790146a1439SMasami Hiramatsu ret = e_snprintf(buf, 128, "%s:%s", group, event); 1791146a1439SMasami Hiramatsu if (ret < 0) { 17920e43e5d2SMasami Hiramatsu pr_err("Failed to copy event.\n"); 1793146a1439SMasami Hiramatsu return ret; 1794146a1439SMasami Hiramatsu } 1795fa28244dSMasami Hiramatsu 1796bbbb521bSMasami Hiramatsu if (strpbrk(buf, "*?")) { /* Glob-exp */ 1797bbbb521bSMasami Hiramatsu strlist__for_each_safe(ent, n, namelist) 1798bbbb521bSMasami Hiramatsu if (strglobmatch(ent->s, buf)) { 1799bbbb521bSMasami Hiramatsu found++; 18000e60836bSSrikar Dronamraju ret = __del_trace_probe_event(fd, ent); 1801146a1439SMasami Hiramatsu if (ret < 0) 1802146a1439SMasami Hiramatsu break; 18033e340590SMasami Hiramatsu strlist__remove(namelist, ent); 1804fa28244dSMasami Hiramatsu } 1805bbbb521bSMasami Hiramatsu } else { 1806bbbb521bSMasami Hiramatsu ent = strlist__find(namelist, buf); 1807bbbb521bSMasami Hiramatsu if (ent) { 1808bbbb521bSMasami Hiramatsu found++; 18090e60836bSSrikar Dronamraju ret = __del_trace_probe_event(fd, ent); 1810146a1439SMasami Hiramatsu if (ret >= 0) 1811bbbb521bSMasami Hiramatsu strlist__remove(namelist, ent); 1812bbbb521bSMasami Hiramatsu } 1813bbbb521bSMasami Hiramatsu } 1814146a1439SMasami Hiramatsu if (found == 0 && ret >= 0) 1815146a1439SMasami Hiramatsu pr_info("Info: Event \"%s\" does not exist.\n", buf); 1816146a1439SMasami Hiramatsu 1817146a1439SMasami Hiramatsu return ret; 1818bbbb521bSMasami Hiramatsu } 1819fa28244dSMasami Hiramatsu 1820146a1439SMasami Hiramatsu int del_perf_probe_events(struct strlist *dellist) 1821fa28244dSMasami Hiramatsu { 1822146a1439SMasami Hiramatsu int fd, ret = 0; 1823fa28244dSMasami Hiramatsu const char *group, *event; 1824fa28244dSMasami Hiramatsu char *p, *str; 1825fa28244dSMasami Hiramatsu struct str_node *ent; 1826fa28244dSMasami Hiramatsu struct strlist *namelist; 1827fa28244dSMasami Hiramatsu 1828f4d7da49SMasami Hiramatsu fd = open_kprobe_events(true); 1829146a1439SMasami Hiramatsu if (fd < 0) 1830146a1439SMasami Hiramatsu return fd; 1831146a1439SMasami Hiramatsu 1832fa28244dSMasami Hiramatsu /* Get current event names */ 18330e60836bSSrikar Dronamraju namelist = get_probe_trace_event_names(fd, true); 1834146a1439SMasami Hiramatsu if (namelist == NULL) 1835146a1439SMasami Hiramatsu return -EINVAL; 1836fa28244dSMasami Hiramatsu 1837adf365f4SMasami Hiramatsu strlist__for_each(ent, dellist) { 183802b95dadSMasami Hiramatsu str = strdup(ent->s); 183902b95dadSMasami Hiramatsu if (str == NULL) { 184002b95dadSMasami Hiramatsu ret = -ENOMEM; 184102b95dadSMasami Hiramatsu break; 184202b95dadSMasami Hiramatsu } 1843bbbb521bSMasami Hiramatsu pr_debug("Parsing: %s\n", str); 1844fa28244dSMasami Hiramatsu p = strchr(str, ':'); 1845fa28244dSMasami Hiramatsu if (p) { 1846fa28244dSMasami Hiramatsu group = str; 1847fa28244dSMasami Hiramatsu *p = '\0'; 1848fa28244dSMasami Hiramatsu event = p + 1; 1849fa28244dSMasami Hiramatsu } else { 1850bbbb521bSMasami Hiramatsu group = "*"; 1851fa28244dSMasami Hiramatsu event = str; 1852fa28244dSMasami Hiramatsu } 1853bbbb521bSMasami Hiramatsu pr_debug("Group: %s, Event: %s\n", group, event); 18540e60836bSSrikar Dronamraju ret = del_trace_probe_event(fd, group, event, namelist); 1855fa28244dSMasami Hiramatsu free(str); 1856146a1439SMasami Hiramatsu if (ret < 0) 1857146a1439SMasami Hiramatsu break; 1858fa28244dSMasami Hiramatsu } 1859fa28244dSMasami Hiramatsu strlist__delete(namelist); 1860fa28244dSMasami Hiramatsu close(fd); 1861146a1439SMasami Hiramatsu 1862146a1439SMasami Hiramatsu return ret; 1863fa28244dSMasami Hiramatsu } 1864fa28244dSMasami Hiramatsu 1865