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 3650656eecSMasami Hiramatsu #include "event.h" 37e1c01d61SMasami Hiramatsu #include "string.h" 384de189feSMasami Hiramatsu #include "strlist.h" 3950656eecSMasami Hiramatsu #include "debug.h" 4050656eecSMasami Hiramatsu #include "parse-events.h" /* For debugfs_path */ 4150656eecSMasami Hiramatsu #include "probe-event.h" 4250656eecSMasami Hiramatsu 4350656eecSMasami Hiramatsu #define MAX_CMDLEN 256 4450656eecSMasami Hiramatsu #define MAX_PROBE_ARGS 128 4550656eecSMasami Hiramatsu #define PERFPROBE_GROUP "probe" 4650656eecSMasami Hiramatsu 4750656eecSMasami Hiramatsu #define semantic_error(msg ...) die("Semantic error :" msg) 4850656eecSMasami Hiramatsu 494de189feSMasami Hiramatsu /* If there is no space to write, returns -E2BIG. */ 504de189feSMasami Hiramatsu static int e_snprintf(char *str, size_t size, const char *format, ...) 5184988450SMasami Hiramatsu __attribute__((format(printf, 3, 4))); 5284988450SMasami Hiramatsu 5384988450SMasami Hiramatsu static int e_snprintf(char *str, size_t size, const char *format, ...) 544de189feSMasami Hiramatsu { 554de189feSMasami Hiramatsu int ret; 564de189feSMasami Hiramatsu va_list ap; 574de189feSMasami Hiramatsu va_start(ap, format); 584de189feSMasami Hiramatsu ret = vsnprintf(str, size, format, ap); 594de189feSMasami Hiramatsu va_end(ap); 604de189feSMasami Hiramatsu if (ret >= (int)size) 614de189feSMasami Hiramatsu ret = -E2BIG; 624de189feSMasami Hiramatsu return ret; 634de189feSMasami Hiramatsu } 644de189feSMasami Hiramatsu 65b7702a21SMasami Hiramatsu /* Check the name is good for event/group */ 66b7702a21SMasami Hiramatsu static bool check_event_name(const char *name) 67b7702a21SMasami Hiramatsu { 68b7702a21SMasami Hiramatsu if (!isalpha(*name) && *name != '_') 69b7702a21SMasami Hiramatsu return false; 70b7702a21SMasami Hiramatsu while (*++name != '\0') { 71b7702a21SMasami Hiramatsu if (!isalpha(*name) && !isdigit(*name) && *name != '_') 72b7702a21SMasami Hiramatsu return false; 73b7702a21SMasami Hiramatsu } 74b7702a21SMasami Hiramatsu return true; 75b7702a21SMasami Hiramatsu } 76b7702a21SMasami Hiramatsu 7750656eecSMasami Hiramatsu /* Parse probepoint definition. */ 7850656eecSMasami Hiramatsu static void parse_perf_probe_probepoint(char *arg, struct probe_point *pp) 7950656eecSMasami Hiramatsu { 8050656eecSMasami Hiramatsu char *ptr, *tmp; 8150656eecSMasami Hiramatsu char c, nc = 0; 8250656eecSMasami Hiramatsu /* 8350656eecSMasami Hiramatsu * <Syntax> 84af663d75SMasami Hiramatsu * perf probe [EVENT=]SRC:LN 85af663d75SMasami Hiramatsu * perf probe [EVENT=]FUNC[+OFFS|%return][@SRC] 86af663d75SMasami Hiramatsu * 87af663d75SMasami Hiramatsu * TODO:Group name support 8850656eecSMasami Hiramatsu */ 8950656eecSMasami Hiramatsu 90af663d75SMasami Hiramatsu ptr = strchr(arg, '='); 91af663d75SMasami Hiramatsu if (ptr) { /* Event name */ 92af663d75SMasami Hiramatsu *ptr = '\0'; 93af663d75SMasami Hiramatsu tmp = ptr + 1; 94af663d75SMasami Hiramatsu ptr = strchr(arg, ':'); 95af663d75SMasami Hiramatsu if (ptr) /* Group name is not supported yet. */ 96af663d75SMasami Hiramatsu semantic_error("Group name is not supported yet."); 97b7702a21SMasami Hiramatsu if (!check_event_name(arg)) 98b7702a21SMasami Hiramatsu semantic_error("%s is bad for event name -it must " 99b7702a21SMasami Hiramatsu "follow C symbol-naming rule.", arg); 100af663d75SMasami Hiramatsu pp->event = strdup(arg); 101af663d75SMasami Hiramatsu arg = tmp; 102af663d75SMasami Hiramatsu } 103af663d75SMasami Hiramatsu 10450656eecSMasami Hiramatsu ptr = strpbrk(arg, ":+@%"); 10550656eecSMasami Hiramatsu if (ptr) { 10650656eecSMasami Hiramatsu nc = *ptr; 10750656eecSMasami Hiramatsu *ptr++ = '\0'; 10850656eecSMasami Hiramatsu } 10950656eecSMasami Hiramatsu 11050656eecSMasami Hiramatsu /* Check arg is function or file and copy it */ 11150656eecSMasami Hiramatsu if (strchr(arg, '.')) /* File */ 11250656eecSMasami Hiramatsu pp->file = strdup(arg); 11350656eecSMasami Hiramatsu else /* Function */ 11450656eecSMasami Hiramatsu pp->function = strdup(arg); 11550656eecSMasami Hiramatsu DIE_IF(pp->file == NULL && pp->function == NULL); 11650656eecSMasami Hiramatsu 11750656eecSMasami Hiramatsu /* Parse other options */ 11850656eecSMasami Hiramatsu while (ptr) { 11950656eecSMasami Hiramatsu arg = ptr; 12050656eecSMasami Hiramatsu c = nc; 12150656eecSMasami Hiramatsu ptr = strpbrk(arg, ":+@%"); 12250656eecSMasami Hiramatsu if (ptr) { 12350656eecSMasami Hiramatsu nc = *ptr; 12450656eecSMasami Hiramatsu *ptr++ = '\0'; 12550656eecSMasami Hiramatsu } 12650656eecSMasami Hiramatsu switch (c) { 12750656eecSMasami Hiramatsu case ':': /* Line number */ 12850656eecSMasami Hiramatsu pp->line = strtoul(arg, &tmp, 0); 12950656eecSMasami Hiramatsu if (*tmp != '\0') 13050656eecSMasami Hiramatsu semantic_error("There is non-digit charactor" 13150656eecSMasami Hiramatsu " in line number."); 13250656eecSMasami Hiramatsu break; 13350656eecSMasami Hiramatsu case '+': /* Byte offset from a symbol */ 13450656eecSMasami Hiramatsu pp->offset = strtoul(arg, &tmp, 0); 13550656eecSMasami Hiramatsu if (*tmp != '\0') 13650656eecSMasami Hiramatsu semantic_error("There is non-digit charactor" 13750656eecSMasami Hiramatsu " in offset."); 13850656eecSMasami Hiramatsu break; 13950656eecSMasami Hiramatsu case '@': /* File name */ 14050656eecSMasami Hiramatsu if (pp->file) 14150656eecSMasami Hiramatsu semantic_error("SRC@SRC is not allowed."); 14250656eecSMasami Hiramatsu pp->file = strdup(arg); 14350656eecSMasami Hiramatsu DIE_IF(pp->file == NULL); 14450656eecSMasami Hiramatsu if (ptr) 14550656eecSMasami Hiramatsu semantic_error("@SRC must be the last " 14650656eecSMasami Hiramatsu "option."); 14750656eecSMasami Hiramatsu break; 14850656eecSMasami Hiramatsu case '%': /* Probe places */ 14950656eecSMasami Hiramatsu if (strcmp(arg, "return") == 0) { 15050656eecSMasami Hiramatsu pp->retprobe = 1; 15150656eecSMasami Hiramatsu } else /* Others not supported yet */ 15250656eecSMasami Hiramatsu semantic_error("%%%s is not supported.", arg); 15350656eecSMasami Hiramatsu break; 15450656eecSMasami Hiramatsu default: 15550656eecSMasami Hiramatsu DIE_IF("Program has a bug."); 15650656eecSMasami Hiramatsu break; 15750656eecSMasami Hiramatsu } 15850656eecSMasami Hiramatsu } 15950656eecSMasami Hiramatsu 16050656eecSMasami Hiramatsu /* Exclusion check */ 16150656eecSMasami Hiramatsu if (pp->line && pp->offset) 16250656eecSMasami Hiramatsu semantic_error("Offset can't be used with line number."); 16350656eecSMasami Hiramatsu 16450656eecSMasami Hiramatsu if (!pp->line && pp->file && !pp->function) 16550656eecSMasami Hiramatsu semantic_error("File always requires line number."); 16650656eecSMasami Hiramatsu 16750656eecSMasami Hiramatsu if (pp->offset && !pp->function) 16850656eecSMasami Hiramatsu semantic_error("Offset requires an entry function."); 16950656eecSMasami Hiramatsu 17050656eecSMasami Hiramatsu if (pp->retprobe && !pp->function) 17150656eecSMasami Hiramatsu semantic_error("Return probe requires an entry function."); 17250656eecSMasami Hiramatsu 17350656eecSMasami Hiramatsu if ((pp->offset || pp->line) && pp->retprobe) 17450656eecSMasami Hiramatsu semantic_error("Offset/Line can't be used with return probe."); 17550656eecSMasami Hiramatsu 17650656eecSMasami Hiramatsu pr_debug("symbol:%s file:%s line:%d offset:%d, return:%d\n", 17750656eecSMasami Hiramatsu pp->function, pp->file, pp->line, pp->offset, pp->retprobe); 17850656eecSMasami Hiramatsu } 17950656eecSMasami Hiramatsu 18050656eecSMasami Hiramatsu /* Parse perf-probe event definition */ 181fac13fd5SMasami Hiramatsu void parse_perf_probe_event(const char *str, struct probe_point *pp, 182fac13fd5SMasami Hiramatsu bool *need_dwarf) 18350656eecSMasami Hiramatsu { 184e1c01d61SMasami Hiramatsu char **argv; 185fac13fd5SMasami Hiramatsu int argc, i; 186fac13fd5SMasami Hiramatsu 187fac13fd5SMasami Hiramatsu *need_dwarf = false; 18850656eecSMasami Hiramatsu 189e1c01d61SMasami Hiramatsu argv = argv_split(str, &argc); 190e1c01d61SMasami Hiramatsu if (!argv) 191e1c01d61SMasami Hiramatsu die("argv_split failed."); 192e1c01d61SMasami Hiramatsu if (argc > MAX_PROBE_ARGS + 1) 19350656eecSMasami Hiramatsu semantic_error("Too many arguments"); 19450656eecSMasami Hiramatsu 19550656eecSMasami Hiramatsu /* Parse probe point */ 19650656eecSMasami Hiramatsu parse_perf_probe_probepoint(argv[0], pp); 19750656eecSMasami Hiramatsu if (pp->file || pp->line) 198fac13fd5SMasami Hiramatsu *need_dwarf = true; 19950656eecSMasami Hiramatsu 200e1c01d61SMasami Hiramatsu /* Copy arguments and ensure return probe has no C argument */ 20150656eecSMasami Hiramatsu pp->nr_args = argc - 1; 202e1c01d61SMasami Hiramatsu pp->args = zalloc(sizeof(char *) * pp->nr_args); 203e1c01d61SMasami Hiramatsu for (i = 0; i < pp->nr_args; i++) { 204e1c01d61SMasami Hiramatsu pp->args[i] = strdup(argv[i + 1]); 205e1c01d61SMasami Hiramatsu if (!pp->args[i]) 206e1c01d61SMasami Hiramatsu die("Failed to copy argument."); 20750656eecSMasami Hiramatsu if (is_c_varname(pp->args[i])) { 20850656eecSMasami Hiramatsu if (pp->retprobe) 20950656eecSMasami Hiramatsu semantic_error("You can't specify local" 21050656eecSMasami Hiramatsu " variable for kretprobe"); 211fac13fd5SMasami Hiramatsu *need_dwarf = true; 21250656eecSMasami Hiramatsu } 213e1c01d61SMasami Hiramatsu } 21450656eecSMasami Hiramatsu 215e1c01d61SMasami Hiramatsu argv_free(argv); 21650656eecSMasami Hiramatsu } 21750656eecSMasami Hiramatsu 2184de189feSMasami Hiramatsu /* Parse kprobe_events event into struct probe_point */ 219af663d75SMasami Hiramatsu void parse_trace_kprobe_event(const char *str, struct probe_point *pp) 2204de189feSMasami Hiramatsu { 2214de189feSMasami Hiramatsu char pr; 2224de189feSMasami Hiramatsu char *p; 2234de189feSMasami Hiramatsu int ret, i, argc; 2244de189feSMasami Hiramatsu char **argv; 2254de189feSMasami Hiramatsu 2264de189feSMasami Hiramatsu pr_debug("Parsing kprobe_events: %s\n", str); 2274de189feSMasami Hiramatsu argv = argv_split(str, &argc); 2284de189feSMasami Hiramatsu if (!argv) 2294de189feSMasami Hiramatsu die("argv_split failed."); 2304de189feSMasami Hiramatsu if (argc < 2) 2314de189feSMasami Hiramatsu semantic_error("Too less arguments."); 2324de189feSMasami Hiramatsu 2334de189feSMasami Hiramatsu /* Scan event and group name. */ 23493aaa45aSLiming Wang ret = sscanf(argv[0], "%c:%a[^/ \t]/%a[^ \t]", 235af663d75SMasami Hiramatsu &pr, (float *)(void *)&pp->group, 236af663d75SMasami Hiramatsu (float *)(void *)&pp->event); 2374de189feSMasami Hiramatsu if (ret != 3) 2384de189feSMasami Hiramatsu semantic_error("Failed to parse event name: %s", argv[0]); 239af663d75SMasami Hiramatsu pr_debug("Group:%s Event:%s probe:%c\n", pp->group, pp->event, pr); 2404de189feSMasami Hiramatsu 2414de189feSMasami Hiramatsu pp->retprobe = (pr == 'r'); 2424de189feSMasami Hiramatsu 2434de189feSMasami Hiramatsu /* Scan function name and offset */ 244af663d75SMasami Hiramatsu ret = sscanf(argv[1], "%a[^+]+%d", (float *)(void *)&pp->function, 245af663d75SMasami Hiramatsu &pp->offset); 2464de189feSMasami Hiramatsu if (ret == 1) 2474de189feSMasami Hiramatsu pp->offset = 0; 2484de189feSMasami Hiramatsu 2494de189feSMasami Hiramatsu /* kprobe_events doesn't have this information */ 2504de189feSMasami Hiramatsu pp->line = 0; 2514de189feSMasami Hiramatsu pp->file = NULL; 2524de189feSMasami Hiramatsu 2534de189feSMasami Hiramatsu pp->nr_args = argc - 2; 2544de189feSMasami Hiramatsu pp->args = zalloc(sizeof(char *) * pp->nr_args); 2554de189feSMasami Hiramatsu for (i = 0; i < pp->nr_args; i++) { 2564de189feSMasami Hiramatsu p = strchr(argv[i + 2], '='); 2574de189feSMasami Hiramatsu if (p) /* We don't need which register is assigned. */ 2584de189feSMasami Hiramatsu *p = '\0'; 2594de189feSMasami Hiramatsu pp->args[i] = strdup(argv[i + 2]); 2604de189feSMasami Hiramatsu if (!pp->args[i]) 2614de189feSMasami Hiramatsu die("Failed to copy argument."); 2624de189feSMasami Hiramatsu } 2634de189feSMasami Hiramatsu 2644de189feSMasami Hiramatsu argv_free(argv); 2654de189feSMasami Hiramatsu } 2664de189feSMasami Hiramatsu 2677ef17aafSMasami Hiramatsu /* Synthesize only probe point (not argument) */ 2687ef17aafSMasami Hiramatsu int synthesize_perf_probe_point(struct probe_point *pp) 26950656eecSMasami Hiramatsu { 27050656eecSMasami Hiramatsu char *buf; 2714de189feSMasami Hiramatsu char offs[64] = "", line[64] = ""; 2727ef17aafSMasami Hiramatsu int ret; 27350656eecSMasami Hiramatsu 27450656eecSMasami Hiramatsu pp->probes[0] = buf = zalloc(MAX_CMDLEN); 27550656eecSMasami Hiramatsu if (!buf) 27650656eecSMasami Hiramatsu die("Failed to allocate memory by zalloc."); 2774de189feSMasami Hiramatsu if (pp->offset) { 2784de189feSMasami Hiramatsu ret = e_snprintf(offs, 64, "+%d", pp->offset); 2794de189feSMasami Hiramatsu if (ret <= 0) 2804de189feSMasami Hiramatsu goto error; 2814de189feSMasami Hiramatsu } 2824de189feSMasami Hiramatsu if (pp->line) { 2834de189feSMasami Hiramatsu ret = e_snprintf(line, 64, ":%d", pp->line); 2844de189feSMasami Hiramatsu if (ret <= 0) 2854de189feSMasami Hiramatsu goto error; 2864de189feSMasami Hiramatsu } 2874de189feSMasami Hiramatsu 2884de189feSMasami Hiramatsu if (pp->function) 2894de189feSMasami Hiramatsu ret = e_snprintf(buf, MAX_CMDLEN, "%s%s%s%s", pp->function, 2904de189feSMasami Hiramatsu offs, pp->retprobe ? "%return" : "", line); 2914de189feSMasami Hiramatsu else 29284988450SMasami Hiramatsu ret = e_snprintf(buf, MAX_CMDLEN, "%s%s", pp->file, line); 2937ef17aafSMasami Hiramatsu if (ret <= 0) { 2947ef17aafSMasami Hiramatsu error: 2957ef17aafSMasami Hiramatsu free(pp->probes[0]); 2967ef17aafSMasami Hiramatsu pp->probes[0] = NULL; 2977ef17aafSMasami Hiramatsu } 2987ef17aafSMasami Hiramatsu return ret; 2997ef17aafSMasami Hiramatsu } 30050656eecSMasami Hiramatsu 3017ef17aafSMasami Hiramatsu int synthesize_perf_probe_event(struct probe_point *pp) 3027ef17aafSMasami Hiramatsu { 3037ef17aafSMasami Hiramatsu char *buf; 3047ef17aafSMasami Hiramatsu int i, len, ret; 3057ef17aafSMasami Hiramatsu 3067ef17aafSMasami Hiramatsu len = synthesize_perf_probe_point(pp); 3077ef17aafSMasami Hiramatsu if (len < 0) 3087ef17aafSMasami Hiramatsu return 0; 3097ef17aafSMasami Hiramatsu 3107ef17aafSMasami Hiramatsu buf = pp->probes[0]; 31150656eecSMasami Hiramatsu for (i = 0; i < pp->nr_args; i++) { 3124de189feSMasami Hiramatsu ret = e_snprintf(&buf[len], MAX_CMDLEN - len, " %s", 31350656eecSMasami Hiramatsu pp->args[i]); 3144de189feSMasami Hiramatsu if (ret <= 0) 31550656eecSMasami Hiramatsu goto error; 31650656eecSMasami Hiramatsu len += ret; 31750656eecSMasami Hiramatsu } 31850656eecSMasami Hiramatsu pp->found = 1; 31950656eecSMasami Hiramatsu 32050656eecSMasami Hiramatsu return pp->found; 32150656eecSMasami Hiramatsu error: 32250656eecSMasami Hiramatsu free(pp->probes[0]); 3237ef17aafSMasami Hiramatsu pp->probes[0] = NULL; 32450656eecSMasami Hiramatsu 32550656eecSMasami Hiramatsu return ret; 32650656eecSMasami Hiramatsu } 32750656eecSMasami Hiramatsu 3284de189feSMasami Hiramatsu int synthesize_trace_kprobe_event(struct probe_point *pp) 3294de189feSMasami Hiramatsu { 3304de189feSMasami Hiramatsu char *buf; 3314de189feSMasami Hiramatsu int i, len, ret; 3324de189feSMasami Hiramatsu 3334de189feSMasami Hiramatsu pp->probes[0] = buf = zalloc(MAX_CMDLEN); 3344de189feSMasami Hiramatsu if (!buf) 3354de189feSMasami Hiramatsu die("Failed to allocate memory by zalloc."); 3364de189feSMasami Hiramatsu ret = e_snprintf(buf, MAX_CMDLEN, "%s+%d", pp->function, pp->offset); 3374de189feSMasami Hiramatsu if (ret <= 0) 3384de189feSMasami Hiramatsu goto error; 3394de189feSMasami Hiramatsu len = ret; 3404de189feSMasami Hiramatsu 3414de189feSMasami Hiramatsu for (i = 0; i < pp->nr_args; i++) { 3424de189feSMasami Hiramatsu ret = e_snprintf(&buf[len], MAX_CMDLEN - len, " %s", 3434de189feSMasami Hiramatsu pp->args[i]); 3444de189feSMasami Hiramatsu if (ret <= 0) 3454de189feSMasami Hiramatsu goto error; 3464de189feSMasami Hiramatsu len += ret; 3474de189feSMasami Hiramatsu } 3484de189feSMasami Hiramatsu pp->found = 1; 3494de189feSMasami Hiramatsu 3504de189feSMasami Hiramatsu return pp->found; 3514de189feSMasami Hiramatsu error: 3524de189feSMasami Hiramatsu free(pp->probes[0]); 3537ef17aafSMasami Hiramatsu pp->probes[0] = NULL; 3544de189feSMasami Hiramatsu 3554de189feSMasami Hiramatsu return ret; 3564de189feSMasami Hiramatsu } 3574de189feSMasami Hiramatsu 3584de189feSMasami Hiramatsu static int open_kprobe_events(int flags, int mode) 3594de189feSMasami Hiramatsu { 3604de189feSMasami Hiramatsu char buf[PATH_MAX]; 3614de189feSMasami Hiramatsu int ret; 3624de189feSMasami Hiramatsu 3634de189feSMasami Hiramatsu ret = e_snprintf(buf, PATH_MAX, "%s/../kprobe_events", debugfs_path); 3644de189feSMasami Hiramatsu if (ret < 0) 3654de189feSMasami Hiramatsu die("Failed to make kprobe_events path."); 3664de189feSMasami Hiramatsu 3674de189feSMasami Hiramatsu ret = open(buf, flags, mode); 3684de189feSMasami Hiramatsu if (ret < 0) { 3694de189feSMasami Hiramatsu if (errno == ENOENT) 3704de189feSMasami Hiramatsu die("kprobe_events file does not exist -" 371*63bbd5e2SLiming Wang " please rebuild with CONFIG_KPROBE_EVENT."); 3724de189feSMasami Hiramatsu else 3734de189feSMasami Hiramatsu die("Could not open kprobe_events file: %s", 3744de189feSMasami Hiramatsu strerror(errno)); 3754de189feSMasami Hiramatsu } 3764de189feSMasami Hiramatsu return ret; 3774de189feSMasami Hiramatsu } 3784de189feSMasami Hiramatsu 3794de189feSMasami Hiramatsu /* Get raw string list of current kprobe_events */ 3804de189feSMasami Hiramatsu static struct strlist *get_trace_kprobe_event_rawlist(int fd) 3814de189feSMasami Hiramatsu { 3824de189feSMasami Hiramatsu int ret, idx; 3834de189feSMasami Hiramatsu FILE *fp; 3844de189feSMasami Hiramatsu char buf[MAX_CMDLEN]; 3854de189feSMasami Hiramatsu char *p; 3864de189feSMasami Hiramatsu struct strlist *sl; 3874de189feSMasami Hiramatsu 3884de189feSMasami Hiramatsu sl = strlist__new(true, NULL); 3894de189feSMasami Hiramatsu 3904de189feSMasami Hiramatsu fp = fdopen(dup(fd), "r"); 3914de189feSMasami Hiramatsu while (!feof(fp)) { 3924de189feSMasami Hiramatsu p = fgets(buf, MAX_CMDLEN, fp); 3934de189feSMasami Hiramatsu if (!p) 3944de189feSMasami Hiramatsu break; 3954de189feSMasami Hiramatsu 3964de189feSMasami Hiramatsu idx = strlen(p) - 1; 3974de189feSMasami Hiramatsu if (p[idx] == '\n') 3984de189feSMasami Hiramatsu p[idx] = '\0'; 3994de189feSMasami Hiramatsu ret = strlist__add(sl, buf); 4004de189feSMasami Hiramatsu if (ret < 0) 4014de189feSMasami Hiramatsu die("strlist__add failed: %s", strerror(-ret)); 4024de189feSMasami Hiramatsu } 4034de189feSMasami Hiramatsu fclose(fp); 4044de189feSMasami Hiramatsu 4054de189feSMasami Hiramatsu return sl; 4064de189feSMasami Hiramatsu } 4074de189feSMasami Hiramatsu 4084de189feSMasami Hiramatsu /* Free and zero clear probe_point */ 4094de189feSMasami Hiramatsu static void clear_probe_point(struct probe_point *pp) 4104de189feSMasami Hiramatsu { 4114de189feSMasami Hiramatsu int i; 4124de189feSMasami Hiramatsu 413af663d75SMasami Hiramatsu if (pp->event) 414af663d75SMasami Hiramatsu free(pp->event); 415af663d75SMasami Hiramatsu if (pp->group) 416af663d75SMasami Hiramatsu free(pp->group); 4174de189feSMasami Hiramatsu if (pp->function) 4184de189feSMasami Hiramatsu free(pp->function); 4194de189feSMasami Hiramatsu if (pp->file) 4204de189feSMasami Hiramatsu free(pp->file); 4214de189feSMasami Hiramatsu for (i = 0; i < pp->nr_args; i++) 4224de189feSMasami Hiramatsu free(pp->args[i]); 4234de189feSMasami Hiramatsu if (pp->args) 4244de189feSMasami Hiramatsu free(pp->args); 4254de189feSMasami Hiramatsu for (i = 0; i < pp->found; i++) 4264de189feSMasami Hiramatsu free(pp->probes[i]); 4275660ce34SJulia Lawall memset(pp, 0, sizeof(*pp)); 4284de189feSMasami Hiramatsu } 4294de189feSMasami Hiramatsu 430278498d4SMasami Hiramatsu /* Show an event */ 431af663d75SMasami Hiramatsu static void show_perf_probe_event(const char *event, const char *place, 432af663d75SMasami Hiramatsu struct probe_point *pp) 433278498d4SMasami Hiramatsu { 4347e990a51SMasami Hiramatsu int i, ret; 435278498d4SMasami Hiramatsu char buf[128]; 436278498d4SMasami Hiramatsu 437af663d75SMasami Hiramatsu ret = e_snprintf(buf, 128, "%s:%s", pp->group, event); 4387e990a51SMasami Hiramatsu if (ret < 0) 4397e990a51SMasami Hiramatsu die("Failed to copy event: %s", strerror(-ret)); 440278498d4SMasami Hiramatsu printf(" %-40s (on %s", buf, place); 441278498d4SMasami Hiramatsu 442278498d4SMasami Hiramatsu if (pp->nr_args > 0) { 443278498d4SMasami Hiramatsu printf(" with"); 444278498d4SMasami Hiramatsu for (i = 0; i < pp->nr_args; i++) 445278498d4SMasami Hiramatsu printf(" %s", pp->args[i]); 446278498d4SMasami Hiramatsu } 447278498d4SMasami Hiramatsu printf(")\n"); 448278498d4SMasami Hiramatsu } 449278498d4SMasami Hiramatsu 4504de189feSMasami Hiramatsu /* List up current perf-probe events */ 4514de189feSMasami Hiramatsu void show_perf_probe_events(void) 4524de189feSMasami Hiramatsu { 4537ef17aafSMasami Hiramatsu int fd; 4544de189feSMasami Hiramatsu struct probe_point pp; 4554de189feSMasami Hiramatsu struct strlist *rawlist; 4564de189feSMasami Hiramatsu struct str_node *ent; 4574de189feSMasami Hiramatsu 4584de189feSMasami Hiramatsu fd = open_kprobe_events(O_RDONLY, 0); 4594de189feSMasami Hiramatsu rawlist = get_trace_kprobe_event_rawlist(fd); 4604de189feSMasami Hiramatsu close(fd); 4614de189feSMasami Hiramatsu 462adf365f4SMasami Hiramatsu strlist__for_each(ent, rawlist) { 463af663d75SMasami Hiramatsu parse_trace_kprobe_event(ent->s, &pp); 464278498d4SMasami Hiramatsu /* Synthesize only event probe point */ 4657ef17aafSMasami Hiramatsu synthesize_perf_probe_point(&pp); 466278498d4SMasami Hiramatsu /* Show an event */ 467af663d75SMasami Hiramatsu show_perf_probe_event(pp.event, pp.probes[0], &pp); 4684de189feSMasami Hiramatsu clear_probe_point(&pp); 4694de189feSMasami Hiramatsu } 4704de189feSMasami Hiramatsu 4714de189feSMasami Hiramatsu strlist__delete(rawlist); 4724de189feSMasami Hiramatsu } 4734de189feSMasami Hiramatsu 474b498ce1fSMasami Hiramatsu /* Get current perf-probe event names */ 475fa28244dSMasami Hiramatsu static struct strlist *get_perf_event_names(int fd, bool include_group) 476b498ce1fSMasami Hiramatsu { 477fa28244dSMasami Hiramatsu char buf[128]; 478b498ce1fSMasami Hiramatsu struct strlist *sl, *rawlist; 479b498ce1fSMasami Hiramatsu struct str_node *ent; 480af663d75SMasami Hiramatsu struct probe_point pp; 481b498ce1fSMasami Hiramatsu 482af663d75SMasami Hiramatsu memset(&pp, 0, sizeof(pp)); 483b498ce1fSMasami Hiramatsu rawlist = get_trace_kprobe_event_rawlist(fd); 484b498ce1fSMasami Hiramatsu 485e1d2017bSMasami Hiramatsu sl = strlist__new(true, NULL); 486adf365f4SMasami Hiramatsu strlist__for_each(ent, rawlist) { 487af663d75SMasami Hiramatsu parse_trace_kprobe_event(ent->s, &pp); 488fa28244dSMasami Hiramatsu if (include_group) { 489af663d75SMasami Hiramatsu if (e_snprintf(buf, 128, "%s:%s", pp.group, 490af663d75SMasami Hiramatsu pp.event) < 0) 491fa28244dSMasami Hiramatsu die("Failed to copy group:event name."); 492fa28244dSMasami Hiramatsu strlist__add(sl, buf); 493fa28244dSMasami Hiramatsu } else 494af663d75SMasami Hiramatsu strlist__add(sl, pp.event); 495af663d75SMasami Hiramatsu clear_probe_point(&pp); 496b498ce1fSMasami Hiramatsu } 497b498ce1fSMasami Hiramatsu 498b498ce1fSMasami Hiramatsu strlist__delete(rawlist); 499b498ce1fSMasami Hiramatsu 500b498ce1fSMasami Hiramatsu return sl; 501b498ce1fSMasami Hiramatsu } 502b498ce1fSMasami Hiramatsu 503a9b495b0SMasami Hiramatsu static void write_trace_kprobe_event(int fd, const char *buf) 50450656eecSMasami Hiramatsu { 50550656eecSMasami Hiramatsu int ret; 50650656eecSMasami Hiramatsu 507fa28244dSMasami Hiramatsu pr_debug("Writing event: %s\n", buf); 50850656eecSMasami Hiramatsu ret = write(fd, buf, strlen(buf)); 50950656eecSMasami Hiramatsu if (ret <= 0) 510fa28244dSMasami Hiramatsu die("Failed to write event: %s", strerror(errno)); 51150656eecSMasami Hiramatsu } 51250656eecSMasami Hiramatsu 513b498ce1fSMasami Hiramatsu static void get_new_event_name(char *buf, size_t len, const char *base, 514d761b08bSMasami Hiramatsu struct strlist *namelist, bool allow_suffix) 515b498ce1fSMasami Hiramatsu { 516b498ce1fSMasami Hiramatsu int i, ret; 51717f88fcdSMasami Hiramatsu 51817f88fcdSMasami Hiramatsu /* Try no suffix */ 51917f88fcdSMasami Hiramatsu ret = e_snprintf(buf, len, "%s", base); 52017f88fcdSMasami Hiramatsu if (ret < 0) 52117f88fcdSMasami Hiramatsu die("snprintf() failed: %s", strerror(-ret)); 52217f88fcdSMasami Hiramatsu if (!strlist__has_entry(namelist, buf)) 52317f88fcdSMasami Hiramatsu return; 52417f88fcdSMasami Hiramatsu 525d761b08bSMasami Hiramatsu if (!allow_suffix) { 526d761b08bSMasami Hiramatsu pr_warning("Error: event \"%s\" already exists. " 527d761b08bSMasami Hiramatsu "(Use -f to force duplicates.)\n", base); 528d761b08bSMasami Hiramatsu die("Can't add new event."); 529d761b08bSMasami Hiramatsu } 530d761b08bSMasami Hiramatsu 53117f88fcdSMasami Hiramatsu /* Try to add suffix */ 53217f88fcdSMasami Hiramatsu for (i = 1; i < MAX_EVENT_INDEX; i++) { 533b498ce1fSMasami Hiramatsu ret = e_snprintf(buf, len, "%s_%d", base, i); 534b498ce1fSMasami Hiramatsu if (ret < 0) 535b498ce1fSMasami Hiramatsu die("snprintf() failed: %s", strerror(-ret)); 536b498ce1fSMasami Hiramatsu if (!strlist__has_entry(namelist, buf)) 537b498ce1fSMasami Hiramatsu break; 538b498ce1fSMasami Hiramatsu } 539b498ce1fSMasami Hiramatsu if (i == MAX_EVENT_INDEX) 540b498ce1fSMasami Hiramatsu die("Too many events are on the same function."); 541b498ce1fSMasami Hiramatsu } 542b498ce1fSMasami Hiramatsu 543d761b08bSMasami Hiramatsu void add_trace_kprobe_events(struct probe_point *probes, int nr_probes, 544d761b08bSMasami Hiramatsu bool force_add) 54550656eecSMasami Hiramatsu { 54650656eecSMasami Hiramatsu int i, j, fd; 54750656eecSMasami Hiramatsu struct probe_point *pp; 54850656eecSMasami Hiramatsu char buf[MAX_CMDLEN]; 549b498ce1fSMasami Hiramatsu char event[64]; 550b498ce1fSMasami Hiramatsu struct strlist *namelist; 551d761b08bSMasami Hiramatsu bool allow_suffix; 55250656eecSMasami Hiramatsu 553b498ce1fSMasami Hiramatsu fd = open_kprobe_events(O_RDWR, O_APPEND); 554b498ce1fSMasami Hiramatsu /* Get current event names */ 555fa28244dSMasami Hiramatsu namelist = get_perf_event_names(fd, false); 55650656eecSMasami Hiramatsu 55750656eecSMasami Hiramatsu for (j = 0; j < nr_probes; j++) { 55850656eecSMasami Hiramatsu pp = probes + j; 559af663d75SMasami Hiramatsu if (!pp->event) 560af663d75SMasami Hiramatsu pp->event = strdup(pp->function); 561af663d75SMasami Hiramatsu if (!pp->group) 562af663d75SMasami Hiramatsu pp->group = strdup(PERFPROBE_GROUP); 563af663d75SMasami Hiramatsu DIE_IF(!pp->event || !pp->group); 564d761b08bSMasami Hiramatsu /* If force_add is true, suffix search is allowed */ 565d761b08bSMasami Hiramatsu allow_suffix = force_add; 56650656eecSMasami Hiramatsu for (i = 0; i < pp->found; i++) { 567b498ce1fSMasami Hiramatsu /* Get an unused new event name */ 568d761b08bSMasami Hiramatsu get_new_event_name(event, 64, pp->event, namelist, 569d761b08bSMasami Hiramatsu allow_suffix); 570b498ce1fSMasami Hiramatsu snprintf(buf, MAX_CMDLEN, "%c:%s/%s %s\n", 57150656eecSMasami Hiramatsu pp->retprobe ? 'r' : 'p', 572af663d75SMasami Hiramatsu pp->group, event, 57350656eecSMasami Hiramatsu pp->probes[i]); 57450656eecSMasami Hiramatsu write_trace_kprobe_event(fd, buf); 575a9b495b0SMasami Hiramatsu printf("Added new event:\n"); 576a9b495b0SMasami Hiramatsu /* Get the first parameter (probe-point) */ 577a9b495b0SMasami Hiramatsu sscanf(pp->probes[i], "%s", buf); 578af663d75SMasami Hiramatsu show_perf_probe_event(event, buf, pp); 579b498ce1fSMasami Hiramatsu /* Add added event name to namelist */ 580b498ce1fSMasami Hiramatsu strlist__add(namelist, event); 581d761b08bSMasami Hiramatsu /* 582d761b08bSMasami Hiramatsu * Probes after the first probe which comes from same 583d761b08bSMasami Hiramatsu * user input are always allowed to add suffix, because 584d761b08bSMasami Hiramatsu * there might be several addresses corresponding to 585d761b08bSMasami Hiramatsu * one code line. 586d761b08bSMasami Hiramatsu */ 587d761b08bSMasami Hiramatsu allow_suffix = true; 58850656eecSMasami Hiramatsu } 58950656eecSMasami Hiramatsu } 590a9b495b0SMasami Hiramatsu /* Show how to use the event. */ 591a9b495b0SMasami Hiramatsu printf("\nYou can now use it on all perf tools, such as:\n\n"); 592a9b495b0SMasami Hiramatsu printf("\tperf record -e %s:%s -a sleep 1\n\n", PERFPROBE_GROUP, event); 593a9b495b0SMasami Hiramatsu 594e1d2017bSMasami Hiramatsu strlist__delete(namelist); 59550656eecSMasami Hiramatsu close(fd); 59650656eecSMasami Hiramatsu } 597fa28244dSMasami Hiramatsu 598bbbb521bSMasami Hiramatsu static void __del_trace_kprobe_event(int fd, struct str_node *ent) 599bbbb521bSMasami Hiramatsu { 600bbbb521bSMasami Hiramatsu char *p; 601bbbb521bSMasami Hiramatsu char buf[128]; 602bbbb521bSMasami Hiramatsu 603bbbb521bSMasami Hiramatsu /* Convert from perf-probe event to trace-kprobe event */ 604bbbb521bSMasami Hiramatsu if (e_snprintf(buf, 128, "-:%s", ent->s) < 0) 605bbbb521bSMasami Hiramatsu die("Failed to copy event."); 606bbbb521bSMasami Hiramatsu p = strchr(buf + 2, ':'); 607bbbb521bSMasami Hiramatsu if (!p) 608bbbb521bSMasami Hiramatsu die("Internal error: %s should have ':' but not.", ent->s); 609bbbb521bSMasami Hiramatsu *p = '/'; 610bbbb521bSMasami Hiramatsu 611bbbb521bSMasami Hiramatsu write_trace_kprobe_event(fd, buf); 612bbbb521bSMasami Hiramatsu printf("Remove event: %s\n", ent->s); 613bbbb521bSMasami Hiramatsu } 614bbbb521bSMasami Hiramatsu 615fa28244dSMasami Hiramatsu static void del_trace_kprobe_event(int fd, const char *group, 616fa28244dSMasami Hiramatsu const char *event, struct strlist *namelist) 617fa28244dSMasami Hiramatsu { 618fa28244dSMasami Hiramatsu char buf[128]; 619bbbb521bSMasami Hiramatsu struct str_node *ent, *n; 620bbbb521bSMasami Hiramatsu int found = 0; 621fa28244dSMasami Hiramatsu 622fa28244dSMasami Hiramatsu if (e_snprintf(buf, 128, "%s:%s", group, event) < 0) 623fa28244dSMasami Hiramatsu die("Failed to copy event."); 624fa28244dSMasami Hiramatsu 625bbbb521bSMasami Hiramatsu if (strpbrk(buf, "*?")) { /* Glob-exp */ 626bbbb521bSMasami Hiramatsu strlist__for_each_safe(ent, n, namelist) 627bbbb521bSMasami Hiramatsu if (strglobmatch(ent->s, buf)) { 628bbbb521bSMasami Hiramatsu found++; 629bbbb521bSMasami Hiramatsu __del_trace_kprobe_event(fd, ent); 6303e340590SMasami Hiramatsu strlist__remove(namelist, ent); 631fa28244dSMasami Hiramatsu } 632bbbb521bSMasami Hiramatsu } else { 633bbbb521bSMasami Hiramatsu ent = strlist__find(namelist, buf); 634bbbb521bSMasami Hiramatsu if (ent) { 635bbbb521bSMasami Hiramatsu found++; 636bbbb521bSMasami Hiramatsu __del_trace_kprobe_event(fd, ent); 637bbbb521bSMasami Hiramatsu strlist__remove(namelist, ent); 638bbbb521bSMasami Hiramatsu } 639bbbb521bSMasami Hiramatsu } 640bbbb521bSMasami Hiramatsu if (found == 0) 641bbbb521bSMasami Hiramatsu pr_info("Info: event \"%s\" does not exist, could not remove it.\n", buf); 642bbbb521bSMasami Hiramatsu } 643fa28244dSMasami Hiramatsu 644fa28244dSMasami Hiramatsu void del_trace_kprobe_events(struct strlist *dellist) 645fa28244dSMasami Hiramatsu { 646fa28244dSMasami Hiramatsu int fd; 647fa28244dSMasami Hiramatsu const char *group, *event; 648fa28244dSMasami Hiramatsu char *p, *str; 649fa28244dSMasami Hiramatsu struct str_node *ent; 650fa28244dSMasami Hiramatsu struct strlist *namelist; 651fa28244dSMasami Hiramatsu 652fa28244dSMasami Hiramatsu fd = open_kprobe_events(O_RDWR, O_APPEND); 653fa28244dSMasami Hiramatsu /* Get current event names */ 654fa28244dSMasami Hiramatsu namelist = get_perf_event_names(fd, true); 655fa28244dSMasami Hiramatsu 656adf365f4SMasami Hiramatsu strlist__for_each(ent, dellist) { 657fa28244dSMasami Hiramatsu str = strdup(ent->s); 658fa28244dSMasami Hiramatsu if (!str) 659fa28244dSMasami Hiramatsu die("Failed to copy event."); 660bbbb521bSMasami Hiramatsu pr_debug("Parsing: %s\n", str); 661fa28244dSMasami Hiramatsu p = strchr(str, ':'); 662fa28244dSMasami Hiramatsu if (p) { 663fa28244dSMasami Hiramatsu group = str; 664fa28244dSMasami Hiramatsu *p = '\0'; 665fa28244dSMasami Hiramatsu event = p + 1; 666fa28244dSMasami Hiramatsu } else { 667bbbb521bSMasami Hiramatsu group = "*"; 668fa28244dSMasami Hiramatsu event = str; 669fa28244dSMasami Hiramatsu } 670bbbb521bSMasami Hiramatsu pr_debug("Group: %s, Event: %s\n", group, event); 671fa28244dSMasami Hiramatsu del_trace_kprobe_event(fd, group, event, namelist); 672fa28244dSMasami Hiramatsu free(str); 673fa28244dSMasami Hiramatsu } 674fa28244dSMasami Hiramatsu strlist__delete(namelist); 675fa28244dSMasami Hiramatsu close(fd); 676fa28244dSMasami Hiramatsu } 677fa28244dSMasami Hiramatsu 678