blob: 88714dec891223f10e41dd794e08ab8180bcdc52 [file] [log] [blame]
Masami Hiramatsu92f6c722015-07-15 18:14:07 +09001/*
2 * probe-file.c : operate ftrace k/uprobe events files
3 *
4 * Written by Masami Hiramatsu <masami.hiramatsu.pt@hitachi.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 */
Masami Hiramatsudd975492016-06-15 12:28:30 +090017#include <sys/uio.h>
Masami Hiramatsu92f6c722015-07-15 18:14:07 +090018#include "util.h"
19#include "event.h"
20#include "strlist.h"
21#include "debug.h"
22#include "cache.h"
23#include "color.h"
24#include "symbol.h"
25#include "thread.h"
Jiri Olsafbf99622015-09-02 09:56:45 +020026#include <api/fs/tracing_path.h>
Masami Hiramatsu92f6c722015-07-15 18:14:07 +090027#include "probe-event.h"
28#include "probe-file.h"
29#include "session.h"
Alexis Berlemont3b1f8312016-12-14 01:07:32 +010030#include "perf_regs.h"
Masami Hiramatsu92f6c722015-07-15 18:14:07 +090031
Ravi Bangoria2e1f8f72017-02-07 11:15:47 +053032/* 4096 - 2 ('\n' + '\0') */
33#define MAX_CMDLEN 4094
Masami Hiramatsu92f6c722015-07-15 18:14:07 +090034
35static void print_open_warning(int err, bool uprobe)
36{
37 char sbuf[STRERR_BUFSIZE];
38
39 if (err == -ENOENT) {
40 const char *config;
41
42 if (uprobe)
43 config = "CONFIG_UPROBE_EVENTS";
44 else
45 config = "CONFIG_KPROBE_EVENTS";
46
47 pr_warning("%cprobe_events file does not exist"
48 " - please rebuild kernel with %s.\n",
49 uprobe ? 'u' : 'k', config);
50 } else if (err == -ENOTSUP)
51 pr_warning("Tracefs or debugfs is not mounted.\n");
52 else
53 pr_warning("Failed to open %cprobe_events: %s\n",
54 uprobe ? 'u' : 'k',
Arnaldo Carvalho de Meloc8b5f2c2016-07-06 11:56:20 -030055 str_error_r(-err, sbuf, sizeof(sbuf)));
Masami Hiramatsu92f6c722015-07-15 18:14:07 +090056}
57
58static void print_both_open_warning(int kerr, int uerr)
59{
60 /* Both kprobes and uprobes are disabled, warn it. */
61 if (kerr == -ENOTSUP && uerr == -ENOTSUP)
62 pr_warning("Tracefs or debugfs is not mounted.\n");
63 else if (kerr == -ENOENT && uerr == -ENOENT)
64 pr_warning("Please rebuild kernel with CONFIG_KPROBE_EVENTS "
65 "or/and CONFIG_UPROBE_EVENTS.\n");
66 else {
67 char sbuf[STRERR_BUFSIZE];
68 pr_warning("Failed to open kprobe events: %s.\n",
Arnaldo Carvalho de Meloc8b5f2c2016-07-06 11:56:20 -030069 str_error_r(-kerr, sbuf, sizeof(sbuf)));
Masami Hiramatsu92f6c722015-07-15 18:14:07 +090070 pr_warning("Failed to open uprobe events: %s.\n",
Arnaldo Carvalho de Meloc8b5f2c2016-07-06 11:56:20 -030071 str_error_r(-uerr, sbuf, sizeof(sbuf)));
Masami Hiramatsu92f6c722015-07-15 18:14:07 +090072 }
73}
74
Naveen N. Raoe491bc22017-02-23 17:07:23 +053075int open_trace_file(const char *trace_file, bool readwrite)
Masami Hiramatsu92f6c722015-07-15 18:14:07 +090076{
77 char buf[PATH_MAX];
Masami Hiramatsu92f6c722015-07-15 18:14:07 +090078 int ret;
79
Masami Hiramatsu04e11962016-08-24 14:57:58 +090080 ret = e_snprintf(buf, PATH_MAX, "%s/%s",
81 tracing_path, trace_file);
Masami Hiramatsu92f6c722015-07-15 18:14:07 +090082 if (ret >= 0) {
83 pr_debug("Opening %s write=%d\n", buf, readwrite);
84 if (readwrite && !probe_event_dry_run)
85 ret = open(buf, O_RDWR | O_APPEND, 0);
86 else
87 ret = open(buf, O_RDONLY, 0);
88
89 if (ret < 0)
90 ret = -errno;
91 }
92 return ret;
93}
94
95static int open_kprobe_events(bool readwrite)
96{
Naveen N. Raoe491bc22017-02-23 17:07:23 +053097 return open_trace_file("kprobe_events", readwrite);
Masami Hiramatsu92f6c722015-07-15 18:14:07 +090098}
99
100static int open_uprobe_events(bool readwrite)
101{
Naveen N. Raoe491bc22017-02-23 17:07:23 +0530102 return open_trace_file("uprobe_events", readwrite);
Masami Hiramatsu92f6c722015-07-15 18:14:07 +0900103}
104
105int probe_file__open(int flag)
106{
107 int fd;
108
109 if (flag & PF_FL_UPROBE)
110 fd = open_uprobe_events(flag & PF_FL_RW);
111 else
112 fd = open_kprobe_events(flag & PF_FL_RW);
113 if (fd < 0)
114 print_open_warning(fd, flag & PF_FL_UPROBE);
115
116 return fd;
117}
118
119int probe_file__open_both(int *kfd, int *ufd, int flag)
120{
121 if (!kfd || !ufd)
122 return -EINVAL;
123
124 *kfd = open_kprobe_events(flag & PF_FL_RW);
125 *ufd = open_uprobe_events(flag & PF_FL_RW);
126 if (*kfd < 0 && *ufd < 0) {
127 print_both_open_warning(*kfd, *ufd);
128 return *kfd;
129 }
130
131 return 0;
132}
133
134/* Get raw string list of current kprobe_events or uprobe_events */
135struct strlist *probe_file__get_rawlist(int fd)
136{
Colin Ian King03258622016-08-12 22:44:56 +0100137 int ret, idx, fddup;
Masami Hiramatsu92f6c722015-07-15 18:14:07 +0900138 FILE *fp;
139 char buf[MAX_CMDLEN];
140 char *p;
141 struct strlist *sl;
142
Wang Nan421fd082015-11-06 09:50:15 +0000143 if (fd < 0)
144 return NULL;
145
Masami Hiramatsu92f6c722015-07-15 18:14:07 +0900146 sl = strlist__new(NULL, NULL);
Arnaldo Carvalho de Melo60ebc152016-08-15 17:06:47 -0300147 if (sl == NULL)
148 return NULL;
Masami Hiramatsu92f6c722015-07-15 18:14:07 +0900149
Colin Ian King03258622016-08-12 22:44:56 +0100150 fddup = dup(fd);
151 if (fddup < 0)
152 goto out_free_sl;
153
154 fp = fdopen(fddup, "r");
155 if (!fp)
156 goto out_close_fddup;
157
Masami Hiramatsu92f6c722015-07-15 18:14:07 +0900158 while (!feof(fp)) {
159 p = fgets(buf, MAX_CMDLEN, fp);
160 if (!p)
161 break;
162
163 idx = strlen(p) - 1;
164 if (p[idx] == '\n')
165 p[idx] = '\0';
166 ret = strlist__add(sl, buf);
167 if (ret < 0) {
168 pr_debug("strlist__add failed (%d)\n", ret);
Arnaldo Carvalho de Melo60ebc152016-08-15 17:06:47 -0300169 goto out_close_fp;
Masami Hiramatsu92f6c722015-07-15 18:14:07 +0900170 }
171 }
172 fclose(fp);
173
174 return sl;
Colin Ian King03258622016-08-12 22:44:56 +0100175
Arnaldo Carvalho de Melo60ebc152016-08-15 17:06:47 -0300176out_close_fp:
177 fclose(fp);
178 goto out_free_sl;
Colin Ian King03258622016-08-12 22:44:56 +0100179out_close_fddup:
180 close(fddup);
181out_free_sl:
182 strlist__delete(sl);
183 return NULL;
Masami Hiramatsu92f6c722015-07-15 18:14:07 +0900184}
185
186static struct strlist *__probe_file__get_namelist(int fd, bool include_group)
187{
188 char buf[128];
189 struct strlist *sl, *rawlist;
190 struct str_node *ent;
191 struct probe_trace_event tev;
192 int ret = 0;
193
194 memset(&tev, 0, sizeof(tev));
195 rawlist = probe_file__get_rawlist(fd);
196 if (!rawlist)
197 return NULL;
198 sl = strlist__new(NULL, NULL);
Arnaldo Carvalho de Melo602a1f42016-06-23 11:31:20 -0300199 strlist__for_each_entry(ent, rawlist) {
Masami Hiramatsu92f6c722015-07-15 18:14:07 +0900200 ret = parse_probe_trace_command(ent->s, &tev);
201 if (ret < 0)
202 break;
203 if (include_group) {
204 ret = e_snprintf(buf, 128, "%s:%s", tev.group,
205 tev.event);
206 if (ret >= 0)
207 ret = strlist__add(sl, buf);
208 } else
209 ret = strlist__add(sl, tev.event);
210 clear_probe_trace_event(&tev);
211 if (ret < 0)
212 break;
213 }
214 strlist__delete(rawlist);
215
216 if (ret < 0) {
217 strlist__delete(sl);
218 return NULL;
219 }
220 return sl;
221}
222
223/* Get current perf-probe event names */
224struct strlist *probe_file__get_namelist(int fd)
225{
226 return __probe_file__get_namelist(fd, false);
227}
228
229int probe_file__add_event(int fd, struct probe_trace_event *tev)
230{
231 int ret = 0;
232 char *buf = synthesize_probe_trace_command(tev);
233 char sbuf[STRERR_BUFSIZE];
234
235 if (!buf) {
236 pr_debug("Failed to synthesize probe trace event.\n");
237 return -EINVAL;
238 }
239
240 pr_debug("Writing event: %s\n", buf);
241 if (!probe_event_dry_run) {
Masami Hiramatsu6ed07202016-04-26 18:03:04 +0900242 if (write(fd, buf, strlen(buf)) < (int)strlen(buf)) {
Masami Hiramatsu92f6c722015-07-15 18:14:07 +0900243 ret = -errno;
244 pr_warning("Failed to write event: %s\n",
Arnaldo Carvalho de Meloc8b5f2c2016-07-06 11:56:20 -0300245 str_error_r(errno, sbuf, sizeof(sbuf)));
Masami Hiramatsu92f6c722015-07-15 18:14:07 +0900246 }
247 }
248 free(buf);
249
250 return ret;
251}
252
253static int __del_trace_probe_event(int fd, struct str_node *ent)
254{
255 char *p;
256 char buf[128];
257 int ret;
258
259 /* Convert from perf-probe event to trace-probe event */
260 ret = e_snprintf(buf, 128, "-:%s", ent->s);
261 if (ret < 0)
262 goto error;
263
264 p = strchr(buf + 2, ':');
265 if (!p) {
266 pr_debug("Internal error: %s should have ':' but not.\n",
267 ent->s);
268 ret = -ENOTSUP;
269 goto error;
270 }
271 *p = '/';
272
273 pr_debug("Writing event: %s\n", buf);
274 ret = write(fd, buf, strlen(buf));
275 if (ret < 0) {
276 ret = -errno;
277 goto error;
278 }
279
Masami Hiramatsu92f6c722015-07-15 18:14:07 +0900280 return 0;
281error:
282 pr_warning("Failed to delete event: %s\n",
Arnaldo Carvalho de Meloc8b5f2c2016-07-06 11:56:20 -0300283 str_error_r(-ret, buf, sizeof(buf)));
Masami Hiramatsu92f6c722015-07-15 18:14:07 +0900284 return ret;
285}
286
Namhyung Kime607f142015-09-04 21:16:03 +0900287int probe_file__get_events(int fd, struct strfilter *filter,
288 struct strlist *plist)
Masami Hiramatsu92f6c722015-07-15 18:14:07 +0900289{
290 struct strlist *namelist;
291 struct str_node *ent;
292 const char *p;
293 int ret = -ENOENT;
294
Wang Nan421fd082015-11-06 09:50:15 +0000295 if (!plist)
296 return -EINVAL;
297
Masami Hiramatsu92f6c722015-07-15 18:14:07 +0900298 namelist = __probe_file__get_namelist(fd, true);
299 if (!namelist)
300 return -ENOENT;
301
Arnaldo Carvalho de Melo602a1f42016-06-23 11:31:20 -0300302 strlist__for_each_entry(ent, namelist) {
Masami Hiramatsu92f6c722015-07-15 18:14:07 +0900303 p = strchr(ent->s, ':');
304 if ((p && strfilter__compare(filter, p + 1)) ||
305 strfilter__compare(filter, ent->s)) {
Namhyung Kime7895e42015-09-04 21:16:02 +0900306 strlist__add(plist, ent->s);
307 ret = 0;
Masami Hiramatsu92f6c722015-07-15 18:14:07 +0900308 }
309 }
310 strlist__delete(namelist);
311
312 return ret;
313}
Namhyung Kime7895e42015-09-04 21:16:02 +0900314
Namhyung Kime607f142015-09-04 21:16:03 +0900315int probe_file__del_strlist(int fd, struct strlist *namelist)
Namhyung Kime7895e42015-09-04 21:16:02 +0900316{
317 int ret = 0;
318 struct str_node *ent;
319
Arnaldo Carvalho de Melo602a1f42016-06-23 11:31:20 -0300320 strlist__for_each_entry(ent, namelist) {
Namhyung Kime7895e42015-09-04 21:16:02 +0900321 ret = __del_trace_probe_event(fd, ent);
322 if (ret < 0)
323 break;
324 }
325 return ret;
326}
327
328int probe_file__del_events(int fd, struct strfilter *filter)
329{
330 struct strlist *namelist;
331 int ret;
332
333 namelist = strlist__new(NULL, NULL);
334 if (!namelist)
335 return -ENOMEM;
336
337 ret = probe_file__get_events(fd, filter, namelist);
338 if (ret < 0)
339 return ret;
340
341 ret = probe_file__del_strlist(fd, namelist);
342 strlist__delete(namelist);
343
344 return ret;
345}
Masami Hiramatsudd975492016-06-15 12:28:30 +0900346
347/* Caller must ensure to remove this entry from list */
348static void probe_cache_entry__delete(struct probe_cache_entry *entry)
349{
350 if (entry) {
351 BUG_ON(!list_empty(&entry->node));
352
353 strlist__delete(entry->tevlist);
354 clear_perf_probe_event(&entry->pev);
355 zfree(&entry->spev);
356 free(entry);
357 }
358}
359
360static struct probe_cache_entry *
361probe_cache_entry__new(struct perf_probe_event *pev)
362{
363 struct probe_cache_entry *entry = zalloc(sizeof(*entry));
364
365 if (entry) {
366 INIT_LIST_HEAD(&entry->node);
367 entry->tevlist = strlist__new(NULL, NULL);
368 if (!entry->tevlist)
369 zfree(&entry);
370 else if (pev) {
371 entry->spev = synthesize_perf_probe_command(pev);
372 if (!entry->spev ||
373 perf_probe_event__copy(&entry->pev, pev) < 0) {
374 probe_cache_entry__delete(entry);
375 return NULL;
376 }
377 }
378 }
379
380 return entry;
381}
382
Masami Hiramatsu42bba262016-07-12 19:05:18 +0900383int probe_cache_entry__get_event(struct probe_cache_entry *entry,
384 struct probe_trace_event **tevs)
385{
386 struct probe_trace_event *tev;
387 struct str_node *node;
388 int ret, i;
389
390 ret = strlist__nr_entries(entry->tevlist);
391 if (ret > probe_conf.max_probes)
392 return -E2BIG;
393
394 *tevs = zalloc(ret * sizeof(*tev));
395 if (!*tevs)
396 return -ENOMEM;
397
398 i = 0;
399 strlist__for_each_entry(node, entry->tevlist) {
400 tev = &(*tevs)[i++];
401 ret = parse_probe_trace_command(node->s, tev);
402 if (ret < 0)
403 break;
404 }
405 return i;
406}
407
408/* For the kernel probe caches, pass target = NULL or DSO__NAME_KALLSYMS */
Masami Hiramatsudd975492016-06-15 12:28:30 +0900409static int probe_cache__open(struct probe_cache *pcache, const char *target)
410{
411 char cpath[PATH_MAX];
412 char sbuildid[SBUILD_ID_SIZE];
Masami Hiramatsu1f3736c2016-07-01 17:03:26 +0900413 char *dir_name = NULL;
Masami Hiramatsu42bba262016-07-12 19:05:18 +0900414 bool is_kallsyms = false;
Masami Hiramatsudd975492016-06-15 12:28:30 +0900415 int ret, fd;
416
Masami Hiramatsu1f3736c2016-07-01 17:03:26 +0900417 if (target && build_id_cache__cached(target)) {
418 /* This is a cached buildid */
419 strncpy(sbuildid, target, SBUILD_ID_SIZE);
420 dir_name = build_id_cache__linkname(sbuildid, NULL, 0);
421 goto found;
422 }
423
Masami Hiramatsu42bba262016-07-12 19:05:18 +0900424 if (!target || !strcmp(target, DSO__NAME_KALLSYMS)) {
Masami Hiramatsudd975492016-06-15 12:28:30 +0900425 target = DSO__NAME_KALLSYMS;
Masami Hiramatsu42bba262016-07-12 19:05:18 +0900426 is_kallsyms = true;
Masami Hiramatsudd975492016-06-15 12:28:30 +0900427 ret = sysfs__sprintf_build_id("/", sbuildid);
Masami Hiramatsu42bba262016-07-12 19:05:18 +0900428 } else
429 ret = filename__sprintf_build_id(target, sbuildid);
430
Masami Hiramatsudd975492016-06-15 12:28:30 +0900431 if (ret < 0) {
432 pr_debug("Failed to get build-id from %s.\n", target);
433 return ret;
434 }
435
436 /* If we have no buildid cache, make it */
437 if (!build_id_cache__cached(sbuildid)) {
438 ret = build_id_cache__add_s(sbuildid, target,
439 is_kallsyms, NULL);
440 if (ret < 0) {
441 pr_debug("Failed to add build-id cache: %s\n", target);
442 return ret;
443 }
444 }
445
446 dir_name = build_id_cache__cachedir(sbuildid, target, is_kallsyms,
447 false);
Masami Hiramatsu1f3736c2016-07-01 17:03:26 +0900448found:
449 if (!dir_name) {
450 pr_debug("Failed to get cache from %s\n", target);
Masami Hiramatsudd975492016-06-15 12:28:30 +0900451 return -ENOMEM;
Masami Hiramatsu1f3736c2016-07-01 17:03:26 +0900452 }
Masami Hiramatsudd975492016-06-15 12:28:30 +0900453
454 snprintf(cpath, PATH_MAX, "%s/probes", dir_name);
455 fd = open(cpath, O_CREAT | O_RDWR, 0644);
456 if (fd < 0)
457 pr_debug("Failed to open cache(%d): %s\n", fd, cpath);
458 free(dir_name);
459 pcache->fd = fd;
460
461 return fd;
462}
463
464static int probe_cache__load(struct probe_cache *pcache)
465{
466 struct probe_cache_entry *entry = NULL;
467 char buf[MAX_CMDLEN], *p;
Colin Ian King03258622016-08-12 22:44:56 +0100468 int ret = 0, fddup;
Masami Hiramatsudd975492016-06-15 12:28:30 +0900469 FILE *fp;
470
Colin Ian King03258622016-08-12 22:44:56 +0100471 fddup = dup(pcache->fd);
472 if (fddup < 0)
473 return -errno;
474 fp = fdopen(fddup, "r");
Arnaldo Carvalho de Melo60ebc152016-08-15 17:06:47 -0300475 if (!fp) {
476 close(fddup);
Masami Hiramatsudd975492016-06-15 12:28:30 +0900477 return -EINVAL;
Arnaldo Carvalho de Melo60ebc152016-08-15 17:06:47 -0300478 }
Masami Hiramatsudd975492016-06-15 12:28:30 +0900479
480 while (!feof(fp)) {
481 if (!fgets(buf, MAX_CMDLEN, fp))
482 break;
483 p = strchr(buf, '\n');
484 if (p)
485 *p = '\0';
Masami Hiramatsu6430a94e2016-07-01 17:04:10 +0900486 /* #perf_probe_event or %sdt_event */
487 if (buf[0] == '#' || buf[0] == '%') {
Masami Hiramatsudd975492016-06-15 12:28:30 +0900488 entry = probe_cache_entry__new(NULL);
489 if (!entry) {
490 ret = -ENOMEM;
491 goto out;
492 }
Masami Hiramatsu6430a94e2016-07-01 17:04:10 +0900493 if (buf[0] == '%')
494 entry->sdt = true;
Masami Hiramatsudd975492016-06-15 12:28:30 +0900495 entry->spev = strdup(buf + 1);
496 if (entry->spev)
497 ret = parse_perf_probe_command(buf + 1,
498 &entry->pev);
499 else
500 ret = -ENOMEM;
501 if (ret < 0) {
502 probe_cache_entry__delete(entry);
503 goto out;
504 }
505 list_add_tail(&entry->node, &pcache->entries);
506 } else { /* trace_probe_event */
507 if (!entry) {
508 ret = -EINVAL;
509 goto out;
510 }
511 strlist__add(entry->tevlist, buf);
512 }
513 }
514out:
515 fclose(fp);
516 return ret;
517}
518
519static struct probe_cache *probe_cache__alloc(void)
520{
521 struct probe_cache *pcache = zalloc(sizeof(*pcache));
522
523 if (pcache) {
524 INIT_LIST_HEAD(&pcache->entries);
525 pcache->fd = -EINVAL;
526 }
527 return pcache;
528}
529
530void probe_cache__purge(struct probe_cache *pcache)
531{
532 struct probe_cache_entry *entry, *n;
533
534 list_for_each_entry_safe(entry, n, &pcache->entries, node) {
535 list_del_init(&entry->node);
536 probe_cache_entry__delete(entry);
537 }
538}
539
540void probe_cache__delete(struct probe_cache *pcache)
541{
542 if (!pcache)
543 return;
544
545 probe_cache__purge(pcache);
546 if (pcache->fd > 0)
547 close(pcache->fd);
548 free(pcache);
549}
550
551struct probe_cache *probe_cache__new(const char *target)
552{
553 struct probe_cache *pcache = probe_cache__alloc();
554 int ret;
555
556 if (!pcache)
557 return NULL;
558
559 ret = probe_cache__open(pcache, target);
560 if (ret < 0) {
561 pr_debug("Cache open error: %d\n", ret);
562 goto out_err;
563 }
564
565 ret = probe_cache__load(pcache);
566 if (ret < 0) {
567 pr_debug("Cache read error: %d\n", ret);
568 goto out_err;
569 }
570
571 return pcache;
572
573out_err:
574 probe_cache__delete(pcache);
575 return NULL;
576}
577
578static bool streql(const char *a, const char *b)
579{
580 if (a == b)
581 return true;
582
583 if (!a || !b)
584 return false;
585
586 return !strcmp(a, b);
587}
588
Masami Hiramatsubc062232016-07-01 17:03:12 +0900589struct probe_cache_entry *
Masami Hiramatsudd975492016-06-15 12:28:30 +0900590probe_cache__find(struct probe_cache *pcache, struct perf_probe_event *pev)
591{
592 struct probe_cache_entry *entry = NULL;
593 char *cmd = synthesize_perf_probe_command(pev);
594
595 if (!cmd)
596 return NULL;
597
Masami Hiramatsu05bf2c82016-07-12 19:05:04 +0900598 for_each_probe_cache_entry(entry, pcache) {
Masami Hiramatsu36a009f2016-07-12 19:04:43 +0900599 if (pev->sdt) {
600 if (entry->pev.event &&
601 streql(entry->pev.event, pev->event) &&
602 (!pev->group ||
603 streql(entry->pev.group, pev->group)))
604 goto found;
605
606 continue;
607 }
Masami Hiramatsudd975492016-06-15 12:28:30 +0900608 /* Hit if same event name or same command-string */
609 if ((pev->event &&
610 (streql(entry->pev.group, pev->group) &&
611 streql(entry->pev.event, pev->event))) ||
612 (!strcmp(entry->spev, cmd)))
613 goto found;
614 }
615 entry = NULL;
616
617found:
618 free(cmd);
619 return entry;
620}
621
Masami Hiramatsubc062232016-07-01 17:03:12 +0900622struct probe_cache_entry *
623probe_cache__find_by_name(struct probe_cache *pcache,
624 const char *group, const char *event)
625{
626 struct probe_cache_entry *entry = NULL;
627
Masami Hiramatsu05bf2c82016-07-12 19:05:04 +0900628 for_each_probe_cache_entry(entry, pcache) {
Masami Hiramatsubc062232016-07-01 17:03:12 +0900629 /* Hit if same event name or same command-string */
630 if (streql(entry->pev.group, group) &&
631 streql(entry->pev.event, event))
632 goto found;
633 }
634 entry = NULL;
635
636found:
637 return entry;
638}
639
Masami Hiramatsudd975492016-06-15 12:28:30 +0900640int probe_cache__add_entry(struct probe_cache *pcache,
641 struct perf_probe_event *pev,
642 struct probe_trace_event *tevs, int ntevs)
643{
644 struct probe_cache_entry *entry = NULL;
645 char *command;
646 int i, ret = 0;
647
648 if (!pcache || !pev || !tevs || ntevs <= 0) {
649 ret = -EINVAL;
650 goto out_err;
651 }
652
653 /* Remove old cache entry */
654 entry = probe_cache__find(pcache, pev);
655 if (entry) {
656 list_del_init(&entry->node);
657 probe_cache_entry__delete(entry);
658 }
659
660 ret = -ENOMEM;
661 entry = probe_cache_entry__new(pev);
662 if (!entry)
663 goto out_err;
664
665 for (i = 0; i < ntevs; i++) {
666 if (!tevs[i].point.symbol)
667 continue;
668
669 command = synthesize_probe_trace_command(&tevs[i]);
670 if (!command)
671 goto out_err;
672 strlist__add(entry->tevlist, command);
673 free(command);
674 }
675 list_add_tail(&entry->node, &pcache->entries);
676 pr_debug("Added probe cache: %d\n", ntevs);
677 return 0;
678
679out_err:
680 pr_debug("Failed to add probe caches\n");
681 probe_cache_entry__delete(entry);
682 return ret;
683}
684
Arnaldo Carvalho de Melo1c1a3a42016-07-12 12:19:09 -0300685#ifdef HAVE_GELF_GETNOTE_SUPPORT
Masami Hiramatsu6430a94e2016-07-01 17:04:10 +0900686static unsigned long long sdt_note__get_addr(struct sdt_note *note)
687{
688 return note->bit32 ? (unsigned long long)note->addr.a32[0]
689 : (unsigned long long)note->addr.a64[0];
690}
691
Alexis Berlemont3b1f8312016-12-14 01:07:32 +0100692static const char * const type_to_suffix[] = {
693 ":s64", "", "", "", ":s32", "", ":s16", ":s8",
694 "", ":u8", ":u16", "", ":u32", "", "", "", ":u64"
695};
696
Ravi Bangoriad451a202017-03-28 15:17:53 +0530697/*
698 * Isolate the string number and convert it into a decimal value;
699 * this will be an index to get suffix of the uprobe name (defining
700 * the type)
701 */
702static int sdt_arg_parse_size(char *n_ptr, const char **suffix)
703{
704 long type_idx;
705
706 type_idx = strtol(n_ptr, NULL, 10);
707 if (type_idx < -8 || type_idx > 8) {
708 pr_debug4("Failed to get a valid sdt type\n");
709 return -1;
710 }
711
712 *suffix = type_to_suffix[type_idx + 8];
713 return 0;
714}
715
Alexis Berlemont3b1f8312016-12-14 01:07:32 +0100716static int synthesize_sdt_probe_arg(struct strbuf *buf, int i, const char *arg)
717{
Ravi Bangoriad451a202017-03-28 15:17:53 +0530718 char *op, *desc = strdup(arg), *new_op = NULL;
719 const char *suffix = "";
Alexis Berlemont3b1f8312016-12-14 01:07:32 +0100720 int ret = -1;
721
722 if (desc == NULL) {
723 pr_debug4("Allocation error\n");
724 return ret;
725 }
726
Ravi Bangoriad451a202017-03-28 15:17:53 +0530727 /*
728 * Argument is in N@OP format. N is size of the argument and OP is
729 * the actual assembly operand. N can be omitted; in that case
730 * argument is just OP(without @).
731 */
732 op = strchr(desc, '@');
733 if (op) {
734 op[0] = '\0';
735 op++;
736
737 if (sdt_arg_parse_size(desc, &suffix))
Alexis Berlemont3b1f8312016-12-14 01:07:32 +0100738 goto error;
Ravi Bangoriad451a202017-03-28 15:17:53 +0530739 } else {
740 op = desc;
Alexis Berlemont3b1f8312016-12-14 01:07:32 +0100741 }
742
Ravi Bangoriad451a202017-03-28 15:17:53 +0530743 ret = arch_sdt_arg_parse_op(op, &new_op);
Alexis Berlemont3b1f8312016-12-14 01:07:32 +0100744
Ravi Bangoriad451a202017-03-28 15:17:53 +0530745 if (ret < 0)
Alexis Berlemont3b1f8312016-12-14 01:07:32 +0100746 goto error;
747
Ravi Bangoriad451a202017-03-28 15:17:53 +0530748 if (ret == SDT_ARG_VALID) {
749 ret = strbuf_addf(buf, " arg%d=%s%s", i + 1, new_op, suffix);
750 if (ret < 0)
751 goto error;
752 }
753
Alexis Berlemont3b1f8312016-12-14 01:07:32 +0100754 ret = 0;
755error:
756 free(desc);
Ravi Bangoriad451a202017-03-28 15:17:53 +0530757 free(new_op);
Alexis Berlemont3b1f8312016-12-14 01:07:32 +0100758 return ret;
759}
760
761static char *synthesize_sdt_probe_command(struct sdt_note *note,
762 const char *pathname,
763 const char *sdtgrp)
764{
765 struct strbuf buf;
766 char *ret = NULL, **args;
767 int i, args_count;
768
769 if (strbuf_init(&buf, 32) < 0)
770 return NULL;
771
772 if (strbuf_addf(&buf, "p:%s/%s %s:0x%llx",
773 sdtgrp, note->name, pathname,
774 sdt_note__get_addr(note)) < 0)
775 goto error;
776
777 if (!note->args)
778 goto out;
779
780 if (note->args) {
781 args = argv_split(note->args, &args_count);
782
783 for (i = 0; i < args_count; ++i) {
784 if (synthesize_sdt_probe_arg(&buf, i, args[i]) < 0)
785 goto error;
786 }
787 }
788
789out:
790 ret = strbuf_detach(&buf, NULL);
791error:
792 strbuf_release(&buf);
793 return ret;
794}
795
Masami Hiramatsu6430a94e2016-07-01 17:04:10 +0900796int probe_cache__scan_sdt(struct probe_cache *pcache, const char *pathname)
797{
798 struct probe_cache_entry *entry = NULL;
799 struct list_head sdtlist;
800 struct sdt_note *note;
801 char *buf;
802 char sdtgrp[64];
803 int ret;
804
805 INIT_LIST_HEAD(&sdtlist);
806 ret = get_sdt_note_list(&sdtlist, pathname);
807 if (ret < 0) {
Adrian Hunterf9655202016-09-23 17:38:40 +0300808 pr_debug4("Failed to get sdt note: %d\n", ret);
Masami Hiramatsu6430a94e2016-07-01 17:04:10 +0900809 return ret;
810 }
811 list_for_each_entry(note, &sdtlist, note_list) {
812 ret = snprintf(sdtgrp, 64, "sdt_%s", note->provider);
813 if (ret < 0)
814 break;
815 /* Try to find same-name entry */
816 entry = probe_cache__find_by_name(pcache, sdtgrp, note->name);
817 if (!entry) {
818 entry = probe_cache_entry__new(NULL);
819 if (!entry) {
820 ret = -ENOMEM;
821 break;
822 }
823 entry->sdt = true;
824 ret = asprintf(&entry->spev, "%s:%s=%s", sdtgrp,
825 note->name, note->name);
826 if (ret < 0)
827 break;
828 entry->pev.event = strdup(note->name);
829 entry->pev.group = strdup(sdtgrp);
830 list_add_tail(&entry->node, &pcache->entries);
831 }
Alexis Berlemont3b1f8312016-12-14 01:07:32 +0100832 buf = synthesize_sdt_probe_command(note, pathname, sdtgrp);
833 if (!buf) {
834 ret = -ENOMEM;
Masami Hiramatsu6430a94e2016-07-01 17:04:10 +0900835 break;
Alexis Berlemont3b1f8312016-12-14 01:07:32 +0100836 }
837
Masami Hiramatsu6430a94e2016-07-01 17:04:10 +0900838 strlist__add(entry->tevlist, buf);
839 free(buf);
840 entry = NULL;
841 }
842 if (entry) {
843 list_del_init(&entry->node);
844 probe_cache_entry__delete(entry);
845 }
846 cleanup_sdt_note_list(&sdtlist);
847 return ret;
848}
Arnaldo Carvalho de Melo1c1a3a42016-07-12 12:19:09 -0300849#endif
Masami Hiramatsu6430a94e2016-07-01 17:04:10 +0900850
Masami Hiramatsudd975492016-06-15 12:28:30 +0900851static int probe_cache_entry__write(struct probe_cache_entry *entry, int fd)
852{
853 struct str_node *snode;
854 struct stat st;
855 struct iovec iov[3];
Masami Hiramatsu6430a94e2016-07-01 17:04:10 +0900856 const char *prefix = entry->sdt ? "%" : "#";
Masami Hiramatsudd975492016-06-15 12:28:30 +0900857 int ret;
858 /* Save stat for rollback */
859 ret = fstat(fd, &st);
860 if (ret < 0)
861 return ret;
862
Masami Hiramatsu6430a94e2016-07-01 17:04:10 +0900863 pr_debug("Writing cache: %s%s\n", prefix, entry->spev);
864 iov[0].iov_base = (void *)prefix; iov[0].iov_len = 1;
Masami Hiramatsudd975492016-06-15 12:28:30 +0900865 iov[1].iov_base = entry->spev; iov[1].iov_len = strlen(entry->spev);
866 iov[2].iov_base = (void *)"\n"; iov[2].iov_len = 1;
867 ret = writev(fd, iov, 3);
868 if (ret < (int)iov[1].iov_len + 2)
869 goto rollback;
870
Arnaldo Carvalho de Melo602a1f42016-06-23 11:31:20 -0300871 strlist__for_each_entry(snode, entry->tevlist) {
Masami Hiramatsudd975492016-06-15 12:28:30 +0900872 iov[0].iov_base = (void *)snode->s;
873 iov[0].iov_len = strlen(snode->s);
874 iov[1].iov_base = (void *)"\n"; iov[1].iov_len = 1;
875 ret = writev(fd, iov, 2);
876 if (ret < (int)iov[0].iov_len + 1)
877 goto rollback;
878 }
879 return 0;
880
881rollback:
882 /* Rollback to avoid cache file corruption */
883 if (ret > 0)
884 ret = -1;
885 if (ftruncate(fd, st.st_size) < 0)
886 ret = -2;
887
888 return ret;
889}
890
891int probe_cache__commit(struct probe_cache *pcache)
892{
893 struct probe_cache_entry *entry;
894 int ret = 0;
895
896 /* TBD: if we do not update existing entries, skip it */
897 ret = lseek(pcache->fd, 0, SEEK_SET);
898 if (ret < 0)
899 goto out;
900
901 ret = ftruncate(pcache->fd, 0);
902 if (ret < 0)
903 goto out;
904
Masami Hiramatsu05bf2c82016-07-12 19:05:04 +0900905 for_each_probe_cache_entry(entry, pcache) {
Masami Hiramatsudd975492016-06-15 12:28:30 +0900906 ret = probe_cache_entry__write(entry, pcache->fd);
907 pr_debug("Cache committed: %d\n", ret);
908 if (ret < 0)
909 break;
910 }
911out:
912 return ret;
913}
Masami Hiramatsu1f3736c2016-07-01 17:03:26 +0900914
Masami Hiramatsu4a0f65c2016-07-01 17:03:36 +0900915static bool probe_cache_entry__compare(struct probe_cache_entry *entry,
916 struct strfilter *filter)
917{
918 char buf[128], *ptr = entry->spev;
919
920 if (entry->pev.event) {
921 snprintf(buf, 128, "%s:%s", entry->pev.group, entry->pev.event);
922 ptr = buf;
923 }
924 return strfilter__compare(filter, ptr);
925}
926
927int probe_cache__filter_purge(struct probe_cache *pcache,
928 struct strfilter *filter)
929{
930 struct probe_cache_entry *entry, *tmp;
931
932 list_for_each_entry_safe(entry, tmp, &pcache->entries, node) {
933 if (probe_cache_entry__compare(entry, filter)) {
934 pr_info("Removed cached event: %s\n", entry->spev);
935 list_del_init(&entry->node);
936 probe_cache_entry__delete(entry);
937 }
938 }
939 return 0;
940}
941
Masami Hiramatsu1f3736c2016-07-01 17:03:26 +0900942static int probe_cache__show_entries(struct probe_cache *pcache,
943 struct strfilter *filter)
944{
945 struct probe_cache_entry *entry;
Masami Hiramatsu1f3736c2016-07-01 17:03:26 +0900946
Masami Hiramatsu05bf2c82016-07-12 19:05:04 +0900947 for_each_probe_cache_entry(entry, pcache) {
Masami Hiramatsu4a0f65c2016-07-01 17:03:36 +0900948 if (probe_cache_entry__compare(entry, filter))
Masami Hiramatsu1f3736c2016-07-01 17:03:26 +0900949 printf("%s\n", entry->spev);
950 }
951 return 0;
952}
953
954/* Show all cached probes */
955int probe_cache__show_all_caches(struct strfilter *filter)
956{
957 struct probe_cache *pcache;
958 struct strlist *bidlist;
959 struct str_node *nd;
960 char *buf = strfilter__string(filter);
961
962 pr_debug("list cache with filter: %s\n", buf);
963 free(buf);
964
Masami Hiramatsuc3492a32016-07-12 19:04:54 +0900965 bidlist = build_id_cache__list_all(true);
Masami Hiramatsu1f3736c2016-07-01 17:03:26 +0900966 if (!bidlist) {
967 pr_debug("Failed to get buildids: %d\n", errno);
968 return -EINVAL;
969 }
970 strlist__for_each_entry(nd, bidlist) {
971 pcache = probe_cache__new(nd->s);
972 if (!pcache)
973 continue;
974 if (!list_empty(&pcache->entries)) {
975 buf = build_id_cache__origname(nd->s);
976 printf("%s (%s):\n", buf, nd->s);
977 free(buf);
978 probe_cache__show_entries(pcache, filter);
979 }
980 probe_cache__delete(pcache);
981 }
982 strlist__delete(bidlist);
983
984 return 0;
985}
Masami Hiramatsu180b2062016-08-18 17:58:31 +0900986
Naveen N. Rao3da3ea72017-03-08 13:56:08 +0530987enum ftrace_readme {
988 FTRACE_README_PROBE_TYPE_X = 0,
Naveen N. Rao7ab31d92017-03-08 13:56:09 +0530989 FTRACE_README_KRETPROBE_OFFSET,
Naveen N. Rao3da3ea72017-03-08 13:56:08 +0530990 FTRACE_README_END,
Masami Hiramatsu180b2062016-08-18 17:58:31 +0900991};
992
Naveen N. Rao3da3ea72017-03-08 13:56:08 +0530993static struct {
994 const char *pattern;
995 bool avail;
996} ftrace_readme_table[] = {
997#define DEFINE_TYPE(idx, pat) \
998 [idx] = {.pattern = pat, .avail = false}
999 DEFINE_TYPE(FTRACE_README_PROBE_TYPE_X, "*type: * x8/16/32/64,*"),
Naveen N. Rao7ab31d92017-03-08 13:56:09 +05301000 DEFINE_TYPE(FTRACE_README_KRETPROBE_OFFSET, "*place (kretprobe): *"),
Naveen N. Rao3da3ea72017-03-08 13:56:08 +05301001};
1002
1003static bool scan_ftrace_readme(enum ftrace_readme type)
Masami Hiramatsu180b2062016-08-18 17:58:31 +09001004{
Naveen N. Rao3da3ea72017-03-08 13:56:08 +05301005 int fd;
Masami Hiramatsu180b2062016-08-18 17:58:31 +09001006 FILE *fp;
1007 char *buf = NULL;
1008 size_t len = 0;
Naveen N. Rao3da3ea72017-03-08 13:56:08 +05301009 bool ret = false;
1010 static bool scanned = false;
Masami Hiramatsu180b2062016-08-18 17:58:31 +09001011
Naveen N. Rao3da3ea72017-03-08 13:56:08 +05301012 if (scanned)
1013 goto result;
Masami Hiramatsu180b2062016-08-18 17:58:31 +09001014
Naveen N. Raoe491bc22017-02-23 17:07:23 +05301015 fd = open_trace_file("README", false);
1016 if (fd < 0)
Masami Hiramatsu180b2062016-08-18 17:58:31 +09001017 return ret;
1018
Naveen N. Raoe491bc22017-02-23 17:07:23 +05301019 fp = fdopen(fd, "r");
1020 if (!fp) {
1021 close(fd);
1022 return ret;
1023 }
Masami Hiramatsu180b2062016-08-18 17:58:31 +09001024
Naveen N. Rao3da3ea72017-03-08 13:56:08 +05301025 while (getline(&buf, &len, fp) > 0)
1026 for (enum ftrace_readme i = 0; i < FTRACE_README_END; i++)
1027 if (!ftrace_readme_table[i].avail)
1028 ftrace_readme_table[i].avail =
1029 strglobmatch(buf, ftrace_readme_table[i].pattern);
1030 scanned = true;
Masami Hiramatsu180b2062016-08-18 17:58:31 +09001031
1032 fclose(fp);
Masami Hiramatsu180b2062016-08-18 17:58:31 +09001033 free(buf);
1034
Naveen N. Rao3da3ea72017-03-08 13:56:08 +05301035result:
1036 if (type >= FTRACE_README_END)
1037 return false;
1038
1039 return ftrace_readme_table[type].avail;
1040}
1041
1042bool probe_type_is_available(enum probe_type type)
1043{
1044 if (type >= PROBE_TYPE_END)
1045 return false;
1046 else if (type == PROBE_TYPE_X)
1047 return scan_ftrace_readme(FTRACE_README_PROBE_TYPE_X);
1048
1049 return true;
Masami Hiramatsu180b2062016-08-18 17:58:31 +09001050}
Naveen N. Rao7ab31d92017-03-08 13:56:09 +05301051
1052bool kretprobe_offset_is_supported(void)
1053{
1054 return scan_ftrace_readme(FTRACE_README_KRETPROBE_OFFSET);
1055}