diff options
| -rw-r--r-- | tools/perf/Documentation/perf-probe.txt | 6 | ||||
| -rw-r--r-- | tools/perf/builtin-probe.c | 3 | ||||
| -rw-r--r-- | tools/perf/util/probe-event.c | 52 |
3 files changed, 49 insertions, 12 deletions
diff --git a/tools/perf/Documentation/perf-probe.txt b/tools/perf/Documentation/perf-probe.txt index 02bafce4b34..2780d9ce48b 100644 --- a/tools/perf/Documentation/perf-probe.txt +++ b/tools/perf/Documentation/perf-probe.txt | |||
| @@ -34,9 +34,11 @@ OPTIONS | |||
| 34 | Specify vmlinux path which has debuginfo (Dwarf binary). | 34 | Specify vmlinux path which has debuginfo (Dwarf binary). |
| 35 | 35 | ||
| 36 | -m:: | 36 | -m:: |
| 37 | --module=MODNAME:: | 37 | --module=MODNAME|PATH:: |
| 38 | Specify module name in which perf-probe searches probe points | 38 | Specify module name in which perf-probe searches probe points |
| 39 | or lines. | 39 | or lines. If a path of module file is passed, perf-probe |
| 40 | treat it as an offline module (this means you can add a probe on | ||
| 41 | a module which has not been loaded yet). | ||
| 40 | 42 | ||
| 41 | -s:: | 43 | -s:: |
| 42 | --source=PATH:: | 44 | --source=PATH:: |
diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c index 2c0e64d0b4a..5f2a5c7046d 100644 --- a/tools/perf/builtin-probe.c +++ b/tools/perf/builtin-probe.c | |||
| @@ -242,7 +242,8 @@ static const struct option options[] = { | |||
| 242 | OPT_STRING('s', "source", &symbol_conf.source_prefix, | 242 | OPT_STRING('s', "source", &symbol_conf.source_prefix, |
| 243 | "directory", "path to kernel source"), | 243 | "directory", "path to kernel source"), |
| 244 | OPT_STRING('m', "module", ¶ms.target_module, | 244 | OPT_STRING('m', "module", ¶ms.target_module, |
| 245 | "modname", "target module name"), | 245 | "modname|path", |
| 246 | "target module name (for online) or path (for offline)"), | ||
| 246 | #endif | 247 | #endif |
| 247 | OPT__DRY_RUN(&probe_event_dry_run), | 248 | OPT__DRY_RUN(&probe_event_dry_run), |
| 248 | OPT_INTEGER('\0', "max-probes", ¶ms.max_probe_points, | 249 | OPT_INTEGER('\0', "max-probes", ¶ms.max_probe_points, |
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index ee3f41eec5c..b82d54fa2c5 100644 --- a/tools/perf/util/probe-event.c +++ b/tools/perf/util/probe-event.c | |||
| @@ -117,6 +117,10 @@ static struct map *kernel_get_module_map(const char *module) | |||
| 117 | struct rb_node *nd; | 117 | struct rb_node *nd; |
| 118 | struct map_groups *grp = &machine.kmaps; | 118 | struct map_groups *grp = &machine.kmaps; |
| 119 | 119 | ||
| 120 | /* A file path -- this is an offline module */ | ||
| 121 | if (module && strchr(module, '/')) | ||
| 122 | return machine__new_module(&machine, 0, module); | ||
| 123 | |||
| 120 | if (!module) | 124 | if (!module) |
| 121 | module = "kernel"; | 125 | module = "kernel"; |
| 122 | 126 | ||
| @@ -173,12 +177,19 @@ const char *kernel_get_module_path(const char *module) | |||
| 173 | /* Open new debuginfo of given module */ | 177 | /* Open new debuginfo of given module */ |
| 174 | static struct debuginfo *open_debuginfo(const char *module) | 178 | static struct debuginfo *open_debuginfo(const char *module) |
| 175 | { | 179 | { |
| 176 | const char *path = kernel_get_module_path(module); | 180 | const char *path; |
| 177 | 181 | ||
| 178 | if (!path) { | 182 | /* A file path -- this is an offline module */ |
| 179 | pr_err("Failed to find path of %s module.\n", | 183 | if (module && strchr(module, '/')) |
| 180 | module ?: "kernel"); | 184 | path = module; |
| 181 | return NULL; | 185 | else { |
| 186 | path = kernel_get_module_path(module); | ||
| 187 | |||
| 188 | if (!path) { | ||
| 189 | pr_err("Failed to find path of %s module.\n", | ||
| 190 | module ?: "kernel"); | ||
| 191 | return NULL; | ||
| 192 | } | ||
| 182 | } | 193 | } |
| 183 | return debuginfo__new(path); | 194 | return debuginfo__new(path); |
| 184 | } | 195 | } |
| @@ -229,13 +240,36 @@ static int kprobe_convert_to_perf_probe(struct probe_trace_point *tp, | |||
| 229 | static int add_module_to_probe_trace_events(struct probe_trace_event *tevs, | 240 | static int add_module_to_probe_trace_events(struct probe_trace_event *tevs, |
| 230 | int ntevs, const char *module) | 241 | int ntevs, const char *module) |
| 231 | { | 242 | { |
| 232 | int i; | 243 | int i, ret = 0; |
| 244 | char *tmp; | ||
| 245 | |||
| 246 | if (!module) | ||
| 247 | return 0; | ||
| 248 | |||
| 249 | tmp = strrchr(module, '/'); | ||
| 250 | if (tmp) { | ||
| 251 | /* This is a module path -- get the module name */ | ||
| 252 | module = strdup(tmp + 1); | ||
| 253 | if (!module) | ||
| 254 | return -ENOMEM; | ||
| 255 | tmp = strchr(module, '.'); | ||
| 256 | if (tmp) | ||
| 257 | *tmp = '\0'; | ||
| 258 | tmp = (char *)module; /* For free() */ | ||
| 259 | } | ||
| 260 | |||
| 233 | for (i = 0; i < ntevs; i++) { | 261 | for (i = 0; i < ntevs; i++) { |
| 234 | tevs[i].point.module = strdup(module); | 262 | tevs[i].point.module = strdup(module); |
| 235 | if (!tevs[i].point.module) | 263 | if (!tevs[i].point.module) { |
| 236 | return -ENOMEM; | 264 | ret = -ENOMEM; |
| 265 | break; | ||
| 266 | } | ||
| 237 | } | 267 | } |
| 238 | return 0; | 268 | |
| 269 | if (tmp) | ||
| 270 | free(tmp); | ||
| 271 | |||
| 272 | return ret; | ||
| 239 | } | 273 | } |
| 240 | 274 | ||
| 241 | /* Try to find perf_probe_event with debuginfo */ | 275 | /* Try to find perf_probe_event with debuginfo */ |
