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/debugfs.h" 42 #include "util/symbol.h" 43 #include "util/thread.h" 44 #include "util/parse-options.h" 45 #include "util/parse-events.h" /* For debugfs_path */ 46 #include "util/probe-finder.h" 47 #include "util/probe-event.h" 48 49 #define MAX_PATH_LEN 256 50 #define MAX_PROBES 128 51 52 /* Session management structure */ 53 static struct { 54 bool need_dwarf; 55 bool list_events; 56 bool force_add; 57 bool show_lines; 58 int nr_probe; 59 struct probe_point probes[MAX_PROBES]; 60 struct strlist *dellist; 61 struct map_groups kmap_groups; 62 struct map *kmaps[MAP__NR_TYPES]; 63 struct line_range line_range; 64 } session; 65 66 67 /* Parse an event definition. Note that any error must die. */ 68 static void parse_probe_event(const char *str) 69 { 70 struct probe_point *pp = &session.probes[session.nr_probe]; 71 72 pr_debug("probe-definition(%d): %s\n", session.nr_probe, str); 73 if (++session.nr_probe == MAX_PROBES) 74 die("Too many probes (> %d) are specified.", MAX_PROBES); 75 76 /* Parse perf-probe event into probe_point */ 77 parse_perf_probe_event(str, pp, &session.need_dwarf); 78 79 pr_debug("%d arguments\n", pp->nr_args); 80 } 81 82 static void parse_probe_event_argv(int argc, const char **argv) 83 { 84 int i, len; 85 char *buf; 86 87 /* Bind up rest arguments */ 88 len = 0; 89 for (i = 0; i < argc; i++) 90 len += strlen(argv[i]) + 1; 91 buf = zalloc(len + 1); 92 if (!buf) 93 die("Failed to allocate memory for binding arguments."); 94 len = 0; 95 for (i = 0; i < argc; i++) 96 len += sprintf(&buf[len], "%s ", argv[i]); 97 parse_probe_event(buf); 98 free(buf); 99 } 100 101 static int opt_add_probe_event(const struct option *opt __used, 102 const char *str, int unset __used) 103 { 104 if (str) 105 parse_probe_event(str); 106 return 0; 107 } 108 109 static int opt_del_probe_event(const struct option *opt __used, 110 const char *str, int unset __used) 111 { 112 if (str) { 113 if (!session.dellist) 114 session.dellist = strlist__new(true, NULL); 115 strlist__add(session.dellist, str); 116 } 117 return 0; 118 } 119 120 /* Currently just checking function name from symbol map */ 121 static void evaluate_probe_point(struct probe_point *pp) 122 { 123 struct symbol *sym; 124 sym = map__find_symbol_by_name(session.kmaps[MAP__FUNCTION], 125 pp->function, NULL); 126 if (!sym) 127 die("Kernel symbol \'%s\' not found - probe not added.", 128 pp->function); 129 } 130 131 #ifndef NO_LIBDWARF 132 static int open_vmlinux(void) 133 { 134 if (map__load(session.kmaps[MAP__FUNCTION], NULL) < 0) { 135 pr_debug("Failed to load kernel map.\n"); 136 return -EINVAL; 137 } 138 pr_debug("Try to open %s\n", 139 session.kmaps[MAP__FUNCTION]->dso->long_name); 140 return open(session.kmaps[MAP__FUNCTION]->dso->long_name, O_RDONLY); 141 } 142 143 static int opt_show_lines(const struct option *opt __used, 144 const char *str, int unset __used) 145 { 146 if (str) 147 parse_line_range_desc(str, &session.line_range); 148 INIT_LIST_HEAD(&session.line_range.line_list); 149 session.show_lines = true; 150 return 0; 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 "perf probe --line 'LINEDESC'", 160 NULL 161 }; 162 163 static const struct option options[] = { 164 OPT_BOOLEAN('v', "verbose", &verbose, 165 "be more verbose (show parsed arguments, etc)"), 166 #ifndef NO_LIBDWARF 167 OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name, 168 "file", "vmlinux pathname"), 169 #endif 170 OPT_BOOLEAN('l', "list", &session.list_events, 171 "list up current probe events"), 172 OPT_CALLBACK('d', "del", NULL, "[GROUP:]EVENT", "delete a probe event.", 173 opt_del_probe_event), 174 OPT_CALLBACK('a', "add", NULL, 175 #ifdef NO_LIBDWARF 176 "[EVENT=]FUNC[+OFFS|%return] [ARG ...]", 177 #else 178 "[EVENT=]FUNC[+OFFS|%return|:RLN][@SRC]|SRC:ALN [ARG ...]", 179 #endif 180 "probe point definition, where\n" 181 "\t\tGROUP:\tGroup name (optional)\n" 182 "\t\tEVENT:\tEvent name\n" 183 "\t\tFUNC:\tFunction name\n" 184 "\t\tOFFS:\tOffset from function entry (in byte)\n" 185 "\t\t%return:\tPut the probe at function return\n" 186 #ifdef NO_LIBDWARF 187 "\t\tARG:\tProbe argument (only \n" 188 #else 189 "\t\tSRC:\tSource code path\n" 190 "\t\tRLN:\tRelative line number from function entry.\n" 191 "\t\tALN:\tAbsolute line number in file.\n" 192 "\t\tARG:\tProbe argument (local variable name or\n" 193 #endif 194 "\t\t\tkprobe-tracer argument format.)\n", 195 opt_add_probe_event), 196 OPT_BOOLEAN('f', "force", &session.force_add, "forcibly add events" 197 " with existing name"), 198 #ifndef NO_LIBDWARF 199 OPT_CALLBACK('L', "line", NULL, 200 "FUNC[:RLN[+NUM|:RLN2]]|SRC:ALN[+NUM|:ALN2]", 201 "Show source code lines.", opt_show_lines), 202 #endif 203 OPT_END() 204 }; 205 206 /* Initialize symbol maps for vmlinux */ 207 static void init_vmlinux(void) 208 { 209 symbol_conf.sort_by_name = true; 210 if (symbol_conf.vmlinux_name == NULL) 211 symbol_conf.try_vmlinux_path = true; 212 else 213 pr_debug("Use vmlinux: %s\n", symbol_conf.vmlinux_name); 214 if (symbol__init() < 0) 215 die("Failed to init symbol map."); 216 217 map_groups__init(&session.kmap_groups); 218 if (map_groups__create_kernel_maps(&session.kmap_groups, 219 session.kmaps) < 0) 220 die("Failed to create kernel maps."); 221 } 222 223 int cmd_probe(int argc, const char **argv, const char *prefix __used) 224 { 225 int i, ret; 226 #ifndef NO_LIBDWARF 227 int fd; 228 #endif 229 struct probe_point *pp; 230 231 argc = parse_options(argc, argv, options, probe_usage, 232 PARSE_OPT_STOP_AT_NON_OPTION); 233 if (argc > 0) { 234 if (strcmp(argv[0], "-") == 0) { 235 pr_warning(" Error: '-' is not supported.\n"); 236 usage_with_options(probe_usage, options); 237 } 238 parse_probe_event_argv(argc, argv); 239 } 240 241 if ((!session.nr_probe && !session.dellist && !session.list_events && 242 !session.show_lines)) 243 usage_with_options(probe_usage, options); 244 245 if (debugfs_valid_mountpoint(debugfs_path) < 0) 246 die("Failed to find debugfs path."); 247 248 if (session.list_events) { 249 if (session.nr_probe != 0 || session.dellist) { 250 pr_warning(" Error: Don't use --list with" 251 " --add/--del.\n"); 252 usage_with_options(probe_usage, options); 253 } 254 if (session.show_lines) { 255 pr_warning(" Error: Don't use --list with --line.\n"); 256 usage_with_options(probe_usage, options); 257 } 258 show_perf_probe_events(); 259 return 0; 260 } 261 262 #ifndef NO_LIBDWARF 263 if (session.show_lines) { 264 if (session.nr_probe != 0 || session.dellist) { 265 pr_warning(" Error: Don't use --line with" 266 " --add/--del.\n"); 267 usage_with_options(probe_usage, options); 268 } 269 init_vmlinux(); 270 fd = open_vmlinux(); 271 if (fd < 0) 272 die("Could not open debuginfo file."); 273 ret = find_line_range(fd, &session.line_range); 274 if (ret <= 0) 275 die("Source line is not found.\n"); 276 close(fd); 277 show_line_range(&session.line_range); 278 return 0; 279 } 280 #endif 281 282 if (session.dellist) { 283 del_trace_kprobe_events(session.dellist); 284 strlist__delete(session.dellist); 285 if (session.nr_probe == 0) 286 return 0; 287 } 288 289 /* Add probes */ 290 init_vmlinux(); 291 292 if (session.need_dwarf) 293 #ifdef NO_LIBDWARF 294 die("Debuginfo-analysis is not supported"); 295 #else /* !NO_LIBDWARF */ 296 pr_debug("Some probes require debuginfo.\n"); 297 298 fd = open_vmlinux(); 299 if (fd < 0) { 300 if (session.need_dwarf) 301 die("Could not open debuginfo file."); 302 303 pr_debug("Could not open vmlinux/module file." 304 " Try to use symbols.\n"); 305 goto end_dwarf; 306 } 307 308 /* Searching probe points */ 309 for (i = 0; i < session.nr_probe; i++) { 310 pp = &session.probes[i]; 311 if (pp->found) 312 continue; 313 314 lseek(fd, SEEK_SET, 0); 315 ret = find_probepoint(fd, pp); 316 if (ret > 0) 317 continue; 318 if (ret == 0) { /* No error but failed to find probe point. */ 319 synthesize_perf_probe_point(pp); 320 die("Probe point '%s' not found. - probe not added.", 321 pp->probes[0]); 322 } 323 /* Error path */ 324 if (session.need_dwarf) { 325 if (ret == -ENOENT) 326 pr_warning("No dwarf info found in the vmlinux - please rebuild with CONFIG_DEBUG_INFO=y.\n"); 327 die("Could not analyze debuginfo."); 328 } 329 pr_debug("An error occurred in debuginfo analysis." 330 " Try to use symbols.\n"); 331 break; 332 } 333 close(fd); 334 335 end_dwarf: 336 #endif /* !NO_LIBDWARF */ 337 338 /* Synthesize probes without dwarf */ 339 for (i = 0; i < session.nr_probe; i++) { 340 pp = &session.probes[i]; 341 if (pp->found) /* This probe is already found. */ 342 continue; 343 344 evaluate_probe_point(pp); 345 ret = synthesize_trace_kprobe_event(pp); 346 if (ret == -E2BIG) 347 die("probe point definition becomes too long."); 348 else if (ret < 0) 349 die("Failed to synthesize a probe point."); 350 } 351 352 /* Settng up probe points */ 353 add_trace_kprobe_events(session.probes, session.nr_probe, 354 session.force_add); 355 return 0; 356 } 357 358