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