aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/builtin-probe.c
diff options
context:
space:
mode:
authorMasami Hiramatsu <mhiramat@redhat.com>2010-01-06 09:45:34 -0500
committerIngo Molnar <mingo@elte.hu>2010-01-13 04:09:14 -0500
commit631c9def804b2c92b5cca04fb9ff7b5df9e35094 (patch)
tree3ce09a1894f765bbea6538335ef11950287d66ee /tools/perf/builtin-probe.c
parent6964cd2c8efe6e048401f1fe3952a06c563c34c1 (diff)
perf probe: Support --line option to show probable source-code lines
Add --line option to support showing probable source-code lines. perf probe --line SRC:LN[-LN|+NUM] or perf probe --line FUNC[:LN[-LN|+NUM]] This option shows source-code with line number if the line can be probed. Lines without line number (and blue color) means that the line can not be probed, because debuginfo doesn't have the information of those lines. The argument specifies the range of lines, "source.c:100-120" shows lines between 100th to l20th in source.c file. And "func:10+20" shows 20 lines from 10th line of func function. e.g. # ./perf probe --line kernel/sched.c:1080 <kernel/sched.c:1080> * * called with rq->lock held and irqs disabled */ static void hrtick_start(struct rq *rq, u64 delay) { struct hrtimer *timer = &rq->hrtick_timer; 1086 ktime_t time = ktime_add_ns(timer->base->get_time(), delay); hrtimer_set_expires(timer, time); 1090 if (rq == this_rq()) { 1091 hrtimer_restart(timer); 1092 } else if (!rq->hrtick_csd_pending) { 1093 __smp_call_function_single(cpu_of(rq), &rq->hrtick_csd, 1094 rq->hrtick_csd_pending = 1; If you specifying function name, this shows function-relative line number. # ./perf probe --line schedule <schedule:0> asmlinkage void __sched schedule(void) 1 { struct task_struct *prev, *next; unsigned long *switch_count; struct rq *rq; int cpu; need_resched: preempt_disable(); 9 cpu = smp_processor_id(); 10 rq = cpu_rq(cpu); 11 rcu_sched_qs(cpu); 12 prev = rq->curr; 13 switch_count = &prev->nivcsw; Signed-off-by: Masami Hiramatsu <mhiramat@redhat.com> Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: systemtap <systemtap@sources.redhat.com> Cc: DLE <dle-develop@lists.sourceforge.net> Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: Paul Mackerras <paulus@samba.org> Cc: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Mike Galbraith <efault@gmx.de> LKML-Reference: <20100106144534.27218.77939.stgit@dhcp-100-2-132.bos.redhat.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'tools/perf/builtin-probe.c')
-rw-r--r--tools/perf/builtin-probe.c76
1 files changed, 63 insertions, 13 deletions
diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c
index ffdd3fe87b4a..1d3a99ea5ce1 100644
--- a/tools/perf/builtin-probe.c
+++ b/tools/perf/builtin-probe.c
@@ -55,11 +55,13 @@ static struct {
55 bool need_dwarf; 55 bool need_dwarf;
56 bool list_events; 56 bool list_events;
57 bool force_add; 57 bool force_add;
58 bool show_lines;
58 int nr_probe; 59 int nr_probe;
59 struct probe_point probes[MAX_PROBES]; 60 struct probe_point probes[MAX_PROBES];
60 struct strlist *dellist; 61 struct strlist *dellist;
61 struct perf_session *psession; 62 struct perf_session *psession;
62 struct map *kmap; 63 struct map *kmap;
64 struct line_range line_range;
63} session; 65} session;
64 66
65 67
@@ -116,6 +118,15 @@ static int opt_del_probe_event(const struct option *opt __used,
116 return 0; 118 return 0;
117} 119}
118 120
121static int opt_show_lines(const struct option *opt __used,
122 const char *str, int unset __used)
123{
124 if (str)
125 parse_line_range_desc(str, &session.line_range);
126 INIT_LIST_HEAD(&session.line_range.line_list);
127 session.show_lines = true;
128 return 0;
129}
119/* Currently just checking function name from symbol map */ 130/* Currently just checking function name from symbol map */
120static void evaluate_probe_point(struct probe_point *pp) 131static void evaluate_probe_point(struct probe_point *pp)
121{ 132{
@@ -144,6 +155,7 @@ static const char * const probe_usage[] = {
144 "perf probe [<options>] --add 'PROBEDEF' [--add 'PROBEDEF' ...]", 155 "perf probe [<options>] --add 'PROBEDEF' [--add 'PROBEDEF' ...]",
145 "perf probe [<options>] --del '[GROUP:]EVENT' ...", 156 "perf probe [<options>] --del '[GROUP:]EVENT' ...",
146 "perf probe --list", 157 "perf probe --list",
158 "perf probe --line 'LINEDESC'",
147 NULL 159 NULL
148}; 160};
149 161
@@ -182,9 +194,32 @@ static const struct option options[] = {
182 opt_add_probe_event), 194 opt_add_probe_event),
183 OPT_BOOLEAN('f', "force", &session.force_add, "forcibly add events" 195 OPT_BOOLEAN('f', "force", &session.force_add, "forcibly add events"
184 " with existing name"), 196 " with existing name"),
197#ifndef NO_LIBDWARF
198 OPT_CALLBACK('L', "line", NULL,
199 "FUNC[:RLN[+NUM|:RLN2]]|SRC:ALN[+NUM|:ALN2]",
200 "Show source code lines.", opt_show_lines),
201#endif
185 OPT_END() 202 OPT_END()
186}; 203};
187 204
205/* Initialize symbol maps for vmlinux */
206static void init_vmlinux(void)
207{
208 symbol_conf.sort_by_name = true;
209 if (symbol_conf.vmlinux_name == NULL)
210 symbol_conf.try_vmlinux_path = true;
211 else
212 pr_debug("Use vmlinux: %s\n", symbol_conf.vmlinux_name);
213 if (symbol__init() < 0)
214 die("Failed to init symbol map.");
215 session.psession = perf_session__new(NULL, O_WRONLY, false);
216 if (session.psession == NULL)
217 die("Failed to init perf_session.");
218 session.kmap = session.psession->vmlinux_maps[MAP__FUNCTION];
219 if (!session.kmap)
220 die("Could not find kernel map.\n");
221}
222
188int cmd_probe(int argc, const char **argv, const char *prefix __used) 223int cmd_probe(int argc, const char **argv, const char *prefix __used)
189{ 224{
190 int i, ret; 225 int i, ret;
@@ -203,7 +238,8 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used)
203 parse_probe_event_argv(argc, argv); 238 parse_probe_event_argv(argc, argv);
204 } 239 }
205 240
206 if ((!session.nr_probe && !session.dellist && !session.list_events)) 241 if ((!session.nr_probe && !session.dellist && !session.list_events &&
242 !session.show_lines))
207 usage_with_options(probe_usage, options); 243 usage_with_options(probe_usage, options);
208 244
209 if (debugfs_valid_mountpoint(debugfs_path) < 0) 245 if (debugfs_valid_mountpoint(debugfs_path) < 0)
@@ -215,10 +251,34 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used)
215 " --add/--del.\n"); 251 " --add/--del.\n");
216 usage_with_options(probe_usage, options); 252 usage_with_options(probe_usage, options);
217 } 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 }
218 show_perf_probe_events(); 258 show_perf_probe_events();
219 return 0; 259 return 0;
220 } 260 }
221 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
222 if (session.dellist) { 282 if (session.dellist) {
223 del_trace_kprobe_events(session.dellist); 283 del_trace_kprobe_events(session.dellist);
224 strlist__delete(session.dellist); 284 strlist__delete(session.dellist);
@@ -226,18 +286,8 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used)
226 return 0; 286 return 0;
227 } 287 }
228 288
229 /* Initialize symbol maps for vmlinux */ 289 /* Add probes */
230 symbol_conf.sort_by_name = true; 290 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 = session.psession->vmlinux_maps[MAP__FUNCTION];
239 if (!session.kmap)
240 die("Could not find kernel map.\n");
241 291
242 if (session.need_dwarf) 292 if (session.need_dwarf)
243#ifdef NO_LIBDWARF 293#ifdef NO_LIBDWARF