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