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