]> granicus.if.org Git - strace/blob - perf.c
clone: fix print_tls_arg on x86
[strace] / perf.c
1 /*
2  * Copyright (c) 2013 Ben Noordhuis <info@bnoordhuis.nl>
3  * Copyright (c) 2013-2015 Dmitry V. Levin <ldv@altlinux.org>
4  * Copyright (c) 2016 Eugene Syromyatnikov <evgsyr@gmail.com>
5  * Copyright (c) 2015-2019 The strace developers.
6  * All rights reserved.
7  *
8  * SPDX-License-Identifier: LGPL-2.1-or-later
9  */
10
11 #include "defs.h"
12
13 #include "perf_event_struct.h"
14 #include "print_fields.h"
15
16 #include "xlat/hw_breakpoint_len.h"
17 #include "xlat/hw_breakpoint_type.h"
18 #include "xlat/perf_attr_size.h"
19 #include "xlat/perf_branch_sample_type.h"
20 #include "xlat/perf_event_open_flags.h"
21 #include "xlat/perf_event_read_format.h"
22 #include "xlat/perf_event_sample_format.h"
23 #include "xlat/perf_hw_cache_id.h"
24 #include "xlat/perf_hw_cache_op_id.h"
25 #include "xlat/perf_hw_cache_op_result_id.h"
26 #include "xlat/perf_hw_id.h"
27 #include "xlat/perf_sw_ids.h"
28 #include "xlat/perf_type_id.h"
29
30 struct pea_desc {
31         struct perf_event_attr *attr;
32         uint32_t size;
33 };
34
35 static void
36 free_pea_desc(void *pea_desc_ptr)
37 {
38         struct pea_desc *desc = pea_desc_ptr;
39
40         free(desc->attr);
41         free(desc);
42 }
43
44 int
45 fetch_perf_event_attr(struct tcb *const tcp, const kernel_ulong_t addr)
46 {
47         struct pea_desc *desc;
48         struct perf_event_attr *attr;
49         uint32_t size;
50
51         if (umove(tcp, addr + offsetof(struct perf_event_attr, size), &size)) {
52                 printaddr(addr);
53                 return 1;
54         }
55
56         if (size > sizeof(*attr))
57                 size = sizeof(*attr);
58
59         if (!size)
60                 size = PERF_ATTR_SIZE_VER0;
61
62         /*
63          * Kernel (rightfully) deems invalid attribute structures with size less
64          * than first published format size, and we do the same.
65          */
66         if (size < PERF_ATTR_SIZE_VER0) {
67                 printaddr(addr);
68                 return 1;
69         }
70
71         if (abbrev(tcp))
72                 size = offsetofend(struct perf_event_attr, config);
73
74         /* Size should be multiple of 8, but kernel doesn't check for it */
75         /* size &= ~7; */
76
77         attr = xzalloc(sizeof(*attr));
78
79         if (umoven_or_printaddr(tcp, addr, size, attr)) {
80                 free(attr);
81
82                 return 1;
83         }
84
85         desc = xmalloc(sizeof(*desc));
86
87         desc->attr = attr;
88         desc->size = size;
89
90         set_tcb_priv_data(tcp, desc, free_pea_desc);
91
92         return 0;
93 }
94
95 void
96 print_perf_event_attr(struct tcb *const tcp, const kernel_ulong_t addr)
97 {
98         static const char *precise_ip_desc[] = {
99                 "arbitrary skid",
100                 "constant skid",
101                 "requested to have 0 skid",
102                 "must have 0 skid",
103         };
104
105         struct pea_desc *desc;
106         struct perf_event_attr *attr;
107         uint32_t size;
108         uint32_t new_size;
109         int use_new_size = 0;
110
111         /*
112          * Amusingly, kernel accepts structures with only part of the field
113          * present, so we making check like this (instead of checking
114          * offsetofend against size) in order to print fields as kernel sees
115          * them. This also should work great on big endian architectures.
116          */
117 #define _PERF_CHECK_FIELD(_field) \
118                 do { \
119                         if (offsetof(struct perf_event_attr, _field) >= size) \
120                                 goto print_perf_event_attr_out; \
121                 } while (0)
122
123         desc = get_tcb_priv_data(tcp);
124
125         attr = desc->attr;
126         size = desc->size;
127
128         /* The only error which expected to change size field currently */
129         if (tcp->u_error == E2BIG) {
130                 if (umove(tcp, addr + offsetof(struct perf_event_attr, size),
131                     &new_size))
132                         use_new_size = -1;
133                 else
134                         use_new_size = 1;
135         }
136
137         PRINT_FIELD_XVAL("{", *attr, type, perf_type_id, "PERF_TYPE_???");
138         PRINT_FIELD_XVAL(", ", *attr, size, perf_attr_size,
139                          "PERF_ATTR_SIZE_???");
140
141         if (use_new_size) {
142                 tprints(" => ");
143
144                 if (use_new_size > 0)
145                         printxval(perf_attr_size, new_size,
146                                   "PERF_ATTR_SIZE_???");
147                 else
148                         tprints("???");
149         }
150
151         switch (attr->type) {
152         case PERF_TYPE_HARDWARE:
153                 PRINT_FIELD_XVAL(", ", *attr, config, perf_hw_id,
154                                  "PERF_COUNT_HW_???");
155                 break;
156         case PERF_TYPE_SOFTWARE:
157                 PRINT_FIELD_XVAL(", ", *attr, config, perf_sw_ids,
158                                  "PERF_COUNT_SW_???");
159                 break;
160         case PERF_TYPE_TRACEPOINT:
161                 /*
162                  * "The value to use in config can be obtained from under
163                  * debugfs tracing/events/../../id if ftrace is enabled
164                  * in the kernel."
165                  */
166                 PRINT_FIELD_U(", ", *attr, config);
167                 break;
168         case PERF_TYPE_HW_CACHE:
169                 /*
170                  * (perf_hw_cache_id) | (perf_hw_cache_op_id << 8) |
171                  * (perf_hw_cache_op_result_id << 16)
172                  */
173                 tprints(", config=");
174                 printxval(perf_hw_cache_id, attr->config & 0xFF,
175                           "PERF_COUNT_HW_CACHE_???");
176                 tprints("|");
177                 printxval(perf_hw_cache_op_id, (attr->config >> 8) & 0xFF,
178                            "PERF_COUNT_HW_CACHE_OP_???");
179                 tprints("<<8|");
180                 /*
181                  * Current code (see set_ext_hw_attr in arch/x86/events/core.c,
182                  * tile_map_cache_event in arch/tile/kernel/perf_event.c,
183                  * arc_pmu_cache_event in arch/arc/kernel/perf_event.c,
184                  * hw_perf_cache_event in arch/blackfin/kernel/perf_event.c,
185                  * _hw_perf_cache_event in arch/metag/kernel/perf/perf_event.c,
186                  * mipspmu_map_cache_event in arch/mips/kernel/perf_event_mipsxx.c,
187                  * hw_perf_cache_event in arch/powerpc/perf/core-book3s.c,
188                  * hw_perf_cache_event in arch/powerpc/perf/core-fsl-emb.c,
189                  * hw_perf_cache_event in arch/sh/kernel/perf_event.c,
190                  * sparc_map_cache_event in arch/sparc/kernel/perf_event.c,
191                  * xtensa_pmu_cache_event in arch/xtensa/kernel/perf_event.c,
192                  * armpmu_map_cache_event in drivers/perf/arm_pmu.c) assumes
193                  * that cache result is 8 bits in size.
194                  */
195                 printxval(perf_hw_cache_op_result_id,
196                           (attr->config >> 16) & 0xFF,
197                           "PERF_COUNT_HW_CACHE_RESULT_???");
198                 tprints("<<16");
199                 if (attr->config >> 24) {
200                         tprintf("|%#" PRIx64 "<<24", attr->config >> 24);
201                         tprints_comment("PERF_COUNT_HW_CACHE_???");
202                 }
203                 break;
204         case PERF_TYPE_RAW:
205                 /*
206                  * "If type is PERF_TYPE_RAW, then a custom "raw" config
207                  * value is needed. Most CPUs support events that are not
208                  * covered by the "generalized" events. These are
209                  * implementation defined; see your CPU manual (for example the
210                  * Intel Volume 3B documentation or the AMD BIOS and Kernel
211                  * Developer Guide). The libpfm4 library can be used to
212                  * translate from the name in the architectural manuals
213                  * to the raw hex value perf_event_open() expects in this
214                  * field."
215                  */
216         case PERF_TYPE_BREAKPOINT:
217                 /*
218                  * "If type is PERF_TYPE_BREAKPOINT, then leave config set
219                  * to zero. Its parameters are set in other places."
220                  */
221         default:
222                 PRINT_FIELD_X(", ", *attr, config);
223                 break;
224         }
225
226         if (abbrev(tcp))
227                 goto print_perf_event_attr_out;
228
229         if (attr->freq)
230                 PRINT_FIELD_U(", ", *attr, sample_freq);
231         else
232                 PRINT_FIELD_U(", ", *attr, sample_period);
233
234         PRINT_FIELD_FLAGS(", ", *attr, sample_type, perf_event_sample_format,
235                           "PERF_SAMPLE_???");
236         PRINT_FIELD_FLAGS(", ", *attr, read_format, perf_event_read_format,
237                           "PERF_FORMAT_???");
238
239         tprintf(", disabled=%u"
240                 ", inherit=%u"
241                 ", pinned=%u"
242                 ", exclusive=%u"
243                 ", exclusive_user=%u"
244                 ", exclude_kernel=%u"
245                 ", exclude_hv=%u"
246                 ", exclude_idle=%u"
247                 ", mmap=%u"
248                 ", comm=%u"
249                 ", freq=%u"
250                 ", inherit_stat=%u"
251                 ", enable_on_exec=%u"
252                 ", task=%u"
253                 ", watermark=%u"
254                 ", precise_ip=%u",
255                 attr->disabled,
256                 attr->inherit,
257                 attr->pinned,
258                 attr->exclusive,
259                 attr->exclude_user,
260                 attr->exclude_kernel,
261                 attr->exclude_hv,
262                 attr->exclude_idle,
263                 attr->mmap,
264                 attr->comm,
265                 attr->freq,
266                 attr->inherit_stat,
267                 attr->enable_on_exec,
268                 attr->task,
269                 attr->watermark,
270                 attr->precise_ip);
271         tprints_comment(precise_ip_desc[attr->precise_ip]);
272         tprintf(", mmap_data=%u"
273                 ", sample_id_all=%u"
274                 ", exclude_host=%u"
275                 ", exclude_guest=%u"
276                 ", exclude_callchain_kernel=%u"
277                 ", exclude_callchain_user=%u"
278                 ", mmap2=%u"
279                 ", comm_exec=%u"
280                 ", use_clockid=%u"
281                 ", context_switch=%u"
282                 ", write_backward=%u"
283                 ", namespaces=%u",
284                 attr->mmap_data,
285                 attr->sample_id_all,
286                 attr->exclude_host,
287                 attr->exclude_guest,
288                 attr->exclude_callchain_kernel,
289                 attr->exclude_callchain_user,
290                 attr->mmap2,
291                 attr->comm_exec,
292                 attr->use_clockid,
293                 attr->context_switch,
294                 attr->write_backward,
295                 attr->namespaces);
296
297         /*
298          * Print it only in case it is non-zero, since it may contain flags we
299          * are not aware about.
300          */
301         if (attr->__reserved_1) {
302                 tprintf(", __reserved_1=%#" PRIx64,
303                         (uint64_t) attr->__reserved_1);
304                 tprints_comment("Bits 63..29");
305         }
306
307         if (attr->watermark)
308                 PRINT_FIELD_U(", ", *attr, wakeup_watermark);
309         else
310                 PRINT_FIELD_U(", ", *attr, wakeup_events);
311
312         if (attr->type == PERF_TYPE_BREAKPOINT)
313                 /* Any combination of R/W with X is deemed invalid */
314                 PRINT_FIELD_XVAL(", ", *attr, bp_type, hw_breakpoint_type,
315                                  (attr->bp_type <=
316                                         (HW_BREAKPOINT_X | HW_BREAKPOINT_RW))
317                                                 ? "HW_BREAKPOINT_INVALID"
318                                                 : "HW_BREAKPOINT_???");
319
320         if (attr->type == PERF_TYPE_BREAKPOINT)
321                 PRINT_FIELD_X(", ", *attr, bp_addr);
322         else
323                 PRINT_FIELD_X(", ", *attr, config1);
324
325         /*
326          * Fields after bp_addr/config1 are optional and may not present; check
327          * against size is needed.
328          */
329
330         _PERF_CHECK_FIELD(bp_len);
331         if (attr->type == PERF_TYPE_BREAKPOINT)
332                 PRINT_FIELD_U(", ", *attr, bp_len);
333         else
334                 PRINT_FIELD_X(", ", *attr, config2);
335
336         _PERF_CHECK_FIELD(branch_sample_type);
337         if (attr->sample_type & PERF_SAMPLE_BRANCH_STACK) {
338                 PRINT_FIELD_FLAGS(", ", *attr, branch_sample_type,
339                                   perf_branch_sample_type,
340                                   "PERF_SAMPLE_BRANCH_???");
341         }
342
343         _PERF_CHECK_FIELD(sample_regs_user);
344         /*
345          * "This bit mask defines the set of user CPU registers to dump on
346          * samples. The layout of the register mask is architecture-specific and
347          * described in the kernel header
348          * arch/ARCH/include/uapi/asm/perf_regs.h."
349          */
350         PRINT_FIELD_X(", ", *attr, sample_regs_user);
351
352         _PERF_CHECK_FIELD(sample_stack_user);
353         /*
354          * "size of the user stack to dump if PERF_SAMPLE_STACK_USER is
355          * specified."
356          */
357         if (attr->sample_type & PERF_SAMPLE_STACK_USER)
358                 PRINT_FIELD_X(", ", *attr, sample_stack_user);
359
360         if (attr->use_clockid) {
361                 _PERF_CHECK_FIELD(clockid);
362                 PRINT_FIELD_XVAL(", ", *attr, clockid, clocknames, "CLOCK_???");
363         }
364
365         _PERF_CHECK_FIELD(sample_regs_intr);
366         PRINT_FIELD_X(", ", *attr, sample_regs_intr);
367
368         _PERF_CHECK_FIELD(aux_watermark);
369         PRINT_FIELD_U(", ", *attr, aux_watermark);
370
371         _PERF_CHECK_FIELD(sample_max_stack);
372         PRINT_FIELD_U(", ", *attr, sample_max_stack);
373
374         /* _PERF_CHECK_FIELD(__reserved_2);
375         PRINT_FIELD_U(", ", *attr, __reserved2); */
376
377 print_perf_event_attr_out:
378         if ((attr->size && (attr->size > size)) ||
379             (!attr->size && (size < PERF_ATTR_SIZE_VER0)))
380                 tprints(", ...");
381
382         tprints("}");
383 }
384
385 SYS_FUNC(perf_event_open)
386 {
387         /*
388          * We try to copy out the whole structure on entering in order to check
389          * size value on exiting. We do not check the rest of the fields because
390          * they shouldn't be changed, but copy the whole structure instead
391          * of just size field because they could.
392          */
393         if (entering(tcp)) {
394                 if (!fetch_perf_event_attr(tcp, tcp->u_arg[0]))
395                         return 0;
396         } else {
397                 print_perf_event_attr(tcp, tcp->u_arg[0]);
398         }
399
400         tprintf(", %d, %d, ",
401                 (int) tcp->u_arg[1],
402                 (int) tcp->u_arg[2]);
403         printfd(tcp, tcp->u_arg[3]);
404         tprints(", ");
405         printflags64(perf_event_open_flags, tcp->u_arg[4], "PERF_FLAG_???");
406
407         return RVAL_DECODED | RVAL_FD;
408 }