blob: e6a02b1ffd6d59d3da6c0fc37297550e4a73e5e4 [file] [log] [blame]
Masami Hiramatsu50656ee2009-11-30 19:19:58 -05001/*
Srikar Dronamraju0e608362010-07-29 19:43:51 +05302 * probe-event.c : perf-probe definition to probe_events format converter
Masami Hiramatsu50656ee2009-11-30 19:19:58 -05003 *
4 * Written by Masami Hiramatsu <mhiramat@redhat.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 *
20 */
21
Masami Hiramatsu50656ee2009-11-30 19:19:58 -050022#include <sys/utsname.h>
23#include <sys/types.h>
24#include <sys/stat.h>
25#include <fcntl.h>
26#include <errno.h>
27#include <stdio.h>
28#include <unistd.h>
29#include <stdlib.h>
30#include <string.h>
Masami Hiramatsu4de189f2009-11-30 19:20:17 -050031#include <stdarg.h>
32#include <limits.h>
Masami Hiramatsue80711c2011-01-13 21:46:11 +090033#include <elf.h>
Masami Hiramatsu50656ee2009-11-30 19:19:58 -050034
Masami Hiramatsu31facc52010-03-16 18:05:30 -040035#include "util.h"
Masami Hiramatsu50656ee2009-11-30 19:19:58 -050036#include "event.h"
Masami Hiramatsu4de189f2009-11-30 19:20:17 -050037#include "strlist.h"
Masami Hiramatsu50656ee2009-11-30 19:19:58 -050038#include "debug.h"
Masami Hiramatsu72041332010-01-05 17:47:10 -050039#include "cache.h"
Masami Hiramatsu631c9de2010-01-06 09:45:34 -050040#include "color.h"
Masami Hiramatsue0faa8d2010-03-16 18:05:37 -040041#include "symbol.h"
42#include "thread.h"
Borislav Petkov553873e2013-12-09 17:14:23 +010043#include <api/fs/debugfs.h>
Steven Rostedt (Red Hat)23773ca2015-02-02 14:35:07 -050044#include <api/fs/tracefs.h>
Irina Tirdea1d037ca2012-09-11 01:15:03 +030045#include "trace-event.h" /* For __maybe_unused */
Masami Hiramatsu50656ee2009-11-30 19:19:58 -050046#include "probe-event.h"
Masami Hiramatsu4235b042010-03-16 18:06:12 -040047#include "probe-finder.h"
Srikar Dronamraju225466f2012-04-16 17:39:09 +053048#include "session.h"
Masami Hiramatsu50656ee2009-11-30 19:19:58 -050049
50#define MAX_CMDLEN 256
Masami Hiramatsu50656ee2009-11-30 19:19:58 -050051#define PERFPROBE_GROUP "probe"
52
Masami Hiramatsuf4d7da42010-03-16 18:06:05 -040053bool probe_event_dry_run; /* Dry run flag */
Masami Hiramatsuddb2f582015-05-08 10:03:31 +090054struct probe_conf probe_conf;
Masami Hiramatsuf4d7da42010-03-16 18:06:05 -040055
Masami Hiramatsu146a1432010-04-12 13:17:42 -040056#define semantic_error(msg ...) pr_err("Semantic error :" msg)
Masami Hiramatsu50656ee2009-11-30 19:19:58 -050057
Masami Hiramatsu4de189f2009-11-30 19:20:17 -050058/* If there is no space to write, returns -E2BIG. */
59static int e_snprintf(char *str, size_t size, const char *format, ...)
Masami Hiramatsu84988452009-12-07 12:00:53 -050060 __attribute__((format(printf, 3, 4)));
61
62static int e_snprintf(char *str, size_t size, const char *format, ...)
Masami Hiramatsu4de189f2009-11-30 19:20:17 -050063{
64 int ret;
65 va_list ap;
66 va_start(ap, format);
67 ret = vsnprintf(str, size, format, ap);
68 va_end(ap);
69 if (ret >= (int)size)
70 ret = -E2BIG;
71 return ret;
72}
73
Masami Hiramatsu4b4da7f2010-03-22 13:10:26 -030074static char *synthesize_perf_probe_point(struct perf_probe_point *pp);
Masami Hiramatsu981d05a2014-01-16 09:39:44 +000075static void clear_probe_trace_event(struct probe_trace_event *tev);
Masami Hiramatsuee45b6c2014-02-06 05:32:04 +000076static struct machine *host_machine;
Masami Hiramatsue0faa8d2010-03-16 18:05:37 -040077
Masami Hiramatsu469b9b82010-10-21 19:13:41 +090078/* Initialize symbol maps and path of vmlinux/modules */
Masami Hiramatsuee45b6c2014-02-06 05:32:04 +000079static int init_symbol_maps(bool user_only)
Masami Hiramatsue0faa8d2010-03-16 18:05:37 -040080{
Masami Hiramatsu146a1432010-04-12 13:17:42 -040081 int ret;
82
Masami Hiramatsue0faa8d2010-03-16 18:05:37 -040083 symbol_conf.sort_by_name = true;
Namhyung Kim680d9262015-03-06 16:31:27 +090084 symbol_conf.allow_aliases = true;
Namhyung Kim0a7e6d12014-08-12 15:40:45 +090085 ret = symbol__init(NULL);
Masami Hiramatsu146a1432010-04-12 13:17:42 -040086 if (ret < 0) {
87 pr_debug("Failed to init symbol map.\n");
88 goto out;
89 }
Masami Hiramatsue0faa8d2010-03-16 18:05:37 -040090
Masami Hiramatsuee45b6c2014-02-06 05:32:04 +000091 if (host_machine || user_only) /* already initialized */
92 return 0;
Arnaldo Carvalho de Melod28c6222010-04-27 21:20:43 -030093
Masami Hiramatsuee45b6c2014-02-06 05:32:04 +000094 if (symbol_conf.vmlinux_name)
95 pr_debug("Use vmlinux: %s\n", symbol_conf.vmlinux_name);
96
97 host_machine = machine__new_host();
98 if (!host_machine) {
99 pr_debug("machine__new_host() failed.\n");
100 symbol__exit();
101 ret = -1;
Masami Hiramatsu469b9b82010-10-21 19:13:41 +0900102 }
Masami Hiramatsu146a1432010-04-12 13:17:42 -0400103out:
104 if (ret < 0)
105 pr_warning("Failed to init vmlinux path.\n");
106 return ret;
Masami Hiramatsue0faa8d2010-03-16 18:05:37 -0400107}
108
Masami Hiramatsuee45b6c2014-02-06 05:32:04 +0000109static void exit_symbol_maps(void)
110{
111 if (host_machine) {
112 machine__delete(host_machine);
113 host_machine = NULL;
114 }
115 symbol__exit();
116}
117
Masami Hiramatsu469b9b82010-10-21 19:13:41 +0900118static struct symbol *__find_kernel_function_by_name(const char *name,
119 struct map **mapp)
Masami Hiramatsue0faa8d2010-03-16 18:05:37 -0400120{
Masami Hiramatsuee45b6c2014-02-06 05:32:04 +0000121 return machine__find_kernel_function_by_name(host_machine, name, mapp,
Masami Hiramatsu469b9b82010-10-21 19:13:41 +0900122 NULL);
123}
124
Masami Hiramatsu8f33f7d2014-02-06 05:32:20 +0000125static struct symbol *__find_kernel_function(u64 addr, struct map **mapp)
126{
127 return machine__find_kernel_function(host_machine, addr, mapp, NULL);
128}
129
130static struct ref_reloc_sym *kernel_get_ref_reloc_sym(void)
131{
132 /* kmap->ref_reloc_sym should be set if host_machine is initialized */
133 struct kmap *kmap;
134
135 if (map__load(host_machine->vmlinux_maps[MAP__FUNCTION], NULL) < 0)
136 return NULL;
137
138 kmap = map__kmap(host_machine->vmlinux_maps[MAP__FUNCTION]);
Wang Nanba927322015-04-07 08:22:45 +0000139 if (!kmap)
140 return NULL;
Masami Hiramatsu8f33f7d2014-02-06 05:32:20 +0000141 return kmap->ref_reloc_sym;
142}
143
144static u64 kernel_get_symbol_address_by_name(const char *name, bool reloc)
145{
146 struct ref_reloc_sym *reloc_sym;
147 struct symbol *sym;
148 struct map *map;
149
150 /* ref_reloc_sym is just a label. Need a special fix*/
151 reloc_sym = kernel_get_ref_reloc_sym();
152 if (reloc_sym && strcmp(name, reloc_sym->name) == 0)
153 return (reloc) ? reloc_sym->addr : reloc_sym->unrelocated_addr;
154 else {
155 sym = __find_kernel_function_by_name(name, &map);
156 if (sym)
157 return map->unmap_ip(map, sym->start) -
He Kuangf56847c2015-02-27 18:52:53 +0800158 ((reloc) ? 0 : map->reloc);
Masami Hiramatsu8f33f7d2014-02-06 05:32:20 +0000159 }
160 return 0;
161}
162
Masami Hiramatsue80711c2011-01-13 21:46:11 +0900163static struct map *kernel_get_module_map(const char *module)
164{
Masami Hiramatsuee45b6c2014-02-06 05:32:04 +0000165 struct map_groups *grp = &host_machine->kmaps;
Arnaldo Carvalho de Melo1eee78a2015-05-22 12:58:53 -0300166 struct maps *maps = &grp->maps[MAP__FUNCTION];
Arnaldo Carvalho de Melo4bb7123d2015-05-22 11:52:22 -0300167 struct map *pos;
Masami Hiramatsue80711c2011-01-13 21:46:11 +0900168
Masami Hiramatsu14a8fd72011-06-27 16:27:51 +0900169 /* A file path -- this is an offline module */
170 if (module && strchr(module, '/'))
Masami Hiramatsuee45b6c2014-02-06 05:32:04 +0000171 return machine__new_module(host_machine, 0, module);
Masami Hiramatsu14a8fd72011-06-27 16:27:51 +0900172
Masami Hiramatsue80711c2011-01-13 21:46:11 +0900173 if (!module)
174 module = "kernel";
175
Arnaldo Carvalho de Melo4bb7123d2015-05-22 11:52:22 -0300176 for (pos = maps__first(maps); pos; pos = map__next(pos)) {
Masami Hiramatsue80711c2011-01-13 21:46:11 +0900177 if (strncmp(pos->dso->short_name + 1, module,
178 pos->dso->short_name_len - 2) == 0) {
179 return pos;
180 }
181 }
182 return NULL;
183}
184
Masami Hiramatsu9b118ac2015-03-06 16:31:20 +0900185static struct map *get_target_map(const char *target, bool user)
186{
187 /* Init maps of given executable or kernel */
188 if (user)
189 return dso__new_map(target);
190 else
191 return kernel_get_module_map(target);
192}
193
194static void put_target_map(struct map *map, bool user)
195{
196 if (map && user) {
197 /* Only the user map needs to be released */
Arnaldo Carvalho de Melo84c2caf2015-05-25 16:59:56 -0300198 map__put(map);
Masami Hiramatsu9b118ac2015-03-06 16:31:20 +0900199 }
200}
201
202
Masami Hiramatsufb7345b2013-12-26 05:41:53 +0000203static int convert_exec_to_group(const char *exec, char **result)
204{
205 char *ptr1, *ptr2, *exec_copy;
206 char buf[64];
207 int ret;
208
209 exec_copy = strdup(exec);
210 if (!exec_copy)
211 return -ENOMEM;
212
213 ptr1 = basename(exec_copy);
214 if (!ptr1) {
215 ret = -EINVAL;
216 goto out;
217 }
218
219 ptr2 = strpbrk(ptr1, "-._");
220 if (ptr2)
221 *ptr2 = '\0';
222 ret = e_snprintf(buf, 64, "%s_%s", PERFPROBE_GROUP, ptr1);
223 if (ret < 0)
224 goto out;
225
226 *result = strdup(buf);
227 ret = *result ? 0 : -ENOMEM;
228
229out:
230 free(exec_copy);
231 return ret;
232}
233
Masami Hiramatsu9b118ac2015-03-06 16:31:20 +0900234static void clear_perf_probe_point(struct perf_probe_point *pp)
235{
236 free(pp->file);
237 free(pp->function);
238 free(pp->lazy_line);
239}
240
Masami Hiramatsueb948e52014-02-06 05:32:25 +0000241static void clear_probe_trace_events(struct probe_trace_event *tevs, int ntevs)
242{
243 int i;
244
245 for (i = 0; i < ntevs; i++)
246 clear_probe_trace_event(tevs + i);
247}
248
Ingo Molnar89fe8082013-09-30 12:07:11 +0200249#ifdef HAVE_DWARF_SUPPORT
Wang Nan60fb7742015-05-28 02:25:05 +0000250
251static int kernel_get_module_dso(const char *module, struct dso **pdso)
252{
253 struct dso *dso;
254 struct map *map;
255 const char *vmlinux_name;
256 int ret = 0;
257
258 if (module) {
259 list_for_each_entry(dso, &host_machine->kernel_dsos.head,
260 node) {
261 if (strncmp(dso->short_name + 1, module,
262 dso->short_name_len - 2) == 0)
263 goto found;
264 }
265 pr_debug("Failed to find module %s.\n", module);
266 return -ENOENT;
267 }
268
269 map = host_machine->vmlinux_maps[MAP__FUNCTION];
270 dso = map->dso;
271
272 vmlinux_name = symbol_conf.vmlinux_name;
273 dso->load_errno = 0;
274 if (vmlinux_name)
275 ret = dso__load_vmlinux(dso, map, vmlinux_name, false, NULL);
276 else
277 ret = dso__load_vmlinux_path(dso, map, NULL);
278found:
279 *pdso = dso;
280 return ret;
281}
282
Masami Hiramatsu9b118ac2015-03-06 16:31:20 +0900283/*
284 * Some binaries like glibc have special symbols which are on the symbol
285 * table, but not in the debuginfo. If we can find the address of the
286 * symbol from map, we can translate the address back to the probe point.
287 */
288static int find_alternative_probe_point(struct debuginfo *dinfo,
289 struct perf_probe_point *pp,
290 struct perf_probe_point *result,
291 const char *target, bool uprobes)
292{
293 struct map *map = NULL;
294 struct symbol *sym;
295 u64 address = 0;
296 int ret = -ENOENT;
297
298 /* This can work only for function-name based one */
299 if (!pp->function || pp->file)
300 return -ENOTSUP;
301
302 map = get_target_map(target, uprobes);
303 if (!map)
304 return -EINVAL;
305
306 /* Find the address of given function */
307 map__for_each_symbol_by_name(map, pp->function, sym) {
Masami Hiramatsue6d7c912015-03-22 20:40:22 +0900308 if (uprobes)
309 address = sym->start;
310 else
311 address = map->unmap_ip(map, sym->start);
Namhyung Kime578da32015-03-06 16:31:29 +0900312 break;
Masami Hiramatsu9b118ac2015-03-06 16:31:20 +0900313 }
314 if (!address) {
315 ret = -ENOENT;
316 goto out;
317 }
Wang Nanf6c15622015-04-08 02:14:34 +0000318 pr_debug("Symbol %s address found : %" PRIx64 "\n",
319 pp->function, address);
Masami Hiramatsu9b118ac2015-03-06 16:31:20 +0900320
321 ret = debuginfo__find_probe_point(dinfo, (unsigned long)address,
322 result);
323 if (ret <= 0)
324 ret = (!ret) ? -ENOENT : ret;
325 else {
326 result->offset += pp->offset;
327 result->line += pp->line;
He Kuang9d7b45c2015-04-13 19:41:28 +0800328 result->retprobe = pp->retprobe;
Masami Hiramatsu9b118ac2015-03-06 16:31:20 +0900329 ret = 0;
330 }
331
332out:
333 put_target_map(map, uprobes);
334 return ret;
335
336}
337
338static int get_alternative_probe_event(struct debuginfo *dinfo,
339 struct perf_probe_event *pev,
Masami Hiramatsu44225522015-05-08 10:03:28 +0900340 struct perf_probe_point *tmp)
Masami Hiramatsu9b118ac2015-03-06 16:31:20 +0900341{
342 int ret;
343
344 memcpy(tmp, &pev->point, sizeof(*tmp));
345 memset(&pev->point, 0, sizeof(pev->point));
346 ret = find_alternative_probe_point(dinfo, tmp, &pev->point,
Masami Hiramatsu44225522015-05-08 10:03:28 +0900347 pev->target, pev->uprobes);
Masami Hiramatsu9b118ac2015-03-06 16:31:20 +0900348 if (ret < 0)
349 memcpy(&pev->point, tmp, sizeof(*tmp));
350
351 return ret;
352}
Masami Hiramatsua15ad2f2014-02-06 05:32:27 +0000353
Masami Hiramatsu811dd2a2015-03-06 16:31:22 +0900354static int get_alternative_line_range(struct debuginfo *dinfo,
355 struct line_range *lr,
356 const char *target, bool user)
357{
David Ahern6d4a4892015-03-11 10:36:20 -0400358 struct perf_probe_point pp = { .function = lr->function,
359 .file = lr->file,
360 .line = lr->start };
361 struct perf_probe_point result;
Masami Hiramatsu811dd2a2015-03-06 16:31:22 +0900362 int ret, len = 0;
363
David Ahern6d4a4892015-03-11 10:36:20 -0400364 memset(&result, 0, sizeof(result));
365
Masami Hiramatsu811dd2a2015-03-06 16:31:22 +0900366 if (lr->end != INT_MAX)
367 len = lr->end - lr->start;
368 ret = find_alternative_probe_point(dinfo, &pp, &result,
369 target, user);
370 if (!ret) {
371 lr->function = result.function;
372 lr->file = result.file;
373 lr->start = result.line;
374 if (lr->end != INT_MAX)
375 lr->end = lr->start + len;
376 clear_perf_probe_point(&pp);
377 }
378 return ret;
379}
380
Masami Hiramatsuff741782011-06-27 16:27:39 +0900381/* Open new debuginfo of given module */
Masami Hiramatsu92561cb2014-08-15 01:44:32 +0000382static struct debuginfo *open_debuginfo(const char *module, bool silent)
Masami Hiramatsu469b9b82010-10-21 19:13:41 +0900383{
Masami Hiramatsua15ad2f2014-02-06 05:32:27 +0000384 const char *path = module;
Masami Hiramatsu419e8732015-05-27 17:37:18 +0900385 char reason[STRERR_BUFSIZE];
386 struct debuginfo *ret = NULL;
387 struct dso *dso = NULL;
388 int err;
Masami Hiramatsuff741782011-06-27 16:27:39 +0900389
Masami Hiramatsua15ad2f2014-02-06 05:32:27 +0000390 if (!module || !strchr(module, '/')) {
Masami Hiramatsu419e8732015-05-27 17:37:18 +0900391 err = kernel_get_module_dso(module, &dso);
392 if (err < 0) {
393 if (!dso || dso->load_errno == 0) {
394 if (!strerror_r(-err, reason, STRERR_BUFSIZE))
395 strcpy(reason, "(unknown)");
396 } else
397 dso__strerror_load(dso, reason, STRERR_BUFSIZE);
Masami Hiramatsu92561cb2014-08-15 01:44:32 +0000398 if (!silent)
Masami Hiramatsu419e8732015-05-27 17:37:18 +0900399 pr_err("Failed to find the path for %s: %s\n",
400 module ?: "kernel", reason);
Masami Hiramatsu14a8fd72011-06-27 16:27:51 +0900401 return NULL;
402 }
Masami Hiramatsu419e8732015-05-27 17:37:18 +0900403 path = dso->long_name;
Masami Hiramatsu469b9b82010-10-21 19:13:41 +0900404 }
Masami Hiramatsu92561cb2014-08-15 01:44:32 +0000405 ret = debuginfo__new(path);
406 if (!ret && !silent) {
407 pr_warning("The %s file has no debug information.\n", path);
408 if (!module || !strtailcmp(path, ".ko"))
409 pr_warning("Rebuild with CONFIG_DEBUG_INFO=y, ");
410 else
411 pr_warning("Rebuild with -g, ");
412 pr_warning("or install an appropriate debuginfo package.\n");
413 }
414 return ret;
Masami Hiramatsue0faa8d2010-03-16 18:05:37 -0400415}
Masami Hiramatsu4b4da7f2010-03-22 13:10:26 -0300416
Masami Hiramatsu92561cb2014-08-15 01:44:32 +0000417
Masami Hiramatsu99ca4232014-01-16 09:39:49 +0000418static int get_text_start_address(const char *exec, unsigned long *address)
419{
420 Elf *elf;
421 GElf_Ehdr ehdr;
422 GElf_Shdr shdr;
423 int fd, ret = -ENOENT;
424
425 fd = open(exec, O_RDONLY);
426 if (fd < 0)
427 return -errno;
428
429 elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
430 if (elf == NULL)
431 return -EINVAL;
432
433 if (gelf_getehdr(elf, &ehdr) == NULL)
434 goto out;
435
436 if (!elf_section_by_name(elf, &ehdr, &shdr, ".text", NULL))
437 goto out;
438
439 *address = shdr.sh_addr - shdr.sh_offset;
440 ret = 0;
441out:
442 elf_end(elf);
443 return ret;
444}
445
Masami Hiramatsu5a6f6312014-02-06 05:32:23 +0000446/*
447 * Convert trace point to probe point with debuginfo
448 */
449static int find_perf_probe_point_from_dwarf(struct probe_trace_point *tp,
450 struct perf_probe_point *pp,
451 bool is_kprobe)
452{
453 struct debuginfo *dinfo = NULL;
454 unsigned long stext = 0;
455 u64 addr = tp->address;
456 int ret = -ENOENT;
457
458 /* convert the address to dwarf address */
459 if (!is_kprobe) {
460 if (!addr) {
461 ret = -EINVAL;
462 goto error;
463 }
464 ret = get_text_start_address(tp->module, &stext);
465 if (ret < 0)
466 goto error;
467 addr += stext;
468 } else {
469 addr = kernel_get_symbol_address_by_name(tp->symbol, false);
470 if (addr == 0)
471 goto error;
472 addr += tp->offset;
473 }
474
475 pr_debug("try to find information at %" PRIx64 " in %s\n", addr,
476 tp->module ? : "kernel");
477
Masami Hiramatsu92561cb2014-08-15 01:44:32 +0000478 dinfo = open_debuginfo(tp->module, verbose == 0);
Masami Hiramatsu5a6f6312014-02-06 05:32:23 +0000479 if (dinfo) {
480 ret = debuginfo__find_probe_point(dinfo,
481 (unsigned long)addr, pp);
482 debuginfo__delete(dinfo);
Masami Hiramatsu92561cb2014-08-15 01:44:32 +0000483 } else
Masami Hiramatsu5a6f6312014-02-06 05:32:23 +0000484 ret = -ENOENT;
Masami Hiramatsu5a6f6312014-02-06 05:32:23 +0000485
486 if (ret > 0) {
487 pp->retprobe = tp->retprobe;
488 return 0;
489 }
490error:
491 pr_debug("Failed to find corresponding probes from debuginfo.\n");
492 return ret ? : -ENOENT;
493}
494
Masami Hiramatsufb7345b2013-12-26 05:41:53 +0000495static int add_exec_to_probe_trace_events(struct probe_trace_event *tevs,
496 int ntevs, const char *exec)
497{
498 int i, ret = 0;
Masami Hiramatsueb948e52014-02-06 05:32:25 +0000499 unsigned long stext = 0;
Masami Hiramatsufb7345b2013-12-26 05:41:53 +0000500
501 if (!exec)
502 return 0;
503
504 ret = get_text_start_address(exec, &stext);
505 if (ret < 0)
506 return ret;
507
508 for (i = 0; i < ntevs && ret >= 0; i++) {
Masami Hiramatsu981a2372014-02-05 05:18:58 +0000509 /* point.address is the addres of point.symbol + point.offset */
Masami Hiramatsueb948e52014-02-06 05:32:25 +0000510 tevs[i].point.address -= stext;
Masami Hiramatsufb7345b2013-12-26 05:41:53 +0000511 tevs[i].point.module = strdup(exec);
Masami Hiramatsueb948e52014-02-06 05:32:25 +0000512 if (!tevs[i].point.module) {
Masami Hiramatsufb7345b2013-12-26 05:41:53 +0000513 ret = -ENOMEM;
514 break;
515 }
516 tevs[i].uprobes = true;
517 }
518
519 return ret;
520}
521
Masami Hiramatsu190b57f2011-06-27 16:27:45 +0900522static int add_module_to_probe_trace_events(struct probe_trace_event *tevs,
523 int ntevs, const char *module)
524{
Masami Hiramatsu14a8fd72011-06-27 16:27:51 +0900525 int i, ret = 0;
526 char *tmp;
527
528 if (!module)
529 return 0;
530
531 tmp = strrchr(module, '/');
532 if (tmp) {
533 /* This is a module path -- get the module name */
534 module = strdup(tmp + 1);
535 if (!module)
536 return -ENOMEM;
537 tmp = strchr(module, '.');
538 if (tmp)
539 *tmp = '\0';
540 tmp = (char *)module; /* For free() */
541 }
542
Masami Hiramatsu190b57f2011-06-27 16:27:45 +0900543 for (i = 0; i < ntevs; i++) {
544 tevs[i].point.module = strdup(module);
Masami Hiramatsu14a8fd72011-06-27 16:27:51 +0900545 if (!tevs[i].point.module) {
546 ret = -ENOMEM;
547 break;
548 }
Masami Hiramatsu190b57f2011-06-27 16:27:45 +0900549 }
Masami Hiramatsu14a8fd72011-06-27 16:27:51 +0900550
Arnaldo Carvalho de Melof5385652013-12-26 15:54:57 -0300551 free(tmp);
Masami Hiramatsu14a8fd72011-06-27 16:27:51 +0900552 return ret;
Masami Hiramatsu190b57f2011-06-27 16:27:45 +0900553}
554
Masami Hiramatsudfef99c2014-02-06 05:32:16 +0000555/* Post processing the probe events */
556static int post_process_probe_trace_events(struct probe_trace_event *tevs,
557 int ntevs, const char *module,
558 bool uprobe)
559{
560 struct ref_reloc_sym *reloc_sym;
Masami Hiramatsu5a51fcd2015-05-06 21:46:49 +0900561 u64 etext_addr;
Masami Hiramatsudfef99c2014-02-06 05:32:16 +0000562 char *tmp;
Masami Hiramatsu5a51fcd2015-05-06 21:46:49 +0900563 int i, skipped = 0;
Masami Hiramatsudfef99c2014-02-06 05:32:16 +0000564
565 if (uprobe)
566 return add_exec_to_probe_trace_events(tevs, ntevs, module);
567
568 /* Note that currently ref_reloc_sym based probe is not for drivers */
569 if (module)
570 return add_module_to_probe_trace_events(tevs, ntevs, module);
571
Masami Hiramatsu8f33f7d2014-02-06 05:32:20 +0000572 reloc_sym = kernel_get_ref_reloc_sym();
Masami Hiramatsudfef99c2014-02-06 05:32:16 +0000573 if (!reloc_sym) {
574 pr_warning("Relocated base symbol is not found!\n");
575 return -EINVAL;
576 }
Masami Hiramatsu5a51fcd2015-05-06 21:46:49 +0900577 /* Get the address of _etext for checking non-probable text symbol */
578 etext_addr = kernel_get_symbol_address_by_name("_etext", false);
Masami Hiramatsudfef99c2014-02-06 05:32:16 +0000579
580 for (i = 0; i < ntevs; i++) {
Namhyung Kim25dd9172015-01-14 20:18:08 +0900581 if (tevs[i].point.address && !tevs[i].point.retprobe) {
Masami Hiramatsu5a51fcd2015-05-06 21:46:49 +0900582 /* If we found a wrong one, mark it by NULL symbol */
583 if (etext_addr < tevs[i].point.address) {
584 pr_warning("%s+%lu is out of .text, skip it.\n",
585 tevs[i].point.symbol, tevs[i].point.offset);
586 tmp = NULL;
587 skipped++;
588 } else {
589 tmp = strdup(reloc_sym->name);
590 if (!tmp)
591 return -ENOMEM;
592 }
Masami Hiramatsu4c859352015-05-08 10:03:35 +0900593 /* If we have no realname, use symbol for it */
594 if (!tevs[i].point.realname)
595 tevs[i].point.realname = tevs[i].point.symbol;
596 else
597 free(tevs[i].point.symbol);
Masami Hiramatsudfef99c2014-02-06 05:32:16 +0000598 tevs[i].point.symbol = tmp;
599 tevs[i].point.offset = tevs[i].point.address -
600 reloc_sym->unrelocated_addr;
601 }
602 }
Masami Hiramatsu5a51fcd2015-05-06 21:46:49 +0900603 return skipped;
Masami Hiramatsudfef99c2014-02-06 05:32:16 +0000604}
605
Masami Hiramatsu4b4da7f2010-03-22 13:10:26 -0300606/* Try to find perf_probe_event with debuginfo */
Srikar Dronamraju0e608362010-07-29 19:43:51 +0530607static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
Masami Hiramatsuddb2f582015-05-08 10:03:31 +0900608 struct probe_trace_event **tevs)
Masami Hiramatsu4b4da7f2010-03-22 13:10:26 -0300609{
610 bool need_dwarf = perf_probe_event_need_dwarf(pev);
Masami Hiramatsu9b118ac2015-03-06 16:31:20 +0900611 struct perf_probe_point tmp;
Srikar Dronamraju225466f2012-04-16 17:39:09 +0530612 struct debuginfo *dinfo;
Masami Hiramatsu190b57f2011-06-27 16:27:45 +0900613 int ntevs, ret = 0;
Masami Hiramatsu4b4da7f2010-03-22 13:10:26 -0300614
Masami Hiramatsu44225522015-05-08 10:03:28 +0900615 dinfo = open_debuginfo(pev->target, !need_dwarf);
Masami Hiramatsuff741782011-06-27 16:27:39 +0900616 if (!dinfo) {
Masami Hiramatsu92561cb2014-08-15 01:44:32 +0000617 if (need_dwarf)
Masami Hiramatsuff741782011-06-27 16:27:39 +0900618 return -ENOENT;
Masami Hiramatsuff741782011-06-27 16:27:39 +0900619 pr_debug("Could not open debuginfo. Try to use symbols.\n");
Masami Hiramatsu4b4da7f2010-03-22 13:10:26 -0300620 return 0;
621 }
622
Masami Hiramatsudfef99c2014-02-06 05:32:16 +0000623 pr_debug("Try to find probe point from debuginfo.\n");
Masami Hiramatsuff741782011-06-27 16:27:39 +0900624 /* Searching trace events corresponding to a probe event */
Masami Hiramatsuddb2f582015-05-08 10:03:31 +0900625 ntevs = debuginfo__find_trace_events(dinfo, pev, tevs);
Masami Hiramatsuff741782011-06-27 16:27:39 +0900626
Masami Hiramatsu9b118ac2015-03-06 16:31:20 +0900627 if (ntevs == 0) { /* Not found, retry with an alternative */
Masami Hiramatsu44225522015-05-08 10:03:28 +0900628 ret = get_alternative_probe_event(dinfo, pev, &tmp);
Masami Hiramatsu9b118ac2015-03-06 16:31:20 +0900629 if (!ret) {
Masami Hiramatsuddb2f582015-05-08 10:03:31 +0900630 ntevs = debuginfo__find_trace_events(dinfo, pev, tevs);
Masami Hiramatsu9b118ac2015-03-06 16:31:20 +0900631 /*
632 * Write back to the original probe_event for
633 * setting appropriate (user given) event name
634 */
635 clear_perf_probe_point(&pev->point);
636 memcpy(&pev->point, &tmp, sizeof(tmp));
637 }
638 }
639
Masami Hiramatsuff741782011-06-27 16:27:39 +0900640 debuginfo__delete(dinfo);
Masami Hiramatsu4b4da7f2010-03-22 13:10:26 -0300641
Masami Hiramatsu146a1432010-04-12 13:17:42 -0400642 if (ntevs > 0) { /* Succeeded to find trace events */
Masami Hiramatsudfef99c2014-02-06 05:32:16 +0000643 pr_debug("Found %d probe_trace_events.\n", ntevs);
644 ret = post_process_probe_trace_events(*tevs, ntevs,
Masami Hiramatsu44225522015-05-08 10:03:28 +0900645 pev->target, pev->uprobes);
Masami Hiramatsu5a51fcd2015-05-06 21:46:49 +0900646 if (ret < 0 || ret == ntevs) {
Masami Hiramatsu981d05a2014-01-16 09:39:44 +0000647 clear_probe_trace_events(*tevs, ntevs);
648 zfree(tevs);
649 }
Masami Hiramatsu5a51fcd2015-05-06 21:46:49 +0900650 if (ret != ntevs)
651 return ret < 0 ? ret : ntevs;
652 ntevs = 0;
653 /* Fall through */
Masami Hiramatsu146a1432010-04-12 13:17:42 -0400654 }
Masami Hiramatsu4b4da7f2010-03-22 13:10:26 -0300655
Masami Hiramatsu146a1432010-04-12 13:17:42 -0400656 if (ntevs == 0) { /* No error but failed to find probe point. */
Masami Hiramatsu0687eba2015-03-06 16:31:25 +0900657 pr_warning("Probe point '%s' not found.\n",
Masami Hiramatsu146a1432010-04-12 13:17:42 -0400658 synthesize_perf_probe_point(&pev->point));
Masami Hiramatsu0687eba2015-03-06 16:31:25 +0900659 return -ENOENT;
Masami Hiramatsu146a1432010-04-12 13:17:42 -0400660 }
661 /* Error path : ntevs < 0 */
Masami Hiramatsu15eca302010-04-21 15:56:24 -0400662 pr_debug("An error occurred in debuginfo analysis (%d).\n", ntevs);
663 if (ntevs == -EBADF) {
664 pr_warning("Warning: No dwarf info found in the vmlinux - "
665 "please rebuild kernel with CONFIG_DEBUG_INFO=y.\n");
666 if (!need_dwarf) {
Masami Hiramatsu0e43e5d2010-12-17 22:12:11 +0900667 pr_debug("Trying to use symbols.\n");
Masami Hiramatsu15eca302010-04-21 15:56:24 -0400668 return 0;
669 }
Masami Hiramatsu4b4da7f2010-03-22 13:10:26 -0300670 }
Masami Hiramatsu15eca302010-04-21 15:56:24 -0400671 return ntevs;
Masami Hiramatsu4b4da7f2010-03-22 13:10:26 -0300672}
673
674#define LINEBUF_SIZE 256
675#define NR_ADDITIONAL_LINES 2
676
Franck Bui-Huufde52db2010-12-20 15:18:04 +0100677static int __show_one_line(FILE *fp, int l, bool skip, bool show_num)
Masami Hiramatsu4b4da7f2010-03-22 13:10:26 -0300678{
Masami Hiramatsu5f03cba2014-08-14 02:22:34 +0000679 char buf[LINEBUF_SIZE], sbuf[STRERR_BUFSIZE];
Franck Bui-Huubefe3412010-12-20 15:18:01 +0100680 const char *color = show_num ? "" : PERF_COLOR_BLUE;
681 const char *prefix = NULL;
Masami Hiramatsu4b4da7f2010-03-22 13:10:26 -0300682
Franck Bui-Huubefe3412010-12-20 15:18:01 +0100683 do {
Masami Hiramatsu4b4da7f2010-03-22 13:10:26 -0300684 if (fgets(buf, LINEBUF_SIZE, fp) == NULL)
685 goto error;
Franck Bui-Huubefe3412010-12-20 15:18:01 +0100686 if (skip)
687 continue;
688 if (!prefix) {
689 prefix = show_num ? "%7d " : " ";
690 color_fprintf(stdout, color, prefix, l);
Masami Hiramatsu4b4da7f2010-03-22 13:10:26 -0300691 }
Franck Bui-Huubefe3412010-12-20 15:18:01 +0100692 color_fprintf(stdout, color, "%s", buf);
693
694 } while (strchr(buf, '\n') == NULL);
Masami Hiramatsu146a1432010-04-12 13:17:42 -0400695
Franck Bui-Huufde52db2010-12-20 15:18:04 +0100696 return 1;
Masami Hiramatsu4b4da7f2010-03-22 13:10:26 -0300697error:
Franck Bui-Huufde52db2010-12-20 15:18:04 +0100698 if (ferror(fp)) {
Masami Hiramatsu5f03cba2014-08-14 02:22:34 +0000699 pr_warning("File read error: %s\n",
700 strerror_r(errno, sbuf, sizeof(sbuf)));
Franck Bui-Huufde52db2010-12-20 15:18:04 +0100701 return -1;
702 }
703 return 0;
Masami Hiramatsu4b4da7f2010-03-22 13:10:26 -0300704}
705
Franck Bui-Huufde52db2010-12-20 15:18:04 +0100706static int _show_one_line(FILE *fp, int l, bool skip, bool show_num)
707{
708 int rv = __show_one_line(fp, l, skip, show_num);
709 if (rv == 0) {
710 pr_warning("Source file is shorter than expected.\n");
711 rv = -1;
712 }
713 return rv;
714}
715
716#define show_one_line_with_num(f,l) _show_one_line(f,l,false,true)
717#define show_one_line(f,l) _show_one_line(f,l,false,false)
718#define skip_one_line(f,l) _show_one_line(f,l,true,false)
719#define show_one_line_or_eof(f,l) __show_one_line(f,l,false,false)
720
Masami Hiramatsu4b4da7f2010-03-22 13:10:26 -0300721/*
722 * Show line-range always requires debuginfo to find source file and
723 * line number.
724 */
Masami Hiramatsu811dd2a2015-03-06 16:31:22 +0900725static int __show_line_range(struct line_range *lr, const char *module,
726 bool user)
Masami Hiramatsu4b4da7f2010-03-22 13:10:26 -0300727{
Masami Hiramatsud3b63d72010-04-14 18:39:42 -0400728 int l = 1;
Masami Hiramatsu5a622572014-02-06 05:32:09 +0000729 struct int_node *ln;
Masami Hiramatsuff741782011-06-27 16:27:39 +0900730 struct debuginfo *dinfo;
Masami Hiramatsu4b4da7f2010-03-22 13:10:26 -0300731 FILE *fp;
Masami Hiramatsuff741782011-06-27 16:27:39 +0900732 int ret;
Masami Hiramatsu7cf0b792010-07-09 18:28:59 +0900733 char *tmp;
Masami Hiramatsu5f03cba2014-08-14 02:22:34 +0000734 char sbuf[STRERR_BUFSIZE];
Masami Hiramatsu4b4da7f2010-03-22 13:10:26 -0300735
736 /* Search a line range */
Masami Hiramatsu92561cb2014-08-15 01:44:32 +0000737 dinfo = open_debuginfo(module, false);
738 if (!dinfo)
Masami Hiramatsuff741782011-06-27 16:27:39 +0900739 return -ENOENT;
Masami Hiramatsu146a1432010-04-12 13:17:42 -0400740
Masami Hiramatsuff741782011-06-27 16:27:39 +0900741 ret = debuginfo__find_line_range(dinfo, lr);
Masami Hiramatsu811dd2a2015-03-06 16:31:22 +0900742 if (!ret) { /* Not found, retry with an alternative */
743 ret = get_alternative_line_range(dinfo, lr, module, user);
744 if (!ret)
745 ret = debuginfo__find_line_range(dinfo, lr);
746 }
Masami Hiramatsuff741782011-06-27 16:27:39 +0900747 debuginfo__delete(dinfo);
Masami Hiramatsu5ee05b82014-06-06 07:14:06 +0000748 if (ret == 0 || ret == -ENOENT) {
Masami Hiramatsu146a1432010-04-12 13:17:42 -0400749 pr_warning("Specified source line is not found.\n");
750 return -ENOENT;
751 } else if (ret < 0) {
Masami Hiramatsu5ee05b82014-06-06 07:14:06 +0000752 pr_warning("Debuginfo analysis failed.\n");
Masami Hiramatsu146a1432010-04-12 13:17:42 -0400753 return ret;
754 }
Masami Hiramatsu4b4da7f2010-03-22 13:10:26 -0300755
Masami Hiramatsu7cf0b792010-07-09 18:28:59 +0900756 /* Convert source file path */
757 tmp = lr->path;
Masami Hiramatsu6a330a32010-07-09 18:29:11 +0900758 ret = get_real_path(tmp, lr->comp_dir, &lr->path);
He Kuanga78604d2015-03-04 18:01:42 +0800759
760 /* Free old path when new path is assigned */
761 if (tmp != lr->path)
762 free(tmp);
763
Masami Hiramatsu7cf0b792010-07-09 18:28:59 +0900764 if (ret < 0) {
Masami Hiramatsu5ee05b82014-06-06 07:14:06 +0000765 pr_warning("Failed to find source file path.\n");
Masami Hiramatsu7cf0b792010-07-09 18:28:59 +0900766 return ret;
767 }
768
Masami Hiramatsu4b4da7f2010-03-22 13:10:26 -0300769 setup_pager();
770
771 if (lr->function)
Masami Hiramatsu8737ebd2011-02-10 18:08:16 +0900772 fprintf(stdout, "<%s@%s:%d>\n", lr->function, lr->path,
Masami Hiramatsu4b4da7f2010-03-22 13:10:26 -0300773 lr->start - lr->offset);
774 else
Franck Bui-Huu62c15fc2010-12-20 15:18:00 +0100775 fprintf(stdout, "<%s:%d>\n", lr->path, lr->start);
Masami Hiramatsu4b4da7f2010-03-22 13:10:26 -0300776
777 fp = fopen(lr->path, "r");
Masami Hiramatsu146a1432010-04-12 13:17:42 -0400778 if (fp == NULL) {
779 pr_warning("Failed to open %s: %s\n", lr->path,
Masami Hiramatsu5f03cba2014-08-14 02:22:34 +0000780 strerror_r(errno, sbuf, sizeof(sbuf)));
Masami Hiramatsu146a1432010-04-12 13:17:42 -0400781 return -errno;
782 }
Masami Hiramatsu4b4da7f2010-03-22 13:10:26 -0300783 /* Skip to starting line number */
Franck Bui-Huu44b81e92010-12-20 15:18:02 +0100784 while (l < lr->start) {
Franck Bui-Huufde52db2010-12-20 15:18:04 +0100785 ret = skip_one_line(fp, l++);
Franck Bui-Huu44b81e92010-12-20 15:18:02 +0100786 if (ret < 0)
787 goto end;
788 }
Masami Hiramatsu4b4da7f2010-03-22 13:10:26 -0300789
Masami Hiramatsu5a622572014-02-06 05:32:09 +0000790 intlist__for_each(ln, lr->line_list) {
791 for (; ln->i > l; l++) {
Franck Bui-Huufde52db2010-12-20 15:18:04 +0100792 ret = show_one_line(fp, l - lr->offset);
Franck Bui-Huu44b81e92010-12-20 15:18:02 +0100793 if (ret < 0)
794 goto end;
795 }
Franck Bui-Huufde52db2010-12-20 15:18:04 +0100796 ret = show_one_line_with_num(fp, l++ - lr->offset);
Masami Hiramatsu146a1432010-04-12 13:17:42 -0400797 if (ret < 0)
798 goto end;
Masami Hiramatsu4b4da7f2010-03-22 13:10:26 -0300799 }
800
801 if (lr->end == INT_MAX)
802 lr->end = l + NR_ADDITIONAL_LINES;
Franck Bui-Huufde52db2010-12-20 15:18:04 +0100803 while (l <= lr->end) {
804 ret = show_one_line_or_eof(fp, l++ - lr->offset);
805 if (ret <= 0)
Franck Bui-Huu44b81e92010-12-20 15:18:02 +0100806 break;
807 }
Masami Hiramatsu146a1432010-04-12 13:17:42 -0400808end:
Masami Hiramatsu4b4da7f2010-03-22 13:10:26 -0300809 fclose(fp);
Masami Hiramatsu146a1432010-04-12 13:17:42 -0400810 return ret;
Masami Hiramatsu4b4da7f2010-03-22 13:10:26 -0300811}
812
Masami Hiramatsu2b394bc2014-09-17 08:40:54 +0000813int show_line_range(struct line_range *lr, const char *module, bool user)
Masami Hiramatsuee45b6c2014-02-06 05:32:04 +0000814{
815 int ret;
816
Masami Hiramatsu2b394bc2014-09-17 08:40:54 +0000817 ret = init_symbol_maps(user);
Masami Hiramatsuee45b6c2014-02-06 05:32:04 +0000818 if (ret < 0)
819 return ret;
Masami Hiramatsu811dd2a2015-03-06 16:31:22 +0900820 ret = __show_line_range(lr, module, user);
Masami Hiramatsuee45b6c2014-02-06 05:32:04 +0000821 exit_symbol_maps();
822
823 return ret;
824}
825
Masami Hiramatsuff741782011-06-27 16:27:39 +0900826static int show_available_vars_at(struct debuginfo *dinfo,
827 struct perf_probe_event *pev,
Masami Hiramatsuddb2f582015-05-08 10:03:31 +0900828 struct strfilter *_filter)
Masami Hiramatsucf6eb482010-10-21 19:13:23 +0900829{
830 char *buf;
Masami Hiramatsubd09d7b2011-01-20 23:15:39 +0900831 int ret, i, nvars;
Masami Hiramatsucf6eb482010-10-21 19:13:23 +0900832 struct str_node *node;
833 struct variable_list *vls = NULL, *vl;
Masami Hiramatsu9b118ac2015-03-06 16:31:20 +0900834 struct perf_probe_point tmp;
Masami Hiramatsubd09d7b2011-01-20 23:15:39 +0900835 const char *var;
Masami Hiramatsucf6eb482010-10-21 19:13:23 +0900836
837 buf = synthesize_perf_probe_point(&pev->point);
838 if (!buf)
839 return -EINVAL;
840 pr_debug("Searching variables at %s\n", buf);
841
Masami Hiramatsuddb2f582015-05-08 10:03:31 +0900842 ret = debuginfo__find_available_vars_at(dinfo, pev, &vls);
Masami Hiramatsu9b118ac2015-03-06 16:31:20 +0900843 if (!ret) { /* Not found, retry with an alternative */
Masami Hiramatsu44225522015-05-08 10:03:28 +0900844 ret = get_alternative_probe_event(dinfo, pev, &tmp);
Masami Hiramatsu9b118ac2015-03-06 16:31:20 +0900845 if (!ret) {
846 ret = debuginfo__find_available_vars_at(dinfo, pev,
Masami Hiramatsuddb2f582015-05-08 10:03:31 +0900847 &vls);
Masami Hiramatsu9b118ac2015-03-06 16:31:20 +0900848 /* Release the old probe_point */
849 clear_perf_probe_point(&tmp);
850 }
851 }
Masami Hiramatsubd09d7b2011-01-20 23:15:39 +0900852 if (ret <= 0) {
Masami Hiramatsu69e96ea2014-06-06 07:13:59 +0000853 if (ret == 0 || ret == -ENOENT) {
854 pr_err("Failed to find the address of %s\n", buf);
855 ret = -ENOENT;
856 } else
857 pr_warning("Debuginfo analysis failed.\n");
Masami Hiramatsubd09d7b2011-01-20 23:15:39 +0900858 goto end;
859 }
Masami Hiramatsu69e96ea2014-06-06 07:13:59 +0000860
Masami Hiramatsubd09d7b2011-01-20 23:15:39 +0900861 /* Some variables are found */
862 fprintf(stdout, "Available variables at %s\n", buf);
863 for (i = 0; i < ret; i++) {
864 vl = &vls[i];
865 /*
866 * A probe point might be converted to
867 * several trace points.
868 */
869 fprintf(stdout, "\t@<%s+%lu>\n", vl->point.symbol,
870 vl->point.offset);
Arnaldo Carvalho de Melo74cf2492013-12-27 16:55:14 -0300871 zfree(&vl->point.symbol);
Masami Hiramatsubd09d7b2011-01-20 23:15:39 +0900872 nvars = 0;
873 if (vl->vars) {
874 strlist__for_each(node, vl->vars) {
875 var = strchr(node->s, '\t') + 1;
876 if (strfilter__compare(_filter, var)) {
877 fprintf(stdout, "\t\t%s\n", node->s);
878 nvars++;
879 }
880 }
881 strlist__delete(vl->vars);
882 }
883 if (nvars == 0)
884 fprintf(stdout, "\t\t(No matched variables)\n");
885 }
886 free(vls);
887end:
Masami Hiramatsucf6eb482010-10-21 19:13:23 +0900888 free(buf);
889 return ret;
890}
891
892/* Show available variables on given probe point */
893int show_available_vars(struct perf_probe_event *pevs, int npevs,
Masami Hiramatsuddb2f582015-05-08 10:03:31 +0900894 struct strfilter *_filter)
Masami Hiramatsucf6eb482010-10-21 19:13:23 +0900895{
Masami Hiramatsuff741782011-06-27 16:27:39 +0900896 int i, ret = 0;
897 struct debuginfo *dinfo;
Masami Hiramatsucf6eb482010-10-21 19:13:23 +0900898
Masami Hiramatsu2b394bc2014-09-17 08:40:54 +0000899 ret = init_symbol_maps(pevs->uprobes);
Masami Hiramatsucf6eb482010-10-21 19:13:23 +0900900 if (ret < 0)
901 return ret;
902
Masami Hiramatsu44225522015-05-08 10:03:28 +0900903 dinfo = open_debuginfo(pevs->target, false);
Masami Hiramatsuff741782011-06-27 16:27:39 +0900904 if (!dinfo) {
Masami Hiramatsuee45b6c2014-02-06 05:32:04 +0000905 ret = -ENOENT;
906 goto out;
Masami Hiramatsuff741782011-06-27 16:27:39 +0900907 }
908
Masami Hiramatsucf6eb482010-10-21 19:13:23 +0900909 setup_pager();
910
Masami Hiramatsuff741782011-06-27 16:27:39 +0900911 for (i = 0; i < npevs && ret >= 0; i++)
Masami Hiramatsuddb2f582015-05-08 10:03:31 +0900912 ret = show_available_vars_at(dinfo, &pevs[i], _filter);
Masami Hiramatsuff741782011-06-27 16:27:39 +0900913
914 debuginfo__delete(dinfo);
Masami Hiramatsuee45b6c2014-02-06 05:32:04 +0000915out:
916 exit_symbol_maps();
Masami Hiramatsucf6eb482010-10-21 19:13:23 +0900917 return ret;
918}
919
Ingo Molnar89fe8082013-09-30 12:07:11 +0200920#else /* !HAVE_DWARF_SUPPORT */
Masami Hiramatsu4b4da7f2010-03-22 13:10:26 -0300921
Masami Hiramatsu5a6f6312014-02-06 05:32:23 +0000922static int
923find_perf_probe_point_from_dwarf(struct probe_trace_point *tp __maybe_unused,
924 struct perf_probe_point *pp __maybe_unused,
925 bool is_kprobe __maybe_unused)
Masami Hiramatsu4b4da7f2010-03-22 13:10:26 -0300926{
Masami Hiramatsu5a6f6312014-02-06 05:32:23 +0000927 return -ENOSYS;
Masami Hiramatsu4b4da7f2010-03-22 13:10:26 -0300928}
929
Srikar Dronamraju0e608362010-07-29 19:43:51 +0530930static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
Masami Hiramatsuddb2f582015-05-08 10:03:31 +0900931 struct probe_trace_event **tevs __maybe_unused)
Masami Hiramatsu4b4da7f2010-03-22 13:10:26 -0300932{
Masami Hiramatsu146a1432010-04-12 13:17:42 -0400933 if (perf_probe_event_need_dwarf(pev)) {
934 pr_warning("Debuginfo-analysis is not supported.\n");
935 return -ENOSYS;
936 }
Srikar Dronamraju225466f2012-04-16 17:39:09 +0530937
Masami Hiramatsu4b4da7f2010-03-22 13:10:26 -0300938 return 0;
939}
940
Irina Tirdea1d037ca2012-09-11 01:15:03 +0300941int show_line_range(struct line_range *lr __maybe_unused,
Masami Hiramatsu2b394bc2014-09-17 08:40:54 +0000942 const char *module __maybe_unused,
943 bool user __maybe_unused)
Masami Hiramatsu4b4da7f2010-03-22 13:10:26 -0300944{
Masami Hiramatsu146a1432010-04-12 13:17:42 -0400945 pr_warning("Debuginfo-analysis is not supported.\n");
946 return -ENOSYS;
Masami Hiramatsu4b4da7f2010-03-22 13:10:26 -0300947}
948
Irina Tirdea1d037ca2012-09-11 01:15:03 +0300949int show_available_vars(struct perf_probe_event *pevs __maybe_unused,
Masami Hiramatsuddb2f582015-05-08 10:03:31 +0900950 int npevs __maybe_unused,
951 struct strfilter *filter __maybe_unused)
Masami Hiramatsucf6eb482010-10-21 19:13:23 +0900952{
953 pr_warning("Debuginfo-analysis is not supported.\n");
954 return -ENOSYS;
955}
Masami Hiramatsue0faa8d2010-03-16 18:05:37 -0400956#endif
957
Masami Hiramatsue53b00d2014-01-16 09:39:47 +0000958void line_range__clear(struct line_range *lr)
959{
Masami Hiramatsue53b00d2014-01-16 09:39:47 +0000960 free(lr->function);
961 free(lr->file);
962 free(lr->path);
963 free(lr->comp_dir);
Masami Hiramatsu5a622572014-02-06 05:32:09 +0000964 intlist__delete(lr->line_list);
Masami Hiramatsue53b00d2014-01-16 09:39:47 +0000965 memset(lr, 0, sizeof(*lr));
966}
967
Masami Hiramatsu5a622572014-02-06 05:32:09 +0000968int line_range__init(struct line_range *lr)
Masami Hiramatsue53b00d2014-01-16 09:39:47 +0000969{
970 memset(lr, 0, sizeof(*lr));
Masami Hiramatsu5a622572014-02-06 05:32:09 +0000971 lr->line_list = intlist__new(NULL);
972 if (!lr->line_list)
973 return -ENOMEM;
974 else
975 return 0;
Masami Hiramatsue53b00d2014-01-16 09:39:47 +0000976}
977
Franck Bui-Huu21dd9ae2010-12-20 15:18:05 +0100978static int parse_line_num(char **ptr, int *val, const char *what)
979{
980 const char *start = *ptr;
981
982 errno = 0;
983 *val = strtol(*ptr, ptr, 0);
984 if (errno || *ptr == start) {
985 semantic_error("'%s' is not a valid number.\n", what);
986 return -EINVAL;
987 }
988 return 0;
989}
990
Masami Hiramatsu573709f2015-05-06 21:46:47 +0900991/* Check the name is good for event, group or function */
992static bool is_c_func_name(const char *name)
993{
994 if (!isalpha(*name) && *name != '_')
995 return false;
996 while (*++name != '\0') {
997 if (!isalpha(*name) && !isdigit(*name) && *name != '_')
998 return false;
999 }
1000 return true;
1001}
1002
Franck Bui-Huu9d95b582010-12-20 15:18:03 +01001003/*
1004 * Stuff 'lr' according to the line range described by 'arg'.
1005 * The line range syntax is described by:
1006 *
1007 * SRC[:SLN[+NUM|-ELN]]
Masami Hiramatsue116dfa2011-02-10 18:08:10 +09001008 * FNC[@SRC][:SLN[+NUM|-ELN]]
Franck Bui-Huu9d95b582010-12-20 15:18:03 +01001009 */
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001010int parse_line_range_desc(const char *arg, struct line_range *lr)
Masami Hiramatsu631c9de2010-01-06 09:45:34 -05001011{
Masami Hiramatsue116dfa2011-02-10 18:08:10 +09001012 char *range, *file, *name = strdup(arg);
Franck Bui-Huu21dd9ae2010-12-20 15:18:05 +01001013 int err;
Franck Bui-Huu9d95b582010-12-20 15:18:03 +01001014
Franck Bui-Huu21dd9ae2010-12-20 15:18:05 +01001015 if (!name)
1016 return -ENOMEM;
1017
1018 lr->start = 0;
1019 lr->end = INT_MAX;
1020
1021 range = strchr(name, ':');
1022 if (range) {
1023 *range++ = '\0';
1024
1025 err = parse_line_num(&range, &lr->start, "start line");
1026 if (err)
1027 goto err;
1028
1029 if (*range == '+' || *range == '-') {
1030 const char c = *range++;
1031
1032 err = parse_line_num(&range, &lr->end, "end line");
1033 if (err)
1034 goto err;
1035
1036 if (c == '+') {
1037 lr->end += lr->start;
1038 /*
1039 * Adjust the number of lines here.
1040 * If the number of lines == 1, the
1041 * the end of line should be equal to
1042 * the start of line.
1043 */
1044 lr->end--;
1045 }
1046 }
1047
Masami Hiramatsud3b63d72010-04-14 18:39:42 -04001048 pr_debug("Line range is %d to %d\n", lr->start, lr->end);
Franck Bui-Huu21dd9ae2010-12-20 15:18:05 +01001049
1050 err = -EINVAL;
Masami Hiramatsud3b63d72010-04-14 18:39:42 -04001051 if (lr->start > lr->end) {
Masami Hiramatsu631c9de2010-01-06 09:45:34 -05001052 semantic_error("Start line must be smaller"
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001053 " than end line.\n");
Franck Bui-Huu21dd9ae2010-12-20 15:18:05 +01001054 goto err;
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001055 }
Franck Bui-Huu21dd9ae2010-12-20 15:18:05 +01001056 if (*range != '\0') {
1057 semantic_error("Tailing with invalid str '%s'.\n", range);
1058 goto err;
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001059 }
Masami Hiramatsud3b63d72010-04-14 18:39:42 -04001060 }
Masami Hiramatsu02b95da2010-04-12 13:17:56 -04001061
Masami Hiramatsue116dfa2011-02-10 18:08:10 +09001062 file = strchr(name, '@');
1063 if (file) {
1064 *file = '\0';
1065 lr->file = strdup(++file);
1066 if (lr->file == NULL) {
1067 err = -ENOMEM;
1068 goto err;
1069 }
1070 lr->function = name;
Masami Hiramatsu573709f2015-05-06 21:46:47 +09001071 } else if (strchr(name, '/') || strchr(name, '.'))
Franck Bui-Huu21dd9ae2010-12-20 15:18:05 +01001072 lr->file = name;
Masami Hiramatsu573709f2015-05-06 21:46:47 +09001073 else if (is_c_func_name(name))/* We reuse it for checking funcname */
Franck Bui-Huu21dd9ae2010-12-20 15:18:05 +01001074 lr->function = name;
Masami Hiramatsu573709f2015-05-06 21:46:47 +09001075 else { /* Invalid name */
1076 semantic_error("'%s' is not a valid function name.\n", name);
1077 err = -EINVAL;
1078 goto err;
1079 }
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001080
1081 return 0;
Franck Bui-Huu21dd9ae2010-12-20 15:18:05 +01001082err:
1083 free(name);
1084 return err;
Masami Hiramatsu631c9de2010-01-06 09:45:34 -05001085}
1086
Masami Hiramatsu50656ee2009-11-30 19:19:58 -05001087/* Parse probepoint definition. */
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001088static int parse_perf_probe_point(char *arg, struct perf_probe_event *pev)
Masami Hiramatsu50656ee2009-11-30 19:19:58 -05001089{
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001090 struct perf_probe_point *pp = &pev->point;
Masami Hiramatsu50656ee2009-11-30 19:19:58 -05001091 char *ptr, *tmp;
1092 char c, nc = 0;
Naveen N. Rao3099c022015-04-28 17:35:34 +05301093 bool file_spec = false;
Masami Hiramatsu50656ee2009-11-30 19:19:58 -05001094 /*
1095 * <Syntax>
Masami Hiramatsu2a9c8c32010-02-25 08:36:12 -05001096 * perf probe [EVENT=]SRC[:LN|;PTN]
1097 * perf probe [EVENT=]FUNC[@SRC][+OFFS|%return|:LN|;PAT]
Masami Hiramatsuaf663d72009-12-15 10:32:18 -05001098 *
1099 * TODO:Group name support
Masami Hiramatsu50656ee2009-11-30 19:19:58 -05001100 */
Wang Nane59d29e2015-04-28 08:46:09 +00001101 if (!arg)
1102 return -EINVAL;
Masami Hiramatsu50656ee2009-11-30 19:19:58 -05001103
Masami Hiramatsu2a9c8c32010-02-25 08:36:12 -05001104 ptr = strpbrk(arg, ";=@+%");
1105 if (ptr && *ptr == '=') { /* Event name */
Masami Hiramatsuaf663d72009-12-15 10:32:18 -05001106 *ptr = '\0';
1107 tmp = ptr + 1;
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001108 if (strchr(arg, ':')) {
1109 semantic_error("Group name is not supported yet.\n");
1110 return -ENOTSUP;
1111 }
Masami Hiramatsu573709f2015-05-06 21:46:47 +09001112 if (!is_c_func_name(arg)) {
Masami Hiramatsub7702a22009-12-16 17:24:15 -05001113 semantic_error("%s is bad for event name -it must "
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001114 "follow C symbol-naming rule.\n", arg);
1115 return -EINVAL;
1116 }
Masami Hiramatsu02b95da2010-04-12 13:17:56 -04001117 pev->event = strdup(arg);
1118 if (pev->event == NULL)
1119 return -ENOMEM;
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001120 pev->group = NULL;
Masami Hiramatsuaf663d72009-12-15 10:32:18 -05001121 arg = tmp;
1122 }
1123
Naveen N. Rao3099c022015-04-28 17:35:34 +05301124 /*
1125 * Check arg is function or file name and copy it.
1126 *
1127 * We consider arg to be a file spec if and only if it satisfies
1128 * all of the below criteria::
1129 * - it does not include any of "+@%",
1130 * - it includes one of ":;", and
1131 * - it has a period '.' in the name.
1132 *
1133 * Otherwise, we consider arg to be a function specification.
1134 */
1135 if (!strpbrk(arg, "+@%") && (ptr = strpbrk(arg, ";:")) != NULL) {
1136 /* This is a file spec if it includes a '.' before ; or : */
1137 if (memchr(arg, '.', ptr - arg))
1138 file_spec = true;
1139 }
1140
Masami Hiramatsu2a9c8c32010-02-25 08:36:12 -05001141 ptr = strpbrk(arg, ";:+@%");
Masami Hiramatsu50656ee2009-11-30 19:19:58 -05001142 if (ptr) {
1143 nc = *ptr;
1144 *ptr++ = '\0';
1145 }
1146
Masami Hiramatsu02b95da2010-04-12 13:17:56 -04001147 tmp = strdup(arg);
1148 if (tmp == NULL)
1149 return -ENOMEM;
1150
Naveen N. Rao3099c022015-04-28 17:35:34 +05301151 if (file_spec)
Masami Hiramatsu02b95da2010-04-12 13:17:56 -04001152 pp->file = tmp;
Naveen N. Rao3099c022015-04-28 17:35:34 +05301153 else
Masami Hiramatsu02b95da2010-04-12 13:17:56 -04001154 pp->function = tmp;
Masami Hiramatsu50656ee2009-11-30 19:19:58 -05001155
1156 /* Parse other options */
1157 while (ptr) {
1158 arg = ptr;
1159 c = nc;
Masami Hiramatsu2a9c8c32010-02-25 08:36:12 -05001160 if (c == ';') { /* Lazy pattern must be the last part */
Masami Hiramatsu02b95da2010-04-12 13:17:56 -04001161 pp->lazy_line = strdup(arg);
1162 if (pp->lazy_line == NULL)
1163 return -ENOMEM;
Masami Hiramatsu2a9c8c32010-02-25 08:36:12 -05001164 break;
1165 }
1166 ptr = strpbrk(arg, ";:+@%");
Masami Hiramatsu50656ee2009-11-30 19:19:58 -05001167 if (ptr) {
1168 nc = *ptr;
1169 *ptr++ = '\0';
1170 }
1171 switch (c) {
1172 case ':': /* Line number */
1173 pp->line = strtoul(arg, &tmp, 0);
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001174 if (*tmp != '\0') {
Masami Hiramatsu2a9c8c32010-02-25 08:36:12 -05001175 semantic_error("There is non-digit char"
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001176 " in line number.\n");
1177 return -EINVAL;
1178 }
Masami Hiramatsu50656ee2009-11-30 19:19:58 -05001179 break;
1180 case '+': /* Byte offset from a symbol */
1181 pp->offset = strtoul(arg, &tmp, 0);
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001182 if (*tmp != '\0') {
Masami Hiramatsu2a9c8c32010-02-25 08:36:12 -05001183 semantic_error("There is non-digit character"
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001184 " in offset.\n");
1185 return -EINVAL;
1186 }
Masami Hiramatsu50656ee2009-11-30 19:19:58 -05001187 break;
1188 case '@': /* File name */
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001189 if (pp->file) {
1190 semantic_error("SRC@SRC is not allowed.\n");
1191 return -EINVAL;
1192 }
Masami Hiramatsu02b95da2010-04-12 13:17:56 -04001193 pp->file = strdup(arg);
1194 if (pp->file == NULL)
1195 return -ENOMEM;
Masami Hiramatsu50656ee2009-11-30 19:19:58 -05001196 break;
1197 case '%': /* Probe places */
1198 if (strcmp(arg, "return") == 0) {
1199 pp->retprobe = 1;
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001200 } else { /* Others not supported yet */
1201 semantic_error("%%%s is not supported.\n", arg);
1202 return -ENOTSUP;
1203 }
Masami Hiramatsu50656ee2009-11-30 19:19:58 -05001204 break;
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001205 default: /* Buggy case */
1206 pr_err("This program has a bug at %s:%d.\n",
1207 __FILE__, __LINE__);
1208 return -ENOTSUP;
Masami Hiramatsu50656ee2009-11-30 19:19:58 -05001209 break;
1210 }
1211 }
1212
1213 /* Exclusion check */
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001214 if (pp->lazy_line && pp->line) {
Masami Hiramatsu0e43e5d2010-12-17 22:12:11 +09001215 semantic_error("Lazy pattern can't be used with"
1216 " line number.\n");
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001217 return -EINVAL;
1218 }
Masami Hiramatsu2a9c8c32010-02-25 08:36:12 -05001219
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001220 if (pp->lazy_line && pp->offset) {
Masami Hiramatsu0e43e5d2010-12-17 22:12:11 +09001221 semantic_error("Lazy pattern can't be used with offset.\n");
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001222 return -EINVAL;
1223 }
Masami Hiramatsu2a9c8c32010-02-25 08:36:12 -05001224
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001225 if (pp->line && pp->offset) {
Masami Hiramatsu0e43e5d2010-12-17 22:12:11 +09001226 semantic_error("Offset can't be used with line number.\n");
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001227 return -EINVAL;
1228 }
Masami Hiramatsu50656ee2009-11-30 19:19:58 -05001229
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001230 if (!pp->line && !pp->lazy_line && pp->file && !pp->function) {
Masami Hiramatsu2a9c8c32010-02-25 08:36:12 -05001231 semantic_error("File always requires line number or "
Masami Hiramatsu0e43e5d2010-12-17 22:12:11 +09001232 "lazy pattern.\n");
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001233 return -EINVAL;
1234 }
Masami Hiramatsu50656ee2009-11-30 19:19:58 -05001235
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001236 if (pp->offset && !pp->function) {
Masami Hiramatsu0e43e5d2010-12-17 22:12:11 +09001237 semantic_error("Offset requires an entry function.\n");
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001238 return -EINVAL;
1239 }
Masami Hiramatsu50656ee2009-11-30 19:19:58 -05001240
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001241 if (pp->retprobe && !pp->function) {
Masami Hiramatsu0e43e5d2010-12-17 22:12:11 +09001242 semantic_error("Return probe requires an entry function.\n");
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001243 return -EINVAL;
1244 }
Masami Hiramatsu50656ee2009-11-30 19:19:58 -05001245
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001246 if ((pp->offset || pp->line || pp->lazy_line) && pp->retprobe) {
Masami Hiramatsu2a9c8c32010-02-25 08:36:12 -05001247 semantic_error("Offset/Line/Lazy pattern can't be used with "
Masami Hiramatsu0e43e5d2010-12-17 22:12:11 +09001248 "return probe.\n");
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001249 return -EINVAL;
1250 }
Masami Hiramatsu50656ee2009-11-30 19:19:58 -05001251
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001252 pr_debug("symbol:%s file:%s line:%d offset:%lu return:%d lazy:%s\n",
Masami Hiramatsu2a9c8c32010-02-25 08:36:12 -05001253 pp->function, pp->file, pp->line, pp->offset, pp->retprobe,
1254 pp->lazy_line);
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001255 return 0;
Masami Hiramatsu50656ee2009-11-30 19:19:58 -05001256}
1257
Masami Hiramatsu7df2f322010-03-16 18:06:26 -04001258/* Parse perf-probe event argument */
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001259static int parse_perf_probe_arg(char *str, struct perf_probe_arg *arg)
Masami Hiramatsu7df2f322010-03-16 18:06:26 -04001260{
Masami Hiramatsub2a3c122010-05-19 15:57:42 -04001261 char *tmp, *goodname;
Masami Hiramatsu7df2f322010-03-16 18:06:26 -04001262 struct perf_probe_arg_field **fieldp;
1263
1264 pr_debug("parsing arg: %s into ", str);
1265
Masami Hiramatsu48481932010-04-12 13:16:53 -04001266 tmp = strchr(str, '=');
1267 if (tmp) {
Masami Hiramatsu02b95da2010-04-12 13:17:56 -04001268 arg->name = strndup(str, tmp - str);
1269 if (arg->name == NULL)
1270 return -ENOMEM;
Masami Hiramatsu11a1ca32010-04-12 13:17:22 -04001271 pr_debug("name:%s ", arg->name);
Masami Hiramatsu48481932010-04-12 13:16:53 -04001272 str = tmp + 1;
1273 }
1274
Masami Hiramatsu11a1ca32010-04-12 13:17:22 -04001275 tmp = strchr(str, ':');
1276 if (tmp) { /* Type setting */
1277 *tmp = '\0';
Masami Hiramatsu02b95da2010-04-12 13:17:56 -04001278 arg->type = strdup(tmp + 1);
1279 if (arg->type == NULL)
1280 return -ENOMEM;
Masami Hiramatsu11a1ca32010-04-12 13:17:22 -04001281 pr_debug("type:%s ", arg->type);
1282 }
1283
Masami Hiramatsub2a3c122010-05-19 15:57:42 -04001284 tmp = strpbrk(str, "-.[");
Masami Hiramatsu7df2f322010-03-16 18:06:26 -04001285 if (!is_c_varname(str) || !tmp) {
1286 /* A variable, register, symbol or special value */
Masami Hiramatsu02b95da2010-04-12 13:17:56 -04001287 arg->var = strdup(str);
1288 if (arg->var == NULL)
1289 return -ENOMEM;
Masami Hiramatsu48481932010-04-12 13:16:53 -04001290 pr_debug("%s\n", arg->var);
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001291 return 0;
Masami Hiramatsu7df2f322010-03-16 18:06:26 -04001292 }
1293
Masami Hiramatsub2a3c122010-05-19 15:57:42 -04001294 /* Structure fields or array element */
Masami Hiramatsu02b95da2010-04-12 13:17:56 -04001295 arg->var = strndup(str, tmp - str);
1296 if (arg->var == NULL)
1297 return -ENOMEM;
Masami Hiramatsub2a3c122010-05-19 15:57:42 -04001298 goodname = arg->var;
Masami Hiramatsu48481932010-04-12 13:16:53 -04001299 pr_debug("%s, ", arg->var);
Masami Hiramatsu7df2f322010-03-16 18:06:26 -04001300 fieldp = &arg->field;
1301
1302 do {
Masami Hiramatsue334016f12010-04-12 13:17:49 -04001303 *fieldp = zalloc(sizeof(struct perf_probe_arg_field));
1304 if (*fieldp == NULL)
1305 return -ENOMEM;
Masami Hiramatsub2a3c122010-05-19 15:57:42 -04001306 if (*tmp == '[') { /* Array */
1307 str = tmp;
1308 (*fieldp)->index = strtol(str + 1, &tmp, 0);
Masami Hiramatsu7df2f322010-03-16 18:06:26 -04001309 (*fieldp)->ref = true;
Masami Hiramatsub2a3c122010-05-19 15:57:42 -04001310 if (*tmp != ']' || tmp == str + 1) {
1311 semantic_error("Array index must be a"
1312 " number.\n");
1313 return -EINVAL;
1314 }
1315 tmp++;
1316 if (*tmp == '\0')
1317 tmp = NULL;
1318 } else { /* Structure */
1319 if (*tmp == '.') {
1320 str = tmp + 1;
1321 (*fieldp)->ref = false;
1322 } else if (tmp[1] == '>') {
1323 str = tmp + 2;
1324 (*fieldp)->ref = true;
1325 } else {
1326 semantic_error("Argument parse error: %s\n",
1327 str);
1328 return -EINVAL;
1329 }
1330 tmp = strpbrk(str, "-.[");
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001331 }
Masami Hiramatsu7df2f322010-03-16 18:06:26 -04001332 if (tmp) {
Masami Hiramatsu02b95da2010-04-12 13:17:56 -04001333 (*fieldp)->name = strndup(str, tmp - str);
1334 if ((*fieldp)->name == NULL)
1335 return -ENOMEM;
Masami Hiramatsub2a3c122010-05-19 15:57:42 -04001336 if (*str != '[')
1337 goodname = (*fieldp)->name;
Masami Hiramatsu7df2f322010-03-16 18:06:26 -04001338 pr_debug("%s(%d), ", (*fieldp)->name, (*fieldp)->ref);
1339 fieldp = &(*fieldp)->next;
1340 }
1341 } while (tmp);
Masami Hiramatsu02b95da2010-04-12 13:17:56 -04001342 (*fieldp)->name = strdup(str);
1343 if ((*fieldp)->name == NULL)
1344 return -ENOMEM;
Masami Hiramatsub2a3c122010-05-19 15:57:42 -04001345 if (*str != '[')
1346 goodname = (*fieldp)->name;
Masami Hiramatsu7df2f322010-03-16 18:06:26 -04001347 pr_debug("%s(%d)\n", (*fieldp)->name, (*fieldp)->ref);
Masami Hiramatsudf0faf42010-04-12 13:17:00 -04001348
Masami Hiramatsub2a3c122010-05-19 15:57:42 -04001349 /* If no name is specified, set the last field name (not array index)*/
Masami Hiramatsu02b95da2010-04-12 13:17:56 -04001350 if (!arg->name) {
Masami Hiramatsub2a3c122010-05-19 15:57:42 -04001351 arg->name = strdup(goodname);
Masami Hiramatsu02b95da2010-04-12 13:17:56 -04001352 if (arg->name == NULL)
1353 return -ENOMEM;
1354 }
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001355 return 0;
Masami Hiramatsu7df2f322010-03-16 18:06:26 -04001356}
1357
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001358/* Parse perf-probe event command */
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001359int parse_perf_probe_command(const char *cmd, struct perf_probe_event *pev)
Masami Hiramatsu50656ee2009-11-30 19:19:58 -05001360{
Masami Hiramatsue1c01d62009-11-30 19:20:05 -05001361 char **argv;
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001362 int argc, i, ret = 0;
Masami Hiramatsufac13fd2009-12-15 10:31:14 -05001363
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001364 argv = argv_split(cmd, &argc);
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001365 if (!argv) {
1366 pr_debug("Failed to split arguments.\n");
1367 return -ENOMEM;
1368 }
1369 if (argc - 1 > MAX_PROBE_ARGS) {
1370 semantic_error("Too many probe arguments (%d).\n", argc - 1);
1371 ret = -ERANGE;
1372 goto out;
1373 }
Masami Hiramatsu50656ee2009-11-30 19:19:58 -05001374 /* Parse probe point */
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001375 ret = parse_perf_probe_point(argv[0], pev);
1376 if (ret < 0)
1377 goto out;
Masami Hiramatsu50656ee2009-11-30 19:19:58 -05001378
Masami Hiramatsue1c01d62009-11-30 19:20:05 -05001379 /* Copy arguments and ensure return probe has no C argument */
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001380 pev->nargs = argc - 1;
Masami Hiramatsue334016f12010-04-12 13:17:49 -04001381 pev->args = zalloc(sizeof(struct perf_probe_arg) * pev->nargs);
1382 if (pev->args == NULL) {
1383 ret = -ENOMEM;
1384 goto out;
1385 }
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001386 for (i = 0; i < pev->nargs && ret >= 0; i++) {
1387 ret = parse_perf_probe_arg(argv[i + 1], &pev->args[i]);
1388 if (ret >= 0 &&
1389 is_c_varname(pev->args[i].var) && pev->point.retprobe) {
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001390 semantic_error("You can't specify local variable for"
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001391 " kretprobe.\n");
1392 ret = -EINVAL;
1393 }
Masami Hiramatsue1c01d62009-11-30 19:20:05 -05001394 }
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001395out:
Masami Hiramatsue1c01d62009-11-30 19:20:05 -05001396 argv_free(argv);
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001397
1398 return ret;
Masami Hiramatsu50656ee2009-11-30 19:19:58 -05001399}
1400
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001401/* Return true if this perf_probe_event requires debuginfo */
1402bool perf_probe_event_need_dwarf(struct perf_probe_event *pev)
Masami Hiramatsu4de189f2009-11-30 19:20:17 -05001403{
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001404 int i;
1405
1406 if (pev->point.file || pev->point.line || pev->point.lazy_line)
1407 return true;
1408
1409 for (i = 0; i < pev->nargs; i++)
Masami Hiramatsu48481932010-04-12 13:16:53 -04001410 if (is_c_varname(pev->args[i].var))
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001411 return true;
1412
1413 return false;
1414}
1415
Srikar Dronamraju0e608362010-07-29 19:43:51 +05301416/* Parse probe_events event into struct probe_point */
1417static int parse_probe_trace_command(const char *cmd,
Masami Hiramatsu190b57f2011-06-27 16:27:45 +09001418 struct probe_trace_event *tev)
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001419{
Srikar Dronamraju0e608362010-07-29 19:43:51 +05301420 struct probe_trace_point *tp = &tev->point;
Masami Hiramatsu4de189f2009-11-30 19:20:17 -05001421 char pr;
1422 char *p;
Irina Tirdeabcbd0042012-09-20 23:37:50 +03001423 char *argv0_str = NULL, *fmt, *fmt1_str, *fmt2_str, *fmt3_str;
Masami Hiramatsu4de189f2009-11-30 19:20:17 -05001424 int ret, i, argc;
1425 char **argv;
1426
Srikar Dronamraju0e608362010-07-29 19:43:51 +05301427 pr_debug("Parsing probe_events: %s\n", cmd);
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001428 argv = argv_split(cmd, &argc);
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001429 if (!argv) {
1430 pr_debug("Failed to split arguments.\n");
1431 return -ENOMEM;
1432 }
1433 if (argc < 2) {
1434 semantic_error("Too few probe arguments.\n");
1435 ret = -ERANGE;
1436 goto out;
1437 }
Masami Hiramatsu4de189f2009-11-30 19:20:17 -05001438
1439 /* Scan event and group name. */
Irina Tirdeabcbd0042012-09-20 23:37:50 +03001440 argv0_str = strdup(argv[0]);
1441 if (argv0_str == NULL) {
1442 ret = -ENOMEM;
1443 goto out;
1444 }
1445 fmt1_str = strtok_r(argv0_str, ":", &fmt);
1446 fmt2_str = strtok_r(NULL, "/", &fmt);
1447 fmt3_str = strtok_r(NULL, " \t", &fmt);
1448 if (fmt1_str == NULL || strlen(fmt1_str) != 1 || fmt2_str == NULL
1449 || fmt3_str == NULL) {
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001450 semantic_error("Failed to parse event name: %s\n", argv[0]);
1451 ret = -EINVAL;
1452 goto out;
1453 }
Irina Tirdeabcbd0042012-09-20 23:37:50 +03001454 pr = fmt1_str[0];
1455 tev->group = strdup(fmt2_str);
1456 tev->event = strdup(fmt3_str);
1457 if (tev->group == NULL || tev->event == NULL) {
1458 ret = -ENOMEM;
1459 goto out;
1460 }
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001461 pr_debug("Group:%s Event:%s probe:%c\n", tev->group, tev->event, pr);
Masami Hiramatsu4de189f2009-11-30 19:20:17 -05001462
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001463 tp->retprobe = (pr == 'r');
Masami Hiramatsu4de189f2009-11-30 19:20:17 -05001464
Masami Hiramatsu190b57f2011-06-27 16:27:45 +09001465 /* Scan module name(if there), function name and offset */
1466 p = strchr(argv[1], ':');
1467 if (p) {
1468 tp->module = strndup(argv[1], p - argv[1]);
1469 p++;
1470 } else
1471 p = argv[1];
Irina Tirdeabcbd0042012-09-20 23:37:50 +03001472 fmt1_str = strtok_r(p, "+", &fmt);
Masami Hiramatsu5a6f6312014-02-06 05:32:23 +00001473 if (fmt1_str[0] == '0') /* only the address started with 0x */
1474 tp->address = strtoul(fmt1_str, NULL, 0);
1475 else {
1476 /* Only the symbol-based probe has offset */
1477 tp->symbol = strdup(fmt1_str);
1478 if (tp->symbol == NULL) {
1479 ret = -ENOMEM;
1480 goto out;
1481 }
1482 fmt2_str = strtok_r(NULL, "", &fmt);
1483 if (fmt2_str == NULL)
1484 tp->offset = 0;
1485 else
1486 tp->offset = strtoul(fmt2_str, NULL, 10);
Irina Tirdeabcbd0042012-09-20 23:37:50 +03001487 }
Masami Hiramatsu4de189f2009-11-30 19:20:17 -05001488
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001489 tev->nargs = argc - 2;
Srikar Dronamraju0e608362010-07-29 19:43:51 +05301490 tev->args = zalloc(sizeof(struct probe_trace_arg) * tev->nargs);
Masami Hiramatsue334016f12010-04-12 13:17:49 -04001491 if (tev->args == NULL) {
1492 ret = -ENOMEM;
1493 goto out;
1494 }
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001495 for (i = 0; i < tev->nargs; i++) {
Masami Hiramatsu4de189f2009-11-30 19:20:17 -05001496 p = strchr(argv[i + 2], '=');
1497 if (p) /* We don't need which register is assigned. */
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001498 *p++ = '\0';
1499 else
1500 p = argv[i + 2];
Masami Hiramatsu02b95da2010-04-12 13:17:56 -04001501 tev->args[i].name = strdup(argv[i + 2]);
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001502 /* TODO: parse regs and offset */
Masami Hiramatsu02b95da2010-04-12 13:17:56 -04001503 tev->args[i].value = strdup(p);
1504 if (tev->args[i].name == NULL || tev->args[i].value == NULL) {
1505 ret = -ENOMEM;
1506 goto out;
1507 }
Masami Hiramatsu4de189f2009-11-30 19:20:17 -05001508 }
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001509 ret = 0;
1510out:
Irina Tirdeabcbd0042012-09-20 23:37:50 +03001511 free(argv0_str);
Masami Hiramatsu4de189f2009-11-30 19:20:17 -05001512 argv_free(argv);
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001513 return ret;
Masami Hiramatsu4de189f2009-11-30 19:20:17 -05001514}
1515
Masami Hiramatsu7df2f322010-03-16 18:06:26 -04001516/* Compose only probe arg */
1517int synthesize_perf_probe_arg(struct perf_probe_arg *pa, char *buf, size_t len)
1518{
1519 struct perf_probe_arg_field *field = pa->field;
1520 int ret;
1521 char *tmp = buf;
1522
Masami Hiramatsu48481932010-04-12 13:16:53 -04001523 if (pa->name && pa->var)
1524 ret = e_snprintf(tmp, len, "%s=%s", pa->name, pa->var);
1525 else
1526 ret = e_snprintf(tmp, len, "%s", pa->name ? pa->name : pa->var);
Masami Hiramatsu7df2f322010-03-16 18:06:26 -04001527 if (ret <= 0)
1528 goto error;
1529 tmp += ret;
1530 len -= ret;
1531
1532 while (field) {
Masami Hiramatsub2a3c122010-05-19 15:57:42 -04001533 if (field->name[0] == '[')
1534 ret = e_snprintf(tmp, len, "%s", field->name);
1535 else
1536 ret = e_snprintf(tmp, len, "%s%s",
1537 field->ref ? "->" : ".", field->name);
Masami Hiramatsu7df2f322010-03-16 18:06:26 -04001538 if (ret <= 0)
1539 goto error;
1540 tmp += ret;
1541 len -= ret;
1542 field = field->next;
1543 }
Masami Hiramatsu11a1ca32010-04-12 13:17:22 -04001544
1545 if (pa->type) {
1546 ret = e_snprintf(tmp, len, ":%s", pa->type);
1547 if (ret <= 0)
1548 goto error;
1549 tmp += ret;
1550 len -= ret;
1551 }
1552
Masami Hiramatsu7df2f322010-03-16 18:06:26 -04001553 return tmp - buf;
1554error:
Masami Hiramatsu5f03cba2014-08-14 02:22:34 +00001555 pr_debug("Failed to synthesize perf probe argument: %d\n", ret);
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001556 return ret;
Masami Hiramatsu7df2f322010-03-16 18:06:26 -04001557}
1558
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001559/* Compose only probe point (not argument) */
1560static char *synthesize_perf_probe_point(struct perf_probe_point *pp)
Masami Hiramatsu50656ee2009-11-30 19:19:58 -05001561{
Masami Hiramatsufb1587d2010-03-16 18:06:19 -04001562 char *buf, *tmp;
1563 char offs[32] = "", line[32] = "", file[32] = "";
1564 int ret, len;
Masami Hiramatsu50656ee2009-11-30 19:19:58 -05001565
Masami Hiramatsue334016f12010-04-12 13:17:49 -04001566 buf = zalloc(MAX_CMDLEN);
1567 if (buf == NULL) {
1568 ret = -ENOMEM;
1569 goto error;
1570 }
Masami Hiramatsu4de189f2009-11-30 19:20:17 -05001571 if (pp->offset) {
Masami Hiramatsufb1587d2010-03-16 18:06:19 -04001572 ret = e_snprintf(offs, 32, "+%lu", pp->offset);
Masami Hiramatsu4de189f2009-11-30 19:20:17 -05001573 if (ret <= 0)
1574 goto error;
1575 }
1576 if (pp->line) {
Masami Hiramatsufb1587d2010-03-16 18:06:19 -04001577 ret = e_snprintf(line, 32, ":%d", pp->line);
1578 if (ret <= 0)
1579 goto error;
1580 }
1581 if (pp->file) {
Franck Bui-Huu32ae2ad2010-12-23 16:04:23 +01001582 tmp = pp->file;
1583 len = strlen(tmp);
1584 if (len > 30) {
1585 tmp = strchr(pp->file + len - 30, '/');
1586 tmp = tmp ? tmp + 1 : pp->file + len - 30;
1587 }
1588 ret = e_snprintf(file, 32, "@%s", tmp);
Masami Hiramatsu4de189f2009-11-30 19:20:17 -05001589 if (ret <= 0)
1590 goto error;
1591 }
1592
1593 if (pp->function)
Masami Hiramatsufb1587d2010-03-16 18:06:19 -04001594 ret = e_snprintf(buf, MAX_CMDLEN, "%s%s%s%s%s", pp->function,
1595 offs, pp->retprobe ? "%return" : "", line,
1596 file);
Masami Hiramatsu4de189f2009-11-30 19:20:17 -05001597 else
Masami Hiramatsufb1587d2010-03-16 18:06:19 -04001598 ret = e_snprintf(buf, MAX_CMDLEN, "%s%s", file, line);
Masami Hiramatsu4de189f2009-11-30 19:20:17 -05001599 if (ret <= 0)
1600 goto error;
Masami Hiramatsu4de189f2009-11-30 19:20:17 -05001601
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001602 return buf;
1603error:
Masami Hiramatsu5f03cba2014-08-14 02:22:34 +00001604 pr_debug("Failed to synthesize perf probe point: %d\n", ret);
Arnaldo Carvalho de Melof5385652013-12-26 15:54:57 -03001605 free(buf);
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001606 return NULL;
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001607}
1608
1609#if 0
1610char *synthesize_perf_probe_command(struct perf_probe_event *pev)
1611{
1612 char *buf;
1613 int i, len, ret;
1614
1615 buf = synthesize_perf_probe_point(&pev->point);
1616 if (!buf)
1617 return NULL;
1618
1619 len = strlen(buf);
1620 for (i = 0; i < pev->nargs; i++) {
Masami Hiramatsu4de189f2009-11-30 19:20:17 -05001621 ret = e_snprintf(&buf[len], MAX_CMDLEN - len, " %s",
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001622 pev->args[i].name);
1623 if (ret <= 0) {
1624 free(buf);
1625 return NULL;
1626 }
1627 len += ret;
1628 }
1629
1630 return buf;
1631}
1632#endif
1633
Srikar Dronamraju0e608362010-07-29 19:43:51 +05301634static int __synthesize_probe_trace_arg_ref(struct probe_trace_arg_ref *ref,
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001635 char **buf, size_t *buflen,
1636 int depth)
1637{
1638 int ret;
1639 if (ref->next) {
Srikar Dronamraju0e608362010-07-29 19:43:51 +05301640 depth = __synthesize_probe_trace_arg_ref(ref->next, buf,
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001641 buflen, depth + 1);
1642 if (depth < 0)
1643 goto out;
1644 }
1645
1646 ret = e_snprintf(*buf, *buflen, "%+ld(", ref->offset);
1647 if (ret < 0)
1648 depth = ret;
1649 else {
1650 *buf += ret;
1651 *buflen -= ret;
1652 }
1653out:
1654 return depth;
1655
1656}
1657
Srikar Dronamraju0e608362010-07-29 19:43:51 +05301658static int synthesize_probe_trace_arg(struct probe_trace_arg *arg,
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001659 char *buf, size_t buflen)
1660{
Srikar Dronamraju0e608362010-07-29 19:43:51 +05301661 struct probe_trace_arg_ref *ref = arg->ref;
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001662 int ret, depth = 0;
1663 char *tmp = buf;
1664
1665 /* Argument name or separator */
1666 if (arg->name)
1667 ret = e_snprintf(buf, buflen, " %s=", arg->name);
1668 else
1669 ret = e_snprintf(buf, buflen, " ");
1670 if (ret < 0)
1671 return ret;
1672 buf += ret;
1673 buflen -= ret;
1674
Masami Hiramatsub7dcb852010-05-19 15:57:49 -04001675 /* Special case: @XXX */
1676 if (arg->value[0] == '@' && arg->ref)
1677 ref = ref->next;
1678
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001679 /* Dereferencing arguments */
Masami Hiramatsub7dcb852010-05-19 15:57:49 -04001680 if (ref) {
Srikar Dronamraju0e608362010-07-29 19:43:51 +05301681 depth = __synthesize_probe_trace_arg_ref(ref, &buf,
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001682 &buflen, 1);
1683 if (depth < 0)
1684 return depth;
1685 }
1686
1687 /* Print argument value */
Masami Hiramatsub7dcb852010-05-19 15:57:49 -04001688 if (arg->value[0] == '@' && arg->ref)
1689 ret = e_snprintf(buf, buflen, "%s%+ld", arg->value,
1690 arg->ref->offset);
1691 else
1692 ret = e_snprintf(buf, buflen, "%s", arg->value);
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001693 if (ret < 0)
1694 return ret;
1695 buf += ret;
1696 buflen -= ret;
1697
1698 /* Closing */
1699 while (depth--) {
1700 ret = e_snprintf(buf, buflen, ")");
1701 if (ret < 0)
1702 return ret;
1703 buf += ret;
1704 buflen -= ret;
1705 }
Masami Hiramatsu49849122010-04-12 13:17:15 -04001706 /* Print argument type */
1707 if (arg->type) {
1708 ret = e_snprintf(buf, buflen, ":%s", arg->type);
1709 if (ret <= 0)
1710 return ret;
1711 buf += ret;
1712 }
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001713
1714 return buf - tmp;
1715}
1716
Srikar Dronamraju0e608362010-07-29 19:43:51 +05301717char *synthesize_probe_trace_command(struct probe_trace_event *tev)
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001718{
Srikar Dronamraju0e608362010-07-29 19:43:51 +05301719 struct probe_trace_point *tp = &tev->point;
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001720 char *buf;
1721 int i, len, ret;
1722
Masami Hiramatsue334016f12010-04-12 13:17:49 -04001723 buf = zalloc(MAX_CMDLEN);
1724 if (buf == NULL)
1725 return NULL;
1726
Masami Hiramatsueb948e52014-02-06 05:32:25 +00001727 len = e_snprintf(buf, MAX_CMDLEN, "%c:%s/%s ", tp->retprobe ? 'r' : 'p',
1728 tev->group, tev->event);
1729 if (len <= 0)
1730 goto error;
1731
1732 /* Uprobes must have tp->address and tp->module */
1733 if (tev->uprobes && (!tp->address || !tp->module))
1734 goto error;
1735
1736 /* Use the tp->address for uprobes */
Srikar Dronamraju225466f2012-04-16 17:39:09 +05301737 if (tev->uprobes)
Masami Hiramatsueb948e52014-02-06 05:32:25 +00001738 ret = e_snprintf(buf + len, MAX_CMDLEN - len, "%s:0x%lx",
1739 tp->module, tp->address);
Srikar Dronamraju225466f2012-04-16 17:39:09 +05301740 else
Masami Hiramatsueb948e52014-02-06 05:32:25 +00001741 ret = e_snprintf(buf + len, MAX_CMDLEN - len, "%s%s%s+%lu",
Srikar Dronamraju225466f2012-04-16 17:39:09 +05301742 tp->module ?: "", tp->module ? ":" : "",
1743 tp->symbol, tp->offset);
1744
Masami Hiramatsueb948e52014-02-06 05:32:25 +00001745 if (ret <= 0)
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001746 goto error;
Masami Hiramatsueb948e52014-02-06 05:32:25 +00001747 len += ret;
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001748
1749 for (i = 0; i < tev->nargs; i++) {
Srikar Dronamraju0e608362010-07-29 19:43:51 +05301750 ret = synthesize_probe_trace_arg(&tev->args[i], buf + len,
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001751 MAX_CMDLEN - len);
Masami Hiramatsu4de189f2009-11-30 19:20:17 -05001752 if (ret <= 0)
1753 goto error;
1754 len += ret;
1755 }
Masami Hiramatsu4de189f2009-11-30 19:20:17 -05001756
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001757 return buf;
Masami Hiramatsu4de189f2009-11-30 19:20:17 -05001758error:
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001759 free(buf);
1760 return NULL;
1761}
Masami Hiramatsu4de189f2009-11-30 19:20:17 -05001762
Masami Hiramatsu5a6f6312014-02-06 05:32:23 +00001763static int find_perf_probe_point_from_map(struct probe_trace_point *tp,
1764 struct perf_probe_point *pp,
1765 bool is_kprobe)
1766{
1767 struct symbol *sym = NULL;
1768 struct map *map;
1769 u64 addr;
1770 int ret = -ENOENT;
1771
1772 if (!is_kprobe) {
1773 map = dso__new_map(tp->module);
1774 if (!map)
1775 goto out;
1776 addr = tp->address;
1777 sym = map__find_symbol(map, addr, NULL);
1778 } else {
1779 addr = kernel_get_symbol_address_by_name(tp->symbol, true);
1780 if (addr) {
1781 addr += tp->offset;
1782 sym = __find_kernel_function(addr, &map);
1783 }
1784 }
1785 if (!sym)
1786 goto out;
1787
1788 pp->retprobe = tp->retprobe;
1789 pp->offset = addr - map->unmap_ip(map, sym->start);
1790 pp->function = strdup(sym->name);
1791 ret = pp->function ? 0 : -ENOMEM;
1792
1793out:
1794 if (map && !is_kprobe) {
Arnaldo Carvalho de Melo84c2caf2015-05-25 16:59:56 -03001795 map__put(map);
Masami Hiramatsu5a6f6312014-02-06 05:32:23 +00001796 }
1797
1798 return ret;
1799}
1800
1801static int convert_to_perf_probe_point(struct probe_trace_point *tp,
1802 struct perf_probe_point *pp,
1803 bool is_kprobe)
1804{
1805 char buf[128];
1806 int ret;
1807
1808 ret = find_perf_probe_point_from_dwarf(tp, pp, is_kprobe);
1809 if (!ret)
1810 return 0;
1811 ret = find_perf_probe_point_from_map(tp, pp, is_kprobe);
1812 if (!ret)
1813 return 0;
1814
1815 pr_debug("Failed to find probe point from both of dwarf and map.\n");
1816
1817 if (tp->symbol) {
1818 pp->function = strdup(tp->symbol);
1819 pp->offset = tp->offset;
1820 } else if (!tp->module && !is_kprobe) {
1821 ret = e_snprintf(buf, 128, "0x%" PRIx64, (u64)tp->address);
1822 if (ret < 0)
1823 return ret;
1824 pp->function = strdup(buf);
1825 pp->offset = 0;
1826 }
1827 if (pp->function == NULL)
1828 return -ENOMEM;
1829
1830 pp->retprobe = tp->retprobe;
1831
1832 return 0;
1833}
1834
Srikar Dronamraju0e608362010-07-29 19:43:51 +05301835static int convert_to_perf_probe_event(struct probe_trace_event *tev,
Srikar Dronamraju225466f2012-04-16 17:39:09 +05301836 struct perf_probe_event *pev, bool is_kprobe)
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001837{
Masami Hiramatsu02b95da2010-04-12 13:17:56 -04001838 char buf[64] = "";
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001839 int i, ret;
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001840
Masami Hiramatsu4b4da7f2010-03-22 13:10:26 -03001841 /* Convert event/group name */
Masami Hiramatsu02b95da2010-04-12 13:17:56 -04001842 pev->event = strdup(tev->event);
1843 pev->group = strdup(tev->group);
1844 if (pev->event == NULL || pev->group == NULL)
1845 return -ENOMEM;
Masami Hiramatsufb1587d2010-03-16 18:06:19 -04001846
Masami Hiramatsu4b4da7f2010-03-22 13:10:26 -03001847 /* Convert trace_point to probe_point */
Masami Hiramatsu5a6f6312014-02-06 05:32:23 +00001848 ret = convert_to_perf_probe_point(&tev->point, &pev->point, is_kprobe);
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001849 if (ret < 0)
1850 return ret;
Masami Hiramatsu4b4da7f2010-03-22 13:10:26 -03001851
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001852 /* Convert trace_arg to probe_arg */
1853 pev->nargs = tev->nargs;
Masami Hiramatsue334016f12010-04-12 13:17:49 -04001854 pev->args = zalloc(sizeof(struct perf_probe_arg) * pev->nargs);
1855 if (pev->args == NULL)
1856 return -ENOMEM;
Masami Hiramatsu02b95da2010-04-12 13:17:56 -04001857 for (i = 0; i < tev->nargs && ret >= 0; i++) {
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001858 if (tev->args[i].name)
Masami Hiramatsu02b95da2010-04-12 13:17:56 -04001859 pev->args[i].name = strdup(tev->args[i].name);
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001860 else {
Srikar Dronamraju0e608362010-07-29 19:43:51 +05301861 ret = synthesize_probe_trace_arg(&tev->args[i],
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001862 buf, 64);
Masami Hiramatsu02b95da2010-04-12 13:17:56 -04001863 pev->args[i].name = strdup(buf);
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001864 }
Masami Hiramatsu02b95da2010-04-12 13:17:56 -04001865 if (pev->args[i].name == NULL && ret >= 0)
1866 ret = -ENOMEM;
1867 }
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001868
1869 if (ret < 0)
1870 clear_perf_probe_event(pev);
1871
1872 return ret;
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001873}
1874
1875void clear_perf_probe_event(struct perf_probe_event *pev)
1876{
Masami Hiramatsu7df2f322010-03-16 18:06:26 -04001877 struct perf_probe_arg_field *field, *next;
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001878 int i;
1879
Arnaldo Carvalho de Melof5385652013-12-26 15:54:57 -03001880 free(pev->event);
1881 free(pev->group);
Masami Hiramatsu7afb3fa2015-04-01 19:25:39 +09001882 free(pev->target);
Masami Hiramatsu9b118ac2015-03-06 16:31:20 +09001883 clear_perf_probe_point(&pev->point);
Arnaldo Carvalho de Melof5385652013-12-26 15:54:57 -03001884
Masami Hiramatsu7df2f322010-03-16 18:06:26 -04001885 for (i = 0; i < pev->nargs; i++) {
Arnaldo Carvalho de Melof5385652013-12-26 15:54:57 -03001886 free(pev->args[i].name);
1887 free(pev->args[i].var);
1888 free(pev->args[i].type);
Masami Hiramatsu7df2f322010-03-16 18:06:26 -04001889 field = pev->args[i].field;
1890 while (field) {
1891 next = field->next;
Arnaldo Carvalho de Melo74cf2492013-12-27 16:55:14 -03001892 zfree(&field->name);
Masami Hiramatsu7df2f322010-03-16 18:06:26 -04001893 free(field);
1894 field = next;
1895 }
1896 }
Arnaldo Carvalho de Melof5385652013-12-26 15:54:57 -03001897 free(pev->args);
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001898 memset(pev, 0, sizeof(*pev));
1899}
1900
Srikar Dronamraju0e608362010-07-29 19:43:51 +05301901static void clear_probe_trace_event(struct probe_trace_event *tev)
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001902{
Srikar Dronamraju0e608362010-07-29 19:43:51 +05301903 struct probe_trace_arg_ref *ref, *next;
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001904 int i;
1905
Arnaldo Carvalho de Melof5385652013-12-26 15:54:57 -03001906 free(tev->event);
1907 free(tev->group);
1908 free(tev->point.symbol);
Masami Hiramatsu4c859352015-05-08 10:03:35 +09001909 free(tev->point.realname);
Arnaldo Carvalho de Melof5385652013-12-26 15:54:57 -03001910 free(tev->point.module);
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001911 for (i = 0; i < tev->nargs; i++) {
Arnaldo Carvalho de Melof5385652013-12-26 15:54:57 -03001912 free(tev->args[i].name);
1913 free(tev->args[i].value);
1914 free(tev->args[i].type);
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001915 ref = tev->args[i].ref;
1916 while (ref) {
1917 next = ref->next;
1918 free(ref);
1919 ref = next;
1920 }
1921 }
Arnaldo Carvalho de Melof5385652013-12-26 15:54:57 -03001922 free(tev->args);
Masami Hiramatsu4235b042010-03-16 18:06:12 -04001923 memset(tev, 0, sizeof(*tev));
Masami Hiramatsu4de189f2009-11-30 19:20:17 -05001924}
1925
Masami Hiramatsu5e451872014-08-13 16:12:48 +00001926static void print_open_warning(int err, bool is_kprobe)
Srikar Dronamraju225466f2012-04-16 17:39:09 +05301927{
Masami Hiramatsu5f03cba2014-08-14 02:22:34 +00001928 char sbuf[STRERR_BUFSIZE];
Srikar Dronamraju225466f2012-04-16 17:39:09 +05301929
Masami Hiramatsu5e451872014-08-13 16:12:48 +00001930 if (err == -ENOENT) {
Srikar Dronamraju225466f2012-04-16 17:39:09 +05301931 const char *config;
1932
1933 if (!is_kprobe)
1934 config = "CONFIG_UPROBE_EVENTS";
1935 else
1936 config = "CONFIG_KPROBE_EVENTS";
1937
Masami Hiramatsu5e451872014-08-13 16:12:48 +00001938 pr_warning("%cprobe_events file does not exist"
1939 " - please rebuild kernel with %s.\n",
1940 is_kprobe ? 'k' : 'u', config);
1941 } else if (err == -ENOTSUP)
Steven Rostedt (Red Hat)23773ca2015-02-02 14:35:07 -05001942 pr_warning("Tracefs or debugfs is not mounted.\n");
Masami Hiramatsu5e451872014-08-13 16:12:48 +00001943 else
1944 pr_warning("Failed to open %cprobe_events: %s\n",
1945 is_kprobe ? 'k' : 'u',
1946 strerror_r(-err, sbuf, sizeof(sbuf)));
Srikar Dronamraju225466f2012-04-16 17:39:09 +05301947}
1948
Masami Hiramatsu467ec082014-08-13 16:12:50 +00001949static void print_both_open_warning(int kerr, int uerr)
1950{
1951 /* Both kprobes and uprobes are disabled, warn it. */
1952 if (kerr == -ENOTSUP && uerr == -ENOTSUP)
Steven Rostedt (Red Hat)23773ca2015-02-02 14:35:07 -05001953 pr_warning("Tracefs or debugfs is not mounted.\n");
Masami Hiramatsu467ec082014-08-13 16:12:50 +00001954 else if (kerr == -ENOENT && uerr == -ENOENT)
1955 pr_warning("Please rebuild kernel with CONFIG_KPROBE_EVENTS "
1956 "or/and CONFIG_UPROBE_EVENTS.\n");
1957 else {
Masami Hiramatsu5f03cba2014-08-14 02:22:34 +00001958 char sbuf[STRERR_BUFSIZE];
Masami Hiramatsu467ec082014-08-13 16:12:50 +00001959 pr_warning("Failed to open kprobe events: %s.\n",
1960 strerror_r(-kerr, sbuf, sizeof(sbuf)));
1961 pr_warning("Failed to open uprobe events: %s.\n",
1962 strerror_r(-uerr, sbuf, sizeof(sbuf)));
1963 }
1964}
1965
Masami Hiramatsu5e451872014-08-13 16:12:48 +00001966static int open_probe_events(const char *trace_file, bool readwrite)
Masami Hiramatsu4de189f2009-11-30 19:20:17 -05001967{
1968 char buf[PATH_MAX];
Masami Hiramatsu7ca59892010-04-14 18:39:28 -04001969 const char *__debugfs;
Steven Rostedt (Red Hat)23773ca2015-02-02 14:35:07 -05001970 const char *tracing_dir = "";
Masami Hiramatsu4de189f2009-11-30 19:20:17 -05001971 int ret;
1972
Steven Rostedt (Red Hat)23773ca2015-02-02 14:35:07 -05001973 __debugfs = tracefs_find_mountpoint();
1974 if (__debugfs == NULL) {
1975 tracing_dir = "tracing/";
Masami Hiramatsu7ca59892010-04-14 18:39:28 -04001976
Steven Rostedt (Red Hat)23773ca2015-02-02 14:35:07 -05001977 __debugfs = debugfs_find_mountpoint();
1978 if (__debugfs == NULL)
1979 return -ENOTSUP;
1980 }
1981
1982 ret = e_snprintf(buf, PATH_MAX, "%s/%s%s",
1983 __debugfs, tracing_dir, trace_file);
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001984 if (ret >= 0) {
Masami Hiramatsu7ca59892010-04-14 18:39:28 -04001985 pr_debug("Opening %s write=%d\n", buf, readwrite);
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001986 if (readwrite && !probe_event_dry_run)
Masami Hiramatsub8dc3982015-05-06 21:46:42 +09001987 ret = open(buf, O_RDWR | O_APPEND, 0);
Masami Hiramatsu146a1432010-04-12 13:17:42 -04001988 else
1989 ret = open(buf, O_RDONLY, 0);
Masami Hiramatsuf4d7da42010-03-16 18:06:05 -04001990
Srikar Dronamraju225466f2012-04-16 17:39:09 +05301991 if (ret < 0)
Masami Hiramatsu5e451872014-08-13 16:12:48 +00001992 ret = -errno;
Masami Hiramatsu4de189f2009-11-30 19:20:17 -05001993 }
1994 return ret;
1995}
1996
Srikar Dronamraju225466f2012-04-16 17:39:09 +05301997static int open_kprobe_events(bool readwrite)
1998{
Steven Rostedt (Red Hat)23773ca2015-02-02 14:35:07 -05001999 return open_probe_events("kprobe_events", readwrite);
Srikar Dronamraju225466f2012-04-16 17:39:09 +05302000}
2001
2002static int open_uprobe_events(bool readwrite)
2003{
Steven Rostedt (Red Hat)23773ca2015-02-02 14:35:07 -05002004 return open_probe_events("uprobe_events", readwrite);
Srikar Dronamraju225466f2012-04-16 17:39:09 +05302005}
2006
2007/* Get raw string list of current kprobe_events or uprobe_events */
Srikar Dronamraju0e608362010-07-29 19:43:51 +05302008static struct strlist *get_probe_trace_command_rawlist(int fd)
Masami Hiramatsu4de189f2009-11-30 19:20:17 -05002009{
2010 int ret, idx;
2011 FILE *fp;
2012 char buf[MAX_CMDLEN];
2013 char *p;
2014 struct strlist *sl;
2015
2016 sl = strlist__new(true, NULL);
2017
2018 fp = fdopen(dup(fd), "r");
2019 while (!feof(fp)) {
2020 p = fgets(buf, MAX_CMDLEN, fp);
2021 if (!p)
2022 break;
2023
2024 idx = strlen(p) - 1;
2025 if (p[idx] == '\n')
2026 p[idx] = '\0';
2027 ret = strlist__add(sl, buf);
Masami Hiramatsu146a1432010-04-12 13:17:42 -04002028 if (ret < 0) {
Masami Hiramatsu6eb08662014-08-14 02:22:30 +00002029 pr_debug("strlist__add failed (%d)\n", ret);
Masami Hiramatsu146a1432010-04-12 13:17:42 -04002030 strlist__delete(sl);
2031 return NULL;
2032 }
Masami Hiramatsu4de189f2009-11-30 19:20:17 -05002033 }
2034 fclose(fp);
2035
2036 return sl;
2037}
2038
Masami Hiramatsu9aaf5a52015-02-19 23:31:13 +09002039struct kprobe_blacklist_node {
2040 struct list_head list;
2041 unsigned long start;
2042 unsigned long end;
2043 char *symbol;
2044};
2045
2046static void kprobe_blacklist__delete(struct list_head *blacklist)
2047{
2048 struct kprobe_blacklist_node *node;
2049
2050 while (!list_empty(blacklist)) {
2051 node = list_first_entry(blacklist,
2052 struct kprobe_blacklist_node, list);
2053 list_del(&node->list);
2054 free(node->symbol);
2055 free(node);
2056 }
2057}
2058
2059static int kprobe_blacklist__load(struct list_head *blacklist)
2060{
2061 struct kprobe_blacklist_node *node;
2062 const char *__debugfs = debugfs_find_mountpoint();
2063 char buf[PATH_MAX], *p;
2064 FILE *fp;
2065 int ret;
2066
2067 if (__debugfs == NULL)
2068 return -ENOTSUP;
2069
2070 ret = e_snprintf(buf, PATH_MAX, "%s/kprobes/blacklist", __debugfs);
2071 if (ret < 0)
2072 return ret;
2073
2074 fp = fopen(buf, "r");
2075 if (!fp)
2076 return -errno;
2077
2078 ret = 0;
2079 while (fgets(buf, PATH_MAX, fp)) {
2080 node = zalloc(sizeof(*node));
2081 if (!node) {
2082 ret = -ENOMEM;
2083 break;
2084 }
2085 INIT_LIST_HEAD(&node->list);
2086 list_add_tail(&node->list, blacklist);
2087 if (sscanf(buf, "0x%lx-0x%lx", &node->start, &node->end) != 2) {
2088 ret = -EINVAL;
2089 break;
2090 }
2091 p = strchr(buf, '\t');
2092 if (p) {
2093 p++;
2094 if (p[strlen(p) - 1] == '\n')
2095 p[strlen(p) - 1] = '\0';
2096 } else
2097 p = (char *)"unknown";
2098 node->symbol = strdup(p);
2099 if (!node->symbol) {
2100 ret = -ENOMEM;
2101 break;
2102 }
2103 pr_debug2("Blacklist: 0x%lx-0x%lx, %s\n",
2104 node->start, node->end, node->symbol);
2105 ret++;
2106 }
2107 if (ret < 0)
2108 kprobe_blacklist__delete(blacklist);
2109 fclose(fp);
2110
2111 return ret;
2112}
2113
2114static struct kprobe_blacklist_node *
2115kprobe_blacklist__find_by_address(struct list_head *blacklist,
2116 unsigned long address)
2117{
2118 struct kprobe_blacklist_node *node;
2119
2120 list_for_each_entry(node, blacklist, list) {
2121 if (node->start <= address && address <= node->end)
2122 return node;
2123 }
2124
2125 return NULL;
2126}
2127
Masami Hiramatsu278498d2009-12-08 17:02:40 -05002128/* Show an event */
Masami Hiramatsufb226cc2014-02-06 05:32:13 +00002129static int show_perf_probe_event(struct perf_probe_event *pev,
2130 const char *module)
Masami Hiramatsu278498d2009-12-08 17:02:40 -05002131{
Masami Hiramatsu7e990a52009-12-15 10:31:21 -05002132 int i, ret;
Masami Hiramatsu278498d2009-12-08 17:02:40 -05002133 char buf[128];
Masami Hiramatsu4235b042010-03-16 18:06:12 -04002134 char *place;
Masami Hiramatsu278498d2009-12-08 17:02:40 -05002135
Masami Hiramatsu4235b042010-03-16 18:06:12 -04002136 /* Synthesize only event probe point */
2137 place = synthesize_perf_probe_point(&pev->point);
Masami Hiramatsu146a1432010-04-12 13:17:42 -04002138 if (!place)
2139 return -EINVAL;
Masami Hiramatsu4235b042010-03-16 18:06:12 -04002140
2141 ret = e_snprintf(buf, 128, "%s:%s", pev->group, pev->event);
Masami Hiramatsu7e990a52009-12-15 10:31:21 -05002142 if (ret < 0)
Masami Hiramatsu146a1432010-04-12 13:17:42 -04002143 return ret;
2144
Masami Hiramatsu5e17b282014-10-27 16:31:31 -04002145 pr_info(" %-20s (on %s", buf, place);
Masami Hiramatsufb226cc2014-02-06 05:32:13 +00002146 if (module)
Masami Hiramatsu5e17b282014-10-27 16:31:31 -04002147 pr_info(" in %s", module);
Masami Hiramatsu278498d2009-12-08 17:02:40 -05002148
Masami Hiramatsu4235b042010-03-16 18:06:12 -04002149 if (pev->nargs > 0) {
Masami Hiramatsu5e17b282014-10-27 16:31:31 -04002150 pr_info(" with");
Masami Hiramatsu7df2f322010-03-16 18:06:26 -04002151 for (i = 0; i < pev->nargs; i++) {
Masami Hiramatsu146a1432010-04-12 13:17:42 -04002152 ret = synthesize_perf_probe_arg(&pev->args[i],
2153 buf, 128);
2154 if (ret < 0)
2155 break;
Masami Hiramatsu5e17b282014-10-27 16:31:31 -04002156 pr_info(" %s", buf);
Masami Hiramatsu7df2f322010-03-16 18:06:26 -04002157 }
Masami Hiramatsu278498d2009-12-08 17:02:40 -05002158 }
Masami Hiramatsu5e17b282014-10-27 16:31:31 -04002159 pr_info(")\n");
Masami Hiramatsu4235b042010-03-16 18:06:12 -04002160 free(place);
Masami Hiramatsu146a1432010-04-12 13:17:42 -04002161 return ret;
Masami Hiramatsu278498d2009-12-08 17:02:40 -05002162}
2163
Masami Hiramatsub6a89642015-04-24 18:47:50 +09002164static bool filter_probe_trace_event(struct probe_trace_event *tev,
2165 struct strfilter *filter)
2166{
2167 char tmp[128];
2168
2169 /* At first, check the event name itself */
2170 if (strfilter__compare(filter, tev->event))
2171 return true;
2172
2173 /* Next, check the combination of name and group */
2174 if (e_snprintf(tmp, 128, "%s:%s", tev->group, tev->event) < 0)
2175 return false;
2176 return strfilter__compare(filter, tmp);
2177}
2178
2179static int __show_perf_probe_events(int fd, bool is_kprobe,
2180 struct strfilter *filter)
Masami Hiramatsu4de189f2009-11-30 19:20:17 -05002181{
Srikar Dronamraju225466f2012-04-16 17:39:09 +05302182 int ret = 0;
Srikar Dronamraju0e608362010-07-29 19:43:51 +05302183 struct probe_trace_event tev;
Masami Hiramatsu4235b042010-03-16 18:06:12 -04002184 struct perf_probe_event pev;
Masami Hiramatsu4de189f2009-11-30 19:20:17 -05002185 struct strlist *rawlist;
2186 struct str_node *ent;
2187
Masami Hiramatsu4235b042010-03-16 18:06:12 -04002188 memset(&tev, 0, sizeof(tev));
2189 memset(&pev, 0, sizeof(pev));
Masami Hiramatsu72041332010-01-05 17:47:10 -05002190
Srikar Dronamraju0e608362010-07-29 19:43:51 +05302191 rawlist = get_probe_trace_command_rawlist(fd);
Masami Hiramatsu146a1432010-04-12 13:17:42 -04002192 if (!rawlist)
Masami Hiramatsu6eb08662014-08-14 02:22:30 +00002193 return -ENOMEM;
Masami Hiramatsu4de189f2009-11-30 19:20:17 -05002194
Masami Hiramatsuadf365f2009-12-15 10:32:03 -05002195 strlist__for_each(ent, rawlist) {
Srikar Dronamraju0e608362010-07-29 19:43:51 +05302196 ret = parse_probe_trace_command(ent->s, &tev);
Masami Hiramatsu146a1432010-04-12 13:17:42 -04002197 if (ret >= 0) {
Masami Hiramatsub6a89642015-04-24 18:47:50 +09002198 if (!filter_probe_trace_event(&tev, filter))
2199 goto next;
Srikar Dronamraju225466f2012-04-16 17:39:09 +05302200 ret = convert_to_perf_probe_event(&tev, &pev,
2201 is_kprobe);
Masami Hiramatsu146a1432010-04-12 13:17:42 -04002202 if (ret >= 0)
Masami Hiramatsufb226cc2014-02-06 05:32:13 +00002203 ret = show_perf_probe_event(&pev,
2204 tev.point.module);
Masami Hiramatsu146a1432010-04-12 13:17:42 -04002205 }
Masami Hiramatsub6a89642015-04-24 18:47:50 +09002206next:
Masami Hiramatsu4235b042010-03-16 18:06:12 -04002207 clear_perf_probe_event(&pev);
Srikar Dronamraju0e608362010-07-29 19:43:51 +05302208 clear_probe_trace_event(&tev);
Masami Hiramatsu146a1432010-04-12 13:17:42 -04002209 if (ret < 0)
2210 break;
Masami Hiramatsu4de189f2009-11-30 19:20:17 -05002211 }
Masami Hiramatsu4de189f2009-11-30 19:20:17 -05002212 strlist__delete(rawlist);
Masami Hiramatsu146a1432010-04-12 13:17:42 -04002213
2214 return ret;
Masami Hiramatsu4de189f2009-11-30 19:20:17 -05002215}
2216
Srikar Dronamraju225466f2012-04-16 17:39:09 +05302217/* List up current perf-probe events */
Masami Hiramatsub6a89642015-04-24 18:47:50 +09002218int show_perf_probe_events(struct strfilter *filter)
Srikar Dronamraju225466f2012-04-16 17:39:09 +05302219{
Masami Hiramatsu5e451872014-08-13 16:12:48 +00002220 int kp_fd, up_fd, ret;
Srikar Dronamraju225466f2012-04-16 17:39:09 +05302221
2222 setup_pager();
Srikar Dronamraju225466f2012-04-16 17:39:09 +05302223
Masami Hiramatsuee45b6c2014-02-06 05:32:04 +00002224 ret = init_symbol_maps(false);
Srikar Dronamraju225466f2012-04-16 17:39:09 +05302225 if (ret < 0)
2226 return ret;
2227
Masami Hiramatsu5e451872014-08-13 16:12:48 +00002228 kp_fd = open_kprobe_events(false);
2229 if (kp_fd >= 0) {
Masami Hiramatsub6a89642015-04-24 18:47:50 +09002230 ret = __show_perf_probe_events(kp_fd, true, filter);
Masami Hiramatsu5e451872014-08-13 16:12:48 +00002231 close(kp_fd);
2232 if (ret < 0)
2233 goto out;
Srikar Dronamraju225466f2012-04-16 17:39:09 +05302234 }
2235
Masami Hiramatsu5e451872014-08-13 16:12:48 +00002236 up_fd = open_uprobe_events(false);
2237 if (kp_fd < 0 && up_fd < 0) {
Masami Hiramatsu467ec082014-08-13 16:12:50 +00002238 print_both_open_warning(kp_fd, up_fd);
Masami Hiramatsu5e451872014-08-13 16:12:48 +00002239 ret = kp_fd;
2240 goto out;
2241 }
2242
2243 if (up_fd >= 0) {
Masami Hiramatsub6a89642015-04-24 18:47:50 +09002244 ret = __show_perf_probe_events(up_fd, false, filter);
Masami Hiramatsu5e451872014-08-13 16:12:48 +00002245 close(up_fd);
2246 }
2247out:
Masami Hiramatsuee45b6c2014-02-06 05:32:04 +00002248 exit_symbol_maps();
Srikar Dronamraju225466f2012-04-16 17:39:09 +05302249 return ret;
2250}
2251
Masami Hiramatsub498ce12009-11-30 19:20:25 -05002252/* Get current perf-probe event names */
Srikar Dronamraju0e608362010-07-29 19:43:51 +05302253static struct strlist *get_probe_trace_event_names(int fd, bool include_group)
Masami Hiramatsub498ce12009-11-30 19:20:25 -05002254{
Masami Hiramatsufa282442009-12-08 17:03:23 -05002255 char buf[128];
Masami Hiramatsub498ce12009-11-30 19:20:25 -05002256 struct strlist *sl, *rawlist;
2257 struct str_node *ent;
Srikar Dronamraju0e608362010-07-29 19:43:51 +05302258 struct probe_trace_event tev;
Masami Hiramatsu146a1432010-04-12 13:17:42 -04002259 int ret = 0;
Masami Hiramatsub498ce12009-11-30 19:20:25 -05002260
Masami Hiramatsu4235b042010-03-16 18:06:12 -04002261 memset(&tev, 0, sizeof(tev));
Srikar Dronamraju0e608362010-07-29 19:43:51 +05302262 rawlist = get_probe_trace_command_rawlist(fd);
Masami Hiramatsu6eb08662014-08-14 02:22:30 +00002263 if (!rawlist)
2264 return NULL;
Masami Hiramatsue1d20172009-12-07 12:00:46 -05002265 sl = strlist__new(true, NULL);
Masami Hiramatsuadf365f2009-12-15 10:32:03 -05002266 strlist__for_each(ent, rawlist) {
Srikar Dronamraju0e608362010-07-29 19:43:51 +05302267 ret = parse_probe_trace_command(ent->s, &tev);
Masami Hiramatsu146a1432010-04-12 13:17:42 -04002268 if (ret < 0)
2269 break;
Masami Hiramatsufa282442009-12-08 17:03:23 -05002270 if (include_group) {
Masami Hiramatsu146a1432010-04-12 13:17:42 -04002271 ret = e_snprintf(buf, 128, "%s:%s", tev.group,
2272 tev.event);
2273 if (ret >= 0)
2274 ret = strlist__add(sl, buf);
Masami Hiramatsufa282442009-12-08 17:03:23 -05002275 } else
Masami Hiramatsu146a1432010-04-12 13:17:42 -04002276 ret = strlist__add(sl, tev.event);
Srikar Dronamraju0e608362010-07-29 19:43:51 +05302277 clear_probe_trace_event(&tev);
Masami Hiramatsu146a1432010-04-12 13:17:42 -04002278 if (ret < 0)
2279 break;
Masami Hiramatsub498ce12009-11-30 19:20:25 -05002280 }
Masami Hiramatsub498ce12009-11-30 19:20:25 -05002281 strlist__delete(rawlist);
2282
Masami Hiramatsu146a1432010-04-12 13:17:42 -04002283 if (ret < 0) {
2284 strlist__delete(sl);
2285 return NULL;
2286 }
Masami Hiramatsub498ce12009-11-30 19:20:25 -05002287 return sl;
2288}
2289
Srikar Dronamraju0e608362010-07-29 19:43:51 +05302290static int write_probe_trace_event(int fd, struct probe_trace_event *tev)
Masami Hiramatsu50656ee2009-11-30 19:19:58 -05002291{
Frederic Weisbecker6eca8cc2010-04-21 02:01:05 +02002292 int ret = 0;
Srikar Dronamraju0e608362010-07-29 19:43:51 +05302293 char *buf = synthesize_probe_trace_command(tev);
Masami Hiramatsu5f03cba2014-08-14 02:22:34 +00002294 char sbuf[STRERR_BUFSIZE];
Masami Hiramatsu50656ee2009-11-30 19:19:58 -05002295
Masami Hiramatsu146a1432010-04-12 13:17:42 -04002296 if (!buf) {
Srikar Dronamraju0e608362010-07-29 19:43:51 +05302297 pr_debug("Failed to synthesize probe trace event.\n");
Masami Hiramatsu146a1432010-04-12 13:17:42 -04002298 return -EINVAL;
2299 }
2300
Masami Hiramatsufa282442009-12-08 17:03:23 -05002301 pr_debug("Writing event: %s\n", buf);
Masami Hiramatsuf4d7da42010-03-16 18:06:05 -04002302 if (!probe_event_dry_run) {
2303 ret = write(fd, buf, strlen(buf));
Namhyung Kim7949ba12015-01-10 19:33:48 +09002304 if (ret <= 0) {
2305 ret = -errno;
Masami Hiramatsu146a1432010-04-12 13:17:42 -04002306 pr_warning("Failed to write event: %s\n",
Masami Hiramatsu5f03cba2014-08-14 02:22:34 +00002307 strerror_r(errno, sbuf, sizeof(sbuf)));
Namhyung Kim7949ba12015-01-10 19:33:48 +09002308 }
Masami Hiramatsuf4d7da42010-03-16 18:06:05 -04002309 }
Masami Hiramatsu4235b042010-03-16 18:06:12 -04002310 free(buf);
Masami Hiramatsu146a1432010-04-12 13:17:42 -04002311 return ret;
Masami Hiramatsu50656ee2009-11-30 19:19:58 -05002312}
2313
Masami Hiramatsu146a1432010-04-12 13:17:42 -04002314static int get_new_event_name(char *buf, size_t len, const char *base,
2315 struct strlist *namelist, bool allow_suffix)
Masami Hiramatsub498ce12009-11-30 19:20:25 -05002316{
2317 int i, ret;
Masami Hiramatsu17f88fc2009-12-08 17:03:02 -05002318
Naveen N. Rao3099c022015-04-28 17:35:34 +05302319 if (*base == '.')
2320 base++;
2321
Masami Hiramatsu17f88fc2009-12-08 17:03:02 -05002322 /* Try no suffix */
2323 ret = e_snprintf(buf, len, "%s", base);
Masami Hiramatsu146a1432010-04-12 13:17:42 -04002324 if (ret < 0) {
Masami Hiramatsu5f03cba2014-08-14 02:22:34 +00002325 pr_debug("snprintf() failed: %d\n", ret);
Masami Hiramatsu146a1432010-04-12 13:17:42 -04002326 return ret;
2327 }
Masami Hiramatsu17f88fc2009-12-08 17:03:02 -05002328 if (!strlist__has_entry(namelist, buf))
Masami Hiramatsu146a1432010-04-12 13:17:42 -04002329 return 0;
Masami Hiramatsu17f88fc2009-12-08 17:03:02 -05002330
Masami Hiramatsud761b082009-12-15 10:32:25 -05002331 if (!allow_suffix) {
2332 pr_warning("Error: event \"%s\" already exists. "
2333 "(Use -f to force duplicates.)\n", base);
Masami Hiramatsu146a1432010-04-12 13:17:42 -04002334 return -EEXIST;
Masami Hiramatsud761b082009-12-15 10:32:25 -05002335 }
2336
Masami Hiramatsu17f88fc2009-12-08 17:03:02 -05002337 /* Try to add suffix */
2338 for (i = 1; i < MAX_EVENT_INDEX; i++) {
Masami Hiramatsub498ce12009-11-30 19:20:25 -05002339 ret = e_snprintf(buf, len, "%s_%d", base, i);
Masami Hiramatsu146a1432010-04-12 13:17:42 -04002340 if (ret < 0) {
Masami Hiramatsu5f03cba2014-08-14 02:22:34 +00002341 pr_debug("snprintf() failed: %d\n", ret);
Masami Hiramatsu146a1432010-04-12 13:17:42 -04002342 return ret;
2343 }
Masami Hiramatsub498ce12009-11-30 19:20:25 -05002344 if (!strlist__has_entry(namelist, buf))
2345 break;
2346 }
Masami Hiramatsu146a1432010-04-12 13:17:42 -04002347 if (i == MAX_EVENT_INDEX) {
2348 pr_warning("Too many events are on the same function.\n");
2349 ret = -ERANGE;
2350 }
2351
2352 return ret;
Masami Hiramatsub498ce12009-11-30 19:20:25 -05002353}
2354
Masami Hiramatsu79702f62015-02-28 11:53:29 +09002355/* Warn if the current kernel's uprobe implementation is old */
2356static void warn_uprobe_event_compat(struct probe_trace_event *tev)
2357{
2358 int i;
2359 char *buf = synthesize_probe_trace_command(tev);
2360
2361 /* Old uprobe event doesn't support memory dereference */
2362 if (!tev->uprobes || tev->nargs == 0 || !buf)
2363 goto out;
2364
2365 for (i = 0; i < tev->nargs; i++)
2366 if (strglobmatch(tev->args[i].value, "[$@+-]*")) {
2367 pr_warning("Please upgrade your kernel to at least "
2368 "3.14 to have access to feature %s\n",
2369 tev->args[i].value);
2370 break;
2371 }
2372out:
2373 free(buf);
2374}
2375
Srikar Dronamraju0e608362010-07-29 19:43:51 +05302376static int __add_probe_trace_events(struct perf_probe_event *pev,
2377 struct probe_trace_event *tevs,
Masami Hiramatsu146a1432010-04-12 13:17:42 -04002378 int ntevs, bool allow_suffix)
Masami Hiramatsu50656ee2009-11-30 19:19:58 -05002379{
Masami Hiramatsu146a1432010-04-12 13:17:42 -04002380 int i, fd, ret;
Srikar Dronamraju0e608362010-07-29 19:43:51 +05302381 struct probe_trace_event *tev = NULL;
Masami Hiramatsu4235b042010-03-16 18:06:12 -04002382 char buf[64];
2383 const char *event, *group;
Masami Hiramatsub498ce12009-11-30 19:20:25 -05002384 struct strlist *namelist;
Masami Hiramatsu9aaf5a52015-02-19 23:31:13 +09002385 LIST_HEAD(blacklist);
2386 struct kprobe_blacklist_node *node;
Masami Hiramatsu4c859352015-05-08 10:03:35 +09002387 bool safename;
Masami Hiramatsu50656ee2009-11-30 19:19:58 -05002388
Srikar Dronamraju225466f2012-04-16 17:39:09 +05302389 if (pev->uprobes)
2390 fd = open_uprobe_events(true);
2391 else
2392 fd = open_kprobe_events(true);
2393
Masami Hiramatsu5e451872014-08-13 16:12:48 +00002394 if (fd < 0) {
2395 print_open_warning(fd, !pev->uprobes);
Masami Hiramatsu146a1432010-04-12 13:17:42 -04002396 return fd;
Masami Hiramatsu5e451872014-08-13 16:12:48 +00002397 }
2398
Masami Hiramatsub498ce12009-11-30 19:20:25 -05002399 /* Get current event names */
Srikar Dronamraju0e608362010-07-29 19:43:51 +05302400 namelist = get_probe_trace_event_names(fd, false);
Masami Hiramatsu146a1432010-04-12 13:17:42 -04002401 if (!namelist) {
2402 pr_debug("Failed to get current event list.\n");
Masami Hiramatsuae2cb1a2015-05-06 21:46:40 +09002403 ret = -ENOMEM;
2404 goto close_out;
Masami Hiramatsu146a1432010-04-12 13:17:42 -04002405 }
Masami Hiramatsu9aaf5a52015-02-19 23:31:13 +09002406 /* Get kprobe blacklist if exists */
2407 if (!pev->uprobes) {
2408 ret = kprobe_blacklist__load(&blacklist);
2409 if (ret < 0)
2410 pr_debug("No kprobe blacklist support, ignored\n");
2411 }
Masami Hiramatsu50656ee2009-11-30 19:19:58 -05002412
Masami Hiramatsu4c859352015-05-08 10:03:35 +09002413 safename = (pev->point.function && !strisglob(pev->point.function));
Masami Hiramatsu146a1432010-04-12 13:17:42 -04002414 ret = 0;
Masami Hiramatsu5e17b282014-10-27 16:31:31 -04002415 pr_info("Added new event%s\n", (ntevs > 1) ? "s:" : ":");
Masami Hiramatsu02b95da2010-04-12 13:17:56 -04002416 for (i = 0; i < ntevs; i++) {
Masami Hiramatsu4235b042010-03-16 18:06:12 -04002417 tev = &tevs[i];
Masami Hiramatsu5a51fcd2015-05-06 21:46:49 +09002418 /* Skip if the symbol is out of .text (marked previously) */
2419 if (!tev->point.symbol)
2420 continue;
Masami Hiramatsu9aaf5a52015-02-19 23:31:13 +09002421 /* Ensure that the address is NOT blacklisted */
2422 node = kprobe_blacklist__find_by_address(&blacklist,
2423 tev->point.address);
2424 if (node) {
2425 pr_warning("Warning: Skipped probing on blacklisted function: %s\n", node->symbol);
2426 continue;
2427 }
2428
Masami Hiramatsu4235b042010-03-16 18:06:12 -04002429 if (pev->event)
2430 event = pev->event;
2431 else
Masami Hiramatsu4c859352015-05-08 10:03:35 +09002432 if (safename)
Masami Hiramatsu4235b042010-03-16 18:06:12 -04002433 event = pev->point.function;
2434 else
Masami Hiramatsu4c859352015-05-08 10:03:35 +09002435 event = tev->point.realname;
Masami Hiramatsu4235b042010-03-16 18:06:12 -04002436 if (pev->group)
2437 group = pev->group;
2438 else
2439 group = PERFPROBE_GROUP;
2440
2441 /* Get an unused new event name */
Masami Hiramatsu146a1432010-04-12 13:17:42 -04002442 ret = get_new_event_name(buf, 64, event,
2443 namelist, allow_suffix);
2444 if (ret < 0)
2445 break;
Masami Hiramatsu4235b042010-03-16 18:06:12 -04002446 event = buf;
2447
Masami Hiramatsu02b95da2010-04-12 13:17:56 -04002448 tev->event = strdup(event);
2449 tev->group = strdup(group);
2450 if (tev->event == NULL || tev->group == NULL) {
2451 ret = -ENOMEM;
2452 break;
2453 }
Srikar Dronamraju0e608362010-07-29 19:43:51 +05302454 ret = write_probe_trace_event(fd, tev);
Masami Hiramatsu146a1432010-04-12 13:17:42 -04002455 if (ret < 0)
2456 break;
Masami Hiramatsu4235b042010-03-16 18:06:12 -04002457 /* Add added event name to namelist */
2458 strlist__add(namelist, event);
2459
2460 /* Trick here - save current event/group */
2461 event = pev->event;
2462 group = pev->group;
2463 pev->event = tev->event;
2464 pev->group = tev->group;
Masami Hiramatsufb226cc2014-02-06 05:32:13 +00002465 show_perf_probe_event(pev, tev->point.module);
Masami Hiramatsu4235b042010-03-16 18:06:12 -04002466 /* Trick here - restore current event/group */
2467 pev->event = (char *)event;
2468 pev->group = (char *)group;
2469
2470 /*
2471 * Probes after the first probe which comes from same
2472 * user input are always allowed to add suffix, because
2473 * there might be several addresses corresponding to
2474 * one code line.
2475 */
2476 allow_suffix = true;
Masami Hiramatsu50656ee2009-11-30 19:19:58 -05002477 }
Masami Hiramatsu79702f62015-02-28 11:53:29 +09002478 if (ret == -EINVAL && pev->uprobes)
2479 warn_uprobe_event_compat(tev);
Masami Hiramatsu146a1432010-04-12 13:17:42 -04002480
Masami Hiramatsu9aaf5a52015-02-19 23:31:13 +09002481 /* Note that it is possible to skip all events because of blacklist */
2482 if (ret >= 0 && tev->event) {
Masami Hiramatsu146a1432010-04-12 13:17:42 -04002483 /* Show how to use the event. */
Masami Hiramatsu5e17b282014-10-27 16:31:31 -04002484 pr_info("\nYou can now use it in all perf tools, such as:\n\n");
2485 pr_info("\tperf record -e %s:%s -aR sleep 1\n\n", tev->group,
Masami Hiramatsu146a1432010-04-12 13:17:42 -04002486 tev->event);
2487 }
Masami Hiramatsua9b495b2009-12-08 17:02:47 -05002488
Masami Hiramatsu9aaf5a52015-02-19 23:31:13 +09002489 kprobe_blacklist__delete(&blacklist);
Masami Hiramatsue1d20172009-12-07 12:00:46 -05002490 strlist__delete(namelist);
Masami Hiramatsuae2cb1a2015-05-06 21:46:40 +09002491close_out:
Masami Hiramatsu50656ee2009-11-30 19:19:58 -05002492 close(fd);
Masami Hiramatsu146a1432010-04-12 13:17:42 -04002493 return ret;
Masami Hiramatsu50656ee2009-11-30 19:19:58 -05002494}
Masami Hiramatsufa282442009-12-08 17:03:23 -05002495
Namhyung Kim564c62a2015-01-14 20:18:07 +09002496static int find_probe_functions(struct map *map, char *name)
Masami Hiramatsueb948e52014-02-06 05:32:25 +00002497{
Namhyung Kim564c62a2015-01-14 20:18:07 +09002498 int found = 0;
Arnaldo Carvalho de Melo0a3873a2015-01-16 16:40:25 -03002499 struct symbol *sym;
Masami Hiramatsu4c859352015-05-08 10:03:35 +09002500 struct rb_node *tmp;
Namhyung Kim564c62a2015-01-14 20:18:07 +09002501
Wang Nan75e4a2a2015-05-15 12:14:44 +00002502 if (map__load(map, NULL) < 0)
2503 return 0;
2504
Masami Hiramatsu4c859352015-05-08 10:03:35 +09002505 map__for_each_symbol(map, sym, tmp) {
2506 if (strglobmatch(sym->name, name))
2507 found++;
Masami Hiramatsueb948e52014-02-06 05:32:25 +00002508 }
Namhyung Kim564c62a2015-01-14 20:18:07 +09002509
2510 return found;
Masami Hiramatsueb948e52014-02-06 05:32:25 +00002511}
2512
2513#define strdup_or_goto(str, label) \
2514 ({ char *__p = strdup(str); if (!__p) goto label; __p; })
2515
Naveen N. Rao7b6ff0b2015-04-28 17:35:40 +05302516void __weak arch__fix_tev_from_maps(struct perf_probe_event *pev __maybe_unused,
2517 struct probe_trace_event *tev __maybe_unused,
2518 struct map *map __maybe_unused) { }
2519
Masami Hiramatsueb948e52014-02-06 05:32:25 +00002520/*
2521 * Find probe function addresses from map.
2522 * Return an error or the number of found probe_trace_event
2523 */
2524static int find_probe_trace_events_from_map(struct perf_probe_event *pev,
Masami Hiramatsuddb2f582015-05-08 10:03:31 +09002525 struct probe_trace_event **tevs)
Masami Hiramatsueb948e52014-02-06 05:32:25 +00002526{
2527 struct map *map = NULL;
Masami Hiramatsueb948e52014-02-06 05:32:25 +00002528 struct ref_reloc_sym *reloc_sym = NULL;
2529 struct symbol *sym;
Masami Hiramatsueb948e52014-02-06 05:32:25 +00002530 struct probe_trace_event *tev;
2531 struct perf_probe_point *pp = &pev->point;
2532 struct probe_trace_point *tp;
Namhyung Kim564c62a2015-01-14 20:18:07 +09002533 int num_matched_functions;
Masami Hiramatsueb948e52014-02-06 05:32:25 +00002534 int ret, i;
2535
Masami Hiramatsu44225522015-05-08 10:03:28 +09002536 map = get_target_map(pev->target, pev->uprobes);
Masami Hiramatsueb948e52014-02-06 05:32:25 +00002537 if (!map) {
2538 ret = -EINVAL;
2539 goto out;
2540 }
2541
2542 /*
2543 * Load matched symbols: Since the different local symbols may have
2544 * same name but different addresses, this lists all the symbols.
2545 */
Namhyung Kim564c62a2015-01-14 20:18:07 +09002546 num_matched_functions = find_probe_functions(map, pp->function);
2547 if (num_matched_functions == 0) {
Masami Hiramatsueb948e52014-02-06 05:32:25 +00002548 pr_err("Failed to find symbol %s in %s\n", pp->function,
Masami Hiramatsu44225522015-05-08 10:03:28 +09002549 pev->target ? : "kernel");
Masami Hiramatsueb948e52014-02-06 05:32:25 +00002550 ret = -ENOENT;
2551 goto out;
Masami Hiramatsuddb2f582015-05-08 10:03:31 +09002552 } else if (num_matched_functions > probe_conf.max_probes) {
Masami Hiramatsueb948e52014-02-06 05:32:25 +00002553 pr_err("Too many functions matched in %s\n",
Masami Hiramatsu44225522015-05-08 10:03:28 +09002554 pev->target ? : "kernel");
Masami Hiramatsueb948e52014-02-06 05:32:25 +00002555 ret = -E2BIG;
2556 goto out;
2557 }
2558
Namhyung Kim25dd9172015-01-14 20:18:08 +09002559 if (!pev->uprobes && !pp->retprobe) {
He Kuang0560a0c2015-03-20 09:56:56 +08002560 reloc_sym = kernel_get_ref_reloc_sym();
Masami Hiramatsueb948e52014-02-06 05:32:25 +00002561 if (!reloc_sym) {
2562 pr_warning("Relocated base symbol is not found!\n");
2563 ret = -EINVAL;
2564 goto out;
2565 }
2566 }
2567
2568 /* Setup result trace-probe-events */
2569 *tevs = zalloc(sizeof(*tev) * num_matched_functions);
2570 if (!*tevs) {
2571 ret = -ENOMEM;
2572 goto out;
2573 }
2574
2575 ret = 0;
Namhyung Kim564c62a2015-01-14 20:18:07 +09002576
Arnaldo Carvalho de Melo0a3873a2015-01-16 16:40:25 -03002577 map__for_each_symbol_by_name(map, pp->function, sym) {
Masami Hiramatsueb948e52014-02-06 05:32:25 +00002578 tev = (*tevs) + ret;
2579 tp = &tev->point;
2580 if (ret == num_matched_functions) {
2581 pr_warning("Too many symbols are listed. Skip it.\n");
2582 break;
2583 }
2584 ret++;
2585
2586 if (pp->offset > sym->end - sym->start) {
2587 pr_warning("Offset %ld is bigger than the size of %s\n",
2588 pp->offset, sym->name);
2589 ret = -ENOENT;
2590 goto err_out;
2591 }
2592 /* Add one probe point */
2593 tp->address = map->unmap_ip(map, sym->start) + pp->offset;
2594 if (reloc_sym) {
2595 tp->symbol = strdup_or_goto(reloc_sym->name, nomem_out);
2596 tp->offset = tp->address - reloc_sym->addr;
2597 } else {
2598 tp->symbol = strdup_or_goto(sym->name, nomem_out);
2599 tp->offset = pp->offset;
2600 }
2601 tp->retprobe = pp->retprobe;
Masami Hiramatsu44225522015-05-08 10:03:28 +09002602 if (pev->target)
2603 tev->point.module = strdup_or_goto(pev->target,
2604 nomem_out);
Masami Hiramatsueb948e52014-02-06 05:32:25 +00002605 tev->uprobes = pev->uprobes;
2606 tev->nargs = pev->nargs;
2607 if (tev->nargs) {
2608 tev->args = zalloc(sizeof(struct probe_trace_arg) *
2609 tev->nargs);
2610 if (tev->args == NULL)
2611 goto nomem_out;
2612 }
2613 for (i = 0; i < tev->nargs; i++) {
2614 if (pev->args[i].name)
2615 tev->args[i].name =
2616 strdup_or_goto(pev->args[i].name,
2617 nomem_out);
2618
2619 tev->args[i].value = strdup_or_goto(pev->args[i].var,
2620 nomem_out);
2621 if (pev->args[i].type)
2622 tev->args[i].type =
2623 strdup_or_goto(pev->args[i].type,
2624 nomem_out);
2625 }
Naveen N. Rao7b6ff0b2015-04-28 17:35:40 +05302626 arch__fix_tev_from_maps(pev, tev, map);
Masami Hiramatsueb948e52014-02-06 05:32:25 +00002627 }
2628
2629out:
Masami Hiramatsu9b118ac2015-03-06 16:31:20 +09002630 put_target_map(map, pev->uprobes);
Masami Hiramatsueb948e52014-02-06 05:32:25 +00002631 return ret;
2632
2633nomem_out:
2634 ret = -ENOMEM;
2635err_out:
2636 clear_probe_trace_events(*tevs, num_matched_functions);
2637 zfree(tevs);
2638 goto out;
2639}
2640
Naveen N. Raod5c2e2c2015-04-28 17:35:39 +05302641bool __weak arch__prefers_symtab(void) { return false; }
2642
Srikar Dronamraju0e608362010-07-29 19:43:51 +05302643static int convert_to_probe_trace_events(struct perf_probe_event *pev,
Masami Hiramatsuddb2f582015-05-08 10:03:31 +09002644 struct probe_trace_event **tevs)
Masami Hiramatsue0faa8d2010-03-16 18:05:37 -04002645{
Masami Hiramatsueb948e52014-02-06 05:32:25 +00002646 int ret;
Masami Hiramatsu4235b042010-03-16 18:06:12 -04002647
Masami Hiramatsufb7345b2013-12-26 05:41:53 +00002648 if (pev->uprobes && !pev->group) {
2649 /* Replace group name if not given */
Masami Hiramatsu44225522015-05-08 10:03:28 +09002650 ret = convert_exec_to_group(pev->target, &pev->group);
Masami Hiramatsufb7345b2013-12-26 05:41:53 +00002651 if (ret != 0) {
2652 pr_warning("Failed to make a group name.\n");
2653 return ret;
2654 }
2655 }
2656
Naveen N. Raod5c2e2c2015-04-28 17:35:39 +05302657 if (arch__prefers_symtab() && !perf_probe_event_need_dwarf(pev)) {
Masami Hiramatsuddb2f582015-05-08 10:03:31 +09002658 ret = find_probe_trace_events_from_map(pev, tevs);
Naveen N. Raod5c2e2c2015-04-28 17:35:39 +05302659 if (ret > 0)
2660 return ret; /* Found in symbol table */
2661 }
2662
Masami Hiramatsu4b4da7f2010-03-22 13:10:26 -03002663 /* Convert perf_probe_event with debuginfo */
Masami Hiramatsuddb2f582015-05-08 10:03:31 +09002664 ret = try_to_find_probe_trace_events(pev, tevs);
Masami Hiramatsue334016f12010-04-12 13:17:49 -04002665 if (ret != 0)
Masami Hiramatsu190b57f2011-06-27 16:27:45 +09002666 return ret; /* Found in debuginfo or got an error */
Masami Hiramatsue0faa8d2010-03-16 18:05:37 -04002667
Masami Hiramatsuddb2f582015-05-08 10:03:31 +09002668 return find_probe_trace_events_from_map(pev, tevs);
Masami Hiramatsu4235b042010-03-16 18:06:12 -04002669}
2670
2671struct __event_package {
2672 struct perf_probe_event *pev;
Srikar Dronamraju0e608362010-07-29 19:43:51 +05302673 struct probe_trace_event *tevs;
Masami Hiramatsu4235b042010-03-16 18:06:12 -04002674 int ntevs;
2675};
2676
Masami Hiramatsuddb2f582015-05-08 10:03:31 +09002677int add_perf_probe_events(struct perf_probe_event *pevs, int npevs)
Masami Hiramatsu4235b042010-03-16 18:06:12 -04002678{
Masami Hiramatsu146a1432010-04-12 13:17:42 -04002679 int i, j, ret;
Masami Hiramatsu4235b042010-03-16 18:06:12 -04002680 struct __event_package *pkgs;
2681
Srikar Dronamraju225466f2012-04-16 17:39:09 +05302682 ret = 0;
Masami Hiramatsue334016f12010-04-12 13:17:49 -04002683 pkgs = zalloc(sizeof(struct __event_package) * npevs);
Srikar Dronamraju225466f2012-04-16 17:39:09 +05302684
Masami Hiramatsue334016f12010-04-12 13:17:49 -04002685 if (pkgs == NULL)
2686 return -ENOMEM;
Masami Hiramatsu4235b042010-03-16 18:06:12 -04002687
Masami Hiramatsuee45b6c2014-02-06 05:32:04 +00002688 ret = init_symbol_maps(pevs->uprobes);
Masami Hiramatsu449e5b22010-08-03 11:11:40 +09002689 if (ret < 0) {
2690 free(pkgs);
Masami Hiramatsu146a1432010-04-12 13:17:42 -04002691 return ret;
Masami Hiramatsu449e5b22010-08-03 11:11:40 +09002692 }
Masami Hiramatsu4235b042010-03-16 18:06:12 -04002693
2694 /* Loop 1: convert all events */
2695 for (i = 0; i < npevs; i++) {
2696 pkgs[i].pev = &pevs[i];
2697 /* Convert with or without debuginfo */
Srikar Dronamraju0e608362010-07-29 19:43:51 +05302698 ret = convert_to_probe_trace_events(pkgs[i].pev,
Masami Hiramatsuddb2f582015-05-08 10:03:31 +09002699 &pkgs[i].tevs);
Masami Hiramatsu146a1432010-04-12 13:17:42 -04002700 if (ret < 0)
2701 goto end;
2702 pkgs[i].ntevs = ret;
Masami Hiramatsu4235b042010-03-16 18:06:12 -04002703 }
2704
2705 /* Loop 2: add all events */
Arnaldo Carvalho de Melo8635bf62011-02-22 06:56:18 -03002706 for (i = 0; i < npevs; i++) {
Srikar Dronamraju0e608362010-07-29 19:43:51 +05302707 ret = __add_probe_trace_events(pkgs[i].pev, pkgs[i].tevs,
Masami Hiramatsuddb2f582015-05-08 10:03:31 +09002708 pkgs[i].ntevs,
2709 probe_conf.force_add);
Arnaldo Carvalho de Melofbee6322011-02-21 13:23:57 -03002710 if (ret < 0)
2711 break;
2712 }
Masami Hiramatsu146a1432010-04-12 13:17:42 -04002713end:
Masami Hiramatsu449e5b22010-08-03 11:11:40 +09002714 /* Loop 3: cleanup and free trace events */
2715 for (i = 0; i < npevs; i++) {
Masami Hiramatsu146a1432010-04-12 13:17:42 -04002716 for (j = 0; j < pkgs[i].ntevs; j++)
Srikar Dronamraju0e608362010-07-29 19:43:51 +05302717 clear_probe_trace_event(&pkgs[i].tevs[j]);
Arnaldo Carvalho de Melo74cf2492013-12-27 16:55:14 -03002718 zfree(&pkgs[i].tevs);
Masami Hiramatsu449e5b22010-08-03 11:11:40 +09002719 }
2720 free(pkgs);
Masami Hiramatsuee45b6c2014-02-06 05:32:04 +00002721 exit_symbol_maps();
Masami Hiramatsu146a1432010-04-12 13:17:42 -04002722
2723 return ret;
Masami Hiramatsue0faa8d2010-03-16 18:05:37 -04002724}
2725
Srikar Dronamraju0e608362010-07-29 19:43:51 +05302726static int __del_trace_probe_event(int fd, struct str_node *ent)
Masami Hiramatsubbbb5212009-12-15 10:32:10 -05002727{
2728 char *p;
2729 char buf[128];
Masami Hiramatsu4235b042010-03-16 18:06:12 -04002730 int ret;
Masami Hiramatsubbbb5212009-12-15 10:32:10 -05002731
Srikar Dronamraju0e608362010-07-29 19:43:51 +05302732 /* Convert from perf-probe event to trace-probe event */
Masami Hiramatsu146a1432010-04-12 13:17:42 -04002733 ret = e_snprintf(buf, 128, "-:%s", ent->s);
2734 if (ret < 0)
2735 goto error;
2736
Masami Hiramatsubbbb5212009-12-15 10:32:10 -05002737 p = strchr(buf + 2, ':');
Masami Hiramatsu146a1432010-04-12 13:17:42 -04002738 if (!p) {
2739 pr_debug("Internal error: %s should have ':' but not.\n",
2740 ent->s);
2741 ret = -ENOTSUP;
2742 goto error;
2743 }
Masami Hiramatsubbbb5212009-12-15 10:32:10 -05002744 *p = '/';
2745
Masami Hiramatsu4235b042010-03-16 18:06:12 -04002746 pr_debug("Writing event: %s\n", buf);
2747 ret = write(fd, buf, strlen(buf));
Masami Hiramatsu44a56042011-10-04 19:45:04 +09002748 if (ret < 0) {
2749 ret = -errno;
Masami Hiramatsu146a1432010-04-12 13:17:42 -04002750 goto error;
Masami Hiramatsu44a56042011-10-04 19:45:04 +09002751 }
Masami Hiramatsu146a1432010-04-12 13:17:42 -04002752
Masami Hiramatsu5e17b282014-10-27 16:31:31 -04002753 pr_info("Removed event: %s\n", ent->s);
Masami Hiramatsu146a1432010-04-12 13:17:42 -04002754 return 0;
2755error:
Masami Hiramatsu5f03cba2014-08-14 02:22:34 +00002756 pr_warning("Failed to delete event: %s\n",
2757 strerror_r(-ret, buf, sizeof(buf)));
Masami Hiramatsu146a1432010-04-12 13:17:42 -04002758 return ret;
Masami Hiramatsubbbb5212009-12-15 10:32:10 -05002759}
2760
Masami Hiramatsu307a4642015-05-05 11:29:48 +09002761static int del_trace_probe_events(int fd, struct strfilter *filter,
2762 struct strlist *namelist)
Masami Hiramatsufa282442009-12-08 17:03:23 -05002763{
Masami Hiramatsu307a4642015-05-05 11:29:48 +09002764 struct str_node *ent;
2765 const char *p;
Masami Hiramatsu6dbe31f2015-04-23 22:46:14 +09002766 int ret = -ENOENT;
Masami Hiramatsufa282442009-12-08 17:03:23 -05002767
Masami Hiramatsu307a4642015-05-05 11:29:48 +09002768 if (!namelist)
2769 return -ENOENT;
2770
2771 strlist__for_each(ent, namelist) {
2772 p = strchr(ent->s, ':');
2773 if ((p && strfilter__compare(filter, p + 1)) ||
2774 strfilter__compare(filter, ent->s)) {
Srikar Dronamraju0e608362010-07-29 19:43:51 +05302775 ret = __del_trace_probe_event(fd, ent);
Masami Hiramatsu307a4642015-05-05 11:29:48 +09002776 if (ret < 0)
2777 break;
Masami Hiramatsubbbb5212009-12-15 10:32:10 -05002778 }
2779 }
Masami Hiramatsu146a1432010-04-12 13:17:42 -04002780
2781 return ret;
Masami Hiramatsufa282442009-12-08 17:03:23 -05002782}
2783
Masami Hiramatsu307a4642015-05-05 11:29:48 +09002784int del_perf_probe_events(struct strfilter *filter)
Masami Hiramatsufa282442009-12-08 17:03:23 -05002785{
Masami Hiramatsu307a4642015-05-05 11:29:48 +09002786 int ret, ret2, ufd = -1, kfd = -1;
Srikar Dronamraju225466f2012-04-16 17:39:09 +05302787 struct strlist *namelist = NULL, *unamelist = NULL;
Masami Hiramatsu307a4642015-05-05 11:29:48 +09002788 char *str = strfilter__string(filter);
2789
2790 if (!str)
2791 return -EINVAL;
2792
2793 pr_debug("Delete filter: \'%s\'\n", str);
Masami Hiramatsu146a1432010-04-12 13:17:42 -04002794
Masami Hiramatsufa282442009-12-08 17:03:23 -05002795 /* Get current event names */
Srikar Dronamraju225466f2012-04-16 17:39:09 +05302796 kfd = open_kprobe_events(true);
Masami Hiramatsu467ec082014-08-13 16:12:50 +00002797 if (kfd >= 0)
2798 namelist = get_probe_trace_event_names(kfd, true);
Srikar Dronamraju225466f2012-04-16 17:39:09 +05302799
Srikar Dronamraju225466f2012-04-16 17:39:09 +05302800 ufd = open_uprobe_events(true);
Masami Hiramatsu467ec082014-08-13 16:12:50 +00002801 if (ufd >= 0)
Srikar Dronamraju225466f2012-04-16 17:39:09 +05302802 unamelist = get_probe_trace_event_names(ufd, true);
2803
Masami Hiramatsu467ec082014-08-13 16:12:50 +00002804 if (kfd < 0 && ufd < 0) {
2805 print_both_open_warning(kfd, ufd);
Masami Hiramatsu307a4642015-05-05 11:29:48 +09002806 ret = kfd;
Masami Hiramatsu467ec082014-08-13 16:12:50 +00002807 goto error;
2808 }
2809
Masami Hiramatsu307a4642015-05-05 11:29:48 +09002810 ret = del_trace_probe_events(kfd, filter, namelist);
2811 if (ret < 0 && ret != -ENOENT)
Srikar Dronamraju225466f2012-04-16 17:39:09 +05302812 goto error;
Masami Hiramatsufa282442009-12-08 17:03:23 -05002813
Masami Hiramatsu307a4642015-05-05 11:29:48 +09002814 ret2 = del_trace_probe_events(ufd, filter, unamelist);
Masami Hiramatsudddc7ee2015-05-27 17:37:25 +09002815 if (ret2 < 0 && ret2 != -ENOENT) {
Masami Hiramatsu307a4642015-05-05 11:29:48 +09002816 ret = ret2;
Masami Hiramatsudddc7ee2015-05-27 17:37:25 +09002817 goto error;
2818 }
2819 if (ret == -ENOENT && ret2 == -ENOENT)
Masami Hiramatsu307a4642015-05-05 11:29:48 +09002820 pr_debug("\"%s\" does not hit any event.\n", str);
2821 /* Note that this is silently ignored */
Masami Hiramatsudddc7ee2015-05-27 17:37:25 +09002822 ret = 0;
Srikar Dronamraju225466f2012-04-16 17:39:09 +05302823
2824error:
2825 if (kfd >= 0) {
Srikar Dronamrajua23c4dc2012-05-31 17:16:43 +05302826 strlist__delete(namelist);
Srikar Dronamraju225466f2012-04-16 17:39:09 +05302827 close(kfd);
2828 }
2829
2830 if (ufd >= 0) {
Srikar Dronamrajua23c4dc2012-05-31 17:16:43 +05302831 strlist__delete(unamelist);
Srikar Dronamraju225466f2012-04-16 17:39:09 +05302832 close(ufd);
2833 }
Masami Hiramatsu307a4642015-05-05 11:29:48 +09002834 free(str);
Masami Hiramatsu146a1432010-04-12 13:17:42 -04002835
2836 return ret;
Masami Hiramatsufa282442009-12-08 17:03:23 -05002837}
Srikar Dronamraju225466f2012-04-16 17:39:09 +05302838
Masami Hiramatsu3c422582011-01-20 23:15:45 +09002839/* TODO: don't use a global variable for filter ... */
2840static struct strfilter *available_func_filter;
Masami Hiramatsufa282442009-12-08 17:03:23 -05002841
Masami Hiramatsue80711c2011-01-13 21:46:11 +09002842/*
Masami Hiramatsu3c422582011-01-20 23:15:45 +09002843 * If a symbol corresponds to a function with global binding and
2844 * matches filter return 0. For all others return 1.
Masami Hiramatsue80711c2011-01-13 21:46:11 +09002845 */
Irina Tirdea1d037ca2012-09-11 01:15:03 +03002846static int filter_available_functions(struct map *map __maybe_unused,
Masami Hiramatsu3c422582011-01-20 23:15:45 +09002847 struct symbol *sym)
Masami Hiramatsue80711c2011-01-13 21:46:11 +09002848{
Namhyung Kime578da32015-03-06 16:31:29 +09002849 if (strfilter__compare(available_func_filter, sym->name))
Masami Hiramatsu3c422582011-01-20 23:15:45 +09002850 return 0;
2851 return 1;
Masami Hiramatsue80711c2011-01-13 21:46:11 +09002852}
2853
Masami Hiramatsu2df58632014-02-06 05:32:11 +00002854int show_available_funcs(const char *target, struct strfilter *_filter,
2855 bool user)
Masami Hiramatsue80711c2011-01-13 21:46:11 +09002856{
Masami Hiramatsu2df58632014-02-06 05:32:11 +00002857 struct map *map;
2858 int ret;
2859
2860 ret = init_symbol_maps(user);
2861 if (ret < 0)
2862 return ret;
2863
2864 /* Get a symbol map */
2865 if (user)
2866 map = dso__new_map(target);
2867 else
2868 map = kernel_get_module_map(target);
2869 if (!map) {
2870 pr_err("Failed to get a map for %s\n", (target) ? : "kernel");
Masami Hiramatsue80711c2011-01-13 21:46:11 +09002871 return -EINVAL;
2872 }
Masami Hiramatsu2df58632014-02-06 05:32:11 +00002873
2874 /* Load symbols with given filter */
2875 available_func_filter = _filter;
2876 if (map__load(map, filter_available_functions)) {
2877 pr_err("Failed to load symbols in %s\n", (target) ? : "kernel");
2878 goto end;
2879 }
Masami Hiramatsue80711c2011-01-13 21:46:11 +09002880 if (!dso__sorted_by_name(map->dso, map->type))
2881 dso__sort_by_name(map->dso, map->type);
2882
Masami Hiramatsu2df58632014-02-06 05:32:11 +00002883 /* Show all (filtered) symbols */
Srikar Dronamraju225466f2012-04-16 17:39:09 +05302884 setup_pager();
Masami Hiramatsu2df58632014-02-06 05:32:11 +00002885 dso__fprintf_symbols_by_name(map->dso, map->type, stdout);
2886end:
2887 if (user) {
Arnaldo Carvalho de Melo84c2caf2015-05-25 16:59:56 -03002888 map__put(map);
Masami Hiramatsu2df58632014-02-06 05:32:11 +00002889 }
2890 exit_symbol_maps();
Srikar Dronamraju225466f2012-04-16 17:39:09 +05302891
Masami Hiramatsu2df58632014-02-06 05:32:11 +00002892 return ret;
Srikar Dronamraju225466f2012-04-16 17:39:09 +05302893}
2894