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