1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * probe-file.c : operate ftrace k/uprobe events files
4 *
5 * Written by Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
6 */
7 #include <errno.h>
8 #include <fcntl.h>
9 #include <sys/stat.h>
10 #include <sys/types.h>
11 #include <sys/uio.h>
12 #include <unistd.h>
13 #include <linux/zalloc.h>
14 #include "namespaces.h"
15 #include "event.h"
16 #include "strlist.h"
17 #include "strfilter.h"
18 #include "debug.h"
19 #include "build-id.h"
20 #include "dso.h"
21 #include "color.h"
22 #include "symbol.h"
23 #include "strbuf.h"
24 #include <api/fs/tracing_path.h>
25 #include <api/fs/fs.h>
26 #include "probe-event.h"
27 #include "probe-file.h"
28 #include "session.h"
29 #include "perf_regs.h"
30 #include "string2.h"
31 #include "dwarf-regs.h"
32
33 /* 4096 - 2 ('\n' + '\0') */
34 #define MAX_CMDLEN 4094
35
print_common_warning(int err,bool readwrite)36 static bool print_common_warning(int err, bool readwrite)
37 {
38 if (err == -EACCES)
39 pr_warning("No permission to %s tracefs.\nPlease %s\n",
40 readwrite ? "write" : "read",
41 readwrite ? "run this command again with sudo." :
42 "try 'sudo mount -o remount,mode=755 /sys/kernel/tracing/'");
43 else
44 return false;
45
46 return true;
47 }
48
print_configure_probe_event(int kerr,int uerr)49 static bool print_configure_probe_event(int kerr, int uerr)
50 {
51 const char *config, *file;
52
53 if (kerr == -ENOENT && uerr == -ENOENT) {
54 file = "{k,u}probe_events";
55 config = "CONFIG_KPROBE_EVENTS=y and CONFIG_UPROBE_EVENTS=y";
56 } else if (kerr == -ENOENT) {
57 file = "kprobe_events";
58 config = "CONFIG_KPROBE_EVENTS=y";
59 } else if (uerr == -ENOENT) {
60 file = "uprobe_events";
61 config = "CONFIG_UPROBE_EVENTS=y";
62 } else
63 return false;
64
65 if (!debugfs__configured() && !tracefs__configured())
66 pr_warning("Debugfs or tracefs is not mounted\n"
67 "Please try 'sudo mount -t tracefs nodev /sys/kernel/tracing/'\n");
68 else
69 pr_warning("%s/%s does not exist.\nPlease rebuild kernel with %s.\n",
70 tracing_path_mount(), file, config);
71
72 return true;
73 }
74
print_open_warning(int err,bool uprobe,bool readwrite)75 static void print_open_warning(int err, bool uprobe, bool readwrite)
76 {
77 char sbuf[STRERR_BUFSIZE];
78
79 if (print_common_warning(err, readwrite))
80 return;
81
82 if (print_configure_probe_event(uprobe ? 0 : err, uprobe ? err : 0))
83 return;
84
85 pr_warning("Failed to open %s/%cprobe_events: %s\n",
86 tracing_path_mount(), uprobe ? 'u' : 'k',
87 str_error_r(-err, sbuf, sizeof(sbuf)));
88 }
89
print_both_open_warning(int kerr,int uerr,bool readwrite)90 static void print_both_open_warning(int kerr, int uerr, bool readwrite)
91 {
92 char sbuf[STRERR_BUFSIZE];
93
94 if (kerr == uerr && print_common_warning(kerr, readwrite))
95 return;
96
97 if (print_configure_probe_event(kerr, uerr))
98 return;
99
100 if (kerr < 0)
101 pr_warning("Failed to open %s/kprobe_events: %s.\n",
102 tracing_path_mount(),
103 str_error_r(-kerr, sbuf, sizeof(sbuf)));
104 if (uerr < 0)
105 pr_warning("Failed to open %s/uprobe_events: %s.\n",
106 tracing_path_mount(),
107 str_error_r(-uerr, sbuf, sizeof(sbuf)));
108 }
109
open_trace_file(const char * trace_file,bool readwrite)110 int open_trace_file(const char *trace_file, bool readwrite)
111 {
112 char buf[PATH_MAX];
113 int ret;
114
115 ret = e_snprintf(buf, PATH_MAX, "%s/%s", tracing_path_mount(), trace_file);
116 if (ret >= 0) {
117 pr_debug("Opening %s write=%d\n", buf, readwrite);
118 if (readwrite && !probe_event_dry_run)
119 ret = open(buf, O_RDWR | O_APPEND, 0);
120 else
121 ret = open(buf, O_RDONLY, 0);
122
123 if (ret < 0)
124 ret = -errno;
125 }
126 return ret;
127 }
128
open_kprobe_events(bool readwrite)129 static int open_kprobe_events(bool readwrite)
130 {
131 return open_trace_file("kprobe_events", readwrite);
132 }
133
open_uprobe_events(bool readwrite)134 static int open_uprobe_events(bool readwrite)
135 {
136 return open_trace_file("uprobe_events", readwrite);
137 }
138
probe_file__open(int flag)139 int probe_file__open(int flag)
140 {
141 int fd;
142
143 if (flag & PF_FL_UPROBE)
144 fd = open_uprobe_events(flag & PF_FL_RW);
145 else
146 fd = open_kprobe_events(flag & PF_FL_RW);
147 if (fd < 0)
148 print_open_warning(fd, flag & PF_FL_UPROBE, flag & PF_FL_RW);
149
150 return fd;
151 }
152
probe_file__open_both(int * kfd,int * ufd,int flag)153 int probe_file__open_both(int *kfd, int *ufd, int flag)
154 {
155 if (!kfd || !ufd)
156 return -EINVAL;
157
158 *kfd = open_kprobe_events(flag & PF_FL_RW);
159 *ufd = open_uprobe_events(flag & PF_FL_RW);
160 if (*kfd < 0 && *ufd < 0) {
161 print_both_open_warning(*kfd, *ufd, flag & PF_FL_RW);
162 return *kfd;
163 }
164
165 return 0;
166 }
167
168 /* Get raw string list of current kprobe_events or uprobe_events */
probe_file__get_rawlist(int fd)169 struct strlist *probe_file__get_rawlist(int fd)
170 {
171 int ret, idx, fddup;
172 FILE *fp;
173 char buf[MAX_CMDLEN];
174 char *p;
175 struct strlist *sl;
176
177 if (fd < 0)
178 return NULL;
179
180 sl = strlist__new(NULL, NULL);
181 if (sl == NULL)
182 return NULL;
183
184 fddup = dup(fd);
185 if (fddup < 0)
186 goto out_free_sl;
187
188 fp = fdopen(fddup, "r");
189 if (!fp)
190 goto out_close_fddup;
191
192 while (!feof(fp)) {
193 p = fgets(buf, MAX_CMDLEN, fp);
194 if (!p)
195 break;
196
197 idx = strlen(p) - 1;
198 if (p[idx] == '\n')
199 p[idx] = '\0';
200 ret = strlist__add(sl, buf);
201 if (ret < 0) {
202 pr_debug("strlist__add failed (%d)\n", ret);
203 goto out_close_fp;
204 }
205 }
206 fclose(fp);
207
208 return sl;
209
210 out_close_fp:
211 fclose(fp);
212 goto out_free_sl;
213 out_close_fddup:
214 close(fddup);
215 out_free_sl:
216 strlist__delete(sl);
217 return NULL;
218 }
219
__probe_file__get_namelist(int fd,bool include_group)220 static struct strlist *__probe_file__get_namelist(int fd, bool include_group)
221 {
222 char buf[128];
223 struct strlist *sl, *rawlist;
224 struct str_node *ent;
225 struct probe_trace_event tev;
226 int ret = 0;
227
228 memset(&tev, 0, sizeof(tev));
229 rawlist = probe_file__get_rawlist(fd);
230 if (!rawlist)
231 return NULL;
232 sl = strlist__new(NULL, NULL);
233 strlist__for_each_entry(ent, rawlist) {
234 ret = parse_probe_trace_command(ent->s, &tev);
235 if (ret < 0)
236 break;
237 if (include_group) {
238 ret = e_snprintf(buf, 128, "%s:%s", tev.group,
239 tev.event);
240 if (ret >= 0)
241 ret = strlist__add(sl, buf);
242 } else
243 ret = strlist__add(sl, tev.event);
244 clear_probe_trace_event(&tev);
245 /* Skip if there is same name multi-probe event in the list */
246 if (ret == -EEXIST)
247 ret = 0;
248 if (ret < 0)
249 break;
250 }
251 strlist__delete(rawlist);
252
253 if (ret < 0) {
254 strlist__delete(sl);
255 return NULL;
256 }
257 return sl;
258 }
259
260 /* Get current perf-probe event names */
probe_file__get_namelist(int fd)261 struct strlist *probe_file__get_namelist(int fd)
262 {
263 return __probe_file__get_namelist(fd, false);
264 }
265
probe_file__add_event(int fd,struct probe_trace_event * tev)266 int probe_file__add_event(int fd, struct probe_trace_event *tev)
267 {
268 int ret = 0;
269 char *buf = synthesize_probe_trace_command(tev);
270 char sbuf[STRERR_BUFSIZE];
271
272 if (!buf) {
273 pr_debug("Failed to synthesize probe trace event.\n");
274 return -EINVAL;
275 }
276
277 pr_debug("Writing event: %s\n", buf);
278 if (!probe_event_dry_run) {
279 if (write(fd, buf, strlen(buf)) < (int)strlen(buf)) {
280 ret = -errno;
281 pr_warning("Failed to write event: %s\n",
282 str_error_r(errno, sbuf, sizeof(sbuf)));
283 }
284 }
285 free(buf);
286
287 return ret;
288 }
289
__del_trace_probe_event(int fd,struct str_node * ent)290 static int __del_trace_probe_event(int fd, struct str_node *ent)
291 {
292 char *p;
293 char buf[128];
294 int ret;
295
296 /* Convert from perf-probe event to trace-probe event */
297 ret = e_snprintf(buf, 128, "-:%s", ent->s);
298 if (ret < 0)
299 goto error;
300
301 p = strchr(buf + 2, ':');
302 if (!p) {
303 pr_debug("Internal error: %s should have ':' but not.\n",
304 ent->s);
305 ret = -ENOTSUP;
306 goto error;
307 }
308 *p = '/';
309
310 pr_debug("Writing event: %s\n", buf);
311 ret = write(fd, buf, strlen(buf));
312 if (ret < 0) {
313 ret = -errno;
314 goto error;
315 }
316
317 return 0;
318 error:
319 pr_warning("Failed to delete event: %s\n",
320 str_error_r(-ret, buf, sizeof(buf)));
321 return ret;
322 }
323
probe_file__get_events(int fd,struct strfilter * filter,struct strlist * plist)324 int probe_file__get_events(int fd, struct strfilter *filter,
325 struct strlist *plist)
326 {
327 struct strlist *namelist;
328 struct str_node *ent;
329 const char *p;
330 int ret = -ENOENT;
331
332 if (!plist)
333 return -EINVAL;
334
335 namelist = __probe_file__get_namelist(fd, true);
336 if (!namelist)
337 return -ENOENT;
338
339 strlist__for_each_entry(ent, namelist) {
340 p = strchr(ent->s, ':');
341 if ((p && strfilter__compare(filter, p + 1)) ||
342 strfilter__compare(filter, ent->s)) {
343 ret = strlist__add(plist, ent->s);
344 if (ret == -ENOMEM) {
345 pr_err("strlist__add failed with -ENOMEM\n");
346 goto out;
347 }
348 ret = 0;
349 }
350 }
351 out:
352 strlist__delete(namelist);
353
354 return ret;
355 }
356
probe_file__del_strlist(int fd,struct strlist * namelist)357 int probe_file__del_strlist(int fd, struct strlist *namelist)
358 {
359 int ret = 0;
360 struct str_node *ent;
361
362 strlist__for_each_entry(ent, namelist) {
363 ret = __del_trace_probe_event(fd, ent);
364 if (ret < 0)
365 break;
366 }
367 return ret;
368 }
369
370 /* Caller must ensure to remove this entry from list */
probe_cache_entry__delete(struct probe_cache_entry * entry)371 static void probe_cache_entry__delete(struct probe_cache_entry *entry)
372 {
373 if (entry) {
374 BUG_ON(!list_empty(&entry->node));
375
376 strlist__delete(entry->tevlist);
377 clear_perf_probe_event(&entry->pev);
378 zfree(&entry->spev);
379 free(entry);
380 }
381 }
382
383 static struct probe_cache_entry *
probe_cache_entry__new(struct perf_probe_event * pev)384 probe_cache_entry__new(struct perf_probe_event *pev)
385 {
386 struct probe_cache_entry *entry = zalloc(sizeof(*entry));
387
388 if (entry) {
389 INIT_LIST_HEAD(&entry->node);
390 entry->tevlist = strlist__new(NULL, NULL);
391 if (!entry->tevlist)
392 zfree(&entry);
393 else if (pev) {
394 entry->spev = synthesize_perf_probe_command(pev);
395 if (!entry->spev ||
396 perf_probe_event__copy(&entry->pev, pev) < 0) {
397 probe_cache_entry__delete(entry);
398 return NULL;
399 }
400 }
401 }
402
403 return entry;
404 }
405
probe_cache_entry__get_event(struct probe_cache_entry * entry,struct probe_trace_event ** tevs)406 int probe_cache_entry__get_event(struct probe_cache_entry *entry,
407 struct probe_trace_event **tevs)
408 {
409 struct probe_trace_event *tev;
410 struct str_node *node;
411 int ret, i;
412
413 ret = strlist__nr_entries(entry->tevlist);
414 if (ret > probe_conf.max_probes)
415 return -E2BIG;
416
417 *tevs = zalloc(ret * sizeof(*tev));
418 if (!*tevs)
419 return -ENOMEM;
420
421 i = 0;
422 strlist__for_each_entry(node, entry->tevlist) {
423 tev = &(*tevs)[i++];
424 ret = parse_probe_trace_command(node->s, tev);
425 if (ret < 0)
426 break;
427 }
428 return i;
429 }
430
431 /* For the kernel probe caches, pass target = NULL or DSO__NAME_KALLSYMS */
probe_cache__open(struct probe_cache * pcache,const char * target,struct nsinfo * nsi)432 static int probe_cache__open(struct probe_cache *pcache, const char *target,
433 struct nsinfo *nsi)
434 {
435 char cpath[PATH_MAX];
436 char sbuildid[SBUILD_ID_SIZE];
437 char *dir_name = NULL;
438 bool is_kallsyms = false;
439 int ret, fd;
440 struct nscookie nsc;
441
442 if (target && build_id_cache__cached(target)) {
443 /* This is a cached buildid */
444 strlcpy(sbuildid, target, SBUILD_ID_SIZE);
445 dir_name = build_id_cache__linkname(sbuildid, NULL, 0);
446 goto found;
447 }
448
449 if (!target || !strcmp(target, DSO__NAME_KALLSYMS)) {
450 target = DSO__NAME_KALLSYMS;
451 is_kallsyms = true;
452 ret = sysfs__snprintf_build_id("/", sbuildid, sizeof(sbuildid));
453 } else {
454 nsinfo__mountns_enter(nsi, &nsc);
455 ret = filename__snprintf_build_id(target, sbuildid, sizeof(sbuildid));
456 nsinfo__mountns_exit(&nsc);
457 }
458
459 if (ret < 0) {
460 pr_debug("Failed to get build-id from %s.\n", target);
461 return ret;
462 }
463
464 /* If we have no buildid cache, make it */
465 if (!build_id_cache__cached(sbuildid)) {
466 ret = build_id_cache__add_s(sbuildid, target, nsi,
467 is_kallsyms, NULL);
468 if (ret < 0) {
469 pr_debug("Failed to add build-id cache: %s\n", target);
470 return ret;
471 }
472 }
473
474 dir_name = build_id_cache__cachedir(sbuildid, target, nsi, is_kallsyms,
475 false);
476 found:
477 if (!dir_name) {
478 pr_debug("Failed to get cache from %s\n", target);
479 return -ENOMEM;
480 }
481
482 snprintf(cpath, PATH_MAX, "%s/probes", dir_name);
483 fd = open(cpath, O_CREAT | O_RDWR, 0644);
484 if (fd < 0)
485 pr_debug("Failed to open cache(%d): %s\n", fd, cpath);
486 free(dir_name);
487 pcache->fd = fd;
488
489 return fd;
490 }
491
probe_cache__load(struct probe_cache * pcache)492 static int probe_cache__load(struct probe_cache *pcache)
493 {
494 struct probe_cache_entry *entry = NULL;
495 char buf[MAX_CMDLEN], *p;
496 int ret = 0, fddup;
497 FILE *fp;
498
499 fddup = dup(pcache->fd);
500 if (fddup < 0)
501 return -errno;
502 fp = fdopen(fddup, "r");
503 if (!fp) {
504 close(fddup);
505 return -EINVAL;
506 }
507
508 while (!feof(fp)) {
509 if (!fgets(buf, MAX_CMDLEN, fp))
510 break;
511 p = strchr(buf, '\n');
512 if (p)
513 *p = '\0';
514 /* #perf_probe_event or %sdt_event */
515 if (buf[0] == '#' || buf[0] == '%') {
516 entry = probe_cache_entry__new(NULL);
517 if (!entry) {
518 ret = -ENOMEM;
519 goto out;
520 }
521 if (buf[0] == '%')
522 entry->sdt = true;
523 entry->spev = strdup(buf + 1);
524 if (entry->spev)
525 ret = parse_perf_probe_command(buf + 1,
526 &entry->pev);
527 else
528 ret = -ENOMEM;
529 if (ret < 0) {
530 probe_cache_entry__delete(entry);
531 goto out;
532 }
533 list_add_tail(&entry->node, &pcache->entries);
534 } else { /* trace_probe_event */
535 if (!entry) {
536 ret = -EINVAL;
537 goto out;
538 }
539 ret = strlist__add(entry->tevlist, buf);
540 if (ret == -ENOMEM) {
541 pr_err("strlist__add failed with -ENOMEM\n");
542 goto out;
543 }
544 }
545 }
546 out:
547 fclose(fp);
548 return ret;
549 }
550
probe_cache__alloc(void)551 static struct probe_cache *probe_cache__alloc(void)
552 {
553 struct probe_cache *pcache = zalloc(sizeof(*pcache));
554
555 if (pcache) {
556 INIT_LIST_HEAD(&pcache->entries);
557 pcache->fd = -EINVAL;
558 }
559 return pcache;
560 }
561
probe_cache__purge(struct probe_cache * pcache)562 void probe_cache__purge(struct probe_cache *pcache)
563 {
564 struct probe_cache_entry *entry, *n;
565
566 list_for_each_entry_safe(entry, n, &pcache->entries, node) {
567 list_del_init(&entry->node);
568 probe_cache_entry__delete(entry);
569 }
570 }
571
probe_cache__delete(struct probe_cache * pcache)572 void probe_cache__delete(struct probe_cache *pcache)
573 {
574 if (!pcache)
575 return;
576
577 probe_cache__purge(pcache);
578 if (pcache->fd > 0)
579 close(pcache->fd);
580 free(pcache);
581 }
582
probe_cache__new(const char * target,struct nsinfo * nsi)583 struct probe_cache *probe_cache__new(const char *target, struct nsinfo *nsi)
584 {
585 struct probe_cache *pcache = probe_cache__alloc();
586 int ret;
587
588 if (!pcache)
589 return NULL;
590
591 ret = probe_cache__open(pcache, target, nsi);
592 if (ret < 0) {
593 pr_debug("Cache open error: %d\n", ret);
594 goto out_err;
595 }
596
597 ret = probe_cache__load(pcache);
598 if (ret < 0) {
599 pr_debug("Cache read error: %d\n", ret);
600 goto out_err;
601 }
602
603 return pcache;
604
605 out_err:
606 probe_cache__delete(pcache);
607 return NULL;
608 }
609
streql(const char * a,const char * b)610 static bool streql(const char *a, const char *b)
611 {
612 if (a == b)
613 return true;
614
615 if (!a || !b)
616 return false;
617
618 return !strcmp(a, b);
619 }
620
621 struct probe_cache_entry *
probe_cache__find(struct probe_cache * pcache,struct perf_probe_event * pev)622 probe_cache__find(struct probe_cache *pcache, struct perf_probe_event *pev)
623 {
624 struct probe_cache_entry *entry = NULL;
625 char *cmd = synthesize_perf_probe_command(pev);
626
627 if (!cmd)
628 return NULL;
629
630 for_each_probe_cache_entry(entry, pcache) {
631 if (pev->sdt) {
632 if (entry->pev.event &&
633 streql(entry->pev.event, pev->event) &&
634 (!pev->group ||
635 streql(entry->pev.group, pev->group)))
636 goto found;
637
638 continue;
639 }
640 /* Hit if same event name or same command-string */
641 if ((pev->event &&
642 (streql(entry->pev.group, pev->group) &&
643 streql(entry->pev.event, pev->event))) ||
644 (!strcmp(entry->spev, cmd)))
645 goto found;
646 }
647 entry = NULL;
648
649 found:
650 free(cmd);
651 return entry;
652 }
653
654 struct probe_cache_entry *
probe_cache__find_by_name(struct probe_cache * pcache,const char * group,const char * event)655 probe_cache__find_by_name(struct probe_cache *pcache,
656 const char *group, const char *event)
657 {
658 struct probe_cache_entry *entry = NULL;
659
660 for_each_probe_cache_entry(entry, pcache) {
661 /* Hit if same event name or same command-string */
662 if (streql(entry->pev.group, group) &&
663 streql(entry->pev.event, event))
664 goto found;
665 }
666 entry = NULL;
667
668 found:
669 return entry;
670 }
671
probe_cache__add_entry(struct probe_cache * pcache,struct perf_probe_event * pev,struct probe_trace_event * tevs,int ntevs)672 int probe_cache__add_entry(struct probe_cache *pcache,
673 struct perf_probe_event *pev,
674 struct probe_trace_event *tevs, int ntevs)
675 {
676 struct probe_cache_entry *entry = NULL;
677 char *command;
678 int i, ret = 0;
679
680 if (!pcache || !pev || !tevs || ntevs <= 0) {
681 ret = -EINVAL;
682 goto out_err;
683 }
684
685 /* Remove old cache entry */
686 entry = probe_cache__find(pcache, pev);
687 if (entry) {
688 list_del_init(&entry->node);
689 probe_cache_entry__delete(entry);
690 }
691
692 ret = -ENOMEM;
693 entry = probe_cache_entry__new(pev);
694 if (!entry)
695 goto out_err;
696
697 for (i = 0; i < ntevs; i++) {
698 if (!tevs[i].point.symbol)
699 continue;
700
701 command = synthesize_probe_trace_command(&tevs[i]);
702 if (!command)
703 goto out_err;
704 ret = strlist__add(entry->tevlist, command);
705 if (ret == -ENOMEM) {
706 pr_err("strlist__add failed with -ENOMEM\n");
707 goto out_err;
708 }
709
710 free(command);
711 }
712 list_add_tail(&entry->node, &pcache->entries);
713 pr_debug("Added probe cache: %d\n", ntevs);
714 return 0;
715
716 out_err:
717 pr_debug("Failed to add probe caches\n");
718 probe_cache_entry__delete(entry);
719 return ret;
720 }
721
722 #ifdef HAVE_GELF_GETNOTE_SUPPORT
sdt_note__get_addr(struct sdt_note * note)723 static unsigned long long sdt_note__get_addr(struct sdt_note *note)
724 {
725 return note->bit32 ?
726 (unsigned long long)note->addr.a32[SDT_NOTE_IDX_LOC] :
727 (unsigned long long)note->addr.a64[SDT_NOTE_IDX_LOC];
728 }
729
sdt_note__get_ref_ctr_offset(struct sdt_note * note)730 static unsigned long long sdt_note__get_ref_ctr_offset(struct sdt_note *note)
731 {
732 return note->bit32 ?
733 (unsigned long long)note->addr.a32[SDT_NOTE_IDX_REFCTR] :
734 (unsigned long long)note->addr.a64[SDT_NOTE_IDX_REFCTR];
735 }
736
737 static const char * const type_to_suffix[] = {
738 ":s64", "", "", "", ":s32", "", ":s16", ":s8",
739 "", ":u8", ":u16", "", ":u32", "", "", "", ":u64"
740 };
741
742 /*
743 * Isolate the string number and convert it into a decimal value;
744 * this will be an index to get suffix of the uprobe name (defining
745 * the type)
746 */
sdt_arg_parse_size(char * n_ptr,const char ** suffix)747 static int sdt_arg_parse_size(char *n_ptr, const char **suffix)
748 {
749 long type_idx;
750
751 type_idx = strtol(n_ptr, NULL, 10);
752 if (type_idx < -8 || type_idx > 8) {
753 pr_debug4("Failed to get a valid sdt type\n");
754 return -1;
755 }
756
757 *suffix = type_to_suffix[type_idx + 8];
758 return 0;
759 }
760
synthesize_sdt_probe_arg(struct strbuf * buf,int i,const char * arg)761 static int synthesize_sdt_probe_arg(struct strbuf *buf, int i, const char *arg)
762 {
763 char *op, *desc = strdup(arg), *new_op = NULL;
764 const char *suffix = "";
765 int ret = -1;
766
767 if (desc == NULL) {
768 pr_debug4("Allocation error\n");
769 return ret;
770 }
771
772 /*
773 * Argument is in N@OP format. N is size of the argument and OP is
774 * the actual assembly operand. N can be omitted; in that case
775 * argument is just OP(without @).
776 */
777 op = strchr(desc, '@');
778 if (op) {
779 op[0] = '\0';
780 op++;
781
782 if (sdt_arg_parse_size(desc, &suffix))
783 goto error;
784 } else {
785 op = desc;
786 }
787
788 ret = perf_sdt_arg_parse_op(EM_HOST, op, &new_op);
789
790 if (ret < 0)
791 goto error;
792
793 if (ret == SDT_ARG_VALID) {
794 ret = strbuf_addf(buf, " arg%d=%s%s", i + 1, new_op, suffix);
795 if (ret < 0)
796 goto error;
797 }
798
799 ret = 0;
800 error:
801 free(desc);
802 free(new_op);
803 return ret;
804 }
805
synthesize_sdt_probe_command(struct sdt_note * note,const char * pathname,const char * sdtgrp)806 static char *synthesize_sdt_probe_command(struct sdt_note *note,
807 const char *pathname,
808 const char *sdtgrp)
809 {
810 struct strbuf buf;
811 char *ret = NULL;
812 int i, args_count, err;
813 unsigned long long ref_ctr_offset;
814 char *arg;
815 int arg_idx = 0;
816
817 if (strbuf_init(&buf, 32) < 0)
818 return NULL;
819
820 err = strbuf_addf(&buf, "p:%s/%s %s:0x%llx",
821 sdtgrp, note->name, pathname,
822 sdt_note__get_addr(note));
823
824 ref_ctr_offset = sdt_note__get_ref_ctr_offset(note);
825 if (ref_ctr_offset && err >= 0)
826 err = strbuf_addf(&buf, "(0x%llx)", ref_ctr_offset);
827
828 if (err < 0)
829 goto error;
830
831 if (!note->args)
832 goto out;
833
834 if (note->args) {
835 char **args = argv_split(note->args, &args_count);
836
837 if (args == NULL)
838 goto error;
839
840 for (i = 0; i < args_count; ) {
841 /*
842 * FIXUP: Arm64 ELF section '.note.stapsdt' uses string
843 * format "-4@[sp, NUM]" if a probe is to access data in
844 * the stack, e.g. below is an example for the SDT
845 * Arguments:
846 *
847 * Arguments: -4@[sp, 12] -4@[sp, 8] -4@[sp, 4]
848 *
849 * Since the string introduces an extra space character
850 * in the middle of square brackets, the argument is
851 * divided into two items. Fixup for this case, if an
852 * item contains sub string "[sp,", need to concatenate
853 * the two items.
854 */
855 if (strstr(args[i], "[sp,") && (i+1) < args_count) {
856 err = asprintf(&arg, "%s %s", args[i], args[i+1]);
857 i += 2;
858 } else {
859 err = asprintf(&arg, "%s", args[i]);
860 i += 1;
861 }
862
863 /* Failed to allocate memory */
864 if (err < 0) {
865 argv_free(args);
866 goto error;
867 }
868
869 if (synthesize_sdt_probe_arg(&buf, arg_idx, arg) < 0) {
870 free(arg);
871 argv_free(args);
872 goto error;
873 }
874
875 free(arg);
876 arg_idx++;
877 }
878
879 argv_free(args);
880 }
881
882 out:
883 ret = strbuf_detach(&buf, NULL);
884 error:
885 strbuf_release(&buf);
886 return ret;
887 }
888
probe_cache__scan_sdt(struct probe_cache * pcache,const char * pathname)889 int probe_cache__scan_sdt(struct probe_cache *pcache, const char *pathname)
890 {
891 struct probe_cache_entry *entry = NULL;
892 struct list_head sdtlist;
893 struct sdt_note *note;
894 char *buf;
895 char sdtgrp[64];
896 int ret;
897
898 INIT_LIST_HEAD(&sdtlist);
899 ret = get_sdt_note_list(&sdtlist, pathname);
900 if (ret < 0) {
901 pr_debug4("Failed to get sdt note: %d\n", ret);
902 return ret;
903 }
904 list_for_each_entry(note, &sdtlist, note_list) {
905 ret = snprintf(sdtgrp, 64, "sdt_%s", note->provider);
906 if (ret < 0)
907 break;
908 /* Try to find same-name entry */
909 entry = probe_cache__find_by_name(pcache, sdtgrp, note->name);
910 if (!entry) {
911 entry = probe_cache_entry__new(NULL);
912 if (!entry) {
913 ret = -ENOMEM;
914 break;
915 }
916 entry->sdt = true;
917 ret = asprintf(&entry->spev, "%s:%s=%s", sdtgrp,
918 note->name, note->name);
919 if (ret < 0)
920 break;
921 entry->pev.event = strdup(note->name);
922 entry->pev.group = strdup(sdtgrp);
923 list_add_tail(&entry->node, &pcache->entries);
924 }
925 buf = synthesize_sdt_probe_command(note, pathname, sdtgrp);
926 if (!buf) {
927 ret = -ENOMEM;
928 break;
929 }
930
931 ret = strlist__add(entry->tevlist, buf);
932
933 free(buf);
934 entry = NULL;
935
936 if (ret == -ENOMEM) {
937 pr_err("strlist__add failed with -ENOMEM\n");
938 break;
939 }
940 }
941 if (entry) {
942 list_del_init(&entry->node);
943 probe_cache_entry__delete(entry);
944 }
945 cleanup_sdt_note_list(&sdtlist);
946 return ret;
947 }
948 #endif
949
probe_cache_entry__write(struct probe_cache_entry * entry,int fd)950 static int probe_cache_entry__write(struct probe_cache_entry *entry, int fd)
951 {
952 struct str_node *snode;
953 struct stat st;
954 struct iovec iov[3];
955 const char *prefix = entry->sdt ? "%" : "#";
956 int ret;
957 /* Save stat for rollback */
958 ret = fstat(fd, &st);
959 if (ret < 0)
960 return ret;
961
962 pr_debug("Writing cache: %s%s\n", prefix, entry->spev);
963 iov[0].iov_base = (void *)prefix; iov[0].iov_len = 1;
964 iov[1].iov_base = entry->spev; iov[1].iov_len = strlen(entry->spev);
965 iov[2].iov_base = (void *)"\n"; iov[2].iov_len = 1;
966 ret = writev(fd, iov, 3);
967 if (ret < (int)iov[1].iov_len + 2)
968 goto rollback;
969
970 strlist__for_each_entry(snode, entry->tevlist) {
971 iov[0].iov_base = (void *)snode->s;
972 iov[0].iov_len = strlen(snode->s);
973 iov[1].iov_base = (void *)"\n"; iov[1].iov_len = 1;
974 ret = writev(fd, iov, 2);
975 if (ret < (int)iov[0].iov_len + 1)
976 goto rollback;
977 }
978 return 0;
979
980 rollback:
981 /* Rollback to avoid cache file corruption */
982 if (ret > 0)
983 ret = -1;
984 if (ftruncate(fd, st.st_size) < 0)
985 ret = -2;
986
987 return ret;
988 }
989
probe_cache__commit(struct probe_cache * pcache)990 int probe_cache__commit(struct probe_cache *pcache)
991 {
992 struct probe_cache_entry *entry;
993 int ret = 0;
994
995 /* TBD: if we do not update existing entries, skip it */
996 ret = lseek(pcache->fd, 0, SEEK_SET);
997 if (ret < 0)
998 goto out;
999
1000 ret = ftruncate(pcache->fd, 0);
1001 if (ret < 0)
1002 goto out;
1003
1004 for_each_probe_cache_entry(entry, pcache) {
1005 ret = probe_cache_entry__write(entry, pcache->fd);
1006 pr_debug("Cache committed: %d\n", ret);
1007 if (ret < 0)
1008 break;
1009 }
1010 out:
1011 return ret;
1012 }
1013
probe_cache_entry__compare(struct probe_cache_entry * entry,struct strfilter * filter)1014 static bool probe_cache_entry__compare(struct probe_cache_entry *entry,
1015 struct strfilter *filter)
1016 {
1017 char buf[128], *ptr = entry->spev;
1018
1019 if (entry->pev.event) {
1020 snprintf(buf, 128, "%s:%s", entry->pev.group, entry->pev.event);
1021 ptr = buf;
1022 }
1023 return strfilter__compare(filter, ptr);
1024 }
1025
probe_cache__filter_purge(struct probe_cache * pcache,struct strfilter * filter)1026 int probe_cache__filter_purge(struct probe_cache *pcache,
1027 struct strfilter *filter)
1028 {
1029 struct probe_cache_entry *entry, *tmp;
1030
1031 list_for_each_entry_safe(entry, tmp, &pcache->entries, node) {
1032 if (probe_cache_entry__compare(entry, filter)) {
1033 pr_info("Removed cached event: %s\n", entry->spev);
1034 list_del_init(&entry->node);
1035 probe_cache_entry__delete(entry);
1036 }
1037 }
1038 return 0;
1039 }
1040
probe_cache__show_entries(struct probe_cache * pcache,struct strfilter * filter)1041 static int probe_cache__show_entries(struct probe_cache *pcache,
1042 struct strfilter *filter)
1043 {
1044 struct probe_cache_entry *entry;
1045
1046 for_each_probe_cache_entry(entry, pcache) {
1047 if (probe_cache_entry__compare(entry, filter))
1048 printf("%s\n", entry->spev);
1049 }
1050 return 0;
1051 }
1052
1053 /* Show all cached probes */
probe_cache__show_all_caches(struct strfilter * filter)1054 int probe_cache__show_all_caches(struct strfilter *filter)
1055 {
1056 struct probe_cache *pcache;
1057 struct strlist *bidlist;
1058 struct str_node *nd;
1059 char *buf = strfilter__string(filter);
1060
1061 pr_debug("list cache with filter: %s\n", buf);
1062 free(buf);
1063
1064 bidlist = build_id_cache__list_all(true);
1065 if (!bidlist) {
1066 pr_debug("Failed to get buildids: %d\n", errno);
1067 return -EINVAL;
1068 }
1069 strlist__for_each_entry(nd, bidlist) {
1070 pcache = probe_cache__new(nd->s, NULL);
1071 if (!pcache)
1072 continue;
1073 if (!list_empty(&pcache->entries)) {
1074 buf = build_id_cache__origname(nd->s);
1075 printf("%s (%s):\n", buf, nd->s);
1076 free(buf);
1077 probe_cache__show_entries(pcache, filter);
1078 }
1079 probe_cache__delete(pcache);
1080 }
1081 strlist__delete(bidlist);
1082
1083 return 0;
1084 }
1085
1086 enum ftrace_readme {
1087 FTRACE_README_PROBE_TYPE_X = 0,
1088 FTRACE_README_KRETPROBE_OFFSET,
1089 FTRACE_README_UPROBE_REF_CTR,
1090 FTRACE_README_USER_ACCESS,
1091 FTRACE_README_MULTIPROBE_EVENT,
1092 FTRACE_README_IMMEDIATE_VALUE,
1093 FTRACE_README_END,
1094 };
1095
1096 static struct {
1097 const char *pattern;
1098 bool avail;
1099 } ftrace_readme_table[] = {
1100 #define DEFINE_TYPE(idx, pat) \
1101 [idx] = {.pattern = pat, .avail = false}
1102 DEFINE_TYPE(FTRACE_README_PROBE_TYPE_X, "*type: * x8/16/32/64,*"),
1103 DEFINE_TYPE(FTRACE_README_KRETPROBE_OFFSET, "*place (kretprobe): *"),
1104 DEFINE_TYPE(FTRACE_README_UPROBE_REF_CTR, "*ref_ctr_offset*"),
1105 DEFINE_TYPE(FTRACE_README_USER_ACCESS, "*u]<offset>*"),
1106 DEFINE_TYPE(FTRACE_README_MULTIPROBE_EVENT, "*Create/append/*"),
1107 DEFINE_TYPE(FTRACE_README_IMMEDIATE_VALUE, "*\\imm-value,*"),
1108 };
1109
scan_ftrace_readme(enum ftrace_readme type)1110 static bool scan_ftrace_readme(enum ftrace_readme type)
1111 {
1112 int fd;
1113 FILE *fp;
1114 char *buf = NULL;
1115 size_t len = 0;
1116 bool ret = false;
1117 static bool scanned = false;
1118
1119 if (scanned)
1120 goto result;
1121
1122 fd = open_trace_file("README", false);
1123 if (fd < 0)
1124 return ret;
1125
1126 fp = fdopen(fd, "r");
1127 if (!fp) {
1128 close(fd);
1129 return ret;
1130 }
1131
1132 while (getline(&buf, &len, fp) > 0)
1133 for (enum ftrace_readme i = 0; i < FTRACE_README_END; i++)
1134 if (!ftrace_readme_table[i].avail)
1135 ftrace_readme_table[i].avail =
1136 strglobmatch(buf, ftrace_readme_table[i].pattern);
1137 scanned = true;
1138
1139 fclose(fp);
1140 free(buf);
1141
1142 result:
1143 if (type >= FTRACE_README_END)
1144 return false;
1145
1146 return ftrace_readme_table[type].avail;
1147 }
1148
probe_type_is_available(enum probe_type type)1149 bool probe_type_is_available(enum probe_type type)
1150 {
1151 if (type >= PROBE_TYPE_END)
1152 return false;
1153 else if (type == PROBE_TYPE_X)
1154 return scan_ftrace_readme(FTRACE_README_PROBE_TYPE_X);
1155
1156 return true;
1157 }
1158
kretprobe_offset_is_supported(void)1159 bool kretprobe_offset_is_supported(void)
1160 {
1161 return scan_ftrace_readme(FTRACE_README_KRETPROBE_OFFSET);
1162 }
1163
uprobe_ref_ctr_is_supported(void)1164 bool uprobe_ref_ctr_is_supported(void)
1165 {
1166 return scan_ftrace_readme(FTRACE_README_UPROBE_REF_CTR);
1167 }
1168
user_access_is_supported(void)1169 bool user_access_is_supported(void)
1170 {
1171 return scan_ftrace_readme(FTRACE_README_USER_ACCESS);
1172 }
1173
multiprobe_event_is_supported(void)1174 bool multiprobe_event_is_supported(void)
1175 {
1176 return scan_ftrace_readme(FTRACE_README_MULTIPROBE_EVENT);
1177 }
1178
immediate_value_is_supported(void)1179 bool immediate_value_is_supported(void)
1180 {
1181 return scan_ftrace_readme(FTRACE_README_IMMEDIATE_VALUE);
1182 }
1183