1 /* 2 * builtin-probe.c 3 * 4 * Builtin probe command: Set up probe events by C expression 5 * 6 * Written by Masami Hiramatsu <mhiramat@redhat.com> 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation; either version 2 of the License, or 11 * (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 21 * 22 */ 23 #define _GNU_SOURCE 24 #include <sys/utsname.h> 25 #include <sys/types.h> 26 #include <sys/stat.h> 27 #include <fcntl.h> 28 #include <errno.h> 29 #include <stdio.h> 30 #include <unistd.h> 31 #include <stdlib.h> 32 #include <string.h> 33 34 #undef _GNU_SOURCE 35 #include "perf.h" 36 #include "builtin.h" 37 #include "util/util.h" 38 #include "util/strlist.h" 39 #include "util/event.h" 40 #include "util/debug.h" 41 #include "util/parse-options.h" 42 #include "util/parse-events.h" /* For debugfs_path */ 43 #include "util/probe-finder.h" 44 #include "util/probe-event.h" 45 46 /* Default vmlinux search paths */ 47 #define NR_SEARCH_PATH 4 48 const char *default_search_path[NR_SEARCH_PATH] = { 49 "/lib/modules/%s/build/vmlinux", /* Custom build kernel */ 50 "/usr/lib/debug/lib/modules/%s/vmlinux", /* Red Hat debuginfo */ 51 "/boot/vmlinux-debug-%s", /* Ubuntu */ 52 "./vmlinux", /* CWD */ 53 }; 54 55 #define MAX_PATH_LEN 256 56 #define MAX_PROBES 128 57 58 /* Session management structure */ 59 static struct { 60 char *vmlinux; 61 char *release; 62 int need_dwarf; 63 int nr_probe; 64 struct probe_point probes[MAX_PROBES]; 65 struct strlist *dellist; 66 } session; 67 68 static bool listing; 69 70 /* Parse an event definition. Note that any error must die. */ 71 static void parse_probe_event(const char *str) 72 { 73 struct probe_point *pp = &session.probes[session.nr_probe]; 74 75 pr_debug("probe-definition(%d): %s\n", session.nr_probe, str); 76 if (++session.nr_probe == MAX_PROBES) 77 die("Too many probes (> %d) are specified.", MAX_PROBES); 78 79 /* Parse perf-probe event into probe_point */ 80 session.need_dwarf = parse_perf_probe_event(str, pp); 81 82 pr_debug("%d arguments\n", pp->nr_args); 83 } 84 85 static void parse_probe_event_argv(int argc, const char **argv) 86 { 87 int i, len; 88 char *buf; 89 90 /* Bind up rest arguments */ 91 len = 0; 92 for (i = 0; i < argc; i++) 93 len += strlen(argv[i]) + 1; 94 buf = zalloc(len + 1); 95 if (!buf) 96 die("Failed to allocate memory for binding arguments."); 97 len = 0; 98 for (i = 0; i < argc; i++) 99 len += sprintf(&buf[len], "%s ", argv[i]); 100 parse_probe_event(buf); 101 free(buf); 102 } 103 104 static int opt_add_probe_event(const struct option *opt __used, 105 const char *str, int unset __used) 106 { 107 if (str) 108 parse_probe_event(str); 109 return 0; 110 } 111 112 static int opt_del_probe_event(const struct option *opt __used, 113 const char *str, int unset __used) 114 { 115 if (str) { 116 if (!session.dellist) 117 session.dellist = strlist__new(true, NULL); 118 strlist__add(session.dellist, str); 119 } 120 return 0; 121 } 122 123 #ifndef NO_LIBDWARF 124 static int open_default_vmlinux(void) 125 { 126 struct utsname uts; 127 char fname[MAX_PATH_LEN]; 128 int fd, ret, i; 129 130 ret = uname(&uts); 131 if (ret) { 132 pr_debug("uname() failed.\n"); 133 return -errno; 134 } 135 session.release = uts.release; 136 for (i = 0; i < NR_SEARCH_PATH; i++) { 137 ret = snprintf(fname, MAX_PATH_LEN, 138 default_search_path[i], session.release); 139 if (ret >= MAX_PATH_LEN || ret < 0) { 140 pr_debug("Filename(%d,%s) is too long.\n", i, 141 uts.release); 142 errno = E2BIG; 143 return -E2BIG; 144 } 145 pr_debug("try to open %s\n", fname); 146 fd = open(fname, O_RDONLY); 147 if (fd >= 0) 148 break; 149 } 150 return fd; 151 } 152 #endif 153 154 static const char * const probe_usage[] = { 155 "perf probe [<options>] 'PROBEDEF' ['PROBEDEF' ...]", 156 "perf probe [<options>] --add 'PROBEDEF' [--add 'PROBEDEF' ...]", 157 "perf probe [<options>] --del '[GROUP:]EVENT' ...", 158 "perf probe --list", 159 NULL 160 }; 161 162 static const struct option options[] = { 163 OPT_BOOLEAN('v', "verbose", &verbose, 164 "be more verbose (show parsed arguments, etc)"), 165 #ifndef NO_LIBDWARF 166 OPT_STRING('k', "vmlinux", &session.vmlinux, "file", 167 "vmlinux/module pathname"), 168 #endif 169 OPT_BOOLEAN('l', "list", &listing, "list up current probe events"), 170 OPT_CALLBACK('d', "del", NULL, "[GROUP:]EVENT", "delete a probe event.", 171 opt_del_probe_event), 172 OPT_CALLBACK('a', "add", NULL, 173 #ifdef NO_LIBDWARF 174 "FUNC[+OFFS|%return] [ARG ...]", 175 #else 176 "FUNC[+OFFS|%return|:RLN][@SRC]|SRC:ALN [ARG ...]", 177 #endif 178 "probe point definition, where\n" 179 "\t\tGRP:\tGroup name (optional)\n" 180 "\t\tNAME:\tEvent name\n" 181 "\t\tFUNC:\tFunction name\n" 182 "\t\tOFFS:\tOffset from function entry (in byte)\n" 183 "\t\t%return:\tPut the probe at function return\n" 184 #ifdef NO_LIBDWARF 185 "\t\tARG:\tProbe argument (only \n" 186 #else 187 "\t\tSRC:\tSource code path\n" 188 "\t\tRLN:\tRelative line number from function entry.\n" 189 "\t\tALN:\tAbsolute line number in file.\n" 190 "\t\tARG:\tProbe argument (local variable name or\n" 191 #endif 192 "\t\t\tkprobe-tracer argument format.)\n", 193 opt_add_probe_event), 194 OPT_END() 195 }; 196 197 int cmd_probe(int argc, const char **argv, const char *prefix __used) 198 { 199 int i, ret; 200 #ifndef NO_LIBDWARF 201 int fd; 202 #endif 203 struct probe_point *pp; 204 205 argc = parse_options(argc, argv, options, probe_usage, 206 PARSE_OPT_STOP_AT_NON_OPTION); 207 if (argc > 0) 208 parse_probe_event_argv(argc, argv); 209 210 if ((session.nr_probe == 0 && !session.dellist && !listing)) 211 usage_with_options(probe_usage, options); 212 213 if (listing) { 214 if (session.nr_probe != 0 || session.dellist) { 215 pr_warning(" Error: Don't use --list with" 216 " --add/--del.\n"); 217 usage_with_options(probe_usage, options); 218 } 219 show_perf_probe_events(); 220 return 0; 221 } 222 223 if (session.dellist) { 224 del_trace_kprobe_events(session.dellist); 225 strlist__delete(session.dellist); 226 if (session.nr_probe == 0) 227 return 0; 228 } 229 230 if (session.need_dwarf) 231 #ifdef NO_LIBDWARF 232 die("Debuginfo-analysis is not supported"); 233 #else /* !NO_LIBDWARF */ 234 pr_debug("Some probes require debuginfo.\n"); 235 236 if (session.vmlinux) { 237 pr_debug("Try to open %s.", session.vmlinux); 238 fd = open(session.vmlinux, O_RDONLY); 239 } else 240 fd = open_default_vmlinux(); 241 if (fd < 0) { 242 if (session.need_dwarf) 243 die("Could not open debuginfo file."); 244 245 pr_debug("Could not open vmlinux/module file." 246 " Try to use symbols.\n"); 247 goto end_dwarf; 248 } 249 250 /* Searching probe points */ 251 for (i = 0; i < session.nr_probe; i++) { 252 pp = &session.probes[i]; 253 if (pp->found) 254 continue; 255 256 lseek(fd, SEEK_SET, 0); 257 ret = find_probepoint(fd, pp); 258 if (ret < 0) { 259 if (session.need_dwarf) 260 die("Could not analyze debuginfo."); 261 262 pr_warning("An error occurred in debuginfo analysis. Try to use symbols.\n"); 263 break; 264 } 265 if (ret == 0) /* No error but failed to find probe point. */ 266 die("No probe point found."); 267 } 268 close(fd); 269 270 end_dwarf: 271 #endif /* !NO_LIBDWARF */ 272 273 /* Synthesize probes without dwarf */ 274 for (i = 0; i < session.nr_probe; i++) { 275 pp = &session.probes[i]; 276 if (pp->found) /* This probe is already found. */ 277 continue; 278 279 ret = synthesize_trace_kprobe_event(pp); 280 if (ret == -E2BIG) 281 die("probe point definition becomes too long."); 282 else if (ret < 0) 283 die("Failed to synthesize a probe point."); 284 } 285 286 /* Settng up probe points */ 287 add_trace_kprobe_events(session.probes, session.nr_probe); 288 return 0; 289 } 290 291