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