150656eecSMasami Hiramatsu /* 250656eecSMasami Hiramatsu * probe-event.c : perf-probe definition to kprobe_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); 75e0faa8d3SMasami Hiramatsu static struct map_groups kmap_groups; 76e0faa8d3SMasami Hiramatsu static struct map *kmaps[MAP__NR_TYPES]; 77e0faa8d3SMasami Hiramatsu 784b4da7f7SMasami Hiramatsu /* Initialize symbol maps and path of vmlinux */ 79146a1439SMasami Hiramatsu static int init_vmlinux(void) 80e0faa8d3SMasami Hiramatsu { 81a1645ce1SZhang, Yanmin struct dso *kernel; 82146a1439SMasami Hiramatsu int ret; 83146a1439SMasami Hiramatsu 84e0faa8d3SMasami Hiramatsu symbol_conf.sort_by_name = true; 85e0faa8d3SMasami Hiramatsu if (symbol_conf.vmlinux_name == NULL) 86e0faa8d3SMasami Hiramatsu symbol_conf.try_vmlinux_path = true; 87e0faa8d3SMasami Hiramatsu else 88e0faa8d3SMasami Hiramatsu pr_debug("Use vmlinux: %s\n", symbol_conf.vmlinux_name); 89146a1439SMasami Hiramatsu ret = symbol__init(); 90146a1439SMasami Hiramatsu if (ret < 0) { 91146a1439SMasami Hiramatsu pr_debug("Failed to init symbol map.\n"); 92146a1439SMasami Hiramatsu goto out; 93146a1439SMasami Hiramatsu } 94e0faa8d3SMasami Hiramatsu 95a1645ce1SZhang, Yanmin kernel = dso__new_kernel(symbol_conf.vmlinux_name); 96a1645ce1SZhang, Yanmin if (kernel == NULL) 97a1645ce1SZhang, Yanmin die("Failed to create kernel dso."); 98a1645ce1SZhang, Yanmin 99e0faa8d3SMasami Hiramatsu map_groups__init(&kmap_groups); 100a1645ce1SZhang, Yanmin ret = __map_groups__create_kernel_maps(&kmap_groups, kmaps, kernel); 101146a1439SMasami Hiramatsu if (ret < 0) 102146a1439SMasami Hiramatsu pr_debug("Failed to create kernel maps.\n"); 103146a1439SMasami Hiramatsu 104146a1439SMasami Hiramatsu out: 105146a1439SMasami Hiramatsu if (ret < 0) 106146a1439SMasami Hiramatsu pr_warning("Failed to init vmlinux path.\n"); 107146a1439SMasami Hiramatsu return ret; 108e0faa8d3SMasami Hiramatsu } 109e0faa8d3SMasami Hiramatsu 1104b4da7f7SMasami Hiramatsu #ifdef DWARF_SUPPORT 111e0faa8d3SMasami Hiramatsu static int open_vmlinux(void) 112e0faa8d3SMasami Hiramatsu { 113e0faa8d3SMasami Hiramatsu if (map__load(kmaps[MAP__FUNCTION], NULL) < 0) { 114e0faa8d3SMasami Hiramatsu pr_debug("Failed to load kernel map.\n"); 115e0faa8d3SMasami Hiramatsu return -EINVAL; 116e0faa8d3SMasami Hiramatsu } 117e0faa8d3SMasami Hiramatsu pr_debug("Try to open %s\n", kmaps[MAP__FUNCTION]->dso->long_name); 118e0faa8d3SMasami Hiramatsu return open(kmaps[MAP__FUNCTION]->dso->long_name, O_RDONLY); 119e0faa8d3SMasami Hiramatsu } 1204b4da7f7SMasami Hiramatsu 121146a1439SMasami Hiramatsu /* Convert trace point to probe point with debuginfo */ 122146a1439SMasami Hiramatsu static int convert_to_perf_probe_point(struct kprobe_trace_point *tp, 1234b4da7f7SMasami Hiramatsu struct perf_probe_point *pp) 1244b4da7f7SMasami Hiramatsu { 1254b4da7f7SMasami Hiramatsu struct symbol *sym; 126146a1439SMasami Hiramatsu int fd, ret = -ENOENT; 1274b4da7f7SMasami Hiramatsu 1284b4da7f7SMasami Hiramatsu sym = map__find_symbol_by_name(kmaps[MAP__FUNCTION], 1294b4da7f7SMasami Hiramatsu tp->symbol, NULL); 1304b4da7f7SMasami Hiramatsu if (sym) { 1314b4da7f7SMasami Hiramatsu fd = open_vmlinux(); 132146a1439SMasami Hiramatsu if (fd >= 0) { 133146a1439SMasami Hiramatsu ret = find_perf_probe_point(fd, 134146a1439SMasami Hiramatsu sym->start + tp->offset, pp); 1354b4da7f7SMasami Hiramatsu close(fd); 1364b4da7f7SMasami Hiramatsu } 137146a1439SMasami Hiramatsu } 1384b4da7f7SMasami Hiramatsu if (ret <= 0) { 139146a1439SMasami Hiramatsu pr_debug("Failed to find corresponding probes from " 140146a1439SMasami Hiramatsu "debuginfo. Use kprobe event information.\n"); 14102b95dadSMasami Hiramatsu pp->function = strdup(tp->symbol); 14202b95dadSMasami Hiramatsu if (pp->function == NULL) 14302b95dadSMasami Hiramatsu return -ENOMEM; 1444b4da7f7SMasami Hiramatsu pp->offset = tp->offset; 1454b4da7f7SMasami Hiramatsu } 1464b4da7f7SMasami Hiramatsu pp->retprobe = tp->retprobe; 147146a1439SMasami Hiramatsu 148146a1439SMasami Hiramatsu return 0; 1494b4da7f7SMasami Hiramatsu } 1504b4da7f7SMasami Hiramatsu 1514b4da7f7SMasami Hiramatsu /* Try to find perf_probe_event with debuginfo */ 1524b4da7f7SMasami Hiramatsu static int try_to_find_kprobe_trace_events(struct perf_probe_event *pev, 1534b4da7f7SMasami Hiramatsu struct kprobe_trace_event **tevs) 1544b4da7f7SMasami Hiramatsu { 1554b4da7f7SMasami Hiramatsu bool need_dwarf = perf_probe_event_need_dwarf(pev); 1564b4da7f7SMasami Hiramatsu int fd, ntevs; 1574b4da7f7SMasami Hiramatsu 1584b4da7f7SMasami Hiramatsu fd = open_vmlinux(); 1594b4da7f7SMasami Hiramatsu if (fd < 0) { 160146a1439SMasami Hiramatsu if (need_dwarf) { 161146a1439SMasami Hiramatsu pr_warning("Failed to open debuginfo file.\n"); 162146a1439SMasami Hiramatsu return fd; 163146a1439SMasami Hiramatsu } 1644b4da7f7SMasami Hiramatsu pr_debug("Could not open vmlinux. Try to use symbols.\n"); 1654b4da7f7SMasami Hiramatsu return 0; 1664b4da7f7SMasami Hiramatsu } 1674b4da7f7SMasami Hiramatsu 1684b4da7f7SMasami Hiramatsu /* Searching trace events corresponding to probe event */ 1694b4da7f7SMasami Hiramatsu ntevs = find_kprobe_trace_events(fd, pev, tevs); 1704b4da7f7SMasami Hiramatsu close(fd); 1714b4da7f7SMasami Hiramatsu 172146a1439SMasami Hiramatsu if (ntevs > 0) { /* Succeeded to find trace events */ 173146a1439SMasami Hiramatsu pr_debug("find %d kprobe_trace_events.\n", ntevs); 1744b4da7f7SMasami Hiramatsu return ntevs; 175146a1439SMasami Hiramatsu } 1764b4da7f7SMasami Hiramatsu 177146a1439SMasami Hiramatsu if (ntevs == 0) { /* No error but failed to find probe point. */ 178146a1439SMasami Hiramatsu pr_warning("Probe point '%s' not found.\n", 1794b4da7f7SMasami Hiramatsu synthesize_perf_probe_point(&pev->point)); 180146a1439SMasami Hiramatsu return -ENOENT; 181146a1439SMasami Hiramatsu } 182146a1439SMasami Hiramatsu /* Error path : ntevs < 0 */ 1834b4da7f7SMasami Hiramatsu if (need_dwarf) { 184b55a87adSMasami Hiramatsu if (ntevs == -EBADF) 1854b4da7f7SMasami Hiramatsu pr_warning("No dwarf info found in the vmlinux - " 1864b4da7f7SMasami Hiramatsu "please rebuild with CONFIG_DEBUG_INFO=y.\n"); 187146a1439SMasami Hiramatsu return ntevs; 1884b4da7f7SMasami Hiramatsu } 1894b4da7f7SMasami Hiramatsu pr_debug("An error occurred in debuginfo analysis." 1904b4da7f7SMasami Hiramatsu " Try to use symbols.\n"); 1914b4da7f7SMasami Hiramatsu return 0; 1924b4da7f7SMasami Hiramatsu } 1934b4da7f7SMasami Hiramatsu 1944b4da7f7SMasami Hiramatsu #define LINEBUF_SIZE 256 1954b4da7f7SMasami Hiramatsu #define NR_ADDITIONAL_LINES 2 1964b4da7f7SMasami Hiramatsu 197d3b63d7aSMasami Hiramatsu static int show_one_line(FILE *fp, int l, bool skip, bool show_num) 1984b4da7f7SMasami Hiramatsu { 1994b4da7f7SMasami Hiramatsu char buf[LINEBUF_SIZE]; 2004b4da7f7SMasami Hiramatsu const char *color = PERF_COLOR_BLUE; 2014b4da7f7SMasami Hiramatsu 2024b4da7f7SMasami Hiramatsu if (fgets(buf, LINEBUF_SIZE, fp) == NULL) 2034b4da7f7SMasami Hiramatsu goto error; 2044b4da7f7SMasami Hiramatsu if (!skip) { 2054b4da7f7SMasami Hiramatsu if (show_num) 206d3b63d7aSMasami Hiramatsu fprintf(stdout, "%7d %s", l, buf); 2074b4da7f7SMasami Hiramatsu else 2084b4da7f7SMasami Hiramatsu color_fprintf(stdout, color, " %s", buf); 2094b4da7f7SMasami Hiramatsu } 2104b4da7f7SMasami Hiramatsu 2114b4da7f7SMasami Hiramatsu while (strlen(buf) == LINEBUF_SIZE - 1 && 2124b4da7f7SMasami Hiramatsu buf[LINEBUF_SIZE - 2] != '\n') { 2134b4da7f7SMasami Hiramatsu if (fgets(buf, LINEBUF_SIZE, fp) == NULL) 2144b4da7f7SMasami Hiramatsu goto error; 2154b4da7f7SMasami Hiramatsu if (!skip) { 2164b4da7f7SMasami Hiramatsu if (show_num) 2174b4da7f7SMasami Hiramatsu fprintf(stdout, "%s", buf); 2184b4da7f7SMasami Hiramatsu else 2194b4da7f7SMasami Hiramatsu color_fprintf(stdout, color, "%s", buf); 2204b4da7f7SMasami Hiramatsu } 2214b4da7f7SMasami Hiramatsu } 222146a1439SMasami Hiramatsu 223146a1439SMasami Hiramatsu return 0; 2244b4da7f7SMasami Hiramatsu error: 2254b4da7f7SMasami Hiramatsu if (feof(fp)) 226146a1439SMasami Hiramatsu pr_warning("Source file is shorter than expected.\n"); 2274b4da7f7SMasami Hiramatsu else 228146a1439SMasami Hiramatsu pr_warning("File read error: %s\n", strerror(errno)); 229146a1439SMasami Hiramatsu 230146a1439SMasami Hiramatsu return -1; 2314b4da7f7SMasami Hiramatsu } 2324b4da7f7SMasami Hiramatsu 2334b4da7f7SMasami Hiramatsu /* 2344b4da7f7SMasami Hiramatsu * Show line-range always requires debuginfo to find source file and 2354b4da7f7SMasami Hiramatsu * line number. 2364b4da7f7SMasami Hiramatsu */ 237146a1439SMasami Hiramatsu int show_line_range(struct line_range *lr) 2384b4da7f7SMasami Hiramatsu { 239d3b63d7aSMasami Hiramatsu int l = 1; 2404b4da7f7SMasami Hiramatsu struct line_node *ln; 2414b4da7f7SMasami Hiramatsu FILE *fp; 2424b4da7f7SMasami Hiramatsu int fd, ret; 2434b4da7f7SMasami Hiramatsu 2444b4da7f7SMasami Hiramatsu /* Search a line range */ 245146a1439SMasami Hiramatsu ret = init_vmlinux(); 246146a1439SMasami Hiramatsu if (ret < 0) 247146a1439SMasami Hiramatsu return ret; 248146a1439SMasami Hiramatsu 2494b4da7f7SMasami Hiramatsu fd = open_vmlinux(); 250146a1439SMasami Hiramatsu if (fd < 0) { 251146a1439SMasami Hiramatsu pr_warning("Failed to open debuginfo file.\n"); 252146a1439SMasami Hiramatsu return fd; 253146a1439SMasami Hiramatsu } 254146a1439SMasami Hiramatsu 2554b4da7f7SMasami Hiramatsu ret = find_line_range(fd, lr); 2564b4da7f7SMasami Hiramatsu close(fd); 257146a1439SMasami Hiramatsu if (ret == 0) { 258146a1439SMasami Hiramatsu pr_warning("Specified source line is not found.\n"); 259146a1439SMasami Hiramatsu return -ENOENT; 260146a1439SMasami Hiramatsu } else if (ret < 0) { 261146a1439SMasami Hiramatsu pr_warning("Debuginfo analysis failed. (%d)\n", ret); 262146a1439SMasami Hiramatsu return ret; 263146a1439SMasami Hiramatsu } 2644b4da7f7SMasami Hiramatsu 2654b4da7f7SMasami Hiramatsu setup_pager(); 2664b4da7f7SMasami Hiramatsu 2674b4da7f7SMasami Hiramatsu if (lr->function) 2684b4da7f7SMasami Hiramatsu fprintf(stdout, "<%s:%d>\n", lr->function, 2694b4da7f7SMasami Hiramatsu lr->start - lr->offset); 2704b4da7f7SMasami Hiramatsu else 2714b4da7f7SMasami Hiramatsu fprintf(stdout, "<%s:%d>\n", lr->file, lr->start); 2724b4da7f7SMasami Hiramatsu 2734b4da7f7SMasami Hiramatsu fp = fopen(lr->path, "r"); 274146a1439SMasami Hiramatsu if (fp == NULL) { 275146a1439SMasami Hiramatsu pr_warning("Failed to open %s: %s\n", lr->path, 276146a1439SMasami Hiramatsu strerror(errno)); 277146a1439SMasami Hiramatsu return -errno; 278146a1439SMasami Hiramatsu } 2794b4da7f7SMasami Hiramatsu /* Skip to starting line number */ 280146a1439SMasami Hiramatsu while (l < lr->start && ret >= 0) 281146a1439SMasami Hiramatsu ret = show_one_line(fp, l++, true, false); 282146a1439SMasami Hiramatsu if (ret < 0) 283146a1439SMasami Hiramatsu goto end; 2844b4da7f7SMasami Hiramatsu 2854b4da7f7SMasami Hiramatsu list_for_each_entry(ln, &lr->line_list, list) { 286146a1439SMasami Hiramatsu while (ln->line > l && ret >= 0) 287146a1439SMasami Hiramatsu ret = show_one_line(fp, (l++) - lr->offset, 288146a1439SMasami Hiramatsu false, false); 289146a1439SMasami Hiramatsu if (ret >= 0) 290146a1439SMasami Hiramatsu ret = show_one_line(fp, (l++) - lr->offset, 291146a1439SMasami Hiramatsu false, true); 292146a1439SMasami Hiramatsu if (ret < 0) 293146a1439SMasami Hiramatsu goto end; 2944b4da7f7SMasami Hiramatsu } 2954b4da7f7SMasami Hiramatsu 2964b4da7f7SMasami Hiramatsu if (lr->end == INT_MAX) 2974b4da7f7SMasami Hiramatsu lr->end = l + NR_ADDITIONAL_LINES; 298dda4ab34SMasami Hiramatsu while (l <= lr->end && !feof(fp) && ret >= 0) 299146a1439SMasami Hiramatsu ret = show_one_line(fp, (l++) - lr->offset, false, false); 300146a1439SMasami Hiramatsu end: 3014b4da7f7SMasami Hiramatsu fclose(fp); 302146a1439SMasami Hiramatsu return ret; 3034b4da7f7SMasami Hiramatsu } 3044b4da7f7SMasami Hiramatsu 3054b4da7f7SMasami Hiramatsu #else /* !DWARF_SUPPORT */ 3064b4da7f7SMasami Hiramatsu 307146a1439SMasami Hiramatsu static int convert_to_perf_probe_point(struct kprobe_trace_point *tp, 3084b4da7f7SMasami Hiramatsu struct perf_probe_point *pp) 3094b4da7f7SMasami Hiramatsu { 31002b95dadSMasami Hiramatsu pp->function = strdup(tp->symbol); 31102b95dadSMasami Hiramatsu if (pp->function == NULL) 31202b95dadSMasami Hiramatsu return -ENOMEM; 3134b4da7f7SMasami Hiramatsu pp->offset = tp->offset; 3144b4da7f7SMasami Hiramatsu pp->retprobe = tp->retprobe; 315146a1439SMasami Hiramatsu 316146a1439SMasami Hiramatsu return 0; 3174b4da7f7SMasami Hiramatsu } 3184b4da7f7SMasami Hiramatsu 3194b4da7f7SMasami Hiramatsu static int try_to_find_kprobe_trace_events(struct perf_probe_event *pev, 3204b4da7f7SMasami Hiramatsu struct kprobe_trace_event **tevs __unused) 3214b4da7f7SMasami Hiramatsu { 322146a1439SMasami Hiramatsu if (perf_probe_event_need_dwarf(pev)) { 323146a1439SMasami Hiramatsu pr_warning("Debuginfo-analysis is not supported.\n"); 324146a1439SMasami Hiramatsu return -ENOSYS; 325146a1439SMasami Hiramatsu } 3264b4da7f7SMasami Hiramatsu return 0; 3274b4da7f7SMasami Hiramatsu } 3284b4da7f7SMasami Hiramatsu 329146a1439SMasami Hiramatsu int show_line_range(struct line_range *lr __unused) 3304b4da7f7SMasami Hiramatsu { 331146a1439SMasami Hiramatsu pr_warning("Debuginfo-analysis is not supported.\n"); 332146a1439SMasami Hiramatsu return -ENOSYS; 3334b4da7f7SMasami Hiramatsu } 3344b4da7f7SMasami Hiramatsu 335e0faa8d3SMasami Hiramatsu #endif 336e0faa8d3SMasami Hiramatsu 337146a1439SMasami Hiramatsu int parse_line_range_desc(const char *arg, struct line_range *lr) 338631c9defSMasami Hiramatsu { 339631c9defSMasami Hiramatsu const char *ptr; 340631c9defSMasami Hiramatsu char *tmp; 341631c9defSMasami Hiramatsu /* 342631c9defSMasami Hiramatsu * <Syntax> 343631c9defSMasami Hiramatsu * SRC:SLN[+NUM|-ELN] 344631c9defSMasami Hiramatsu * FUNC[:SLN[+NUM|-ELN]] 345631c9defSMasami Hiramatsu */ 346631c9defSMasami Hiramatsu ptr = strchr(arg, ':'); 347631c9defSMasami Hiramatsu if (ptr) { 348d3b63d7aSMasami Hiramatsu lr->start = (int)strtoul(ptr + 1, &tmp, 0); 349dda4ab34SMasami Hiramatsu if (*tmp == '+') { 350d3b63d7aSMasami Hiramatsu lr->end = lr->start + (int)strtoul(tmp + 1, &tmp, 0); 351dda4ab34SMasami Hiramatsu lr->end--; /* 352dda4ab34SMasami Hiramatsu * Adjust the number of lines here. 353dda4ab34SMasami Hiramatsu * If the number of lines == 1, the 354dda4ab34SMasami Hiramatsu * the end of line should be equal to 355dda4ab34SMasami Hiramatsu * the start of line. 356dda4ab34SMasami Hiramatsu */ 357dda4ab34SMasami Hiramatsu } else if (*tmp == '-') 358d3b63d7aSMasami Hiramatsu lr->end = (int)strtoul(tmp + 1, &tmp, 0); 359631c9defSMasami Hiramatsu else 360d3b63d7aSMasami Hiramatsu lr->end = INT_MAX; 361d3b63d7aSMasami Hiramatsu pr_debug("Line range is %d to %d\n", lr->start, lr->end); 362d3b63d7aSMasami Hiramatsu if (lr->start > lr->end) { 363631c9defSMasami Hiramatsu semantic_error("Start line must be smaller" 364146a1439SMasami Hiramatsu " than end line.\n"); 365146a1439SMasami Hiramatsu return -EINVAL; 366146a1439SMasami Hiramatsu } 367146a1439SMasami Hiramatsu if (*tmp != '\0') { 368146a1439SMasami Hiramatsu semantic_error("Tailing with invalid character '%d'.\n", 369631c9defSMasami Hiramatsu *tmp); 370146a1439SMasami Hiramatsu return -EINVAL; 371146a1439SMasami Hiramatsu } 37202b95dadSMasami Hiramatsu tmp = strndup(arg, (ptr - arg)); 373d3b63d7aSMasami Hiramatsu } else { 37402b95dadSMasami Hiramatsu tmp = strdup(arg); 375d3b63d7aSMasami Hiramatsu lr->end = INT_MAX; 376d3b63d7aSMasami Hiramatsu } 37702b95dadSMasami Hiramatsu 37802b95dadSMasami Hiramatsu if (tmp == NULL) 37902b95dadSMasami Hiramatsu return -ENOMEM; 380631c9defSMasami Hiramatsu 381631c9defSMasami Hiramatsu if (strchr(tmp, '.')) 382631c9defSMasami Hiramatsu lr->file = tmp; 383631c9defSMasami Hiramatsu else 384631c9defSMasami Hiramatsu lr->function = tmp; 385146a1439SMasami Hiramatsu 386146a1439SMasami Hiramatsu return 0; 387631c9defSMasami Hiramatsu } 388631c9defSMasami Hiramatsu 389b7702a21SMasami Hiramatsu /* Check the name is good for event/group */ 390b7702a21SMasami Hiramatsu static bool check_event_name(const char *name) 391b7702a21SMasami Hiramatsu { 392b7702a21SMasami Hiramatsu if (!isalpha(*name) && *name != '_') 393b7702a21SMasami Hiramatsu return false; 394b7702a21SMasami Hiramatsu while (*++name != '\0') { 395b7702a21SMasami Hiramatsu if (!isalpha(*name) && !isdigit(*name) && *name != '_') 396b7702a21SMasami Hiramatsu return false; 397b7702a21SMasami Hiramatsu } 398b7702a21SMasami Hiramatsu return true; 399b7702a21SMasami Hiramatsu } 400b7702a21SMasami Hiramatsu 40150656eecSMasami Hiramatsu /* Parse probepoint definition. */ 402146a1439SMasami Hiramatsu static int parse_perf_probe_point(char *arg, struct perf_probe_event *pev) 40350656eecSMasami Hiramatsu { 4044235b045SMasami Hiramatsu struct perf_probe_point *pp = &pev->point; 40550656eecSMasami Hiramatsu char *ptr, *tmp; 40650656eecSMasami Hiramatsu char c, nc = 0; 40750656eecSMasami Hiramatsu /* 40850656eecSMasami Hiramatsu * <Syntax> 4092a9c8c36SMasami Hiramatsu * perf probe [EVENT=]SRC[:LN|;PTN] 4102a9c8c36SMasami Hiramatsu * perf probe [EVENT=]FUNC[@SRC][+OFFS|%return|:LN|;PAT] 411af663d75SMasami Hiramatsu * 412af663d75SMasami Hiramatsu * TODO:Group name support 41350656eecSMasami Hiramatsu */ 41450656eecSMasami Hiramatsu 4152a9c8c36SMasami Hiramatsu ptr = strpbrk(arg, ";=@+%"); 4162a9c8c36SMasami Hiramatsu if (ptr && *ptr == '=') { /* Event name */ 417af663d75SMasami Hiramatsu *ptr = '\0'; 418af663d75SMasami Hiramatsu tmp = ptr + 1; 419146a1439SMasami Hiramatsu if (strchr(arg, ':')) { 420146a1439SMasami Hiramatsu semantic_error("Group name is not supported yet.\n"); 421146a1439SMasami Hiramatsu return -ENOTSUP; 422146a1439SMasami Hiramatsu } 423146a1439SMasami Hiramatsu if (!check_event_name(arg)) { 424b7702a21SMasami Hiramatsu semantic_error("%s is bad for event name -it must " 425146a1439SMasami Hiramatsu "follow C symbol-naming rule.\n", arg); 426146a1439SMasami Hiramatsu return -EINVAL; 427146a1439SMasami Hiramatsu } 42802b95dadSMasami Hiramatsu pev->event = strdup(arg); 42902b95dadSMasami Hiramatsu if (pev->event == NULL) 43002b95dadSMasami Hiramatsu return -ENOMEM; 4314235b045SMasami Hiramatsu pev->group = NULL; 432af663d75SMasami Hiramatsu arg = tmp; 433af663d75SMasami Hiramatsu } 434af663d75SMasami Hiramatsu 4352a9c8c36SMasami Hiramatsu ptr = strpbrk(arg, ";:+@%"); 43650656eecSMasami Hiramatsu if (ptr) { 43750656eecSMasami Hiramatsu nc = *ptr; 43850656eecSMasami Hiramatsu *ptr++ = '\0'; 43950656eecSMasami Hiramatsu } 44050656eecSMasami Hiramatsu 44102b95dadSMasami Hiramatsu tmp = strdup(arg); 44202b95dadSMasami Hiramatsu if (tmp == NULL) 44302b95dadSMasami Hiramatsu return -ENOMEM; 44402b95dadSMasami Hiramatsu 44550656eecSMasami Hiramatsu /* Check arg is function or file and copy it */ 44602b95dadSMasami Hiramatsu if (strchr(tmp, '.')) /* File */ 44702b95dadSMasami Hiramatsu pp->file = tmp; 44850656eecSMasami Hiramatsu else /* Function */ 44902b95dadSMasami Hiramatsu pp->function = tmp; 45050656eecSMasami Hiramatsu 45150656eecSMasami Hiramatsu /* Parse other options */ 45250656eecSMasami Hiramatsu while (ptr) { 45350656eecSMasami Hiramatsu arg = ptr; 45450656eecSMasami Hiramatsu c = nc; 4552a9c8c36SMasami Hiramatsu if (c == ';') { /* Lazy pattern must be the last part */ 45602b95dadSMasami Hiramatsu pp->lazy_line = strdup(arg); 45702b95dadSMasami Hiramatsu if (pp->lazy_line == NULL) 45802b95dadSMasami Hiramatsu return -ENOMEM; 4592a9c8c36SMasami Hiramatsu break; 4602a9c8c36SMasami Hiramatsu } 4612a9c8c36SMasami Hiramatsu ptr = strpbrk(arg, ";:+@%"); 46250656eecSMasami Hiramatsu if (ptr) { 46350656eecSMasami Hiramatsu nc = *ptr; 46450656eecSMasami Hiramatsu *ptr++ = '\0'; 46550656eecSMasami Hiramatsu } 46650656eecSMasami Hiramatsu switch (c) { 46750656eecSMasami Hiramatsu case ':': /* Line number */ 46850656eecSMasami Hiramatsu pp->line = strtoul(arg, &tmp, 0); 469146a1439SMasami Hiramatsu if (*tmp != '\0') { 4702a9c8c36SMasami Hiramatsu semantic_error("There is non-digit char" 471146a1439SMasami Hiramatsu " in line number.\n"); 472146a1439SMasami Hiramatsu return -EINVAL; 473146a1439SMasami Hiramatsu } 47450656eecSMasami Hiramatsu break; 47550656eecSMasami Hiramatsu case '+': /* Byte offset from a symbol */ 47650656eecSMasami Hiramatsu pp->offset = strtoul(arg, &tmp, 0); 477146a1439SMasami Hiramatsu if (*tmp != '\0') { 4782a9c8c36SMasami Hiramatsu semantic_error("There is non-digit character" 479146a1439SMasami Hiramatsu " in offset.\n"); 480146a1439SMasami Hiramatsu return -EINVAL; 481146a1439SMasami Hiramatsu } 48250656eecSMasami Hiramatsu break; 48350656eecSMasami Hiramatsu case '@': /* File name */ 484146a1439SMasami Hiramatsu if (pp->file) { 485146a1439SMasami Hiramatsu semantic_error("SRC@SRC is not allowed.\n"); 486146a1439SMasami Hiramatsu return -EINVAL; 487146a1439SMasami Hiramatsu } 48802b95dadSMasami Hiramatsu pp->file = strdup(arg); 48902b95dadSMasami Hiramatsu if (pp->file == NULL) 49002b95dadSMasami Hiramatsu return -ENOMEM; 49150656eecSMasami Hiramatsu break; 49250656eecSMasami Hiramatsu case '%': /* Probe places */ 49350656eecSMasami Hiramatsu if (strcmp(arg, "return") == 0) { 49450656eecSMasami Hiramatsu pp->retprobe = 1; 495146a1439SMasami Hiramatsu } else { /* Others not supported yet */ 496146a1439SMasami Hiramatsu semantic_error("%%%s is not supported.\n", arg); 497146a1439SMasami Hiramatsu return -ENOTSUP; 498146a1439SMasami Hiramatsu } 49950656eecSMasami Hiramatsu break; 500146a1439SMasami Hiramatsu default: /* Buggy case */ 501146a1439SMasami Hiramatsu pr_err("This program has a bug at %s:%d.\n", 502146a1439SMasami Hiramatsu __FILE__, __LINE__); 503146a1439SMasami Hiramatsu return -ENOTSUP; 50450656eecSMasami Hiramatsu break; 50550656eecSMasami Hiramatsu } 50650656eecSMasami Hiramatsu } 50750656eecSMasami Hiramatsu 50850656eecSMasami Hiramatsu /* Exclusion check */ 509146a1439SMasami Hiramatsu if (pp->lazy_line && pp->line) { 5102a9c8c36SMasami Hiramatsu semantic_error("Lazy pattern can't be used with line number."); 511146a1439SMasami Hiramatsu return -EINVAL; 512146a1439SMasami Hiramatsu } 5132a9c8c36SMasami Hiramatsu 514146a1439SMasami Hiramatsu if (pp->lazy_line && pp->offset) { 5152a9c8c36SMasami Hiramatsu semantic_error("Lazy pattern can't be used with offset."); 516146a1439SMasami Hiramatsu return -EINVAL; 517146a1439SMasami Hiramatsu } 5182a9c8c36SMasami Hiramatsu 519146a1439SMasami Hiramatsu if (pp->line && pp->offset) { 52050656eecSMasami Hiramatsu semantic_error("Offset can't be used with line number."); 521146a1439SMasami Hiramatsu return -EINVAL; 522146a1439SMasami Hiramatsu } 52350656eecSMasami Hiramatsu 524146a1439SMasami Hiramatsu if (!pp->line && !pp->lazy_line && pp->file && !pp->function) { 5252a9c8c36SMasami Hiramatsu semantic_error("File always requires line number or " 5262a9c8c36SMasami Hiramatsu "lazy pattern."); 527146a1439SMasami Hiramatsu return -EINVAL; 528146a1439SMasami Hiramatsu } 52950656eecSMasami Hiramatsu 530146a1439SMasami Hiramatsu if (pp->offset && !pp->function) { 53150656eecSMasami Hiramatsu semantic_error("Offset requires an entry function."); 532146a1439SMasami Hiramatsu return -EINVAL; 533146a1439SMasami Hiramatsu } 53450656eecSMasami Hiramatsu 535146a1439SMasami Hiramatsu if (pp->retprobe && !pp->function) { 53650656eecSMasami Hiramatsu semantic_error("Return probe requires an entry function."); 537146a1439SMasami Hiramatsu return -EINVAL; 538146a1439SMasami Hiramatsu } 53950656eecSMasami Hiramatsu 540146a1439SMasami Hiramatsu if ((pp->offset || pp->line || pp->lazy_line) && pp->retprobe) { 5412a9c8c36SMasami Hiramatsu semantic_error("Offset/Line/Lazy pattern can't be used with " 5422a9c8c36SMasami Hiramatsu "return probe."); 543146a1439SMasami Hiramatsu return -EINVAL; 544146a1439SMasami Hiramatsu } 54550656eecSMasami Hiramatsu 5464235b045SMasami Hiramatsu pr_debug("symbol:%s file:%s line:%d offset:%lu return:%d lazy:%s\n", 5472a9c8c36SMasami Hiramatsu pp->function, pp->file, pp->line, pp->offset, pp->retprobe, 5482a9c8c36SMasami Hiramatsu pp->lazy_line); 549146a1439SMasami Hiramatsu return 0; 55050656eecSMasami Hiramatsu } 55150656eecSMasami Hiramatsu 5527df2f329SMasami Hiramatsu /* Parse perf-probe event argument */ 553146a1439SMasami Hiramatsu static int parse_perf_probe_arg(char *str, struct perf_probe_arg *arg) 5547df2f329SMasami Hiramatsu { 55548481938SMasami Hiramatsu char *tmp; 5567df2f329SMasami Hiramatsu struct perf_probe_arg_field **fieldp; 5577df2f329SMasami Hiramatsu 5587df2f329SMasami Hiramatsu pr_debug("parsing arg: %s into ", str); 5597df2f329SMasami Hiramatsu 56048481938SMasami Hiramatsu tmp = strchr(str, '='); 56148481938SMasami Hiramatsu if (tmp) { 56202b95dadSMasami Hiramatsu arg->name = strndup(str, tmp - str); 56302b95dadSMasami Hiramatsu if (arg->name == NULL) 56402b95dadSMasami Hiramatsu return -ENOMEM; 56511a1ca35SMasami Hiramatsu pr_debug("name:%s ", arg->name); 56648481938SMasami Hiramatsu str = tmp + 1; 56748481938SMasami Hiramatsu } 56848481938SMasami Hiramatsu 56911a1ca35SMasami Hiramatsu tmp = strchr(str, ':'); 57011a1ca35SMasami Hiramatsu if (tmp) { /* Type setting */ 57111a1ca35SMasami Hiramatsu *tmp = '\0'; 57202b95dadSMasami Hiramatsu arg->type = strdup(tmp + 1); 57302b95dadSMasami Hiramatsu if (arg->type == NULL) 57402b95dadSMasami Hiramatsu return -ENOMEM; 57511a1ca35SMasami Hiramatsu pr_debug("type:%s ", arg->type); 57611a1ca35SMasami Hiramatsu } 57711a1ca35SMasami Hiramatsu 5787df2f329SMasami Hiramatsu tmp = strpbrk(str, "-."); 5797df2f329SMasami Hiramatsu if (!is_c_varname(str) || !tmp) { 5807df2f329SMasami Hiramatsu /* A variable, register, symbol or special value */ 58102b95dadSMasami Hiramatsu arg->var = strdup(str); 58202b95dadSMasami Hiramatsu if (arg->var == NULL) 58302b95dadSMasami Hiramatsu return -ENOMEM; 58448481938SMasami Hiramatsu pr_debug("%s\n", arg->var); 585146a1439SMasami Hiramatsu return 0; 5867df2f329SMasami Hiramatsu } 5877df2f329SMasami Hiramatsu 5887df2f329SMasami Hiramatsu /* Structure fields */ 58902b95dadSMasami Hiramatsu arg->var = strndup(str, tmp - str); 59002b95dadSMasami Hiramatsu if (arg->var == NULL) 59102b95dadSMasami Hiramatsu return -ENOMEM; 59248481938SMasami Hiramatsu pr_debug("%s, ", arg->var); 5937df2f329SMasami Hiramatsu fieldp = &arg->field; 5947df2f329SMasami Hiramatsu 5957df2f329SMasami Hiramatsu do { 596e334016fSMasami Hiramatsu *fieldp = zalloc(sizeof(struct perf_probe_arg_field)); 597e334016fSMasami Hiramatsu if (*fieldp == NULL) 598e334016fSMasami Hiramatsu return -ENOMEM; 5997df2f329SMasami Hiramatsu if (*tmp == '.') { 6007df2f329SMasami Hiramatsu str = tmp + 1; 6017df2f329SMasami Hiramatsu (*fieldp)->ref = false; 6027df2f329SMasami Hiramatsu } else if (tmp[1] == '>') { 6037df2f329SMasami Hiramatsu str = tmp + 2; 6047df2f329SMasami Hiramatsu (*fieldp)->ref = true; 605146a1439SMasami Hiramatsu } else { 606146a1439SMasami Hiramatsu semantic_error("Argument parse error: %s\n", str); 607146a1439SMasami Hiramatsu return -EINVAL; 608146a1439SMasami Hiramatsu } 6097df2f329SMasami Hiramatsu 6107df2f329SMasami Hiramatsu tmp = strpbrk(str, "-."); 6117df2f329SMasami Hiramatsu if (tmp) { 61202b95dadSMasami Hiramatsu (*fieldp)->name = strndup(str, tmp - str); 61302b95dadSMasami Hiramatsu if ((*fieldp)->name == NULL) 61402b95dadSMasami Hiramatsu return -ENOMEM; 6157df2f329SMasami Hiramatsu pr_debug("%s(%d), ", (*fieldp)->name, (*fieldp)->ref); 6167df2f329SMasami Hiramatsu fieldp = &(*fieldp)->next; 6177df2f329SMasami Hiramatsu } 6187df2f329SMasami Hiramatsu } while (tmp); 61902b95dadSMasami Hiramatsu (*fieldp)->name = strdup(str); 62002b95dadSMasami Hiramatsu if ((*fieldp)->name == NULL) 62102b95dadSMasami Hiramatsu return -ENOMEM; 6227df2f329SMasami Hiramatsu pr_debug("%s(%d)\n", (*fieldp)->name, (*fieldp)->ref); 623df0faf4bSMasami Hiramatsu 624df0faf4bSMasami Hiramatsu /* If no name is specified, set the last field name */ 62502b95dadSMasami Hiramatsu if (!arg->name) { 62602b95dadSMasami Hiramatsu arg->name = strdup((*fieldp)->name); 62702b95dadSMasami Hiramatsu if (arg->name == NULL) 62802b95dadSMasami Hiramatsu return -ENOMEM; 62902b95dadSMasami Hiramatsu } 630146a1439SMasami Hiramatsu return 0; 6317df2f329SMasami Hiramatsu } 6327df2f329SMasami Hiramatsu 6334235b045SMasami Hiramatsu /* Parse perf-probe event command */ 634146a1439SMasami Hiramatsu int parse_perf_probe_command(const char *cmd, struct perf_probe_event *pev) 63550656eecSMasami Hiramatsu { 636e1c01d61SMasami Hiramatsu char **argv; 637146a1439SMasami Hiramatsu int argc, i, ret = 0; 638fac13fd5SMasami Hiramatsu 6394235b045SMasami Hiramatsu argv = argv_split(cmd, &argc); 640146a1439SMasami Hiramatsu if (!argv) { 641146a1439SMasami Hiramatsu pr_debug("Failed to split arguments.\n"); 642146a1439SMasami Hiramatsu return -ENOMEM; 643146a1439SMasami Hiramatsu } 644146a1439SMasami Hiramatsu if (argc - 1 > MAX_PROBE_ARGS) { 645146a1439SMasami Hiramatsu semantic_error("Too many probe arguments (%d).\n", argc - 1); 646146a1439SMasami Hiramatsu ret = -ERANGE; 647146a1439SMasami Hiramatsu goto out; 648146a1439SMasami Hiramatsu } 64950656eecSMasami Hiramatsu /* Parse probe point */ 650146a1439SMasami Hiramatsu ret = parse_perf_probe_point(argv[0], pev); 651146a1439SMasami Hiramatsu if (ret < 0) 652146a1439SMasami Hiramatsu goto out; 65350656eecSMasami Hiramatsu 654e1c01d61SMasami Hiramatsu /* Copy arguments and ensure return probe has no C argument */ 6554235b045SMasami Hiramatsu pev->nargs = argc - 1; 656e334016fSMasami Hiramatsu pev->args = zalloc(sizeof(struct perf_probe_arg) * pev->nargs); 657e334016fSMasami Hiramatsu if (pev->args == NULL) { 658e334016fSMasami Hiramatsu ret = -ENOMEM; 659e334016fSMasami Hiramatsu goto out; 660e334016fSMasami Hiramatsu } 661146a1439SMasami Hiramatsu for (i = 0; i < pev->nargs && ret >= 0; i++) { 662146a1439SMasami Hiramatsu ret = parse_perf_probe_arg(argv[i + 1], &pev->args[i]); 663146a1439SMasami Hiramatsu if (ret >= 0 && 664146a1439SMasami Hiramatsu is_c_varname(pev->args[i].var) && pev->point.retprobe) { 6654235b045SMasami Hiramatsu semantic_error("You can't specify local variable for" 666146a1439SMasami Hiramatsu " kretprobe.\n"); 667146a1439SMasami Hiramatsu ret = -EINVAL; 668e1c01d61SMasami Hiramatsu } 669146a1439SMasami Hiramatsu } 670146a1439SMasami Hiramatsu out: 671e1c01d61SMasami Hiramatsu argv_free(argv); 672146a1439SMasami Hiramatsu 673146a1439SMasami Hiramatsu return ret; 67450656eecSMasami Hiramatsu } 67550656eecSMasami Hiramatsu 6764235b045SMasami Hiramatsu /* Return true if this perf_probe_event requires debuginfo */ 6774235b045SMasami Hiramatsu bool perf_probe_event_need_dwarf(struct perf_probe_event *pev) 6784de189feSMasami Hiramatsu { 6794235b045SMasami Hiramatsu int i; 6804235b045SMasami Hiramatsu 6814235b045SMasami Hiramatsu if (pev->point.file || pev->point.line || pev->point.lazy_line) 6824235b045SMasami Hiramatsu return true; 6834235b045SMasami Hiramatsu 6844235b045SMasami Hiramatsu for (i = 0; i < pev->nargs; i++) 68548481938SMasami Hiramatsu if (is_c_varname(pev->args[i].var)) 6864235b045SMasami Hiramatsu return true; 6874235b045SMasami Hiramatsu 6884235b045SMasami Hiramatsu return false; 6894235b045SMasami Hiramatsu } 6904235b045SMasami Hiramatsu 6914235b045SMasami Hiramatsu /* Parse kprobe_events event into struct probe_point */ 692146a1439SMasami Hiramatsu int parse_kprobe_trace_command(const char *cmd, struct kprobe_trace_event *tev) 6934235b045SMasami Hiramatsu { 6944235b045SMasami Hiramatsu struct kprobe_trace_point *tp = &tev->point; 6954de189feSMasami Hiramatsu char pr; 6964de189feSMasami Hiramatsu char *p; 6974de189feSMasami Hiramatsu int ret, i, argc; 6984de189feSMasami Hiramatsu char **argv; 6994de189feSMasami Hiramatsu 7004235b045SMasami Hiramatsu pr_debug("Parsing kprobe_events: %s\n", cmd); 7014235b045SMasami Hiramatsu argv = argv_split(cmd, &argc); 702146a1439SMasami Hiramatsu if (!argv) { 703146a1439SMasami Hiramatsu pr_debug("Failed to split arguments.\n"); 704146a1439SMasami Hiramatsu return -ENOMEM; 705146a1439SMasami Hiramatsu } 706146a1439SMasami Hiramatsu if (argc < 2) { 707146a1439SMasami Hiramatsu semantic_error("Too few probe arguments.\n"); 708146a1439SMasami Hiramatsu ret = -ERANGE; 709146a1439SMasami Hiramatsu goto out; 710146a1439SMasami Hiramatsu } 7114de189feSMasami Hiramatsu 7124de189feSMasami Hiramatsu /* Scan event and group name. */ 71393aaa45aSLiming Wang ret = sscanf(argv[0], "%c:%a[^/ \t]/%a[^ \t]", 7144235b045SMasami Hiramatsu &pr, (float *)(void *)&tev->group, 7154235b045SMasami Hiramatsu (float *)(void *)&tev->event); 716146a1439SMasami Hiramatsu if (ret != 3) { 717146a1439SMasami Hiramatsu semantic_error("Failed to parse event name: %s\n", argv[0]); 718146a1439SMasami Hiramatsu ret = -EINVAL; 719146a1439SMasami Hiramatsu goto out; 720146a1439SMasami Hiramatsu } 7214235b045SMasami Hiramatsu pr_debug("Group:%s Event:%s probe:%c\n", tev->group, tev->event, pr); 7224de189feSMasami Hiramatsu 7234235b045SMasami Hiramatsu tp->retprobe = (pr == 'r'); 7244de189feSMasami Hiramatsu 7254de189feSMasami Hiramatsu /* Scan function name and offset */ 7264235b045SMasami Hiramatsu ret = sscanf(argv[1], "%a[^+]+%lu", (float *)(void *)&tp->symbol, 7274235b045SMasami Hiramatsu &tp->offset); 7284de189feSMasami Hiramatsu if (ret == 1) 7294235b045SMasami Hiramatsu tp->offset = 0; 7304de189feSMasami Hiramatsu 7314235b045SMasami Hiramatsu tev->nargs = argc - 2; 732e334016fSMasami Hiramatsu tev->args = zalloc(sizeof(struct kprobe_trace_arg) * tev->nargs); 733e334016fSMasami Hiramatsu if (tev->args == NULL) { 734e334016fSMasami Hiramatsu ret = -ENOMEM; 735e334016fSMasami Hiramatsu goto out; 736e334016fSMasami Hiramatsu } 7374235b045SMasami Hiramatsu for (i = 0; i < tev->nargs; i++) { 7384de189feSMasami Hiramatsu p = strchr(argv[i + 2], '='); 7394de189feSMasami Hiramatsu if (p) /* We don't need which register is assigned. */ 7404235b045SMasami Hiramatsu *p++ = '\0'; 7414235b045SMasami Hiramatsu else 7424235b045SMasami Hiramatsu p = argv[i + 2]; 74302b95dadSMasami Hiramatsu tev->args[i].name = strdup(argv[i + 2]); 7444235b045SMasami Hiramatsu /* TODO: parse regs and offset */ 74502b95dadSMasami Hiramatsu tev->args[i].value = strdup(p); 74602b95dadSMasami Hiramatsu if (tev->args[i].name == NULL || tev->args[i].value == NULL) { 74702b95dadSMasami Hiramatsu ret = -ENOMEM; 74802b95dadSMasami Hiramatsu goto out; 74902b95dadSMasami Hiramatsu } 7504de189feSMasami Hiramatsu } 751146a1439SMasami Hiramatsu ret = 0; 752146a1439SMasami Hiramatsu out: 7534de189feSMasami Hiramatsu argv_free(argv); 754146a1439SMasami Hiramatsu return ret; 7554de189feSMasami Hiramatsu } 7564de189feSMasami Hiramatsu 7577df2f329SMasami Hiramatsu /* Compose only probe arg */ 7587df2f329SMasami Hiramatsu int synthesize_perf_probe_arg(struct perf_probe_arg *pa, char *buf, size_t len) 7597df2f329SMasami Hiramatsu { 7607df2f329SMasami Hiramatsu struct perf_probe_arg_field *field = pa->field; 7617df2f329SMasami Hiramatsu int ret; 7627df2f329SMasami Hiramatsu char *tmp = buf; 7637df2f329SMasami Hiramatsu 76448481938SMasami Hiramatsu if (pa->name && pa->var) 76548481938SMasami Hiramatsu ret = e_snprintf(tmp, len, "%s=%s", pa->name, pa->var); 76648481938SMasami Hiramatsu else 76748481938SMasami Hiramatsu ret = e_snprintf(tmp, len, "%s", pa->name ? pa->name : pa->var); 7687df2f329SMasami Hiramatsu if (ret <= 0) 7697df2f329SMasami Hiramatsu goto error; 7707df2f329SMasami Hiramatsu tmp += ret; 7717df2f329SMasami Hiramatsu len -= ret; 7727df2f329SMasami Hiramatsu 7737df2f329SMasami Hiramatsu while (field) { 7747df2f329SMasami Hiramatsu ret = e_snprintf(tmp, len, "%s%s", field->ref ? "->" : ".", 7757df2f329SMasami Hiramatsu field->name); 7767df2f329SMasami Hiramatsu if (ret <= 0) 7777df2f329SMasami Hiramatsu goto error; 7787df2f329SMasami Hiramatsu tmp += ret; 7797df2f329SMasami Hiramatsu len -= ret; 7807df2f329SMasami Hiramatsu field = field->next; 7817df2f329SMasami Hiramatsu } 78211a1ca35SMasami Hiramatsu 78311a1ca35SMasami Hiramatsu if (pa->type) { 78411a1ca35SMasami Hiramatsu ret = e_snprintf(tmp, len, ":%s", pa->type); 78511a1ca35SMasami Hiramatsu if (ret <= 0) 78611a1ca35SMasami Hiramatsu goto error; 78711a1ca35SMasami Hiramatsu tmp += ret; 78811a1ca35SMasami Hiramatsu len -= ret; 78911a1ca35SMasami Hiramatsu } 79011a1ca35SMasami Hiramatsu 7917df2f329SMasami Hiramatsu return tmp - buf; 7927df2f329SMasami Hiramatsu error: 793146a1439SMasami Hiramatsu pr_debug("Failed to synthesize perf probe argument: %s", 794146a1439SMasami Hiramatsu strerror(-ret)); 795146a1439SMasami Hiramatsu return ret; 7967df2f329SMasami Hiramatsu } 7977df2f329SMasami Hiramatsu 7984235b045SMasami Hiramatsu /* Compose only probe point (not argument) */ 7994235b045SMasami Hiramatsu static char *synthesize_perf_probe_point(struct perf_probe_point *pp) 80050656eecSMasami Hiramatsu { 801fb1587d8SMasami Hiramatsu char *buf, *tmp; 802fb1587d8SMasami Hiramatsu char offs[32] = "", line[32] = "", file[32] = ""; 803fb1587d8SMasami Hiramatsu int ret, len; 80450656eecSMasami Hiramatsu 805e334016fSMasami Hiramatsu buf = zalloc(MAX_CMDLEN); 806e334016fSMasami Hiramatsu if (buf == NULL) { 807e334016fSMasami Hiramatsu ret = -ENOMEM; 808e334016fSMasami Hiramatsu goto error; 809e334016fSMasami Hiramatsu } 8104de189feSMasami Hiramatsu if (pp->offset) { 811fb1587d8SMasami Hiramatsu ret = e_snprintf(offs, 32, "+%lu", pp->offset); 8124de189feSMasami Hiramatsu if (ret <= 0) 8134de189feSMasami Hiramatsu goto error; 8144de189feSMasami Hiramatsu } 8154de189feSMasami Hiramatsu if (pp->line) { 816fb1587d8SMasami Hiramatsu ret = e_snprintf(line, 32, ":%d", pp->line); 817fb1587d8SMasami Hiramatsu if (ret <= 0) 818fb1587d8SMasami Hiramatsu goto error; 819fb1587d8SMasami Hiramatsu } 820fb1587d8SMasami Hiramatsu if (pp->file) { 821dd259c5dSMasami Hiramatsu len = strlen(pp->file) - 31; 822fb1587d8SMasami Hiramatsu if (len < 0) 823fb1587d8SMasami Hiramatsu len = 0; 824fb1587d8SMasami Hiramatsu tmp = strchr(pp->file + len, '/'); 825fb1587d8SMasami Hiramatsu if (!tmp) 826dd259c5dSMasami Hiramatsu tmp = pp->file + len; 827fb1587d8SMasami Hiramatsu ret = e_snprintf(file, 32, "@%s", tmp + 1); 8284de189feSMasami Hiramatsu if (ret <= 0) 8294de189feSMasami Hiramatsu goto error; 8304de189feSMasami Hiramatsu } 8314de189feSMasami Hiramatsu 8324de189feSMasami Hiramatsu if (pp->function) 833fb1587d8SMasami Hiramatsu ret = e_snprintf(buf, MAX_CMDLEN, "%s%s%s%s%s", pp->function, 834fb1587d8SMasami Hiramatsu offs, pp->retprobe ? "%return" : "", line, 835fb1587d8SMasami Hiramatsu file); 8364de189feSMasami Hiramatsu else 837fb1587d8SMasami Hiramatsu ret = e_snprintf(buf, MAX_CMDLEN, "%s%s", file, line); 8384235b045SMasami Hiramatsu if (ret <= 0) 8394235b045SMasami Hiramatsu goto error; 8404235b045SMasami Hiramatsu 8414235b045SMasami Hiramatsu return buf; 8424235b045SMasami Hiramatsu error: 843146a1439SMasami Hiramatsu pr_debug("Failed to synthesize perf probe point: %s", 844146a1439SMasami Hiramatsu strerror(-ret)); 845e334016fSMasami Hiramatsu if (buf) 846146a1439SMasami Hiramatsu free(buf); 847146a1439SMasami Hiramatsu return NULL; 8484235b045SMasami Hiramatsu } 8494235b045SMasami Hiramatsu 8504235b045SMasami Hiramatsu #if 0 8514235b045SMasami Hiramatsu char *synthesize_perf_probe_command(struct perf_probe_event *pev) 8524235b045SMasami Hiramatsu { 8534235b045SMasami Hiramatsu char *buf; 8544235b045SMasami Hiramatsu int i, len, ret; 8554235b045SMasami Hiramatsu 8564235b045SMasami Hiramatsu buf = synthesize_perf_probe_point(&pev->point); 8574235b045SMasami Hiramatsu if (!buf) 8584235b045SMasami Hiramatsu return NULL; 8594235b045SMasami Hiramatsu 8604235b045SMasami Hiramatsu len = strlen(buf); 8614235b045SMasami Hiramatsu for (i = 0; i < pev->nargs; i++) { 8624235b045SMasami Hiramatsu ret = e_snprintf(&buf[len], MAX_CMDLEN - len, " %s", 8634235b045SMasami Hiramatsu pev->args[i].name); 8647ef17aafSMasami Hiramatsu if (ret <= 0) { 8654235b045SMasami Hiramatsu free(buf); 8664235b045SMasami Hiramatsu return NULL; 8677ef17aafSMasami Hiramatsu } 8684235b045SMasami Hiramatsu len += ret; 8697ef17aafSMasami Hiramatsu } 87050656eecSMasami Hiramatsu 8714235b045SMasami Hiramatsu return buf; 8724235b045SMasami Hiramatsu } 8734235b045SMasami Hiramatsu #endif 8744235b045SMasami Hiramatsu 8754235b045SMasami Hiramatsu static int __synthesize_kprobe_trace_arg_ref(struct kprobe_trace_arg_ref *ref, 8764235b045SMasami Hiramatsu char **buf, size_t *buflen, 8774235b045SMasami Hiramatsu int depth) 8787ef17aafSMasami Hiramatsu { 8794235b045SMasami Hiramatsu int ret; 8804235b045SMasami Hiramatsu if (ref->next) { 8814235b045SMasami Hiramatsu depth = __synthesize_kprobe_trace_arg_ref(ref->next, buf, 8824235b045SMasami Hiramatsu buflen, depth + 1); 8834235b045SMasami Hiramatsu if (depth < 0) 8844235b045SMasami Hiramatsu goto out; 8854235b045SMasami Hiramatsu } 8864235b045SMasami Hiramatsu 8874235b045SMasami Hiramatsu ret = e_snprintf(*buf, *buflen, "%+ld(", ref->offset); 8884235b045SMasami Hiramatsu if (ret < 0) 8894235b045SMasami Hiramatsu depth = ret; 8904235b045SMasami Hiramatsu else { 8914235b045SMasami Hiramatsu *buf += ret; 8924235b045SMasami Hiramatsu *buflen -= ret; 8934235b045SMasami Hiramatsu } 8944235b045SMasami Hiramatsu out: 8954235b045SMasami Hiramatsu return depth; 8964235b045SMasami Hiramatsu 8974235b045SMasami Hiramatsu } 8984235b045SMasami Hiramatsu 8994235b045SMasami Hiramatsu static int synthesize_kprobe_trace_arg(struct kprobe_trace_arg *arg, 9004235b045SMasami Hiramatsu char *buf, size_t buflen) 9014235b045SMasami Hiramatsu { 9024235b045SMasami Hiramatsu int ret, depth = 0; 9034235b045SMasami Hiramatsu char *tmp = buf; 9044235b045SMasami Hiramatsu 9054235b045SMasami Hiramatsu /* Argument name or separator */ 9064235b045SMasami Hiramatsu if (arg->name) 9074235b045SMasami Hiramatsu ret = e_snprintf(buf, buflen, " %s=", arg->name); 9084235b045SMasami Hiramatsu else 9094235b045SMasami Hiramatsu ret = e_snprintf(buf, buflen, " "); 9104235b045SMasami Hiramatsu if (ret < 0) 9114235b045SMasami Hiramatsu return ret; 9124235b045SMasami Hiramatsu buf += ret; 9134235b045SMasami Hiramatsu buflen -= ret; 9144235b045SMasami Hiramatsu 9154235b045SMasami Hiramatsu /* Dereferencing arguments */ 9164235b045SMasami Hiramatsu if (arg->ref) { 9174235b045SMasami Hiramatsu depth = __synthesize_kprobe_trace_arg_ref(arg->ref, &buf, 9184235b045SMasami Hiramatsu &buflen, 1); 9194235b045SMasami Hiramatsu if (depth < 0) 9204235b045SMasami Hiramatsu return depth; 9214235b045SMasami Hiramatsu } 9224235b045SMasami Hiramatsu 9234235b045SMasami Hiramatsu /* Print argument value */ 9244235b045SMasami Hiramatsu ret = e_snprintf(buf, buflen, "%s", arg->value); 9254235b045SMasami Hiramatsu if (ret < 0) 9264235b045SMasami Hiramatsu return ret; 9274235b045SMasami Hiramatsu buf += ret; 9284235b045SMasami Hiramatsu buflen -= ret; 9294235b045SMasami Hiramatsu 9304235b045SMasami Hiramatsu /* Closing */ 9314235b045SMasami Hiramatsu while (depth--) { 9324235b045SMasami Hiramatsu ret = e_snprintf(buf, buflen, ")"); 9334235b045SMasami Hiramatsu if (ret < 0) 9344235b045SMasami Hiramatsu return ret; 9354235b045SMasami Hiramatsu buf += ret; 9364235b045SMasami Hiramatsu buflen -= ret; 9374235b045SMasami Hiramatsu } 9384984912eSMasami Hiramatsu /* Print argument type */ 9394984912eSMasami Hiramatsu if (arg->type) { 9404984912eSMasami Hiramatsu ret = e_snprintf(buf, buflen, ":%s", arg->type); 9414984912eSMasami Hiramatsu if (ret <= 0) 9424984912eSMasami Hiramatsu return ret; 9434984912eSMasami Hiramatsu buf += ret; 9444984912eSMasami Hiramatsu } 9454235b045SMasami Hiramatsu 9464235b045SMasami Hiramatsu return buf - tmp; 9474235b045SMasami Hiramatsu } 9484235b045SMasami Hiramatsu 9494235b045SMasami Hiramatsu char *synthesize_kprobe_trace_command(struct kprobe_trace_event *tev) 9504235b045SMasami Hiramatsu { 9514235b045SMasami Hiramatsu struct kprobe_trace_point *tp = &tev->point; 9527ef17aafSMasami Hiramatsu char *buf; 9537ef17aafSMasami Hiramatsu int i, len, ret; 9547ef17aafSMasami Hiramatsu 955e334016fSMasami Hiramatsu buf = zalloc(MAX_CMDLEN); 956e334016fSMasami Hiramatsu if (buf == NULL) 957e334016fSMasami Hiramatsu return NULL; 958e334016fSMasami Hiramatsu 9594235b045SMasami Hiramatsu len = e_snprintf(buf, MAX_CMDLEN, "%c:%s/%s %s+%lu", 9604235b045SMasami Hiramatsu tp->retprobe ? 'r' : 'p', 9614235b045SMasami Hiramatsu tev->group, tev->event, 9624235b045SMasami Hiramatsu tp->symbol, tp->offset); 9634235b045SMasami Hiramatsu if (len <= 0) 9644235b045SMasami Hiramatsu goto error; 9657ef17aafSMasami Hiramatsu 9664235b045SMasami Hiramatsu for (i = 0; i < tev->nargs; i++) { 9674235b045SMasami Hiramatsu ret = synthesize_kprobe_trace_arg(&tev->args[i], buf + len, 9684235b045SMasami Hiramatsu MAX_CMDLEN - len); 9694de189feSMasami Hiramatsu if (ret <= 0) 97050656eecSMasami Hiramatsu goto error; 97150656eecSMasami Hiramatsu len += ret; 97250656eecSMasami Hiramatsu } 97350656eecSMasami Hiramatsu 9744235b045SMasami Hiramatsu return buf; 97550656eecSMasami Hiramatsu error: 9764235b045SMasami Hiramatsu free(buf); 9774235b045SMasami Hiramatsu return NULL; 97850656eecSMasami Hiramatsu } 97950656eecSMasami Hiramatsu 980146a1439SMasami Hiramatsu int convert_to_perf_probe_event(struct kprobe_trace_event *tev, 9814235b045SMasami Hiramatsu struct perf_probe_event *pev) 9824de189feSMasami Hiramatsu { 98302b95dadSMasami Hiramatsu char buf[64] = ""; 984146a1439SMasami Hiramatsu int i, ret; 9854de189feSMasami Hiramatsu 9864b4da7f7SMasami Hiramatsu /* Convert event/group name */ 98702b95dadSMasami Hiramatsu pev->event = strdup(tev->event); 98802b95dadSMasami Hiramatsu pev->group = strdup(tev->group); 98902b95dadSMasami Hiramatsu if (pev->event == NULL || pev->group == NULL) 99002b95dadSMasami Hiramatsu return -ENOMEM; 991fb1587d8SMasami Hiramatsu 9924b4da7f7SMasami Hiramatsu /* Convert trace_point to probe_point */ 993146a1439SMasami Hiramatsu ret = convert_to_perf_probe_point(&tev->point, &pev->point); 994146a1439SMasami Hiramatsu if (ret < 0) 995146a1439SMasami Hiramatsu return ret; 9964b4da7f7SMasami Hiramatsu 9974235b045SMasami Hiramatsu /* Convert trace_arg to probe_arg */ 9984235b045SMasami Hiramatsu pev->nargs = tev->nargs; 999e334016fSMasami Hiramatsu pev->args = zalloc(sizeof(struct perf_probe_arg) * pev->nargs); 1000e334016fSMasami Hiramatsu if (pev->args == NULL) 1001e334016fSMasami Hiramatsu return -ENOMEM; 100202b95dadSMasami Hiramatsu for (i = 0; i < tev->nargs && ret >= 0; i++) { 10034235b045SMasami Hiramatsu if (tev->args[i].name) 100402b95dadSMasami Hiramatsu pev->args[i].name = strdup(tev->args[i].name); 10054235b045SMasami Hiramatsu else { 1006146a1439SMasami Hiramatsu ret = synthesize_kprobe_trace_arg(&tev->args[i], 1007146a1439SMasami Hiramatsu buf, 64); 100802b95dadSMasami Hiramatsu pev->args[i].name = strdup(buf); 100902b95dadSMasami Hiramatsu } 101002b95dadSMasami Hiramatsu if (pev->args[i].name == NULL && ret >= 0) 101102b95dadSMasami Hiramatsu ret = -ENOMEM; 10124de189feSMasami Hiramatsu } 1013146a1439SMasami Hiramatsu 1014146a1439SMasami Hiramatsu if (ret < 0) 1015146a1439SMasami Hiramatsu clear_perf_probe_event(pev); 1016146a1439SMasami Hiramatsu 1017146a1439SMasami Hiramatsu return ret; 10184235b045SMasami Hiramatsu } 10194de189feSMasami Hiramatsu 10204235b045SMasami Hiramatsu void clear_perf_probe_event(struct perf_probe_event *pev) 10214235b045SMasami Hiramatsu { 10224235b045SMasami Hiramatsu struct perf_probe_point *pp = &pev->point; 10237df2f329SMasami Hiramatsu struct perf_probe_arg_field *field, *next; 10244235b045SMasami Hiramatsu int i; 10254de189feSMasami Hiramatsu 10264235b045SMasami Hiramatsu if (pev->event) 10274235b045SMasami Hiramatsu free(pev->event); 10284235b045SMasami Hiramatsu if (pev->group) 10294235b045SMasami Hiramatsu free(pev->group); 10304235b045SMasami Hiramatsu if (pp->file) 10314235b045SMasami Hiramatsu free(pp->file); 10324235b045SMasami Hiramatsu if (pp->function) 10334235b045SMasami Hiramatsu free(pp->function); 10344235b045SMasami Hiramatsu if (pp->lazy_line) 10354235b045SMasami Hiramatsu free(pp->lazy_line); 10367df2f329SMasami Hiramatsu for (i = 0; i < pev->nargs; i++) { 10374235b045SMasami Hiramatsu if (pev->args[i].name) 10384235b045SMasami Hiramatsu free(pev->args[i].name); 103948481938SMasami Hiramatsu if (pev->args[i].var) 104048481938SMasami Hiramatsu free(pev->args[i].var); 104111a1ca35SMasami Hiramatsu if (pev->args[i].type) 104211a1ca35SMasami Hiramatsu free(pev->args[i].type); 10437df2f329SMasami Hiramatsu field = pev->args[i].field; 10447df2f329SMasami Hiramatsu while (field) { 10457df2f329SMasami Hiramatsu next = field->next; 10467df2f329SMasami Hiramatsu if (field->name) 10477df2f329SMasami Hiramatsu free(field->name); 10487df2f329SMasami Hiramatsu free(field); 10497df2f329SMasami Hiramatsu field = next; 10507df2f329SMasami Hiramatsu } 10517df2f329SMasami Hiramatsu } 10524235b045SMasami Hiramatsu if (pev->args) 10534235b045SMasami Hiramatsu free(pev->args); 10544235b045SMasami Hiramatsu memset(pev, 0, sizeof(*pev)); 10554235b045SMasami Hiramatsu } 10564235b045SMasami Hiramatsu 10574235b045SMasami Hiramatsu void clear_kprobe_trace_event(struct kprobe_trace_event *tev) 10584235b045SMasami Hiramatsu { 10594235b045SMasami Hiramatsu struct kprobe_trace_arg_ref *ref, *next; 10604235b045SMasami Hiramatsu int i; 10614235b045SMasami Hiramatsu 10624235b045SMasami Hiramatsu if (tev->event) 10634235b045SMasami Hiramatsu free(tev->event); 10644235b045SMasami Hiramatsu if (tev->group) 10654235b045SMasami Hiramatsu free(tev->group); 10664235b045SMasami Hiramatsu if (tev->point.symbol) 10674235b045SMasami Hiramatsu free(tev->point.symbol); 10684235b045SMasami Hiramatsu for (i = 0; i < tev->nargs; i++) { 10694235b045SMasami Hiramatsu if (tev->args[i].name) 10704235b045SMasami Hiramatsu free(tev->args[i].name); 10714235b045SMasami Hiramatsu if (tev->args[i].value) 10724235b045SMasami Hiramatsu free(tev->args[i].value); 10734984912eSMasami Hiramatsu if (tev->args[i].type) 10744984912eSMasami Hiramatsu free(tev->args[i].type); 10754235b045SMasami Hiramatsu ref = tev->args[i].ref; 10764235b045SMasami Hiramatsu while (ref) { 10774235b045SMasami Hiramatsu next = ref->next; 10784235b045SMasami Hiramatsu free(ref); 10794235b045SMasami Hiramatsu ref = next; 10804235b045SMasami Hiramatsu } 10814235b045SMasami Hiramatsu } 10824235b045SMasami Hiramatsu if (tev->args) 10834235b045SMasami Hiramatsu free(tev->args); 10844235b045SMasami Hiramatsu memset(tev, 0, sizeof(*tev)); 10854de189feSMasami Hiramatsu } 10864de189feSMasami Hiramatsu 1087f4d7da49SMasami Hiramatsu static int open_kprobe_events(bool readwrite) 10884de189feSMasami Hiramatsu { 10894de189feSMasami Hiramatsu char buf[PATH_MAX]; 10907ca5989dSMasami Hiramatsu const char *__debugfs; 10914de189feSMasami Hiramatsu int ret; 10924de189feSMasami Hiramatsu 10937ca5989dSMasami Hiramatsu __debugfs = debugfs_find_mountpoint(); 10947ca5989dSMasami Hiramatsu if (__debugfs == NULL) { 10957ca5989dSMasami Hiramatsu pr_warning("Debugfs is not mounted.\n"); 10967ca5989dSMasami Hiramatsu return -ENOENT; 10977ca5989dSMasami Hiramatsu } 10987ca5989dSMasami Hiramatsu 10997ca5989dSMasami Hiramatsu ret = e_snprintf(buf, PATH_MAX, "%stracing/kprobe_events", __debugfs); 1100146a1439SMasami Hiramatsu if (ret >= 0) { 11017ca5989dSMasami Hiramatsu pr_debug("Opening %s write=%d\n", buf, readwrite); 1102f4d7da49SMasami Hiramatsu if (readwrite && !probe_event_dry_run) 1103f4d7da49SMasami Hiramatsu ret = open(buf, O_RDWR, O_APPEND); 1104f4d7da49SMasami Hiramatsu else 1105f4d7da49SMasami Hiramatsu ret = open(buf, O_RDONLY, 0); 1106146a1439SMasami Hiramatsu } 1107f4d7da49SMasami Hiramatsu 11084de189feSMasami Hiramatsu if (ret < 0) { 11094de189feSMasami Hiramatsu if (errno == ENOENT) 1110146a1439SMasami Hiramatsu pr_warning("kprobe_events file does not exist - please" 1111146a1439SMasami Hiramatsu " rebuild kernel with CONFIG_KPROBE_EVENT.\n"); 11124de189feSMasami Hiramatsu else 1113146a1439SMasami Hiramatsu pr_warning("Failed to open kprobe_events file: %s\n", 11144de189feSMasami Hiramatsu strerror(errno)); 11154de189feSMasami Hiramatsu } 11164de189feSMasami Hiramatsu return ret; 11174de189feSMasami Hiramatsu } 11184de189feSMasami Hiramatsu 11194de189feSMasami Hiramatsu /* Get raw string list of current kprobe_events */ 11204235b045SMasami Hiramatsu static struct strlist *get_kprobe_trace_command_rawlist(int fd) 11214de189feSMasami Hiramatsu { 11224de189feSMasami Hiramatsu int ret, idx; 11234de189feSMasami Hiramatsu FILE *fp; 11244de189feSMasami Hiramatsu char buf[MAX_CMDLEN]; 11254de189feSMasami Hiramatsu char *p; 11264de189feSMasami Hiramatsu struct strlist *sl; 11274de189feSMasami Hiramatsu 11284de189feSMasami Hiramatsu sl = strlist__new(true, NULL); 11294de189feSMasami Hiramatsu 11304de189feSMasami Hiramatsu fp = fdopen(dup(fd), "r"); 11314de189feSMasami Hiramatsu while (!feof(fp)) { 11324de189feSMasami Hiramatsu p = fgets(buf, MAX_CMDLEN, fp); 11334de189feSMasami Hiramatsu if (!p) 11344de189feSMasami Hiramatsu break; 11354de189feSMasami Hiramatsu 11364de189feSMasami Hiramatsu idx = strlen(p) - 1; 11374de189feSMasami Hiramatsu if (p[idx] == '\n') 11384de189feSMasami Hiramatsu p[idx] = '\0'; 11394de189feSMasami Hiramatsu ret = strlist__add(sl, buf); 1140146a1439SMasami Hiramatsu if (ret < 0) { 1141146a1439SMasami Hiramatsu pr_debug("strlist__add failed: %s\n", strerror(-ret)); 1142146a1439SMasami Hiramatsu strlist__delete(sl); 1143146a1439SMasami Hiramatsu return NULL; 1144146a1439SMasami Hiramatsu } 11454de189feSMasami Hiramatsu } 11464de189feSMasami Hiramatsu fclose(fp); 11474de189feSMasami Hiramatsu 11484de189feSMasami Hiramatsu return sl; 11494de189feSMasami Hiramatsu } 11504de189feSMasami Hiramatsu 1151278498d4SMasami Hiramatsu /* Show an event */ 1152146a1439SMasami Hiramatsu static int show_perf_probe_event(struct perf_probe_event *pev) 1153278498d4SMasami Hiramatsu { 11547e990a51SMasami Hiramatsu int i, ret; 1155278498d4SMasami Hiramatsu char buf[128]; 11564235b045SMasami Hiramatsu char *place; 1157278498d4SMasami Hiramatsu 11584235b045SMasami Hiramatsu /* Synthesize only event probe point */ 11594235b045SMasami Hiramatsu place = synthesize_perf_probe_point(&pev->point); 1160146a1439SMasami Hiramatsu if (!place) 1161146a1439SMasami Hiramatsu return -EINVAL; 11624235b045SMasami Hiramatsu 11634235b045SMasami Hiramatsu ret = e_snprintf(buf, 128, "%s:%s", pev->group, pev->event); 11647e990a51SMasami Hiramatsu if (ret < 0) 1165146a1439SMasami Hiramatsu return ret; 1166146a1439SMasami Hiramatsu 1167fb1587d8SMasami Hiramatsu printf(" %-20s (on %s", buf, place); 1168278498d4SMasami Hiramatsu 11694235b045SMasami Hiramatsu if (pev->nargs > 0) { 1170278498d4SMasami Hiramatsu printf(" with"); 11717df2f329SMasami Hiramatsu for (i = 0; i < pev->nargs; i++) { 1172146a1439SMasami Hiramatsu ret = synthesize_perf_probe_arg(&pev->args[i], 1173146a1439SMasami Hiramatsu buf, 128); 1174146a1439SMasami Hiramatsu if (ret < 0) 1175146a1439SMasami Hiramatsu break; 11767df2f329SMasami Hiramatsu printf(" %s", buf); 11777df2f329SMasami Hiramatsu } 1178278498d4SMasami Hiramatsu } 1179278498d4SMasami Hiramatsu printf(")\n"); 11804235b045SMasami Hiramatsu free(place); 1181146a1439SMasami Hiramatsu return ret; 1182278498d4SMasami Hiramatsu } 1183278498d4SMasami Hiramatsu 11844de189feSMasami Hiramatsu /* List up current perf-probe events */ 1185146a1439SMasami Hiramatsu int show_perf_probe_events(void) 11864de189feSMasami Hiramatsu { 1187146a1439SMasami Hiramatsu int fd, ret; 11884235b045SMasami Hiramatsu struct kprobe_trace_event tev; 11894235b045SMasami Hiramatsu struct perf_probe_event pev; 11904de189feSMasami Hiramatsu struct strlist *rawlist; 11914de189feSMasami Hiramatsu struct str_node *ent; 11924de189feSMasami Hiramatsu 119372041334SMasami Hiramatsu setup_pager(); 1194146a1439SMasami Hiramatsu ret = init_vmlinux(); 1195146a1439SMasami Hiramatsu if (ret < 0) 1196146a1439SMasami Hiramatsu return ret; 11974235b045SMasami Hiramatsu 11984235b045SMasami Hiramatsu memset(&tev, 0, sizeof(tev)); 11994235b045SMasami Hiramatsu memset(&pev, 0, sizeof(pev)); 120072041334SMasami Hiramatsu 1201f4d7da49SMasami Hiramatsu fd = open_kprobe_events(false); 1202146a1439SMasami Hiramatsu if (fd < 0) 1203146a1439SMasami Hiramatsu return fd; 1204146a1439SMasami Hiramatsu 12054235b045SMasami Hiramatsu rawlist = get_kprobe_trace_command_rawlist(fd); 12064de189feSMasami Hiramatsu close(fd); 1207146a1439SMasami Hiramatsu if (!rawlist) 1208146a1439SMasami Hiramatsu return -ENOENT; 12094de189feSMasami Hiramatsu 1210adf365f4SMasami Hiramatsu strlist__for_each(ent, rawlist) { 1211146a1439SMasami Hiramatsu ret = parse_kprobe_trace_command(ent->s, &tev); 1212146a1439SMasami Hiramatsu if (ret >= 0) { 1213146a1439SMasami Hiramatsu ret = convert_to_perf_probe_event(&tev, &pev); 1214146a1439SMasami Hiramatsu if (ret >= 0) 1215146a1439SMasami Hiramatsu ret = show_perf_probe_event(&pev); 1216146a1439SMasami Hiramatsu } 12174235b045SMasami Hiramatsu clear_perf_probe_event(&pev); 12184235b045SMasami Hiramatsu clear_kprobe_trace_event(&tev); 1219146a1439SMasami Hiramatsu if (ret < 0) 1220146a1439SMasami Hiramatsu break; 12214de189feSMasami Hiramatsu } 12224de189feSMasami Hiramatsu strlist__delete(rawlist); 1223146a1439SMasami Hiramatsu 1224146a1439SMasami Hiramatsu return ret; 12254de189feSMasami Hiramatsu } 12264de189feSMasami Hiramatsu 1227b498ce1fSMasami Hiramatsu /* Get current perf-probe event names */ 12284235b045SMasami Hiramatsu static struct strlist *get_kprobe_trace_event_names(int fd, bool include_group) 1229b498ce1fSMasami Hiramatsu { 1230fa28244dSMasami Hiramatsu char buf[128]; 1231b498ce1fSMasami Hiramatsu struct strlist *sl, *rawlist; 1232b498ce1fSMasami Hiramatsu struct str_node *ent; 12334235b045SMasami Hiramatsu struct kprobe_trace_event tev; 1234146a1439SMasami Hiramatsu int ret = 0; 1235b498ce1fSMasami Hiramatsu 12364235b045SMasami Hiramatsu memset(&tev, 0, sizeof(tev)); 1237b498ce1fSMasami Hiramatsu 12384235b045SMasami Hiramatsu rawlist = get_kprobe_trace_command_rawlist(fd); 1239e1d2017bSMasami Hiramatsu sl = strlist__new(true, NULL); 1240adf365f4SMasami Hiramatsu strlist__for_each(ent, rawlist) { 1241146a1439SMasami Hiramatsu ret = parse_kprobe_trace_command(ent->s, &tev); 1242146a1439SMasami Hiramatsu if (ret < 0) 1243146a1439SMasami Hiramatsu break; 1244fa28244dSMasami Hiramatsu if (include_group) { 1245146a1439SMasami Hiramatsu ret = e_snprintf(buf, 128, "%s:%s", tev.group, 1246146a1439SMasami Hiramatsu tev.event); 1247146a1439SMasami Hiramatsu if (ret >= 0) 1248146a1439SMasami Hiramatsu ret = strlist__add(sl, buf); 1249fa28244dSMasami Hiramatsu } else 1250146a1439SMasami Hiramatsu ret = strlist__add(sl, tev.event); 12514235b045SMasami Hiramatsu clear_kprobe_trace_event(&tev); 1252146a1439SMasami Hiramatsu if (ret < 0) 1253146a1439SMasami Hiramatsu break; 1254b498ce1fSMasami Hiramatsu } 1255b498ce1fSMasami Hiramatsu strlist__delete(rawlist); 1256b498ce1fSMasami Hiramatsu 1257146a1439SMasami Hiramatsu if (ret < 0) { 1258146a1439SMasami Hiramatsu strlist__delete(sl); 1259146a1439SMasami Hiramatsu return NULL; 1260146a1439SMasami Hiramatsu } 1261b498ce1fSMasami Hiramatsu return sl; 1262b498ce1fSMasami Hiramatsu } 1263b498ce1fSMasami Hiramatsu 1264146a1439SMasami Hiramatsu static int write_kprobe_trace_event(int fd, struct kprobe_trace_event *tev) 126550656eecSMasami Hiramatsu { 1266*6eca8cc3SFrederic Weisbecker int ret = 0; 12674235b045SMasami Hiramatsu char *buf = synthesize_kprobe_trace_command(tev); 126850656eecSMasami Hiramatsu 1269146a1439SMasami Hiramatsu if (!buf) { 1270146a1439SMasami Hiramatsu pr_debug("Failed to synthesize kprobe trace event.\n"); 1271146a1439SMasami Hiramatsu return -EINVAL; 1272146a1439SMasami Hiramatsu } 1273146a1439SMasami Hiramatsu 1274fa28244dSMasami Hiramatsu pr_debug("Writing event: %s\n", buf); 1275f4d7da49SMasami Hiramatsu if (!probe_event_dry_run) { 127650656eecSMasami Hiramatsu ret = write(fd, buf, strlen(buf)); 127750656eecSMasami Hiramatsu if (ret <= 0) 1278146a1439SMasami Hiramatsu pr_warning("Failed to write event: %s\n", 1279146a1439SMasami Hiramatsu strerror(errno)); 128050656eecSMasami Hiramatsu } 12814235b045SMasami Hiramatsu free(buf); 1282146a1439SMasami Hiramatsu return ret; 1283f4d7da49SMasami Hiramatsu } 128450656eecSMasami Hiramatsu 1285146a1439SMasami Hiramatsu static int get_new_event_name(char *buf, size_t len, const char *base, 1286d761b08bSMasami Hiramatsu struct strlist *namelist, bool allow_suffix) 1287b498ce1fSMasami Hiramatsu { 1288b498ce1fSMasami Hiramatsu int i, ret; 128917f88fcdSMasami Hiramatsu 129017f88fcdSMasami Hiramatsu /* Try no suffix */ 129117f88fcdSMasami Hiramatsu ret = e_snprintf(buf, len, "%s", base); 1292146a1439SMasami Hiramatsu if (ret < 0) { 1293146a1439SMasami Hiramatsu pr_debug("snprintf() failed: %s\n", strerror(-ret)); 1294146a1439SMasami Hiramatsu return ret; 1295146a1439SMasami Hiramatsu } 129617f88fcdSMasami Hiramatsu if (!strlist__has_entry(namelist, buf)) 1297146a1439SMasami Hiramatsu return 0; 129817f88fcdSMasami Hiramatsu 1299d761b08bSMasami Hiramatsu if (!allow_suffix) { 1300d761b08bSMasami Hiramatsu pr_warning("Error: event \"%s\" already exists. " 1301d761b08bSMasami Hiramatsu "(Use -f to force duplicates.)\n", base); 1302146a1439SMasami Hiramatsu return -EEXIST; 1303d761b08bSMasami Hiramatsu } 1304d761b08bSMasami Hiramatsu 130517f88fcdSMasami Hiramatsu /* Try to add suffix */ 130617f88fcdSMasami Hiramatsu for (i = 1; i < MAX_EVENT_INDEX; i++) { 1307b498ce1fSMasami Hiramatsu ret = e_snprintf(buf, len, "%s_%d", base, i); 1308146a1439SMasami Hiramatsu if (ret < 0) { 1309146a1439SMasami Hiramatsu pr_debug("snprintf() failed: %s\n", strerror(-ret)); 1310146a1439SMasami Hiramatsu return ret; 1311146a1439SMasami Hiramatsu } 1312b498ce1fSMasami Hiramatsu if (!strlist__has_entry(namelist, buf)) 1313b498ce1fSMasami Hiramatsu break; 1314b498ce1fSMasami Hiramatsu } 1315146a1439SMasami Hiramatsu if (i == MAX_EVENT_INDEX) { 1316146a1439SMasami Hiramatsu pr_warning("Too many events are on the same function.\n"); 1317146a1439SMasami Hiramatsu ret = -ERANGE; 1318b498ce1fSMasami Hiramatsu } 1319b498ce1fSMasami Hiramatsu 1320146a1439SMasami Hiramatsu return ret; 1321146a1439SMasami Hiramatsu } 1322146a1439SMasami Hiramatsu 1323146a1439SMasami Hiramatsu static int __add_kprobe_trace_events(struct perf_probe_event *pev, 13244235b045SMasami Hiramatsu struct kprobe_trace_event *tevs, 13254235b045SMasami Hiramatsu int ntevs, bool allow_suffix) 132650656eecSMasami Hiramatsu { 1327146a1439SMasami Hiramatsu int i, fd, ret; 132855632770SIngo Molnar struct kprobe_trace_event *tev = NULL; 13294235b045SMasami Hiramatsu char buf[64]; 13304235b045SMasami Hiramatsu const char *event, *group; 1331b498ce1fSMasami Hiramatsu struct strlist *namelist; 133250656eecSMasami Hiramatsu 1333f4d7da49SMasami Hiramatsu fd = open_kprobe_events(true); 1334146a1439SMasami Hiramatsu if (fd < 0) 1335146a1439SMasami Hiramatsu return fd; 1336b498ce1fSMasami Hiramatsu /* Get current event names */ 13374235b045SMasami Hiramatsu namelist = get_kprobe_trace_event_names(fd, false); 1338146a1439SMasami Hiramatsu if (!namelist) { 1339146a1439SMasami Hiramatsu pr_debug("Failed to get current event list.\n"); 1340146a1439SMasami Hiramatsu return -EIO; 1341146a1439SMasami Hiramatsu } 134250656eecSMasami Hiramatsu 1343146a1439SMasami Hiramatsu ret = 0; 13444235b045SMasami Hiramatsu printf("Add new event%s\n", (ntevs > 1) ? "s:" : ":"); 134502b95dadSMasami Hiramatsu for (i = 0; i < ntevs; i++) { 13464235b045SMasami Hiramatsu tev = &tevs[i]; 13474235b045SMasami Hiramatsu if (pev->event) 13484235b045SMasami Hiramatsu event = pev->event; 13494235b045SMasami Hiramatsu else 13504235b045SMasami Hiramatsu if (pev->point.function) 13514235b045SMasami Hiramatsu event = pev->point.function; 13524235b045SMasami Hiramatsu else 13534235b045SMasami Hiramatsu event = tev->point.symbol; 13544235b045SMasami Hiramatsu if (pev->group) 13554235b045SMasami Hiramatsu group = pev->group; 13564235b045SMasami Hiramatsu else 13574235b045SMasami Hiramatsu group = PERFPROBE_GROUP; 13584235b045SMasami Hiramatsu 1359b498ce1fSMasami Hiramatsu /* Get an unused new event name */ 1360146a1439SMasami Hiramatsu ret = get_new_event_name(buf, 64, event, 1361146a1439SMasami Hiramatsu namelist, allow_suffix); 1362146a1439SMasami Hiramatsu if (ret < 0) 1363146a1439SMasami Hiramatsu break; 13644235b045SMasami Hiramatsu event = buf; 13654235b045SMasami Hiramatsu 136602b95dadSMasami Hiramatsu tev->event = strdup(event); 136702b95dadSMasami Hiramatsu tev->group = strdup(group); 136802b95dadSMasami Hiramatsu if (tev->event == NULL || tev->group == NULL) { 136902b95dadSMasami Hiramatsu ret = -ENOMEM; 137002b95dadSMasami Hiramatsu break; 137102b95dadSMasami Hiramatsu } 1372146a1439SMasami Hiramatsu ret = write_kprobe_trace_event(fd, tev); 1373146a1439SMasami Hiramatsu if (ret < 0) 1374146a1439SMasami Hiramatsu break; 1375b498ce1fSMasami Hiramatsu /* Add added event name to namelist */ 1376b498ce1fSMasami Hiramatsu strlist__add(namelist, event); 13774235b045SMasami Hiramatsu 13784235b045SMasami Hiramatsu /* Trick here - save current event/group */ 13794235b045SMasami Hiramatsu event = pev->event; 13804235b045SMasami Hiramatsu group = pev->group; 13814235b045SMasami Hiramatsu pev->event = tev->event; 13824235b045SMasami Hiramatsu pev->group = tev->group; 13834235b045SMasami Hiramatsu show_perf_probe_event(pev); 13844235b045SMasami Hiramatsu /* Trick here - restore current event/group */ 13854235b045SMasami Hiramatsu pev->event = (char *)event; 13864235b045SMasami Hiramatsu pev->group = (char *)group; 13874235b045SMasami Hiramatsu 1388d761b08bSMasami Hiramatsu /* 1389d761b08bSMasami Hiramatsu * Probes after the first probe which comes from same 1390d761b08bSMasami Hiramatsu * user input are always allowed to add suffix, because 1391d761b08bSMasami Hiramatsu * there might be several addresses corresponding to 1392d761b08bSMasami Hiramatsu * one code line. 1393d761b08bSMasami Hiramatsu */ 1394d761b08bSMasami Hiramatsu allow_suffix = true; 139550656eecSMasami Hiramatsu } 1396146a1439SMasami Hiramatsu 1397146a1439SMasami Hiramatsu if (ret >= 0) { 1398a9b495b0SMasami Hiramatsu /* Show how to use the event. */ 1399a9b495b0SMasami Hiramatsu printf("\nYou can now use it on all perf tools, such as:\n\n"); 1400146a1439SMasami Hiramatsu printf("\tperf record -e %s:%s -aR sleep 1\n\n", tev->group, 1401146a1439SMasami Hiramatsu tev->event); 1402146a1439SMasami Hiramatsu } 1403a9b495b0SMasami Hiramatsu 1404e1d2017bSMasami Hiramatsu strlist__delete(namelist); 140550656eecSMasami Hiramatsu close(fd); 1406146a1439SMasami Hiramatsu return ret; 140750656eecSMasami Hiramatsu } 1408fa28244dSMasami Hiramatsu 14094235b045SMasami Hiramatsu static int convert_to_kprobe_trace_events(struct perf_probe_event *pev, 14104235b045SMasami Hiramatsu struct kprobe_trace_event **tevs) 1411e0faa8d3SMasami Hiramatsu { 1412e0faa8d3SMasami Hiramatsu struct symbol *sym; 1413e334016fSMasami Hiramatsu int ret = 0, i; 14144235b045SMasami Hiramatsu struct kprobe_trace_event *tev; 14154235b045SMasami Hiramatsu 14164b4da7f7SMasami Hiramatsu /* Convert perf_probe_event with debuginfo */ 1417e334016fSMasami Hiramatsu ret = try_to_find_kprobe_trace_events(pev, tevs); 1418e334016fSMasami Hiramatsu if (ret != 0) 1419e334016fSMasami Hiramatsu return ret; 1420e0faa8d3SMasami Hiramatsu 14214235b045SMasami Hiramatsu /* Allocate trace event buffer */ 1422e334016fSMasami Hiramatsu tev = *tevs = zalloc(sizeof(struct kprobe_trace_event)); 1423e334016fSMasami Hiramatsu if (tev == NULL) 1424e334016fSMasami Hiramatsu return -ENOMEM; 1425e0faa8d3SMasami Hiramatsu 14264235b045SMasami Hiramatsu /* Copy parameters */ 142702b95dadSMasami Hiramatsu tev->point.symbol = strdup(pev->point.function); 142802b95dadSMasami Hiramatsu if (tev->point.symbol == NULL) { 142902b95dadSMasami Hiramatsu ret = -ENOMEM; 143002b95dadSMasami Hiramatsu goto error; 143102b95dadSMasami Hiramatsu } 14324235b045SMasami Hiramatsu tev->point.offset = pev->point.offset; 14334235b045SMasami Hiramatsu tev->nargs = pev->nargs; 14344235b045SMasami Hiramatsu if (tev->nargs) { 1435e334016fSMasami Hiramatsu tev->args = zalloc(sizeof(struct kprobe_trace_arg) 14364235b045SMasami Hiramatsu * tev->nargs); 1437e334016fSMasami Hiramatsu if (tev->args == NULL) { 143802b95dadSMasami Hiramatsu ret = -ENOMEM; 143902b95dadSMasami Hiramatsu goto error; 1440e334016fSMasami Hiramatsu } 144148481938SMasami Hiramatsu for (i = 0; i < tev->nargs; i++) { 144202b95dadSMasami Hiramatsu if (pev->args[i].name) { 144302b95dadSMasami Hiramatsu tev->args[i].name = strdup(pev->args[i].name); 144402b95dadSMasami Hiramatsu if (tev->args[i].name == NULL) { 144502b95dadSMasami Hiramatsu ret = -ENOMEM; 144602b95dadSMasami Hiramatsu goto error; 144702b95dadSMasami Hiramatsu } 144802b95dadSMasami Hiramatsu } 144902b95dadSMasami Hiramatsu tev->args[i].value = strdup(pev->args[i].var); 145002b95dadSMasami Hiramatsu if (tev->args[i].value == NULL) { 145102b95dadSMasami Hiramatsu ret = -ENOMEM; 145202b95dadSMasami Hiramatsu goto error; 145302b95dadSMasami Hiramatsu } 145402b95dadSMasami Hiramatsu if (pev->args[i].type) { 145502b95dadSMasami Hiramatsu tev->args[i].type = strdup(pev->args[i].type); 145602b95dadSMasami Hiramatsu if (tev->args[i].type == NULL) { 145702b95dadSMasami Hiramatsu ret = -ENOMEM; 145802b95dadSMasami Hiramatsu goto error; 145902b95dadSMasami Hiramatsu } 146002b95dadSMasami Hiramatsu } 146148481938SMasami Hiramatsu } 1462e0faa8d3SMasami Hiramatsu } 1463e0faa8d3SMasami Hiramatsu 14644235b045SMasami Hiramatsu /* Currently just checking function name from symbol map */ 14654235b045SMasami Hiramatsu sym = map__find_symbol_by_name(kmaps[MAP__FUNCTION], 14664235b045SMasami Hiramatsu tev->point.symbol, NULL); 1467146a1439SMasami Hiramatsu if (!sym) { 1468146a1439SMasami Hiramatsu pr_warning("Kernel symbol \'%s\' not found.\n", 14694235b045SMasami Hiramatsu tev->point.symbol); 147002b95dadSMasami Hiramatsu ret = -ENOENT; 147102b95dadSMasami Hiramatsu goto error; 147202b95dadSMasami Hiramatsu } 147302b95dadSMasami Hiramatsu 147402b95dadSMasami Hiramatsu return 1; 147502b95dadSMasami Hiramatsu error: 1476e334016fSMasami Hiramatsu clear_kprobe_trace_event(tev); 1477e334016fSMasami Hiramatsu free(tev); 1478e334016fSMasami Hiramatsu *tevs = NULL; 1479e334016fSMasami Hiramatsu return ret; 14804235b045SMasami Hiramatsu } 14814235b045SMasami Hiramatsu 14824235b045SMasami Hiramatsu struct __event_package { 14834235b045SMasami Hiramatsu struct perf_probe_event *pev; 14844235b045SMasami Hiramatsu struct kprobe_trace_event *tevs; 14854235b045SMasami Hiramatsu int ntevs; 14864235b045SMasami Hiramatsu }; 14874235b045SMasami Hiramatsu 1488146a1439SMasami Hiramatsu int add_perf_probe_events(struct perf_probe_event *pevs, int npevs, 14894235b045SMasami Hiramatsu bool force_add) 14904235b045SMasami Hiramatsu { 1491146a1439SMasami Hiramatsu int i, j, ret; 14924235b045SMasami Hiramatsu struct __event_package *pkgs; 14934235b045SMasami Hiramatsu 1494e334016fSMasami Hiramatsu pkgs = zalloc(sizeof(struct __event_package) * npevs); 1495e334016fSMasami Hiramatsu if (pkgs == NULL) 1496e334016fSMasami Hiramatsu return -ENOMEM; 14974235b045SMasami Hiramatsu 14984235b045SMasami Hiramatsu /* Init vmlinux path */ 1499146a1439SMasami Hiramatsu ret = init_vmlinux(); 1500146a1439SMasami Hiramatsu if (ret < 0) 1501146a1439SMasami Hiramatsu return ret; 15024235b045SMasami Hiramatsu 15034235b045SMasami Hiramatsu /* Loop 1: convert all events */ 15044235b045SMasami Hiramatsu for (i = 0; i < npevs; i++) { 15054235b045SMasami Hiramatsu pkgs[i].pev = &pevs[i]; 15064235b045SMasami Hiramatsu /* Convert with or without debuginfo */ 1507146a1439SMasami Hiramatsu ret = convert_to_kprobe_trace_events(pkgs[i].pev, 15084235b045SMasami Hiramatsu &pkgs[i].tevs); 1509146a1439SMasami Hiramatsu if (ret < 0) 1510146a1439SMasami Hiramatsu goto end; 1511146a1439SMasami Hiramatsu pkgs[i].ntevs = ret; 15124235b045SMasami Hiramatsu } 15134235b045SMasami Hiramatsu 15144235b045SMasami Hiramatsu /* Loop 2: add all events */ 1515146a1439SMasami Hiramatsu for (i = 0; i < npevs && ret >= 0; i++) 1516146a1439SMasami Hiramatsu ret = __add_kprobe_trace_events(pkgs[i].pev, pkgs[i].tevs, 15174235b045SMasami Hiramatsu pkgs[i].ntevs, force_add); 1518146a1439SMasami Hiramatsu end: 1519146a1439SMasami Hiramatsu /* Loop 3: cleanup trace events */ 1520146a1439SMasami Hiramatsu for (i = 0; i < npevs; i++) 1521146a1439SMasami Hiramatsu for (j = 0; j < pkgs[i].ntevs; j++) 1522146a1439SMasami Hiramatsu clear_kprobe_trace_event(&pkgs[i].tevs[j]); 1523146a1439SMasami Hiramatsu 1524146a1439SMasami Hiramatsu return ret; 1525e0faa8d3SMasami Hiramatsu } 1526e0faa8d3SMasami Hiramatsu 1527146a1439SMasami Hiramatsu static int __del_trace_kprobe_event(int fd, struct str_node *ent) 1528bbbb521bSMasami Hiramatsu { 1529bbbb521bSMasami Hiramatsu char *p; 1530bbbb521bSMasami Hiramatsu char buf[128]; 15314235b045SMasami Hiramatsu int ret; 1532bbbb521bSMasami Hiramatsu 1533bbbb521bSMasami Hiramatsu /* Convert from perf-probe event to trace-kprobe event */ 1534146a1439SMasami Hiramatsu ret = e_snprintf(buf, 128, "-:%s", ent->s); 1535146a1439SMasami Hiramatsu if (ret < 0) 1536146a1439SMasami Hiramatsu goto error; 1537146a1439SMasami Hiramatsu 1538bbbb521bSMasami Hiramatsu p = strchr(buf + 2, ':'); 1539146a1439SMasami Hiramatsu if (!p) { 1540146a1439SMasami Hiramatsu pr_debug("Internal error: %s should have ':' but not.\n", 1541146a1439SMasami Hiramatsu ent->s); 1542146a1439SMasami Hiramatsu ret = -ENOTSUP; 1543146a1439SMasami Hiramatsu goto error; 1544146a1439SMasami Hiramatsu } 1545bbbb521bSMasami Hiramatsu *p = '/'; 1546bbbb521bSMasami Hiramatsu 15474235b045SMasami Hiramatsu pr_debug("Writing event: %s\n", buf); 15484235b045SMasami Hiramatsu ret = write(fd, buf, strlen(buf)); 1549146a1439SMasami Hiramatsu if (ret < 0) 1550146a1439SMasami Hiramatsu goto error; 1551146a1439SMasami Hiramatsu 1552bbbb521bSMasami Hiramatsu printf("Remove event: %s\n", ent->s); 1553146a1439SMasami Hiramatsu return 0; 1554146a1439SMasami Hiramatsu error: 1555146a1439SMasami Hiramatsu pr_warning("Failed to delete event: %s\n", strerror(-ret)); 1556146a1439SMasami Hiramatsu return ret; 1557bbbb521bSMasami Hiramatsu } 1558bbbb521bSMasami Hiramatsu 1559146a1439SMasami Hiramatsu static int del_trace_kprobe_event(int fd, const char *group, 1560fa28244dSMasami Hiramatsu const char *event, struct strlist *namelist) 1561fa28244dSMasami Hiramatsu { 1562fa28244dSMasami Hiramatsu char buf[128]; 1563bbbb521bSMasami Hiramatsu struct str_node *ent, *n; 1564146a1439SMasami Hiramatsu int found = 0, ret = 0; 1565fa28244dSMasami Hiramatsu 1566146a1439SMasami Hiramatsu ret = e_snprintf(buf, 128, "%s:%s", group, event); 1567146a1439SMasami Hiramatsu if (ret < 0) { 1568146a1439SMasami Hiramatsu pr_err("Failed to copy event."); 1569146a1439SMasami Hiramatsu return ret; 1570146a1439SMasami Hiramatsu } 1571fa28244dSMasami Hiramatsu 1572bbbb521bSMasami Hiramatsu if (strpbrk(buf, "*?")) { /* Glob-exp */ 1573bbbb521bSMasami Hiramatsu strlist__for_each_safe(ent, n, namelist) 1574bbbb521bSMasami Hiramatsu if (strglobmatch(ent->s, buf)) { 1575bbbb521bSMasami Hiramatsu found++; 1576146a1439SMasami Hiramatsu ret = __del_trace_kprobe_event(fd, ent); 1577146a1439SMasami Hiramatsu if (ret < 0) 1578146a1439SMasami Hiramatsu break; 15793e340590SMasami Hiramatsu strlist__remove(namelist, ent); 1580fa28244dSMasami Hiramatsu } 1581bbbb521bSMasami Hiramatsu } else { 1582bbbb521bSMasami Hiramatsu ent = strlist__find(namelist, buf); 1583bbbb521bSMasami Hiramatsu if (ent) { 1584bbbb521bSMasami Hiramatsu found++; 1585146a1439SMasami Hiramatsu ret = __del_trace_kprobe_event(fd, ent); 1586146a1439SMasami Hiramatsu if (ret >= 0) 1587bbbb521bSMasami Hiramatsu strlist__remove(namelist, ent); 1588bbbb521bSMasami Hiramatsu } 1589bbbb521bSMasami Hiramatsu } 1590146a1439SMasami Hiramatsu if (found == 0 && ret >= 0) 1591146a1439SMasami Hiramatsu pr_info("Info: Event \"%s\" does not exist.\n", buf); 1592146a1439SMasami Hiramatsu 1593146a1439SMasami Hiramatsu return ret; 1594bbbb521bSMasami Hiramatsu } 1595fa28244dSMasami Hiramatsu 1596146a1439SMasami Hiramatsu int del_perf_probe_events(struct strlist *dellist) 1597fa28244dSMasami Hiramatsu { 1598146a1439SMasami Hiramatsu int fd, ret = 0; 1599fa28244dSMasami Hiramatsu const char *group, *event; 1600fa28244dSMasami Hiramatsu char *p, *str; 1601fa28244dSMasami Hiramatsu struct str_node *ent; 1602fa28244dSMasami Hiramatsu struct strlist *namelist; 1603fa28244dSMasami Hiramatsu 1604f4d7da49SMasami Hiramatsu fd = open_kprobe_events(true); 1605146a1439SMasami Hiramatsu if (fd < 0) 1606146a1439SMasami Hiramatsu return fd; 1607146a1439SMasami Hiramatsu 1608fa28244dSMasami Hiramatsu /* Get current event names */ 16094235b045SMasami Hiramatsu namelist = get_kprobe_trace_event_names(fd, true); 1610146a1439SMasami Hiramatsu if (namelist == NULL) 1611146a1439SMasami Hiramatsu return -EINVAL; 1612fa28244dSMasami Hiramatsu 1613adf365f4SMasami Hiramatsu strlist__for_each(ent, dellist) { 161402b95dadSMasami Hiramatsu str = strdup(ent->s); 161502b95dadSMasami Hiramatsu if (str == NULL) { 161602b95dadSMasami Hiramatsu ret = -ENOMEM; 161702b95dadSMasami Hiramatsu break; 161802b95dadSMasami Hiramatsu } 1619bbbb521bSMasami Hiramatsu pr_debug("Parsing: %s\n", str); 1620fa28244dSMasami Hiramatsu p = strchr(str, ':'); 1621fa28244dSMasami Hiramatsu if (p) { 1622fa28244dSMasami Hiramatsu group = str; 1623fa28244dSMasami Hiramatsu *p = '\0'; 1624fa28244dSMasami Hiramatsu event = p + 1; 1625fa28244dSMasami Hiramatsu } else { 1626bbbb521bSMasami Hiramatsu group = "*"; 1627fa28244dSMasami Hiramatsu event = str; 1628fa28244dSMasami Hiramatsu } 1629bbbb521bSMasami Hiramatsu pr_debug("Group: %s, Event: %s\n", group, event); 1630146a1439SMasami Hiramatsu ret = del_trace_kprobe_event(fd, group, event, namelist); 1631fa28244dSMasami Hiramatsu free(str); 1632146a1439SMasami Hiramatsu if (ret < 0) 1633146a1439SMasami Hiramatsu break; 1634fa28244dSMasami Hiramatsu } 1635fa28244dSMasami Hiramatsu strlist__delete(namelist); 1636fa28244dSMasami Hiramatsu close(fd); 1637146a1439SMasami Hiramatsu 1638146a1439SMasami Hiramatsu return ret; 1639fa28244dSMasami Hiramatsu } 1640fa28244dSMasami Hiramatsu 1641