blob: f577e141036257d5351969a70be3c7a1b1165211 [file] [log] [blame]
Masami Hiramatsu4ea42b12009-10-08 17:17:38 -04001/*
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"
Masami Hiramatsufa282442009-12-08 17:03:23 -050038#include "util/strlist.h"
Masami Hiramatsue0faa8d2010-03-16 18:05:37 -040039#include "util/symbol.h"
Masami Hiramatsu89c69c02009-10-16 20:08:10 -040040#include "util/debug.h"
Masami Hiramatsu96c96612009-12-16 17:24:00 -050041#include "util/debugfs.h"
Masami Hiramatsu4ea42b12009-10-08 17:17:38 -040042#include "util/parse-options.h"
43#include "util/parse-events.h" /* For debugfs_path */
44#include "util/probe-finder.h"
Masami Hiramatsu50656ee2009-11-30 19:19:58 -050045#include "util/probe-event.h"
Masami Hiramatsu4ea42b12009-10-08 17:17:38 -040046
Masami Hiramatsu4ea42b12009-10-08 17:17:38 -040047#define MAX_PATH_LEN 256
Masami Hiramatsu4ea42b12009-10-08 17:17:38 -040048
49/* Session management structure */
50static struct {
Masami Hiramatsufac13fd2009-12-15 10:31:14 -050051 bool need_dwarf;
52 bool list_events;
Masami Hiramatsud761b082009-12-15 10:32:25 -050053 bool force_add;
Masami Hiramatsu631c9de2010-01-06 09:45:34 -050054 bool show_lines;
Masami Hiramatsu4ea42b12009-10-08 17:17:38 -040055 int nr_probe;
56 struct probe_point probes[MAX_PROBES];
Masami Hiramatsufa282442009-12-08 17:03:23 -050057 struct strlist *dellist;
Masami Hiramatsu631c9de2010-01-06 09:45:34 -050058 struct line_range line_range;
Masami Hiramatsu12a1fad2010-03-16 18:05:44 -040059} params;
Masami Hiramatsu4ea42b12009-10-08 17:17:38 -040060
Masami Hiramatsu4de189f2009-11-30 19:20:17 -050061
Masami Hiramatsu253977b2009-10-27 16:43:10 -040062/* Parse an event definition. Note that any error must die. */
63static void parse_probe_event(const char *str)
Masami Hiramatsu4ea42b12009-10-08 17:17:38 -040064{
Masami Hiramatsu12a1fad2010-03-16 18:05:44 -040065 struct probe_point *pp = &params.probes[params.nr_probe];
Masami Hiramatsu4ea42b12009-10-08 17:17:38 -040066
Masami Hiramatsu12a1fad2010-03-16 18:05:44 -040067 pr_debug("probe-definition(%d): %s\n", params.nr_probe, str);
68 if (++params.nr_probe == MAX_PROBES)
Masami Hiramatsu50656ee2009-11-30 19:19:58 -050069 die("Too many probes (> %d) are specified.", MAX_PROBES);
Masami Hiramatsu4ea42b12009-10-08 17:17:38 -040070
Masami Hiramatsu50656ee2009-11-30 19:19:58 -050071 /* Parse perf-probe event into probe_point */
Masami Hiramatsu12a1fad2010-03-16 18:05:44 -040072 parse_perf_probe_event(str, pp, &params.need_dwarf);
Masami Hiramatsu23e8ec02009-10-07 18:28:30 -040073
Arnaldo Carvalho de Melob7cb10e2009-10-21 17:34:06 -020074 pr_debug("%d arguments\n", pp->nr_args);
Masami Hiramatsu46ab4922009-10-27 16:43:02 -040075}
76
Masami Hiramatsud1bde3f2009-12-08 17:02:54 -050077static void parse_probe_event_argv(int argc, const char **argv)
78{
79 int i, len;
80 char *buf;
81
82 /* Bind up rest arguments */
83 len = 0;
84 for (i = 0; i < argc; i++)
85 len += strlen(argv[i]) + 1;
Masami Hiramatsu31facc52010-03-16 18:05:30 -040086 buf = xzalloc(len + 1);
Masami Hiramatsud1bde3f2009-12-08 17:02:54 -050087 len = 0;
88 for (i = 0; i < argc; i++)
89 len += sprintf(&buf[len], "%s ", argv[i]);
90 parse_probe_event(buf);
91 free(buf);
92}
93
Masami Hiramatsu253977b2009-10-27 16:43:10 -040094static int opt_add_probe_event(const struct option *opt __used,
Masami Hiramatsu46ab4922009-10-27 16:43:02 -040095 const char *str, int unset __used)
96{
97 if (str)
Masami Hiramatsu253977b2009-10-27 16:43:10 -040098 parse_probe_event(str);
Masami Hiramatsu4ea42b12009-10-08 17:17:38 -040099 return 0;
100}
101
Masami Hiramatsufa282442009-12-08 17:03:23 -0500102static int opt_del_probe_event(const struct option *opt __used,
103 const char *str, int unset __used)
104{
105 if (str) {
Masami Hiramatsu12a1fad2010-03-16 18:05:44 -0400106 if (!params.dellist)
107 params.dellist = strlist__new(true, NULL);
108 strlist__add(params.dellist, str);
Masami Hiramatsufa282442009-12-08 17:03:23 -0500109 }
110 return 0;
111}
112
Masami Hiramatsu804b3602010-02-25 08:35:42 -0500113#ifndef NO_DWARF_SUPPORT
Hitoshi Mitake0eda7382010-01-16 21:31:16 +0900114static int opt_show_lines(const struct option *opt __used,
115 const char *str, int unset __used)
116{
117 if (str)
Masami Hiramatsu12a1fad2010-03-16 18:05:44 -0400118 parse_line_range_desc(str, &params.line_range);
119 INIT_LIST_HEAD(&params.line_range.line_list);
120 params.show_lines = true;
Hitoshi Mitake0eda7382010-01-16 21:31:16 +0900121 return 0;
122}
Masami Hiramatsu23e8ec02009-10-07 18:28:30 -0400123#endif
Masami Hiramatsu4ea42b12009-10-08 17:17:38 -0400124
125static const char * const probe_usage[] = {
Masami Hiramatsu46ab4922009-10-27 16:43:02 -0400126 "perf probe [<options>] 'PROBEDEF' ['PROBEDEF' ...]",
127 "perf probe [<options>] --add 'PROBEDEF' [--add 'PROBEDEF' ...]",
Masami Hiramatsufa282442009-12-08 17:03:23 -0500128 "perf probe [<options>] --del '[GROUP:]EVENT' ...",
Masami Hiramatsu4de189f2009-11-30 19:20:17 -0500129 "perf probe --list",
Masami Hiramatsu804b3602010-02-25 08:35:42 -0500130#ifndef NO_DWARF_SUPPORT
Masami Hiramatsu631c9de2010-01-06 09:45:34 -0500131 "perf probe --line 'LINEDESC'",
Masami Hiramatsuf3ab4812010-02-25 08:35:12 -0500132#endif
Masami Hiramatsu4ea42b12009-10-08 17:17:38 -0400133 NULL
134};
135
136static const struct option options[] = {
Masami Hiramatsu89c69c02009-10-16 20:08:10 -0400137 OPT_BOOLEAN('v', "verbose", &verbose,
138 "be more verbose (show parsed arguments, etc)"),
Masami Hiramatsu804b3602010-02-25 08:35:42 -0500139#ifndef NO_DWARF_SUPPORT
Arnaldo Carvalho de Melo75be6cf2009-12-15 20:04:39 -0200140 OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name,
Masami Hiramatsua1281682009-12-15 10:32:33 -0500141 "file", "vmlinux pathname"),
Masami Hiramatsu23e8ec02009-10-07 18:28:30 -0400142#endif
Masami Hiramatsu12a1fad2010-03-16 18:05:44 -0400143 OPT_BOOLEAN('l', "list", &params.list_events,
Masami Hiramatsufac13fd2009-12-15 10:31:14 -0500144 "list up current probe events"),
Masami Hiramatsufa282442009-12-08 17:03:23 -0500145 OPT_CALLBACK('d', "del", NULL, "[GROUP:]EVENT", "delete a probe event.",
146 opt_del_probe_event),
Masami Hiramatsu46ab4922009-10-27 16:43:02 -0400147 OPT_CALLBACK('a', "add", NULL,
Masami Hiramatsu804b3602010-02-25 08:35:42 -0500148#ifdef NO_DWARF_SUPPORT
Masami Hiramatsu2a9c8c32010-02-25 08:36:12 -0500149 "[EVENT=]FUNC[+OFF|%return] [ARG ...]",
Masami Hiramatsu23e8ec02009-10-07 18:28:30 -0400150#else
Masami Hiramatsu32cb0dd2010-03-03 22:38:43 -0500151 "[EVENT=]FUNC[@SRC][+OFF|%return|:RL|;PT]|SRC:AL|SRC;PT"
Masami Hiramatsu2a9c8c32010-02-25 08:36:12 -0500152 " [ARG ...]",
Masami Hiramatsu23e8ec02009-10-07 18:28:30 -0400153#endif
Masami Hiramatsu4ea42b12009-10-08 17:17:38 -0400154 "probe point definition, where\n"
Masami Hiramatsuaf663d72009-12-15 10:32:18 -0500155 "\t\tGROUP:\tGroup name (optional)\n"
156 "\t\tEVENT:\tEvent name\n"
Masami Hiramatsu4ea42b12009-10-08 17:17:38 -0400157 "\t\tFUNC:\tFunction name\n"
Masami Hiramatsu2a9c8c32010-02-25 08:36:12 -0500158 "\t\tOFF:\tOffset from function entry (in byte)\n"
Masami Hiramatsu253977b2009-10-27 16:43:10 -0400159 "\t\t%return:\tPut the probe at function return\n"
Masami Hiramatsu804b3602010-02-25 08:35:42 -0500160#ifdef NO_DWARF_SUPPORT
Masami Hiramatsu23e8ec02009-10-07 18:28:30 -0400161 "\t\tARG:\tProbe argument (only \n"
162#else
Masami Hiramatsu4ea42b12009-10-08 17:17:38 -0400163 "\t\tSRC:\tSource code path\n"
Masami Hiramatsu2a9c8c32010-02-25 08:36:12 -0500164 "\t\tRL:\tRelative line number from function entry.\n"
165 "\t\tAL:\tAbsolute line number in file.\n"
166 "\t\tPT:\tLazy expression of line code.\n"
Masami Hiramatsu4ea42b12009-10-08 17:17:38 -0400167 "\t\tARG:\tProbe argument (local variable name or\n"
Masami Hiramatsu23e8ec02009-10-07 18:28:30 -0400168#endif
Masami Hiramatsu50656ee2009-11-30 19:19:58 -0500169 "\t\t\tkprobe-tracer argument format.)\n",
Masami Hiramatsu253977b2009-10-27 16:43:10 -0400170 opt_add_probe_event),
Masami Hiramatsu12a1fad2010-03-16 18:05:44 -0400171 OPT_BOOLEAN('f', "force", &params.force_add, "forcibly add events"
Masami Hiramatsud761b082009-12-15 10:32:25 -0500172 " with existing name"),
Masami Hiramatsu804b3602010-02-25 08:35:42 -0500173#ifndef NO_DWARF_SUPPORT
Masami Hiramatsu631c9de2010-01-06 09:45:34 -0500174 OPT_CALLBACK('L', "line", NULL,
175 "FUNC[:RLN[+NUM|:RLN2]]|SRC:ALN[+NUM|:ALN2]",
176 "Show source code lines.", opt_show_lines),
177#endif
Masami Hiramatsu4ea42b12009-10-08 17:17:38 -0400178 OPT_END()
179};
180
Masami Hiramatsu4ea42b12009-10-08 17:17:38 -0400181int cmd_probe(int argc, const char **argv, const char *prefix __used)
182{
Masami Hiramatsu4ea42b12009-10-08 17:17:38 -0400183 argc = parse_options(argc, argv, options, probe_usage,
Masami Hiramatsu46ab4922009-10-27 16:43:02 -0400184 PARSE_OPT_STOP_AT_NON_OPTION);
Masami Hiramatsuce11a602009-12-15 10:31:28 -0500185 if (argc > 0) {
186 if (strcmp(argv[0], "-") == 0) {
187 pr_warning(" Error: '-' is not supported.\n");
188 usage_with_options(probe_usage, options);
189 }
Masami Hiramatsud1bde3f2009-12-08 17:02:54 -0500190 parse_probe_event_argv(argc, argv);
Masami Hiramatsuce11a602009-12-15 10:31:28 -0500191 }
Masami Hiramatsu46ab4922009-10-27 16:43:02 -0400192
Masami Hiramatsu12a1fad2010-03-16 18:05:44 -0400193 if ((!params.nr_probe && !params.dellist && !params.list_events &&
194 !params.show_lines))
Masami Hiramatsu4ea42b12009-10-08 17:17:38 -0400195 usage_with_options(probe_usage, options);
196
Masami Hiramatsu96c96612009-12-16 17:24:00 -0500197 if (debugfs_valid_mountpoint(debugfs_path) < 0)
198 die("Failed to find debugfs path.");
199
Masami Hiramatsu12a1fad2010-03-16 18:05:44 -0400200 if (params.list_events) {
201 if (params.nr_probe != 0 || params.dellist) {
Masami Hiramatsufa282442009-12-08 17:03:23 -0500202 pr_warning(" Error: Don't use --list with"
203 " --add/--del.\n");
204 usage_with_options(probe_usage, options);
205 }
Masami Hiramatsu12a1fad2010-03-16 18:05:44 -0400206 if (params.show_lines) {
Masami Hiramatsu631c9de2010-01-06 09:45:34 -0500207 pr_warning(" Error: Don't use --list with --line.\n");
208 usage_with_options(probe_usage, options);
209 }
Masami Hiramatsu4de189f2009-11-30 19:20:17 -0500210 show_perf_probe_events();
211 return 0;
212 }
213
Masami Hiramatsu804b3602010-02-25 08:35:42 -0500214#ifndef NO_DWARF_SUPPORT
Masami Hiramatsu12a1fad2010-03-16 18:05:44 -0400215 if (params.show_lines) {
216 if (params.nr_probe != 0 || params.dellist) {
Masami Hiramatsu631c9de2010-01-06 09:45:34 -0500217 pr_warning(" Error: Don't use --line with"
218 " --add/--del.\n");
219 usage_with_options(probe_usage, options);
220 }
Masami Hiramatsue0faa8d2010-03-16 18:05:37 -0400221
Masami Hiramatsu12a1fad2010-03-16 18:05:44 -0400222 show_line_range(&params.line_range);
Masami Hiramatsu631c9de2010-01-06 09:45:34 -0500223 return 0;
224 }
225#endif
226
Masami Hiramatsu12a1fad2010-03-16 18:05:44 -0400227 if (params.dellist) {
228 del_trace_kprobe_events(params.dellist);
229 strlist__delete(params.dellist);
230 if (params.nr_probe == 0)
Masami Hiramatsufa282442009-12-08 17:03:23 -0500231 return 0;
232 }
233
Masami Hiramatsu12a1fad2010-03-16 18:05:44 -0400234 add_trace_kprobe_events(params.probes, params.nr_probe,
235 params.force_add, params.need_dwarf);
Masami Hiramatsu4ea42b12009-10-08 17:17:38 -0400236 return 0;
237}
238