aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMasami Hiramatsu <masami.hiramatsu.pt@hitachi.com>2010-10-21 06:13:41 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2010-10-21 14:11:44 -0400
commit469b9b88488e89114bb3e9ac5ee7906b7b96123f (patch)
tree9f002195a8b1167eddbe560ac834e6ba2dedb19f
parentfb8c5a56c7ddbc2b0d2ee7a8da60fe1355f75141 (diff)
perf probe: Add basic module support
Add basic module probe support on perf probe. This introduces "--module <MODNAME>" option to perf probe for putting probes and showing lines and variables in the given module. Currently, this supports only probing on running modules. Supporting off-line module probing is the next step. e.g.) [show lines] # ./perf probe --module drm -L drm_vblank_info <drm_vblank_info:0> 0 int drm_vblank_info(struct seq_file *m, void *data) 1 { struct drm_info_node *node = (struct drm_info_node *) m->private 3 struct drm_device *dev = node->minor->dev; ... [show vars] # ./perf probe --module drm -V drm_vblank_info:3 Available variables at drm_vblank_info:3 @<drm_vblank_info+20> (unknown_type) data struct drm_info_node* node struct seq_file* m [put a probe] # ./perf probe --module drm drm_vblank_info:3 node m Add new event: probe:drm_vblank_info (on drm_vblank_info:3 with node m) You can now use it on all perf tools, such as: perf record -e probe:drm_vblank_info -aR sleep 1 [list probes] # ./perf probe -l probe:drm_vblank_info (on drm_vblank_info:3@drivers/gpu/drm/drm_info.c with ... Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Paul Mackerras <paulus@samba.org> Cc: Ingo Molnar <mingo@elte.hu> Cc: Frederic Weisbecker <fweisbec@gmail.com> LKML-Reference: <20101021101341.3542.71638.stgit@ltc236.sdl.hitachi.co.jp> Signed-off-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-rw-r--r--tools/perf/Documentation/perf-probe.txt9
-rw-r--r--tools/perf/builtin-probe.c11
-rw-r--r--tools/perf/util/map.h10
-rw-r--r--tools/perf/util/probe-event.c123
-rw-r--r--tools/perf/util/probe-event.h10
-rw-r--r--tools/perf/util/probe-finder.c142
-rw-r--r--tools/perf/util/probe-finder.h3
7 files changed, 239 insertions, 69 deletions
diff --git a/tools/perf/Documentation/perf-probe.txt b/tools/perf/Documentation/perf-probe.txt
index 148c178a35a..62de1b7f4e7 100644
--- a/tools/perf/Documentation/perf-probe.txt
+++ b/tools/perf/Documentation/perf-probe.txt
@@ -16,9 +16,9 @@ or
16or 16or
17'perf probe' --list 17'perf probe' --list
18or 18or
19'perf probe' --line='FUNC[:RLN[+NUM|:RLN2]]|SRC:ALN[+NUM|:ALN2]' 19'perf probe' [options] --line='FUNC[:RLN[+NUM|:RLN2]]|SRC:ALN[+NUM|:ALN2]'
20or 20or
21'perf probe' [--externs] --vars='PROBEPOINT' 21'perf probe' [options] --vars='PROBEPOINT'
22 22
23DESCRIPTION 23DESCRIPTION
24----------- 24-----------
@@ -33,6 +33,11 @@ OPTIONS
33--vmlinux=PATH:: 33--vmlinux=PATH::
34 Specify vmlinux path which has debuginfo (Dwarf binary). 34 Specify vmlinux path which has debuginfo (Dwarf binary).
35 35
36-m::
37--module=MODNAME::
38 Specify module name in which perf-probe searches probe points
39 or lines.
40
36-s:: 41-s::
37--source=PATH:: 42--source=PATH::
38 Specify path to kernel source. 43 Specify path to kernel source.
diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c
index bdf60cfdf70..2e000c068cc 100644
--- a/tools/perf/builtin-probe.c
+++ b/tools/perf/builtin-probe.c
@@ -57,6 +57,7 @@ static struct {
57 struct perf_probe_event events[MAX_PROBES]; 57 struct perf_probe_event events[MAX_PROBES];
58 struct strlist *dellist; 58 struct strlist *dellist;
59 struct line_range line_range; 59 struct line_range line_range;
60 const char *target_module;
60 int max_probe_points; 61 int max_probe_points;
61} params; 62} params;
62 63
@@ -162,8 +163,8 @@ static const char * const probe_usage[] = {
162 "perf probe [<options>] --del '[GROUP:]EVENT' ...", 163 "perf probe [<options>] --del '[GROUP:]EVENT' ...",
163 "perf probe --list", 164 "perf probe --list",
164#ifdef DWARF_SUPPORT 165#ifdef DWARF_SUPPORT
165 "perf probe --line 'LINEDESC'", 166 "perf probe [<options>] --line 'LINEDESC'",
166 "perf probe [--externs] --vars 'PROBEPOINT'", 167 "perf probe [<options>] --vars 'PROBEPOINT'",
167#endif 168#endif
168 NULL 169 NULL
169}; 170};
@@ -214,6 +215,8 @@ static const struct option options[] = {
214 "file", "vmlinux pathname"), 215 "file", "vmlinux pathname"),
215 OPT_STRING('s', "source", &symbol_conf.source_prefix, 216 OPT_STRING('s', "source", &symbol_conf.source_prefix,
216 "directory", "path to kernel source"), 217 "directory", "path to kernel source"),
218 OPT_STRING('m', "module", &params.target_module,
219 "modname", "target module name"),
217#endif 220#endif
218 OPT__DRY_RUN(&probe_event_dry_run), 221 OPT__DRY_RUN(&probe_event_dry_run),
219 OPT_INTEGER('\0', "max-probes", &params.max_probe_points, 222 OPT_INTEGER('\0', "max-probes", &params.max_probe_points,
@@ -278,7 +281,7 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used)
278 usage_with_options(probe_usage, options); 281 usage_with_options(probe_usage, options);
279 } 282 }
280 283
281 ret = show_line_range(&params.line_range); 284 ret = show_line_range(&params.line_range, params.target_module);
282 if (ret < 0) 285 if (ret < 0)
283 pr_err(" Error: Failed to show lines. (%d)\n", ret); 286 pr_err(" Error: Failed to show lines. (%d)\n", ret);
284 return ret; 287 return ret;
@@ -291,6 +294,7 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used)
291 } 294 }
292 ret = show_available_vars(params.events, params.nevents, 295 ret = show_available_vars(params.events, params.nevents,
293 params.max_probe_points, 296 params.max_probe_points,
297 params.target_module,
294 params.show_ext_vars); 298 params.show_ext_vars);
295 if (ret < 0) 299 if (ret < 0)
296 pr_err(" Error: Failed to show vars. (%d)\n", ret); 300 pr_err(" Error: Failed to show vars. (%d)\n", ret);
@@ -310,6 +314,7 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used)
310 if (params.nevents) { 314 if (params.nevents) {
311 ret = add_perf_probe_events(params.events, params.nevents, 315 ret = add_perf_probe_events(params.events, params.nevents,
312 params.max_probe_points, 316 params.max_probe_points,
317 params.target_module,
313 params.force_add); 318 params.force_add);
314 if (ret < 0) { 319 if (ret < 0) {
315 pr_err(" Error: Failed to add events. (%d)\n", ret); 320 pr_err(" Error: Failed to add events. (%d)\n", ret);
diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h
index 78575796d5f..b397c038372 100644
--- a/tools/perf/util/map.h
+++ b/tools/perf/util/map.h
@@ -215,6 +215,16 @@ struct symbol *map_groups__find_function_by_name(struct map_groups *self,
215 return map_groups__find_symbol_by_name(self, MAP__FUNCTION, name, mapp, filter); 215 return map_groups__find_symbol_by_name(self, MAP__FUNCTION, name, mapp, filter);
216} 216}
217 217
218static inline
219struct symbol *machine__find_kernel_function_by_name(struct machine *self,
220 const char *name,
221 struct map **mapp,
222 symbol_filter_t filter)
223{
224 return map_groups__find_function_by_name(&self->kmaps, name, mapp,
225 filter);
226}
227
218int map_groups__fixup_overlappings(struct map_groups *self, struct map *map, 228int map_groups__fixup_overlappings(struct map_groups *self, struct map *map,
219 int verbose, FILE *fp); 229 int verbose, FILE *fp);
220 230
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index 82b0976e205..3b6a5297bf1 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -74,10 +74,9 @@ static int e_snprintf(char *str, size_t size, const char *format, ...)
74static char *synthesize_perf_probe_point(struct perf_probe_point *pp); 74static char *synthesize_perf_probe_point(struct perf_probe_point *pp);
75static struct machine machine; 75static struct machine machine;
76 76
77/* Initialize symbol maps and path of vmlinux */ 77/* Initialize symbol maps and path of vmlinux/modules */
78static int init_vmlinux(void) 78static int init_vmlinux(void)
79{ 79{
80 struct dso *kernel;
81 int ret; 80 int ret;
82 81
83 symbol_conf.sort_by_name = true; 82 symbol_conf.sort_by_name = true;
@@ -91,33 +90,61 @@ static int init_vmlinux(void)
91 goto out; 90 goto out;
92 } 91 }
93 92
94 ret = machine__init(&machine, "/", 0); 93 ret = machine__init(&machine, "", HOST_KERNEL_ID);
95 if (ret < 0) 94 if (ret < 0)
96 goto out; 95 goto out;
97 96
98 kernel = dso__new_kernel(symbol_conf.vmlinux_name); 97 if (machine__create_kernel_maps(&machine) < 0) {
99 if (kernel == NULL) 98 pr_debug("machine__create_kernel_maps ");
100 die("Failed to create kernel dso."); 99 goto out;
101 100 }
102 ret = __machine__create_kernel_maps(&machine, kernel);
103 if (ret < 0)
104 pr_debug("Failed to create kernel maps.\n");
105
106out: 101out:
107 if (ret < 0) 102 if (ret < 0)
108 pr_warning("Failed to init vmlinux path.\n"); 103 pr_warning("Failed to init vmlinux path.\n");
109 return ret; 104 return ret;
110} 105}
111 106
107static struct symbol *__find_kernel_function_by_name(const char *name,
108 struct map **mapp)
109{
110 return machine__find_kernel_function_by_name(&machine, name, mapp,
111 NULL);
112}
113
114const char *kernel_get_module_path(const char *module)
115{
116 struct dso *dso;
117
118 if (module) {
119 list_for_each_entry(dso, &machine.kernel_dsos, node) {
120 if (strncmp(dso->short_name + 1, module,
121 dso->short_name_len - 2) == 0)
122 goto found;
123 }
124 pr_debug("Failed to find module %s.\n", module);
125 return NULL;
126 } else {
<