2 * probe-file.c : operate ftrace k/uprobe events files
4 * Written by Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
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.
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.
20 #include <sys/types.h>
23 #include "namespaces.h"
27 #include "strfilter.h"
33 #include <api/fs/tracing_path.h>
34 #include "probe-event.h"
35 #include "probe-file.h"
37 #include "perf_regs.h"
40 /* 4096 - 2 ('\n' + '\0') */
41 #define MAX_CMDLEN 4094
43 static void print_open_warning(int err
, bool uprobe
)
45 char sbuf
[STRERR_BUFSIZE
];
51 config
= "CONFIG_UPROBE_EVENTS";
53 config
= "CONFIG_KPROBE_EVENTS";
55 pr_warning("%cprobe_events file does not exist"
56 " - please rebuild kernel with %s.\n",
57 uprobe
? 'u' : 'k', config
);
58 } else if (err
== -ENOTSUP
)
59 pr_warning("Tracefs or debugfs is not mounted.\n");
61 pr_warning("Failed to open %cprobe_events: %s\n",
63 str_error_r(-err
, sbuf
, sizeof(sbuf
)));
66 static void print_both_open_warning(int kerr
, int uerr
)
68 /* Both kprobes and uprobes are disabled, warn it. */
69 if (kerr
== -ENOTSUP
&& uerr
== -ENOTSUP
)
70 pr_warning("Tracefs or debugfs is not mounted.\n");
71 else if (kerr
== -ENOENT
&& uerr
== -ENOENT
)
72 pr_warning("Please rebuild kernel with CONFIG_KPROBE_EVENTS "
73 "or/and CONFIG_UPROBE_EVENTS.\n");
75 char sbuf
[STRERR_BUFSIZE
];
76 pr_warning("Failed to open kprobe events: %s.\n",
77 str_error_r(-kerr
, sbuf
, sizeof(sbuf
)));
78 pr_warning("Failed to open uprobe events: %s.\n",
79 str_error_r(-uerr
, sbuf
, sizeof(sbuf
)));
83 int open_trace_file(const char *trace_file
, bool readwrite
)
88 ret
= e_snprintf(buf
, PATH_MAX
, "%s/%s", tracing_path_mount(), trace_file
);
90 pr_debug("Opening %s write=%d\n", buf
, readwrite
);
91 if (readwrite
&& !probe_event_dry_run
)
92 ret
= open(buf
, O_RDWR
| O_APPEND
, 0);
94 ret
= open(buf
, O_RDONLY
, 0);
102 static int open_kprobe_events(bool readwrite
)
104 return open_trace_file("kprobe_events", readwrite
);
107 static int open_uprobe_events(bool readwrite
)
109 return open_trace_file("uprobe_events", readwrite
);
112 int probe_file__open(int flag
)
116 if (flag
& PF_FL_UPROBE
)
117 fd
= open_uprobe_events(flag
& PF_FL_RW
);
119 fd
= open_kprobe_events(flag
& PF_FL_RW
);
121 print_open_warning(fd
, flag
& PF_FL_UPROBE
);
126 int probe_file__open_both(int *kfd
, int *ufd
, int flag
)
131 *kfd
= open_kprobe_events(flag
& PF_FL_RW
);
132 *ufd
= open_uprobe_events(flag
& PF_FL_RW
);
133 if (*kfd
< 0 && *ufd
< 0) {
134 print_both_open_warning(*kfd
, *ufd
);
141 /* Get raw string list of current kprobe_events or uprobe_events */
142 struct strlist
*probe_file__get_rawlist(int fd
)
146 char buf
[MAX_CMDLEN
];
153 sl
= strlist__new(NULL
, NULL
);
161 fp
= fdopen(fddup
, "r");
163 goto out_close_fddup
;
166 p
= fgets(buf
, MAX_CMDLEN
, fp
);
173 ret
= strlist__add(sl
, buf
);
175 pr_debug("strlist__add failed (%d)\n", ret
);
193 static struct strlist
*__probe_file__get_namelist(int fd
, bool include_group
)
196 struct strlist
*sl
, *rawlist
;
197 struct str_node
*ent
;
198 struct probe_trace_event tev
;
201 memset(&tev
, 0, sizeof(tev
));
202 rawlist
= probe_file__get_rawlist(fd
);
205 sl
= strlist__new(NULL
, NULL
);
206 strlist__for_each_entry(ent
, rawlist
) {
207 ret
= parse_probe_trace_command(ent
->s
, &tev
);
211 ret
= e_snprintf(buf
, 128, "%s:%s", tev
.group
,
214 ret
= strlist__add(sl
, buf
);
216 ret
= strlist__add(sl
, tev
.event
);
217 clear_probe_trace_event(&tev
);
221 strlist__delete(rawlist
);
230 /* Get current perf-probe event names */
231 struct strlist
*probe_file__get_namelist(int fd
)
233 return __probe_file__get_namelist(fd
, false);
236 int probe_file__add_event(int fd
, struct probe_trace_event
*tev
)
239 char *buf
= synthesize_probe_trace_command(tev
);
240 char sbuf
[STRERR_BUFSIZE
];
243 pr_debug("Failed to synthesize probe trace event.\n");
247 pr_debug("Writing event: %s\n", buf
);
248 if (!probe_event_dry_run
) {
249 if (write(fd
, buf
, strlen(buf
)) < (int)strlen(buf
)) {
251 pr_warning("Failed to write event: %s\n",
252 str_error_r(errno
, sbuf
, sizeof(sbuf
)));
260 static int __del_trace_probe_event(int fd
, struct str_node
*ent
)
266 /* Convert from perf-probe event to trace-probe event */
267 ret
= e_snprintf(buf
, 128, "-:%s", ent
->s
);
271 p
= strchr(buf
+ 2, ':');
273 pr_debug("Internal error: %s should have ':' but not.\n",
280 pr_debug("Writing event: %s\n", buf
);
281 ret
= write(fd
, buf
, strlen(buf
));
289 pr_warning("Failed to delete event: %s\n",
290 str_error_r(-ret
, buf
, sizeof(buf
)));
294 int probe_file__get_events(int fd
, struct strfilter
*filter
,
295 struct strlist
*plist
)
297 struct strlist
*namelist
;
298 struct str_node
*ent
;
305 namelist
= __probe_file__get_namelist(fd
, true);
309 strlist__for_each_entry(ent
, namelist
) {
310 p
= strchr(ent
->s
, ':');
311 if ((p
&& strfilter__compare(filter
, p
+ 1)) ||
312 strfilter__compare(filter
, ent
->s
)) {
313 strlist__add(plist
, ent
->s
);
317 strlist__delete(namelist
);
322 int probe_file__del_strlist(int fd
, struct strlist
*namelist
)
325 struct str_node
*ent
;
327 strlist__for_each_entry(ent
, namelist
) {
328 ret
= __del_trace_probe_event(fd
, ent
);
335 int probe_file__del_events(int fd
, struct strfilter
*filter
)
337 struct strlist
*namelist
;
340 namelist
= strlist__new(NULL
, NULL
);
344 ret
= probe_file__get_events(fd
, filter
, namelist
);
348 ret
= probe_file__del_strlist(fd
, namelist
);
349 strlist__delete(namelist
);
354 /* Caller must ensure to remove this entry from list */
355 static void probe_cache_entry__delete(struct probe_cache_entry
*entry
)
358 BUG_ON(!list_empty(&entry
->node
));
360 strlist__delete(entry
->tevlist
);
361 clear_perf_probe_event(&entry
->pev
);
367 static struct probe_cache_entry
*
368 probe_cache_entry__new(struct perf_probe_event
*pev
)
370 struct probe_cache_entry
*entry
= zalloc(sizeof(*entry
));
373 INIT_LIST_HEAD(&entry
->node
);
374 entry
->tevlist
= strlist__new(NULL
, NULL
);
378 entry
->spev
= synthesize_perf_probe_command(pev
);
380 perf_probe_event__copy(&entry
->pev
, pev
) < 0) {
381 probe_cache_entry__delete(entry
);
390 int probe_cache_entry__get_event(struct probe_cache_entry
*entry
,
391 struct probe_trace_event
**tevs
)
393 struct probe_trace_event
*tev
;
394 struct str_node
*node
;
397 ret
= strlist__nr_entries(entry
->tevlist
);
398 if (ret
> probe_conf
.max_probes
)
401 *tevs
= zalloc(ret
* sizeof(*tev
));
406 strlist__for_each_entry(node
, entry
->tevlist
) {
408 ret
= parse_probe_trace_command(node
->s
, tev
);
415 /* For the kernel probe caches, pass target = NULL or DSO__NAME_KALLSYMS */
416 static int probe_cache__open(struct probe_cache
*pcache
, const char *target
,
419 char cpath
[PATH_MAX
];
420 char sbuildid
[SBUILD_ID_SIZE
];
421 char *dir_name
= NULL
;
422 bool is_kallsyms
= false;
426 if (target
&& build_id_cache__cached(target
)) {
427 /* This is a cached buildid */
428 strlcpy(sbuildid
, target
, SBUILD_ID_SIZE
);
429 dir_name
= build_id_cache__linkname(sbuildid
, NULL
, 0);
433 if (!target
|| !strcmp(target
, DSO__NAME_KALLSYMS
)) {
434 target
= DSO__NAME_KALLSYMS
;
436 ret
= sysfs__sprintf_build_id("/", sbuildid
);
438 nsinfo__mountns_enter(nsi
, &nsc
);
439 ret
= filename__sprintf_build_id(target
, sbuildid
);
440 nsinfo__mountns_exit(&nsc
);
444 pr_debug("Failed to get build-id from %s.\n", target
);
448 /* If we have no buildid cache, make it */
449 if (!build_id_cache__cached(sbuildid
)) {
450 ret
= build_id_cache__add_s(sbuildid
, target
, nsi
,
453 pr_debug("Failed to add build-id cache: %s\n", target
);
458 dir_name
= build_id_cache__cachedir(sbuildid
, target
, nsi
, is_kallsyms
,
462 pr_debug("Failed to get cache from %s\n", target
);
466 snprintf(cpath
, PATH_MAX
, "%s/probes", dir_name
);
467 fd
= open(cpath
, O_CREAT
| O_RDWR
, 0644);
469 pr_debug("Failed to open cache(%d): %s\n", fd
, cpath
);
476 static int probe_cache__load(struct probe_cache
*pcache
)
478 struct probe_cache_entry
*entry
= NULL
;
479 char buf
[MAX_CMDLEN
], *p
;
483 fddup
= dup(pcache
->fd
);
486 fp
= fdopen(fddup
, "r");
493 if (!fgets(buf
, MAX_CMDLEN
, fp
))
495 p
= strchr(buf
, '\n');
498 /* #perf_probe_event or %sdt_event */
499 if (buf
[0] == '#' || buf
[0] == '%') {
500 entry
= probe_cache_entry__new(NULL
);
507 entry
->spev
= strdup(buf
+ 1);
509 ret
= parse_perf_probe_command(buf
+ 1,
514 probe_cache_entry__delete(entry
);
517 list_add_tail(&entry
->node
, &pcache
->entries
);
518 } else { /* trace_probe_event */
523 strlist__add(entry
->tevlist
, buf
);
531 static struct probe_cache
*probe_cache__alloc(void)
533 struct probe_cache
*pcache
= zalloc(sizeof(*pcache
));
536 INIT_LIST_HEAD(&pcache
->entries
);
537 pcache
->fd
= -EINVAL
;
542 void probe_cache__purge(struct probe_cache
*pcache
)
544 struct probe_cache_entry
*entry
, *n
;
546 list_for_each_entry_safe(entry
, n
, &pcache
->entries
, node
) {
547 list_del_init(&entry
->node
);
548 probe_cache_entry__delete(entry
);
552 void probe_cache__delete(struct probe_cache
*pcache
)
557 probe_cache__purge(pcache
);
563 struct probe_cache
*probe_cache__new(const char *target
, struct nsinfo
*nsi
)
565 struct probe_cache
*pcache
= probe_cache__alloc();
571 ret
= probe_cache__open(pcache
, target
, nsi
);
573 pr_debug("Cache open error: %d\n", ret
);
577 ret
= probe_cache__load(pcache
);
579 pr_debug("Cache read error: %d\n", ret
);
586 probe_cache__delete(pcache
);
590 static bool streql(const char *a
, const char *b
)
598 return !strcmp(a
, b
);
601 struct probe_cache_entry
*
602 probe_cache__find(struct probe_cache
*pcache
, struct perf_probe_event
*pev
)
604 struct probe_cache_entry
*entry
= NULL
;
605 char *cmd
= synthesize_perf_probe_command(pev
);
610 for_each_probe_cache_entry(entry
, pcache
) {
612 if (entry
->pev
.event
&&
613 streql(entry
->pev
.event
, pev
->event
) &&
615 streql(entry
->pev
.group
, pev
->group
)))
620 /* Hit if same event name or same command-string */
622 (streql(entry
->pev
.group
, pev
->group
) &&
623 streql(entry
->pev
.event
, pev
->event
))) ||
624 (!strcmp(entry
->spev
, cmd
)))
634 struct probe_cache_entry
*
635 probe_cache__find_by_name(struct probe_cache
*pcache
,
636 const char *group
, const char *event
)
638 struct probe_cache_entry
*entry
= NULL
;
640 for_each_probe_cache_entry(entry
, pcache
) {
641 /* Hit if same event name or same command-string */
642 if (streql(entry
->pev
.group
, group
) &&
643 streql(entry
->pev
.event
, event
))
652 int probe_cache__add_entry(struct probe_cache
*pcache
,
653 struct perf_probe_event
*pev
,
654 struct probe_trace_event
*tevs
, int ntevs
)
656 struct probe_cache_entry
*entry
= NULL
;
660 if (!pcache
|| !pev
|| !tevs
|| ntevs
<= 0) {
665 /* Remove old cache entry */
666 entry
= probe_cache__find(pcache
, pev
);
668 list_del_init(&entry
->node
);
669 probe_cache_entry__delete(entry
);
673 entry
= probe_cache_entry__new(pev
);
677 for (i
= 0; i
< ntevs
; i
++) {
678 if (!tevs
[i
].point
.symbol
)
681 command
= synthesize_probe_trace_command(&tevs
[i
]);
684 strlist__add(entry
->tevlist
, command
);
687 list_add_tail(&entry
->node
, &pcache
->entries
);
688 pr_debug("Added probe cache: %d\n", ntevs
);
692 pr_debug("Failed to add probe caches\n");
693 probe_cache_entry__delete(entry
);
697 #ifdef HAVE_GELF_GETNOTE_SUPPORT
698 static unsigned long long sdt_note__get_addr(struct sdt_note
*note
)
701 (unsigned long long)note
->addr
.a32
[SDT_NOTE_IDX_LOC
] :
702 (unsigned long long)note
->addr
.a64
[SDT_NOTE_IDX_LOC
];
705 static unsigned long long sdt_note__get_ref_ctr_offset(struct sdt_note
*note
)
708 (unsigned long long)note
->addr
.a32
[SDT_NOTE_IDX_REFCTR
] :
709 (unsigned long long)note
->addr
.a64
[SDT_NOTE_IDX_REFCTR
];
712 static const char * const type_to_suffix
[] = {
713 ":s64", "", "", "", ":s32", "", ":s16", ":s8",
714 "", ":u8", ":u16", "", ":u32", "", "", "", ":u64"
718 * Isolate the string number and convert it into a decimal value;
719 * this will be an index to get suffix of the uprobe name (defining
722 static int sdt_arg_parse_size(char *n_ptr
, const char **suffix
)
726 type_idx
= strtol(n_ptr
, NULL
, 10);
727 if (type_idx
< -8 || type_idx
> 8) {
728 pr_debug4("Failed to get a valid sdt type\n");
732 *suffix
= type_to_suffix
[type_idx
+ 8];
736 static int synthesize_sdt_probe_arg(struct strbuf
*buf
, int i
, const char *arg
)
738 char *op
, *desc
= strdup(arg
), *new_op
= NULL
;
739 const char *suffix
= "";
743 pr_debug4("Allocation error\n");
748 * Argument is in N@OP format. N is size of the argument and OP is
749 * the actual assembly operand. N can be omitted; in that case
750 * argument is just OP(without @).
752 op
= strchr(desc
, '@');
757 if (sdt_arg_parse_size(desc
, &suffix
))
763 ret
= arch_sdt_arg_parse_op(op
, &new_op
);
768 if (ret
== SDT_ARG_VALID
) {
769 ret
= strbuf_addf(buf
, " arg%d=%s%s", i
+ 1, new_op
, suffix
);
781 static char *synthesize_sdt_probe_command(struct sdt_note
*note
,
782 const char *pathname
,
786 char *ret
= NULL
, **args
;
787 int i
, args_count
, err
;
788 unsigned long long ref_ctr_offset
;
790 if (strbuf_init(&buf
, 32) < 0)
793 err
= strbuf_addf(&buf
, "p:%s/%s %s:0x%llx",
794 sdtgrp
, note
->name
, pathname
,
795 sdt_note__get_addr(note
));
797 ref_ctr_offset
= sdt_note__get_ref_ctr_offset(note
);
798 if (ref_ctr_offset
&& err
>= 0)
799 err
= strbuf_addf(&buf
, "(0x%llx)", ref_ctr_offset
);
808 args
= argv_split(note
->args
, &args_count
);
810 for (i
= 0; i
< args_count
; ++i
) {
811 if (synthesize_sdt_probe_arg(&buf
, i
, args
[i
]) < 0)
817 ret
= strbuf_detach(&buf
, NULL
);
819 strbuf_release(&buf
);
823 int probe_cache__scan_sdt(struct probe_cache
*pcache
, const char *pathname
)
825 struct probe_cache_entry
*entry
= NULL
;
826 struct list_head sdtlist
;
827 struct sdt_note
*note
;
832 INIT_LIST_HEAD(&sdtlist
);
833 ret
= get_sdt_note_list(&sdtlist
, pathname
);
835 pr_debug4("Failed to get sdt note: %d\n", ret
);
838 list_for_each_entry(note
, &sdtlist
, note_list
) {
839 ret
= snprintf(sdtgrp
, 64, "sdt_%s", note
->provider
);
842 /* Try to find same-name entry */
843 entry
= probe_cache__find_by_name(pcache
, sdtgrp
, note
->name
);
845 entry
= probe_cache_entry__new(NULL
);
851 ret
= asprintf(&entry
->spev
, "%s:%s=%s", sdtgrp
,
852 note
->name
, note
->name
);
855 entry
->pev
.event
= strdup(note
->name
);
856 entry
->pev
.group
= strdup(sdtgrp
);
857 list_add_tail(&entry
->node
, &pcache
->entries
);
859 buf
= synthesize_sdt_probe_command(note
, pathname
, sdtgrp
);
865 strlist__add(entry
->tevlist
, buf
);
870 list_del_init(&entry
->node
);
871 probe_cache_entry__delete(entry
);
873 cleanup_sdt_note_list(&sdtlist
);
878 static int probe_cache_entry__write(struct probe_cache_entry
*entry
, int fd
)
880 struct str_node
*snode
;
883 const char *prefix
= entry
->sdt
? "%" : "#";
885 /* Save stat for rollback */
886 ret
= fstat(fd
, &st
);
890 pr_debug("Writing cache: %s%s\n", prefix
, entry
->spev
);
891 iov
[0].iov_base
= (void *)prefix
; iov
[0].iov_len
= 1;
892 iov
[1].iov_base
= entry
->spev
; iov
[1].iov_len
= strlen(entry
->spev
);
893 iov
[2].iov_base
= (void *)"\n"; iov
[2].iov_len
= 1;
894 ret
= writev(fd
, iov
, 3);
895 if (ret
< (int)iov
[1].iov_len
+ 2)
898 strlist__for_each_entry(snode
, entry
->tevlist
) {
899 iov
[0].iov_base
= (void *)snode
->s
;
900 iov
[0].iov_len
= strlen(snode
->s
);
901 iov
[1].iov_base
= (void *)"\n"; iov
[1].iov_len
= 1;
902 ret
= writev(fd
, iov
, 2);
903 if (ret
< (int)iov
[0].iov_len
+ 1)
909 /* Rollback to avoid cache file corruption */
912 if (ftruncate(fd
, st
.st_size
) < 0)
918 int probe_cache__commit(struct probe_cache
*pcache
)
920 struct probe_cache_entry
*entry
;
923 /* TBD: if we do not update existing entries, skip it */
924 ret
= lseek(pcache
->fd
, 0, SEEK_SET
);
928 ret
= ftruncate(pcache
->fd
, 0);
932 for_each_probe_cache_entry(entry
, pcache
) {
933 ret
= probe_cache_entry__write(entry
, pcache
->fd
);
934 pr_debug("Cache committed: %d\n", ret
);
942 static bool probe_cache_entry__compare(struct probe_cache_entry
*entry
,
943 struct strfilter
*filter
)
945 char buf
[128], *ptr
= entry
->spev
;
947 if (entry
->pev
.event
) {
948 snprintf(buf
, 128, "%s:%s", entry
->pev
.group
, entry
->pev
.event
);
951 return strfilter__compare(filter
, ptr
);
954 int probe_cache__filter_purge(struct probe_cache
*pcache
,
955 struct strfilter
*filter
)
957 struct probe_cache_entry
*entry
, *tmp
;
959 list_for_each_entry_safe(entry
, tmp
, &pcache
->entries
, node
) {
960 if (probe_cache_entry__compare(entry
, filter
)) {
961 pr_info("Removed cached event: %s\n", entry
->spev
);
962 list_del_init(&entry
->node
);
963 probe_cache_entry__delete(entry
);
969 static int probe_cache__show_entries(struct probe_cache
*pcache
,
970 struct strfilter
*filter
)
972 struct probe_cache_entry
*entry
;
974 for_each_probe_cache_entry(entry
, pcache
) {
975 if (probe_cache_entry__compare(entry
, filter
))
976 printf("%s\n", entry
->spev
);
981 /* Show all cached probes */
982 int probe_cache__show_all_caches(struct strfilter
*filter
)
984 struct probe_cache
*pcache
;
985 struct strlist
*bidlist
;
987 char *buf
= strfilter__string(filter
);
989 pr_debug("list cache with filter: %s\n", buf
);
992 bidlist
= build_id_cache__list_all(true);
994 pr_debug("Failed to get buildids: %d\n", errno
);
997 strlist__for_each_entry(nd
, bidlist
) {
998 pcache
= probe_cache__new(nd
->s
, NULL
);
1001 if (!list_empty(&pcache
->entries
)) {
1002 buf
= build_id_cache__origname(nd
->s
);
1003 printf("%s (%s):\n", buf
, nd
->s
);
1005 probe_cache__show_entries(pcache
, filter
);
1007 probe_cache__delete(pcache
);
1009 strlist__delete(bidlist
);
1014 enum ftrace_readme
{
1015 FTRACE_README_PROBE_TYPE_X
= 0,
1016 FTRACE_README_KRETPROBE_OFFSET
,
1017 FTRACE_README_UPROBE_REF_CTR
,
1022 const char *pattern
;
1024 } ftrace_readme_table
[] = {
1025 #define DEFINE_TYPE(idx, pat) \
1026 [idx] = {.pattern = pat, .avail = false}
1027 DEFINE_TYPE(FTRACE_README_PROBE_TYPE_X
, "*type: * x8/16/32/64,*"),
1028 DEFINE_TYPE(FTRACE_README_KRETPROBE_OFFSET
, "*place (kretprobe): *"),
1029 DEFINE_TYPE(FTRACE_README_UPROBE_REF_CTR
, "*ref_ctr_offset*"),
1032 static bool scan_ftrace_readme(enum ftrace_readme type
)
1039 static bool scanned
= false;
1044 fd
= open_trace_file("README", false);
1048 fp
= fdopen(fd
, "r");
1054 while (getline(&buf
, &len
, fp
) > 0)
1055 for (enum ftrace_readme i
= 0; i
< FTRACE_README_END
; i
++)
1056 if (!ftrace_readme_table
[i
].avail
)
1057 ftrace_readme_table
[i
].avail
=
1058 strglobmatch(buf
, ftrace_readme_table
[i
].pattern
);
1065 if (type
>= FTRACE_README_END
)
1068 return ftrace_readme_table
[type
].avail
;
1071 bool probe_type_is_available(enum probe_type type
)
1073 if (type
>= PROBE_TYPE_END
)
1075 else if (type
== PROBE_TYPE_X
)
1076 return scan_ftrace_readme(FTRACE_README_PROBE_TYPE_X
);
1081 bool kretprobe_offset_is_supported(void)
1083 return scan_ftrace_readme(FTRACE_README_KRETPROBE_OFFSET
);
1086 bool uprobe_ref_ctr_is_supported(void)
1088 return scan_ftrace_readme(FTRACE_README_UPROBE_REF_CTR
);