projects/linux·blob master · refs

1184 lines · 25.4 KiB

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