1 // SPDX-License-Identifier: GPL-2.0 2 #include <stdbool.h> 3 #include <linux/err.h> 4 #include <linux/string.h> 5 #include <sys/types.h> 6 #include <sys/stat.h> 7 #include <fcntl.h> 8 #include "evlist.h" 9 #include "evsel.h" 10 #include "thread_map.h" 11 #include "record.h" 12 #include "tests.h" 13 #include "debug.h" 14 #include "util/mmap.h" 15 #include <errno.h> 16 #include <perf/mmap.h> 17 18 #ifndef O_DIRECTORY 19 #define O_DIRECTORY 00200000 20 #endif 21 #ifndef AT_FDCWD 22 #define AT_FDCWD -100 23 #endif 24 25 int test__syscall_openat_tp_fields(struct test *test __maybe_unused, int subtest __maybe_unused) 26 { 27 struct record_opts opts = { 28 .target = { 29 .uid = UINT_MAX, 30 .uses_mmap = true, 31 }, 32 .no_buffering = true, 33 .freq = 1, 34 .mmap_pages = 256, 35 .raw_samples = true, 36 }; 37 const char *filename = "/etc/passwd"; 38 int flags = O_RDONLY | O_DIRECTORY; 39 struct evlist *evlist = evlist__new(); 40 struct evsel *evsel; 41 int err = -1, i, nr_events = 0, nr_polls = 0; 42 char sbuf[STRERR_BUFSIZE]; 43 44 if (evlist == NULL) { 45 pr_debug("%s: perf_evlist__new\n", __func__); 46 goto out; 47 } 48 49 evsel = perf_evsel__newtp("syscalls", "sys_enter_openat"); 50 if (IS_ERR(evsel)) { 51 pr_debug("%s: perf_evsel__newtp\n", __func__); 52 goto out_delete_evlist; 53 } 54 55 evlist__add(evlist, evsel); 56 57 err = perf_evlist__create_maps(evlist, &opts.target); 58 if (err < 0) { 59 pr_debug("%s: perf_evlist__create_maps\n", __func__); 60 goto out_delete_evlist; 61 } 62 63 perf_evsel__config(evsel, &opts, NULL); 64 65 perf_thread_map__set_pid(evlist->core.threads, 0, getpid()); 66 67 err = evlist__open(evlist); 68 if (err < 0) { 69 pr_debug("perf_evlist__open: %s\n", 70 str_error_r(errno, sbuf, sizeof(sbuf))); 71 goto out_delete_evlist; 72 } 73 74 err = evlist__mmap(evlist, UINT_MAX); 75 if (err < 0) { 76 pr_debug("evlist__mmap: %s\n", 77 str_error_r(errno, sbuf, sizeof(sbuf))); 78 goto out_delete_evlist; 79 } 80 81 evlist__enable(evlist); 82 83 /* 84 * Generate the event: 85 */ 86 openat(AT_FDCWD, filename, flags); 87 88 while (1) { 89 int before = nr_events; 90 91 for (i = 0; i < evlist->core.nr_mmaps; i++) { 92 union perf_event *event; 93 struct mmap *md; 94 95 md = &evlist->mmap[i]; 96 if (perf_mmap__read_init(&md->core) < 0) 97 continue; 98 99 while ((event = perf_mmap__read_event(&md->core)) != NULL) { 100 const u32 type = event->header.type; 101 int tp_flags; 102 struct perf_sample sample; 103 104 ++nr_events; 105 106 if (type != PERF_RECORD_SAMPLE) { 107 perf_mmap__consume(&md->core); 108 continue; 109 } 110 111 err = perf_evsel__parse_sample(evsel, event, &sample); 112 if (err) { 113 pr_debug("Can't parse sample, err = %d\n", err); 114 goto out_delete_evlist; 115 } 116 117 tp_flags = perf_evsel__intval(evsel, &sample, "flags"); 118 119 if (flags != tp_flags) { 120 pr_debug("%s: Expected flags=%#x, got %#x\n", 121 __func__, flags, tp_flags); 122 goto out_delete_evlist; 123 } 124 125 goto out_ok; 126 } 127 perf_mmap__read_done(&md->core); 128 } 129 130 if (nr_events == before) 131 evlist__poll(evlist, 10); 132 133 if (++nr_polls > 5) { 134 pr_debug("%s: no events!\n", __func__); 135 goto out_delete_evlist; 136 } 137 } 138 out_ok: 139 err = 0; 140 out_delete_evlist: 141 evlist__delete(evlist); 142 out: 143 return err; 144 } 145