1 /* 2 * Check decoding of perf_event_open syscall. 3 * 4 * Copyright (c) 2016 Eugene Syromyatnikov <evgsyr@gmail.com> 5 * Copyright (c) 2016-2017 The strace developers. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. The name of the author may not be used to endorse or promote products 17 * derived from this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 #include "tests.h" 32 #include <asm/unistd.h> 33 34 #if defined(__NR_perf_event_open) && defined(HAVE_LINUX_PERF_EVENT_H) 35 36 # include <limits.h> 37 # include <stdio.h> 38 # include <unistd.h> 39 40 # include <linux/perf_event.h> 41 42 # include "xlat.h" 43 # include "xlat/perf_event_open_flags.h" 44 45 #if ULONG_MAX > UINT_MAX 46 #define LONG_STR_PREFIX "ffffffff" 47 #else 48 #define LONG_STR_PREFIX "" 49 #endif 50 51 static const char *printaddr(void *ptr) 52 { 53 static char buf[sizeof("0x") + sizeof(void *) * 2]; 54 55 if (ptr == NULL) 56 return "NULL"; 57 58 snprintf(buf, sizeof(buf), "%#lx", (unsigned long)ptr); 59 60 return buf; 61 } 62 63 int 64 main(void) 65 { 66 TAIL_ALLOC_OBJECT_CONST_PTR(struct perf_event_attr, attr); 67 68 attr->type = PERF_TYPE_HARDWARE; 69 attr->size = sizeof(*attr); 70 71 struct { 72 struct perf_event_attr *attr; 73 pid_t pid; 74 int cpu; 75 int group_fd; 76 unsigned long flags; 77 const char *flags_str; 78 } args[] = { 79 { NULL, 0xfacef00d, 0xbadabba7, -1, 80 (unsigned long) 0xFFFFFFFFFFFFFFFFLLU, 81 "PERF_FLAG_FD_NO_GROUP|PERF_FLAG_FD_OUTPUT|" 82 "PERF_FLAG_PID_CGROUP|PERF_FLAG_FD_CLOEXEC|" 83 "0x" LONG_STR_PREFIX "fffffff0" 84 }, 85 { attr + 1, 0, 0, 0, 86 0, "0" }, 87 { attr, -1, -1, 1, 88 PERF_FLAG_FD_CLOEXEC, "PERF_FLAG_FD_CLOEXEC" }, 89 { attr - 1, -100, 100, 0xface1e55, 90 PERF_FLAG_FD_NO_GROUP | PERF_FLAG_FD_OUTPUT | 91 PERF_FLAG_PID_CGROUP | PERF_FLAG_FD_CLOEXEC, 92 "PERF_FLAG_FD_NO_GROUP|PERF_FLAG_FD_OUTPUT|" 93 "PERF_FLAG_PID_CGROUP|PERF_FLAG_FD_CLOEXEC" }, 94 }; 95 size_t i; 96 int rc; 97 98 for (i = 0; i < ARRAY_SIZE(args); i++) { 99 rc = syscall(__NR_perf_event_open, args[i].attr, args[i].pid, 100 args[i].cpu, args[i].group_fd, args[i].flags); 101 printf("perf_event_open(%s, %d, %d, %d, %s) = %s\n", 102 printaddr(args[i].attr), args[i].pid, args[i].cpu, 103 args[i].group_fd, args[i].flags_str, sprintrc(rc)); 104 } 105 106 puts("+++ exited with 0 +++"); 107 return 0; 108 } 109 110 #else 111 112 SKIP_MAIN_UNDEFINED("__NR_perf_event_open && HAVE_LINUX_PERF_EVENT_H"); 113 114 #endif 115