1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * probe-file.c : operate ftrace k/uprobe events files
5 * Written by Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
10 #include <sys/types.h>
13 #include <linux/zalloc.h>
14 #include "namespaces.h"
17 #include "strfilter.h"
24 #include <api/fs/tracing_path.h>
25 #include <api/fs/fs.h>
26 #include "probe-event.h"
27 #include "probe-file.h"
29 #include "perf_regs.h"
32 /* 4096 - 2 ('\n' + '\0') */
33 #define MAX_CMDLEN 4094
35 static bool print_common_warning(int err
, bool readwrite
)
38 pr_warning("No permission to %s tracefs.\nPlease %s\n",
39 readwrite
? "write" : "read",
40 readwrite
? "run this command again with sudo." :
41 "try 'sudo mount -o remount,mode=755 /sys/kernel/tracing/'");
48 static bool print_configure_probe_event(int kerr
, int uerr
)
50 const char *config
, *file
;
52 if (kerr
== -ENOENT
&& uerr
== -ENOENT
) {
53 file
= "{k,u}probe_events";
54 config
= "CONFIG_KPROBE_EVENTS=y and CONFIG_UPROBE_EVENTS=y";
55 } else if (kerr
== -ENOENT
) {
56 file
= "kprobe_events";
57 config
= "CONFIG_KPROBE_EVENTS=y";
58 } else if (uerr
== -ENOENT
) {
59 file
= "uprobe_events";
60 config
= "CONFIG_UPROBE_EVENTS=y";
64 if (!debugfs__configured() && !tracefs__configured())
65 pr_warning("Debugfs or tracefs is not mounted\n"
66 "Please try 'sudo mount -t tracefs nodev /sys/kernel/tracing/'\n");
68 pr_warning("%s/%s does not exist.\nPlease rebuild kernel with %s.\n",
69 tracing_path_mount(), file
, config
);
74 static void print_open_warning(int err
, bool uprobe
, bool readwrite
)
76 char sbuf
[STRERR_BUFSIZE
];
78 if (print_common_warning(err
, readwrite
))
81 if (print_configure_probe_event(uprobe
? 0 : err
, uprobe
? err
: 0))
84 pr_warning("Failed to open %s/%cprobe_events: %s\n",
85 tracing_path_mount(), uprobe
? 'u' : 'k',
86 str_error_r(-err
, sbuf
, sizeof(sbuf
)));
89 static void print_both_open_warning(int kerr
, int uerr
, bool readwrite
)
91 char sbuf
[STRERR_BUFSIZE
];
93 if (kerr
== uerr
&& print_common_warning(kerr
, readwrite
))
96 if (print_configure_probe_event(kerr
, uerr
))
100 pr_warning("Failed to open %s/kprobe_events: %s.\n",
101 tracing_path_mount(),
102 str_error_r(-kerr
, sbuf
, sizeof(sbuf
)));
104 pr_warning("Failed to open %s/uprobe_events: %s.\n",
105 tracing_path_mount(),
106 str_error_r(-uerr
, sbuf
, sizeof(sbuf
)));
109 int open_trace_file(const char *trace_file
, bool readwrite
)
114 ret
= e_snprintf(buf
, PATH_MAX
, "%s/%s", tracing_path_mount(), trace_file
);
116 pr_debug("Opening %s write=%d\n", buf
, readwrite
);
117 if (readwrite
&& !probe_event_dry_run
)
118 ret
= open(buf
, O_RDWR
| O_APPEND
, 0);
120 ret
= open(buf
, O_RDONLY
, 0);
128 static int open_kprobe_events(bool readwrite
)
130 return open_trace_file("kprobe_events", readwrite
);
133 static int open_uprobe_events(bool readwrite
)
135 return open_trace_file("uprobe_events", readwrite
);
138 int probe_file__open(int flag
)
142 if (flag
& PF_FL_UPROBE
)
143 fd
= open_uprobe_events(flag
& PF_FL_RW
);
145 fd
= open_kprobe_events(flag
& PF_FL_RW
);
147 print_open_warning(fd
, flag
& PF_FL_UPROBE
, flag
& PF_FL_RW
);
152 int probe_file__open_both(int *kfd
, int *ufd
, int flag
)
157 *kfd
= open_kprobe_events(flag
& PF_FL_RW
);
158 *ufd
= open_uprobe_events(flag
& PF_FL_RW
);
159 if (*kfd
< 0 && *ufd
< 0) {
160 print_both_open_warning(*kfd
, *ufd
, flag
& PF_FL_RW
);
167 /* Get raw string list of current kprobe_events or uprobe_events */
168 struct strlist
*probe_file__get_rawlist(int fd
)
172 char buf
[MAX_CMDLEN
];
179 sl
= strlist__new(NULL
, NULL
);
187 fp
= fdopen(fddup
, "r");
189 goto out_close_fddup
;
192 p
= fgets(buf
, MAX_CMDLEN
, fp
);
199 ret
= strlist__add(sl
, buf
);
201 pr_debug("strlist__add failed (%d)\n", ret
);
219 static struct strlist
*__probe_file__get_namelist(int fd
, bool include_group
)
222 struct strlist
*sl
, *rawlist
;
223 struct str_node
*ent
;
224 struct probe_trace_event tev
;
227 memset(&tev
, 0, sizeof(tev
));
228 rawlist
= probe_file__get_rawlist(fd
);
231 sl
= strlist__new(NULL
, NULL
);
232 strlist__for_each_entry(ent
, rawlist
) {
233 ret
= parse_probe_trace_command(ent
->s
, &tev
);
237 ret
= e_snprintf(buf
, 128, "%s:%s", tev
.group
,
240 ret
= strlist__add(sl
, buf
);
242 ret
= strlist__add(sl
, tev
.event
);
243 clear_probe_trace_event(&tev
);
244 /* Skip if there is same name multi-probe event in the list */
250 strlist__delete(rawlist
);
259 /* Get current perf-probe event names */
260 struct strlist
*probe_file__get_namelist(int fd
)
262 return __probe_file__get_namelist(fd
, false);
265 int probe_file__add_event(int fd
, struct probe_trace_event
*tev
)
268 char *buf
= synthesize_probe_trace_command(tev
);
269 char sbuf
[STRERR_BUFSIZE
];
272 pr_debug("Failed to synthesize probe trace event.\n");
276 pr_debug("Writing event: %s\n", buf
);
277 if (!probe_event_dry_run
) {
278 if (write(fd
, buf
, strlen(buf
)) < (int)strlen(buf
)) {
280 pr_warning("Failed to write event: %s\n",
281 str_error_r(errno
, sbuf
, sizeof(sbuf
)));
289 static int __del_trace_probe_event(int fd
, struct str_node
*ent
)
295 /* Convert from perf-probe event to trace-probe event */
296 ret
= e_snprintf(buf
, 128, "-:%s", ent
->s
);
300 p
= strchr(buf
+ 2, ':');
302 pr_debug("Internal error: %s should have ':' but not.\n",
309 pr_debug("Writing event: %s\n", buf
);
310 ret
= write(fd
, buf
, strlen(buf
));
318 pr_warning("Failed to delete event: %s\n",
319 str_error_r(-ret
, buf
, sizeof(buf
)));
323 int probe_file__get_events(int fd
, struct strfilter
*filter
,
324 struct strlist
*plist
)
326 struct strlist
*namelist
;
327 struct str_node
*ent
;
334 namelist
= __probe_file__get_namelist(fd
, true);
338 strlist__for_each_entry(ent
, namelist
) {
339 p
= strchr(ent
->s
, ':');
340 if ((p
&& strfilter__compare(filter
, p
+ 1)) ||
341 strfilter__compare(filter
, ent
->s
)) {
342 ret
= strlist__add(plist
, ent
->s
);
343 if (ret
== -ENOMEM
) {
344 pr_err("strlist__add failed with -ENOMEM\n");
351 strlist__delete(namelist
);
356 int probe_file__del_strlist(int fd
, struct strlist
*namelist
)
359 struct str_node
*ent
;
361 strlist__for_each_entry(ent
, namelist
) {
362 ret
= __del_trace_probe_event(fd
, ent
);
369 /* Caller must ensure to remove this entry from list */
370 static void probe_cache_entry__delete(struct probe_cache_entry
*entry
)
373 BUG_ON(!list_empty(&entry
->node
));
375 strlist__delete(entry
->tevlist
);
376 clear_perf_probe_event(&entry
->pev
);
382 static struct probe_cache_entry
*
383 probe_cache_entry__new(struct perf_probe_event
*pev
)
385 struct probe_cache_entry
*entry
= zalloc(sizeof(*entry
));
388 INIT_LIST_HEAD(&entry
->node
);
389 entry
->tevlist
= strlist__new(NULL
, NULL
);
393 entry
->spev
= synthesize_perf_probe_command(pev
);
395 perf_probe_event__copy(&entry
->pev
, pev
) < 0) {
396 probe_cache_entry__delete(entry
);
405 int probe_cache_entry__get_event(struct probe_cache_entry
*entry
,
406 struct probe_trace_event
**tevs
)
408 struct probe_trace_event
*tev
;
409 struct str_node
*node
;
412 ret
= strlist__nr_entries(entry
->tevlist
);
413 if (ret
> probe_conf
.max_probes
)
416 *tevs
= zalloc(ret
* sizeof(*tev
));
421 strlist__for_each_entry(node
, entry
->tevlist
) {
423 ret
= parse_probe_trace_command(node
->s
, tev
);
430 /* For the kernel probe caches, pass target = NULL or DSO__NAME_KALLSYMS */
431 static int probe_cache__open(struct probe_cache
*pcache
, const char *target
,
434 char cpath
[PATH_MAX
];
435 char sbuildid
[SBUILD_ID_SIZE
];
436 char *dir_name
= NULL
;
437 bool is_kallsyms
= false;
441 if (target
&& build_id_cache__cached(target
)) {
442 /* This is a cached buildid */
443 strlcpy(sbuildid
, target
, SBUILD_ID_SIZE
);
444 dir_name
= build_id_cache__linkname(sbuildid
, NULL
, 0);
448 if (!target
|| !strcmp(target
, DSO__NAME_KALLSYMS
)) {
449 target
= DSO__NAME_KALLSYMS
;
451 ret
= sysfs__sprintf_build_id("/", sbuildid
);
453 nsinfo__mountns_enter(nsi
, &nsc
);
454 ret
= filename__sprintf_build_id(target
, sbuildid
);
455 nsinfo__mountns_exit(&nsc
);
459 pr_debug("Failed to get build-id from %s.\n", target
);
463 /* If we have no buildid cache, make it */
464 if (!build_id_cache__cached(sbuildid
)) {
465 ret
= build_id_cache__add_s(sbuildid
, target
, nsi
,
468 pr_debug("Failed to add build-id cache: %s\n", target
);
473 dir_name
= build_id_cache__cachedir(sbuildid
, target
, nsi
, is_kallsyms
,
477 pr_debug("Failed to get cache from %s\n", target
);
481 snprintf(cpath
, PATH_MAX
, "%s/probes", dir_name
);
482 fd
= open(cpath
, O_CREAT
| O_RDWR
, 0644);
484 pr_debug("Failed to open cache(%d): %s\n", fd
, cpath
);
491 static int probe_cache__load(struct probe_cache
*pcache
)
493 struct probe_cache_entry
*entry
= NULL
;
494 char buf
[MAX_CMDLEN
], *p
;
498 fddup
= dup(pcache
->fd
);
501 fp
= fdopen(fddup
, "r");
508 if (!fgets(buf
, MAX_CMDLEN
, fp
))
510 p
= strchr(buf
, '\n');
513 /* #perf_probe_event or %sdt_event */
514 if (buf
[0] == '#' || buf
[0] == '%') {
515 entry
= probe_cache_entry__new(NULL
);
522 entry
->spev
= strdup(buf
+ 1);
524 ret
= parse_perf_probe_command(buf
+ 1,
529 probe_cache_entry__delete(entry
);
532 list_add_tail(&entry
->node
, &pcache
->entries
);
533 } else { /* trace_probe_event */
538 ret
= strlist__add(entry
->tevlist
, buf
);
539 if (ret
== -ENOMEM
) {
540 pr_err("strlist__add failed with -ENOMEM\n");
550 static struct probe_cache
*probe_cache__alloc(void)
552 struct probe_cache
*pcache
= zalloc(sizeof(*pcache
));
555 INIT_LIST_HEAD(&pcache
->entries
);
556 pcache
->fd
= -EINVAL
;
561 void probe_cache__purge(struct probe_cache
*pcache
)
563 struct probe_cache_entry
*entry
, *n
;
565 list_for_each_entry_safe(entry
, n
, &pcache
->entries
, node
) {
566 list_del_init(&entry
->node
);
567 probe_cache_entry__delete(entry
);
571 void probe_cache__delete(struct probe_cache
*pcache
)
576 probe_cache__purge(pcache
);
582 struct probe_cache
*probe_cache__new(const char *target
, struct nsinfo
*nsi
)
584 struct probe_cache
*pcache
= probe_cache__alloc();
590 ret
= probe_cache__open(pcache
, target
, nsi
);
592 pr_debug("Cache open error: %d\n", ret
);
596 ret
= probe_cache__load(pcache
);
598 pr_debug("Cache read error: %d\n", ret
);
605 probe_cache__delete(pcache
);
609 static bool streql(const char *a
, const char *b
)
617 return !strcmp(a
, b
);
620 struct probe_cache_entry
*
621 probe_cache__find(struct probe_cache
*pcache
, struct perf_probe_event
*pev
)
623 struct probe_cache_entry
*entry
= NULL
;
624 char *cmd
= synthesize_perf_probe_command(pev
);
629 for_each_probe_cache_entry(entry
, pcache
) {
631 if (entry
->pev
.event
&&
632 streql(entry
->pev
.event
, pev
->event
) &&
634 streql(entry
->pev
.group
, pev
->group
)))
639 /* Hit if same event name or same command-string */
641 (streql(entry
->pev
.group
, pev
->group
) &&
642 streql(entry
->pev
.event
, pev
->event
))) ||
643 (!strcmp(entry
->spev
, cmd
)))
653 struct probe_cache_entry
*
654 probe_cache__find_by_name(struct probe_cache
*pcache
,
655 const char *group
, const char *event
)
657 struct probe_cache_entry
*entry
= NULL
;
659 for_each_probe_cache_entry(entry
, pcache
) {
660 /* Hit if same event name or same command-string */
661 if (streql(entry
->pev
.group
, group
) &&
662 streql(entry
->pev
.event
, event
))
671 int probe_cache__add_entry(struct probe_cache
*pcache
,
672 struct perf_probe_event
*pev
,
673 struct probe_trace_event
*tevs
, int ntevs
)
675 struct probe_cache_entry
*entry
= NULL
;
679 if (!pcache
|| !pev
|| !tevs
|| ntevs
<= 0) {
684 /* Remove old cache entry */
685 entry
= probe_cache__find(pcache
, pev
);
687 list_del_init(&entry
->node
);
688 probe_cache_entry__delete(entry
);
692 entry
= probe_cache_entry__new(pev
);
696 for (i
= 0; i
< ntevs
; i
++) {
697 if (!tevs
[i
].point
.symbol
)
700 command
= synthesize_probe_trace_command(&tevs
[i
]);
703 ret
= strlist__add(entry
->tevlist
, command
);
704 if (ret
== -ENOMEM
) {
705 pr_err("strlist__add failed with -ENOMEM\n");
711 list_add_tail(&entry
->node
, &pcache
->entries
);
712 pr_debug("Added probe cache: %d\n", ntevs
);
716 pr_debug("Failed to add probe caches\n");
717 probe_cache_entry__delete(entry
);
721 #ifdef HAVE_GELF_GETNOTE_SUPPORT
722 static unsigned long long sdt_note__get_addr(struct sdt_note
*note
)
725 (unsigned long long)note
->addr
.a32
[SDT_NOTE_IDX_LOC
] :
726 (unsigned long long)note
->addr
.a64
[SDT_NOTE_IDX_LOC
];
729 static unsigned long long sdt_note__get_ref_ctr_offset(struct sdt_note
*note
)
732 (unsigned long long)note
->addr
.a32
[SDT_NOTE_IDX_REFCTR
] :
733 (unsigned long long)note
->addr
.a64
[SDT_NOTE_IDX_REFCTR
];
736 static const char * const type_to_suffix
[] = {
737 ":s64", "", "", "", ":s32", "", ":s16", ":s8",
738 "", ":u8", ":u16", "", ":u32", "", "", "", ":u64"
742 * Isolate the string number and convert it into a decimal value;
743 * this will be an index to get suffix of the uprobe name (defining
746 static int sdt_arg_parse_size(char *n_ptr
, const char **suffix
)
750 type_idx
= strtol(n_ptr
, NULL
, 10);
751 if (type_idx
< -8 || type_idx
> 8) {
752 pr_debug4("Failed to get a valid sdt type\n");
756 *suffix
= type_to_suffix
[type_idx
+ 8];
760 static int synthesize_sdt_probe_arg(struct strbuf
*buf
, int i
, const char *arg
)
762 char *op
, *desc
= strdup(arg
), *new_op
= NULL
;
763 const char *suffix
= "";
767 pr_debug4("Allocation error\n");
772 * Argument is in N@OP format. N is size of the argument and OP is
773 * the actual assembly operand. N can be omitted; in that case
774 * argument is just OP(without @).
776 op
= strchr(desc
, '@');
781 if (sdt_arg_parse_size(desc
, &suffix
))
787 ret
= arch_sdt_arg_parse_op(op
, &new_op
);
792 if (ret
== SDT_ARG_VALID
) {
793 ret
= strbuf_addf(buf
, " arg%d=%s%s", i
+ 1, new_op
, suffix
);
805 static char *synthesize_sdt_probe_command(struct sdt_note
*note
,
806 const char *pathname
,
811 int i
, args_count
, err
;
812 unsigned long long ref_ctr_offset
;
816 if (strbuf_init(&buf
, 32) < 0)
819 err
= strbuf_addf(&buf
, "p:%s/%s %s:0x%llx",
820 sdtgrp
, note
->name
, pathname
,
821 sdt_note__get_addr(note
));
823 ref_ctr_offset
= sdt_note__get_ref_ctr_offset(note
);
824 if (ref_ctr_offset
&& err
>= 0)
825 err
= strbuf_addf(&buf
, "(0x%llx)", ref_ctr_offset
);
834 char **args
= argv_split(note
->args
, &args_count
);
839 for (i
= 0; i
< args_count
; ) {
841 * FIXUP: Arm64 ELF section '.note.stapsdt' uses string
842 * format "-4@[sp, NUM]" if a probe is to access data in
843 * the stack, e.g. below is an example for the SDT
846 * Arguments: -4@[sp, 12] -4@[sp, 8] -4@[sp, 4]
848 * Since the string introduces an extra space character
849 * in the middle of square brackets, the argument is
850 * divided into two items. Fixup for this case, if an
851 * item contains sub string "[sp,", need to concatenate
854 if (strstr(args
[i
], "[sp,") && (i
+1) < args_count
) {
855 err
= asprintf(&arg
, "%s %s", args
[i
], args
[i
+1]);
858 err
= asprintf(&arg
, "%s", args
[i
]);
862 /* Failed to allocate memory */
868 if (synthesize_sdt_probe_arg(&buf
, arg_idx
, arg
) < 0) {
882 ret
= strbuf_detach(&buf
, NULL
);
884 strbuf_release(&buf
);
888 int probe_cache__scan_sdt(struct probe_cache
*pcache
, const char *pathname
)
890 struct probe_cache_entry
*entry
= NULL
;
891 struct list_head sdtlist
;
892 struct sdt_note
*note
;
897 INIT_LIST_HEAD(&sdtlist
);
898 ret
= get_sdt_note_list(&sdtlist
, pathname
);
900 pr_debug4("Failed to get sdt note: %d\n", ret
);
903 list_for_each_entry(note
, &sdtlist
, note_list
) {
904 ret
= snprintf(sdtgrp
, 64, "sdt_%s", note
->provider
);
907 /* Try to find same-name entry */
908 entry
= probe_cache__find_by_name(pcache
, sdtgrp
, note
->name
);
910 entry
= probe_cache_entry__new(NULL
);
916 ret
= asprintf(&entry
->spev
, "%s:%s=%s", sdtgrp
,
917 note
->name
, note
->name
);
920 entry
->pev
.event
= strdup(note
->name
);
921 entry
->pev
.group
= strdup(sdtgrp
);
922 list_add_tail(&entry
->node
, &pcache
->entries
);
924 buf
= synthesize_sdt_probe_command(note
, pathname
, sdtgrp
);
930 ret
= strlist__add(entry
->tevlist
, buf
);
935 if (ret
== -ENOMEM
) {
936 pr_err("strlist__add failed with -ENOMEM\n");
941 list_del_init(&entry
->node
);
942 probe_cache_entry__delete(entry
);
944 cleanup_sdt_note_list(&sdtlist
);
949 static int probe_cache_entry__write(struct probe_cache_entry
*entry
, int fd
)
951 struct str_node
*snode
;
954 const char *prefix
= entry
->sdt
? "%" : "#";
956 /* Save stat for rollback */
957 ret
= fstat(fd
, &st
);
961 pr_debug("Writing cache: %s%s\n", prefix
, entry
->spev
);
962 iov
[0].iov_base
= (void *)prefix
; iov
[0].iov_len
= 1;
963 iov
[1].iov_base
= entry
->spev
; iov
[1].iov_len
= strlen(entry
->spev
);
964 iov
[2].iov_base
= (void *)"\n"; iov
[2].iov_len
= 1;
965 ret
= writev(fd
, iov
, 3);
966 if (ret
< (int)iov
[1].iov_len
+ 2)
969 strlist__for_each_entry(snode
, entry
->tevlist
) {
970 iov
[0].iov_base
= (void *)snode
->s
;
971 iov
[0].iov_len
= strlen(snode
->s
);
972 iov
[1].iov_base
= (void *)"\n"; iov
[1].iov_len
= 1;
973 ret
= writev(fd
, iov
, 2);
974 if (ret
< (int)iov
[0].iov_len
+ 1)
980 /* Rollback to avoid cache file corruption */
983 if (ftruncate(fd
, st
.st_size
) < 0)
989 int probe_cache__commit(struct probe_cache
*pcache
)
991 struct probe_cache_entry
*entry
;
994 /* TBD: if we do not update existing entries, skip it */
995 ret
= lseek(pcache
->fd
, 0, SEEK_SET
);
999 ret
= ftruncate(pcache
->fd
, 0);
1003 for_each_probe_cache_entry(entry
, pcache
) {
1004 ret
= probe_cache_entry__write(entry
, pcache
->fd
);
1005 pr_debug("Cache committed: %d\n", ret
);
1013 static bool probe_cache_entry__compare(struct probe_cache_entry
*entry
,
1014 struct strfilter
*filter
)
1016 char buf
[128], *ptr
= entry
->spev
;
1018 if (entry
->pev
.event
) {
1019 snprintf(buf
, 128, "%s:%s", entry
->pev
.group
, entry
->pev
.event
);
1022 return strfilter__compare(filter
, ptr
);
1025 int probe_cache__filter_purge(struct probe_cache
*pcache
,
1026 struct strfilter
*filter
)
1028 struct probe_cache_entry
*entry
, *tmp
;
1030 list_for_each_entry_safe(entry
, tmp
, &pcache
->entries
, node
) {
1031 if (probe_cache_entry__compare(entry
, filter
)) {
1032 pr_info("Removed cached event: %s\n", entry
->spev
);
1033 list_del_init(&entry
->node
);
1034 probe_cache_entry__delete(entry
);
1040 static int probe_cache__show_entries(struct probe_cache
*pcache
,
1041 struct strfilter
*filter
)
1043 struct probe_cache_entry
*entry
;
1045 for_each_probe_cache_entry(entry
, pcache
) {
1046 if (probe_cache_entry__compare(entry
, filter
))
1047 printf("%s\n", entry
->spev
);
1052 /* Show all cached probes */
1053 int probe_cache__show_all_caches(struct strfilter
*filter
)
1055 struct probe_cache
*pcache
;
1056 struct strlist
*bidlist
;
1057 struct str_node
*nd
;
1058 char *buf
= strfilter__string(filter
);
1060 pr_debug("list cache with filter: %s\n", buf
);
1063 bidlist
= build_id_cache__list_all(true);
1065 pr_debug("Failed to get buildids: %d\n", errno
);
1068 strlist__for_each_entry(nd
, bidlist
) {
1069 pcache
= probe_cache__new(nd
->s
, NULL
);
1072 if (!list_empty(&pcache
->entries
)) {
1073 buf
= build_id_cache__origname(nd
->s
);
1074 printf("%s (%s):\n", buf
, nd
->s
);
1076 probe_cache__show_entries(pcache
, filter
);
1078 probe_cache__delete(pcache
);
1080 strlist__delete(bidlist
);
1085 enum ftrace_readme
{
1086 FTRACE_README_PROBE_TYPE_X
= 0,
1087 FTRACE_README_KRETPROBE_OFFSET
,
1088 FTRACE_README_UPROBE_REF_CTR
,
1089 FTRACE_README_USER_ACCESS
,
1090 FTRACE_README_MULTIPROBE_EVENT
,
1091 FTRACE_README_IMMEDIATE_VALUE
,
1096 const char *pattern
;
1098 } ftrace_readme_table
[] = {
1099 #define DEFINE_TYPE(idx, pat) \
1100 [idx] = {.pattern = pat, .avail = false}
1101 DEFINE_TYPE(FTRACE_README_PROBE_TYPE_X
, "*type: * x8/16/32/64,*"),
1102 DEFINE_TYPE(FTRACE_README_KRETPROBE_OFFSET
, "*place (kretprobe): *"),
1103 DEFINE_TYPE(FTRACE_README_UPROBE_REF_CTR
, "*ref_ctr_offset*"),
1104 DEFINE_TYPE(FTRACE_README_USER_ACCESS
, "*u]<offset>*"),
1105 DEFINE_TYPE(FTRACE_README_MULTIPROBE_EVENT
, "*Create/append/*"),
1106 DEFINE_TYPE(FTRACE_README_IMMEDIATE_VALUE
, "*\\imm-value,*"),
1109 static bool scan_ftrace_readme(enum ftrace_readme type
)
1116 static bool scanned
= false;
1121 fd
= open_trace_file("README", false);
1125 fp
= fdopen(fd
, "r");
1131 while (getline(&buf
, &len
, fp
) > 0)
1132 for (enum ftrace_readme i
= 0; i
< FTRACE_README_END
; i
++)
1133 if (!ftrace_readme_table
[i
].avail
)
1134 ftrace_readme_table
[i
].avail
=
1135 strglobmatch(buf
, ftrace_readme_table
[i
].pattern
);
1142 if (type
>= FTRACE_README_END
)
1145 return ftrace_readme_table
[type
].avail
;
1148 bool probe_type_is_available(enum probe_type type
)
1150 if (type
>= PROBE_TYPE_END
)
1152 else if (type
== PROBE_TYPE_X
)
1153 return scan_ftrace_readme(FTRACE_README_PROBE_TYPE_X
);
1158 bool kretprobe_offset_is_supported(void)
1160 return scan_ftrace_readme(FTRACE_README_KRETPROBE_OFFSET
);
1163 bool uprobe_ref_ctr_is_supported(void)
1165 return scan_ftrace_readme(FTRACE_README_UPROBE_REF_CTR
);
1168 bool user_access_is_supported(void)
1170 return scan_ftrace_readme(FTRACE_README_USER_ACCESS
);
1173 bool multiprobe_event_is_supported(void)
1175 return scan_ftrace_readme(FTRACE_README_MULTIPROBE_EVENT
);
1178 bool immediate_value_is_supported(void)
1180 return scan_ftrace_readme(FTRACE_README_IMMEDIATE_VALUE
);