1 /*
2 * Copyright (c) 2018-2021 The strace developers.
3 * All rights reserved.
4 *
5 * SPDX-License-Identifier: LGPL-2.1-or-later
6 */
7
8 #include "defs.h"
9
10 #include <linux/ioctl.h>
11
12 #include "perf_event_struct.h"
13
14 #define XLAT_MACROS_ONLY
15 #include "xlat/perf_ioctl_cmds.h"
16 #undef XLAT_MACROS_ONLY
17
18 #include "xlat/perf_ioctl_flags.h"
19
20 #include MPERS_DEFS
21
22 static int
23 perf_ioctl_query_bpf(struct tcb *const tcp, const kernel_ulong_t arg)
24 {
25 uint32_t info;
26
27 if (entering(tcp)) {
28 tprint_arg_next();
29
30 if (umove_or_printaddr(tcp, arg, &info))
31 return RVAL_IOCTL_DECODED;
32
33 tprint_struct_begin();
34 tprints_field_name("ids_len");
35 PRINT_VAL_U(info);
36 tprint_struct_next();
37
38 return 0;
39 }
40
41 if (syserror(tcp) ||
42 umove(tcp, arg + offsetof(struct perf_event_query_bpf, prog_cnt),
43 &info)) {
44 tprint_more_data_follows();
45 tprint_struct_end();
46
47 return RVAL_IOCTL_DECODED;
48 }
49
50 tprints_field_name("prog_cnt");
51 PRINT_VAL_U(info);
52
53 tprint_struct_next();
54 tprints_field_name("ids");
55 print_array(tcp, arg + offsetof(struct perf_event_query_bpf, ids), info,
56 &info, sizeof(info),
57 tfetch_mem, print_uint_array_member, NULL);
58
59 tprint_struct_end();
60
61 return RVAL_IOCTL_DECODED;
62 }
63
64 static int
65 perf_ioctl_modify_attributes(struct tcb *const tcp, const kernel_ulong_t arg)
66 {
67 tprint_arg_next();
68 if (!fetch_perf_event_attr(tcp, arg))
69 print_perf_event_attr(tcp, arg);
70
71 return RVAL_IOCTL_DECODED;
72 }
73
74 MPERS_PRINTER_DECL(int, perf_ioctl,
75 struct tcb *const tcp, const unsigned int code,
76 const kernel_ulong_t arg)
77 {
78 switch (code) {
79 case PERF_EVENT_IOC_ENABLE:
80 case PERF_EVENT_IOC_DISABLE:
81 case PERF_EVENT_IOC_RESET:
82 tprint_arg_next();
83 printflags(perf_ioctl_flags, arg, "PERF_IOC_FLAG_???");
84
85 return RVAL_IOCTL_DECODED;
86
87 case PERF_EVENT_IOC_REFRESH:
88 tprint_arg_next();
89 PRINT_VAL_D((int) arg);
90
91 return RVAL_IOCTL_DECODED;
92
93 case PERF_EVENT_IOC_PERIOD:
94 tprint_arg_next();
95 printnum_int64(tcp, arg, "%" PRIu64);
96
97 return RVAL_IOCTL_DECODED;
98
99 case PERF_EVENT_IOC_SET_OUTPUT:
100 case PERF_EVENT_IOC_SET_BPF:
101 tprint_arg_next();
102 printfd(tcp, (int) arg);
103
104 return RVAL_IOCTL_DECODED;
105
106 case PERF_EVENT_IOC_PAUSE_OUTPUT:
107 tprint_arg_next();
108 PRINT_VAL_U(arg);
109
110 return RVAL_IOCTL_DECODED;
111
112 /*
113 * The following ioctl requests are personality-specific
114 * due to the pointer size.
115 */
116 case PERF_EVENT_IOC_SET_FILTER:
117 tprint_arg_next();
118 printstr_ex(tcp, arg, get_pagesize(), QUOTE_0_TERMINATED);
119
120 return RVAL_IOCTL_DECODED;
121
122 case PERF_EVENT_IOC_ID:
123 if (entering(tcp))
124 return 0;
125
126 tprint_arg_next();
127 printnum_int64(tcp, arg, "%" PRIu64);
128
129 return RVAL_IOCTL_DECODED;
130
131 case PERF_EVENT_IOC_QUERY_BPF:
132 return perf_ioctl_query_bpf(tcp, arg);
133
134 case PERF_EVENT_IOC_MODIFY_ATTRIBUTES:
135 return perf_ioctl_modify_attributes(tcp, arg);
136
137 default:
138 return RVAL_DECODED;
139 }
140 }