aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/builtin-probe.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/builtin-probe.c')
-rw-r--r--tools/perf/builtin-probe.c126
1 files changed, 89 insertions, 37 deletions
diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c
index c1e6774fd3e..c30a3359234 100644
--- a/tools/perf/builtin-probe.c
+++ b/tools/perf/builtin-probe.c
@@ -41,7 +41,6 @@
41#include "util/debugfs.h" 41#include "util/debugfs.h"
42#include "util/symbol.h" 42#include "util/symbol.h"
43#include "util/thread.h" 43#include "util/thread.h"
44#include "util/session.h"
45#include "util/parse-options.h" 44#include "util/parse-options.h"
46#include "util/parse-events.h" /* For debugfs_path */ 45#include "util/parse-events.h" /* For debugfs_path */
47#include "util/probe-finder.h" 46#include "util/probe-finder.h"
@@ -55,11 +54,13 @@ static struct {
55 bool need_dwarf; 54 bool need_dwarf;
56 bool list_events; 55 bool list_events;
57 bool force_add; 56 bool force_add;
57 bool show_lines;
58 int nr_probe; 58 int nr_probe;
59 struct probe_point probes[MAX_PROBES]; 59 struct probe_point probes[MAX_PROBES];
60 struct strlist *dellist; 60 struct strlist *dellist;
61 struct perf_session *psession; 61 struct map_groups kmap_groups;
62 struct map *kmap; 62 struct map *kmaps[MAP__NR_TYPES];
63 struct line_range line_range;
63} session; 64} session;
64 65
65 66
@@ -120,22 +121,33 @@ static int opt_del_probe_event(const struct option *opt __used,
120static void evaluate_probe_point(struct probe_point *pp) 121static void evaluate_probe_point(struct probe_point *pp)
121{ 122{
122 struct symbol *sym; 123 struct symbol *sym;
123 sym = map__find_symbol_by_name(session.kmap, pp->function, 124 sym = map__find_symbol_by_name(session.kmaps[MAP__FUNCTION],
124 session.psession, NULL); 125 pp->function, NULL);
125 if (!sym) 126 if (!sym)
126 die("Kernel symbol \'%s\' not found - probe not added.", 127 die("Kernel symbol \'%s\' not found - probe not added.",
127 pp->function); 128 pp->function);
128} 129}
129 130
130#ifndef NO_LIBDWARF 131#ifndef NO_DWARF_SUPPORT
131static int open_vmlinux(void) 132static int open_vmlinux(void)
132{ 133{
133 if (map__load(session.kmap, session.psession, NULL) < 0) { 134 if (map__load(session.kmaps[MAP__FUNCTION], NULL) < 0) {
134 pr_debug("Failed to load kernel map.\n"); 135 pr_debug("Failed to load kernel map.\n");
135 return -EINVAL; 136 return -EINVAL;
136 } 137 }
137 pr_debug("Try to open %s\n", session.kmap->dso->long_name); 138 pr_debug("Try to open %s\n",
138 return open(session.kmap->dso->long_name, O_RDONLY); 139 session.kmaps[MAP__FUNCTION]->dso->long_name);
140 return open(session.kmaps[MAP__FUNCTION]->dso->long_name, O_RDONLY);
141}
142
143static 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;
139} 151}
140#endif 152#endif
141 153
@@ -144,13 +156,16 @@ static const char * const probe_usage[] = {
144 "perf probe [<options>] --add 'PROBEDEF' [--add 'PROBEDEF' ...]", 156 "perf probe [<options>] --add 'PROBEDEF' [--add 'PROBEDEF' ...]",
145 "perf probe [<options>] --del '[GROUP:]EVENT' ...", 157 "perf probe [<options>] --del '[GROUP:]EVENT' ...",
146 "perf probe --list", 158 "perf probe --list",
159#ifndef NO_DWARF_SUPPORT
160 "perf probe --line 'LINEDESC'",
161#endif
147 NULL 162 NULL
148}; 163};
149 164
150static const struct option options[] = { 165static const struct option options[] = {
151 OPT_BOOLEAN('v', "verbose", &verbose, 166 OPT_BOOLEAN('v', "verbose", &verbose,
152 "be more verbose (show parsed arguments, etc)"), 167 "be more verbose (show parsed arguments, etc)"),
153#ifndef NO_LIBDWARF 168#ifndef NO_DWARF_SUPPORT
154 OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name, 169 OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name,
155 "file", "vmlinux pathname"), 170 "file", "vmlinux pathname"),
156#endif 171#endif
@@ -159,36 +174,60 @@ static const struct option options[] = {
159 OPT_CALLBACK('d', "del", NULL, "[GROUP:]EVENT", "delete a probe event.", 174 OPT_CALLBACK('d', "del", NULL, "[GROUP:]EVENT", "delete a probe event.",
160 opt_del_probe_event), 175 opt_del_probe_event),
161 OPT_CALLBACK('a', "add", NULL, 176 OPT_CALLBACK('a', "add", NULL,
162#ifdef NO_LIBDWARF 177#ifdef NO_DWARF_SUPPORT
163 "[EVENT=]FUNC[+OFFS|%return] [ARG ...]", 178 "[EVENT=]FUNC[+OFF|%return] [ARG ...]",
164#else 179#else
165 "[EVENT=]FUNC[+OFFS|%return|:RLN][@SRC]|SRC:ALN [ARG ...]", 180 "[EVENT=]FUNC[@SRC][+OFF|%return|:RL|;PT]|SRC:AL|SRC;PT"
181 " [ARG ...]",
166#endif 182#endif
167 "probe point definition, where\n" 183 "probe point definition, where\n"
168 "\t\tGROUP:\tGroup name (optional)\n" 184 "\t\tGROUP:\tGroup name (optional)\n"
169 "\t\tEVENT:\tEvent name\n" 185 "\t\tEVENT:\tEvent name\n"
170 "\t\tFUNC:\tFunction name\n" 186 "\t\tFUNC:\tFunction name\n"
171 "\t\tOFFS:\tOffset from function entry (in byte)\n" 187 "\t\tOFF:\tOffset from function entry (in byte)\n"
172 "\t\t%return:\tPut the probe at function return\n" 188 "\t\t%return:\tPut the probe at function return\n"
173#ifdef NO_LIBDWARF 189#ifdef NO_DWARF_SUPPORT
174 "\t\tARG:\tProbe argument (only \n" 190 "\t\tARG:\tProbe argument (only \n"
175#else 191#else
176 "\t\tSRC:\tSource code path\n" 192 "\t\tSRC:\tSource code path\n"
177 "\t\tRLN:\tRelative line number from function entry.\n" 193 "\t\tRL:\tRelative line number from function entry.\n"
178 "\t\tALN:\tAbsolute line number in file.\n" 194 "\t\tAL:\tAbsolute line number in file.\n"
195 "\t\tPT:\tLazy expression of line code.\n"
179 "\t\tARG:\tProbe argument (local variable name or\n" 196 "\t\tARG:\tProbe argument (local variable name or\n"
180#endif 197#endif
181 "\t\t\tkprobe-tracer argument format.)\n", 198 "\t\t\tkprobe-tracer argument format.)\n",
182 opt_add_probe_event), 199 opt_add_probe_event),
183 OPT_BOOLEAN('f', "force", &session.force_add, "forcibly add events" 200 OPT_BOOLEAN('f', "force", &session.force_add, "forcibly add events"
184 " with existing name"), 201 " with existing name"),
202#ifndef NO_DWARF_SUPPORT
203 OPT_CALLBACK('L', "line", NULL,
204 "FUNC[:RLN[+NUM|:RLN2]]|SRC:ALN[+NUM|:ALN2]",
205 "Show source code lines.", opt_show_lines),
206#endif
185 OPT_END() 207 OPT_END()
186}; 208};
187 209
210/* Initialize symbol maps for vmlinux */
211static void init_vmlinux(void)
212{
213 symbol_conf.sort_by_name = true;
214 if (symbol_conf.vmlinux_name == NULL)
215 symbol_conf.try_vmlinux_path = true;
216 else
217 pr_debug("Use vmlinux: %s\n", symbol_conf.vmlinux_name);
218 if (symbol__init() < 0)
219 die("Failed to init symbol map.");
220
221 map_groups__init(&session.kmap_groups);
222 if (map_groups__create_kernel_maps(&session.kmap_groups,
223 session.kmaps) < 0)
224 die("Failed to create kernel maps.");
225}
226
188int cmd_probe(int argc, const char **argv, const char *prefix __used) 227int cmd_probe(int argc, const char **argv, const char *prefix __used)
189{ 228{
190 int i, ret; 229 int i, ret;
191#ifndef NO_LIBDWARF 230#ifndef NO_DWARF_SUPPORT
192 int fd; 231 int fd;
193#endif 232#endif
194 struct probe_point *pp; 233 struct probe_point *pp;
@@ -203,7 +242,8 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used)
203 parse_probe_event_argv(argc, argv); 242 parse_probe_event_argv(argc, argv);
204 } 243 }
205 244
206 if ((!session.nr_probe && !session.dellist && !session.list_events)) 245 if ((!session.nr_probe && !session.dellist && !session.list_events &&
246 !session.show_lines))
207 usage_with_options(probe_usage, options); 247 usage_with_options(probe_usage, options);
208 248
209 if (debugfs_valid_mountpoint(debugfs_path) < 0) 249 if (debugfs_valid_mountpoint(debugfs_path) < 0)
@@ -215,10 +255,34 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used)
215 " --add/--del.\n"); 255 " --add/--del.\n");
216 usage_with_options(probe_usage, options); 256 usage_with_options(probe_usage, options);
217 } 257 }
258 if (session.show_lines) {
259 pr_warning(" Error: Don't use --list with --line.\n");
260 usage_with_options(probe_usage, options);
261 }
218 show_perf_probe_events(); 262 show_perf_probe_events();
219 return 0; 263 return 0;
220 } 264 }
221 265
266#ifndef NO_DWARF_SUPPORT
267 if (session.show_lines) {
268 if (session.nr_probe != 0 || session.dellist) {
269 pr_warning(" Error: Don't use --line with"
270 " --add/--del.\n");
271 usage_with_options(probe_usage, options);
272 }
273 init_vmlinux();
274 fd = open_vmlinux();
275 if (fd < 0)
276 die("Could not open debuginfo file.");
277 ret = find_line_range(fd, &session.line_range);
278 if (ret <= 0)
279 die("Source line is not found.\n");
280 close(fd);
281 show_line_range(&session.line_range);
282 return 0;
283 }
284#endif
285
222 if (session.dellist) { 286 if (session.dellist) {
223 del_trace_kprobe_events(session.dellist); 287 del_trace_kprobe_events(session.dellist);
224 strlist__delete(session.dellist); 288 strlist__delete(session.dellist);
@@ -226,25 +290,13 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used)
226 return 0; 290 return 0;
227 } 291 }
228 292
229 /* Initialize symbol maps for vmlinux */ 293 /* Add probes */
230 symbol_conf.sort_by_name = true; 294 init_vmlinux();
231 if (symbol_conf.vmlinux_name == NULL)
232 symbol_conf.try_vmlinux_path = true;
233 if (symbol__init() < 0)
234 die("Failed to init symbol map.");
235 session.psession = perf_session__new(NULL, O_WRONLY, false);
236 if (session.psession == NULL)
237 die("Failed to init perf_session.");
238 session.kmap = map_groups__find_by_name(&session.psession->kmaps,
239 MAP__FUNCTION,
240 "[kernel.kallsyms]");
241 if (!session.kmap)
242 die("Could not find kernel map.\n");
243 295
244 if (session.need_dwarf) 296 if (session.need_dwarf)
245#ifdef NO_LIBDWARF 297#ifdef NO_DWARF_SUPPORT
246 die("Debuginfo-analysis is not supported"); 298 die("Debuginfo-analysis is not supported");
247#else /* !NO_LIBDWARF */ 299#else /* !NO_DWARF_SUPPORT */
248 pr_debug("Some probes require debuginfo.\n"); 300 pr_debug("Some probes require debuginfo.\n");
249 301
250 fd = open_vmlinux(); 302 fd = open_vmlinux();
@@ -264,7 +316,7 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used)
264 continue; 316 continue;
265 317
266 lseek(fd, SEEK_SET, 0); 318 lseek(fd, SEEK_SET, 0);
267 ret = find_probepoint(fd, pp); 319 ret = find_probe_point(fd, pp);
268 if (ret > 0) 320 if (ret > 0)
269 continue; 321 continue;
270 if (ret == 0) { /* No error but failed to find probe point. */ 322 if (ret == 0) { /* No error but failed to find probe point. */
@@ -285,7 +337,7 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used)
285 close(fd); 337 close(fd);
286 338
287end_dwarf: 339end_dwarf:
288#endif /* !NO_LIBDWARF */ 340#endif /* !NO_DWARF_SUPPORT */
289 341
290 /* Synthesize probes without dwarf */ 342 /* Synthesize probes without dwarf */
291 for (i = 0; i < session.nr_probe; i++) { 343 for (i = 0; i < session.nr_probe; i++) {