]> granicus.if.org Git - strace/blob - bpf.c
Fix preprocessor indentation
[strace] / bpf.c
1 /*
2  * Copyright (c) 2015-2017 Dmitry V. Levin <ldv@altlinux.org>
3  * Copyright (c) 2017 Quentin Monnet <quentin.monnet@6wind.com>
4  * Copyright (c) 2015-2019 The strace developers.
5  * All rights reserved.
6  *
7  * SPDX-License-Identifier: LGPL-2.1-or-later
8  */
9
10 #include "defs.h"
11 #include "print_fields.h"
12
13 #ifdef HAVE_LINUX_BPF_H
14 # include <linux/bpf.h>
15 #endif
16 #include <linux/filter.h>
17
18 #include "bpf_attr.h"
19
20 #include "xlat/bpf_commands.h"
21 #include "xlat/bpf_file_mode_flags.h"
22 #include "xlat/bpf_map_types.h"
23 #include "xlat/bpf_map_flags.h"
24 #include "xlat/bpf_prog_types.h"
25 #include "xlat/bpf_prog_flags.h"
26 #include "xlat/bpf_map_update_elem_flags.h"
27 #include "xlat/bpf_attach_type.h"
28 #include "xlat/bpf_attach_flags.h"
29 #include "xlat/bpf_query_flags.h"
30 #include "xlat/bpf_task_fd_type.h"
31 #include "xlat/ebpf_regs.h"
32 #include "xlat/numa_node.h"
33
34 #define DECL_BPF_CMD_DECODER(bpf_cmd_decoder)                           \
35 int                                                                     \
36 bpf_cmd_decoder(struct tcb *const tcp,                                  \
37                 const kernel_ulong_t addr,                              \
38                 const unsigned int size,                                \
39                 void *const data)                                       \
40 /* End of DECL_BPF_CMD_DECODER definition. */
41
42 #define BEGIN_BPF_CMD_DECODER(bpf_cmd)                                  \
43         static DECL_BPF_CMD_DECODER(decode_ ## bpf_cmd)                 \
44         {                                                               \
45                 struct bpf_cmd ## _struct attr = {};                    \
46                 const size_t attr_size = bpf_cmd ## _struct_size;       \
47                 const unsigned int len = MIN(size, attr_size);          \
48                 memcpy(&attr, data, len);                               \
49                 do {                                                    \
50 /* End of BEGIN_BPF_CMD_DECODER definition. */
51
52 #define END_BPF_CMD_DECODER(rval)                                       \
53                         decode_attr_extra_data(tcp, data, size, attr_size); \
54                 } while (0);                                            \
55                 tprints("}");                                           \
56                 return (rval);                                          \
57         }                                                               \
58 /* End of END_BPF_CMD_DECODER definition. */
59
60 #define BPF_CMD_ENTRY(bpf_cmd)                                          \
61         [bpf_cmd] = decode_ ## bpf_cmd
62
63 typedef DECL_BPF_CMD_DECODER((*bpf_cmd_decoder_t));
64
65 /*
66  * A note about bpf syscall decoder: it doesn't perform any size sanity checks,
67  * so even if it leads to partial copying of one of the fields, the command
68  * handler will still use the (partially-copied-from-userspace, partially
69  * zeroed) field value.  That's why we stop decoding and check for known sizes
70  * that correspond to released versions of the structure used by the specific
71  * command - it looks like the most sensible way to parse this insanity.
72  */
73
74 static int
75 decode_attr_extra_data(struct tcb *const tcp,
76                        const char *data,
77                        unsigned int size,
78                        const size_t attr_size)
79 {
80         if (size <= attr_size)
81                 return 0;
82
83         data += attr_size;
84         size -= attr_size;
85
86         unsigned int i;
87         for (i = 0; i < size; ++i) {
88                 if (data[i]) {
89                         tprints(", ");
90                         if (abbrev(tcp)) {
91                                 tprints("...");
92                         } else {
93                                 tprintf("/* bytes %zu..%zu */ ",
94                                         attr_size, attr_size + size - 1);
95                                 print_quoted_string(data, size,
96                                                     QUOTE_FORCE_HEX);
97                         }
98                         return RVAL_DECODED;
99                 }
100         }
101
102         return 0;
103 }
104
105 struct ebpf_insn {
106         uint8_t code;
107         uint8_t dst_reg:4;
108         uint8_t src_reg:4;
109         int16_t off;
110         int32_t imm;
111 };
112
113 struct ebpf_insns_data {
114         unsigned int count;
115 };
116
117 static bool
118 print_ebpf_insn(struct tcb * const tcp, void * const elem_buf,
119                 const size_t elem_size, void * const data)
120 {
121         struct ebpf_insns_data *eid = data;
122         struct ebpf_insn *insn = elem_buf;
123
124         if (eid->count++ >= BPF_MAXINSNS) {
125                 tprints("...");
126                 return false;
127         }
128
129         tprints("{code=");
130         print_bpf_filter_code(insn->code, true);
131
132         /* We can't use PRINT_FIELD_XVAL on bit fields */
133         tprints(", dst_reg=");
134         printxval(ebpf_regs, insn->dst_reg, "BPF_REG_???");
135         tprints(", src_reg=");
136         printxval(ebpf_regs, insn->src_reg, "BPF_REG_???");
137
138         PRINT_FIELD_D(", ", *insn, off);
139         PRINT_FIELD_X(", ", *insn, imm);
140         tprints("}");
141
142         return true;
143 }
144
145 static void
146 print_ebpf_prog(struct tcb *const tcp, const uint64_t addr, const uint32_t len)
147 {
148         print_big_u64_addr(addr);
149         if (abbrev(tcp)) {
150                 printaddr(addr);
151         } else {
152                 struct ebpf_insns_data eid = {};
153                 struct ebpf_insn insn;
154
155                 print_array(tcp, addr, len, &insn, sizeof(insn),
156                             tfetch_mem, print_ebpf_insn, &eid);
157         }
158 }
159
160 BEGIN_BPF_CMD_DECODER(BPF_MAP_CREATE)
161 {
162         PRINT_FIELD_XVAL("{", attr, map_type, bpf_map_types,
163                          "BPF_MAP_TYPE_???");
164         PRINT_FIELD_U(", ", attr, key_size);
165         PRINT_FIELD_U(", ", attr, value_size);
166         PRINT_FIELD_U(", ", attr, max_entries);
167
168         /* map_flags field was added in Linux commit v4.6-rc1~91^2~108^2~6. */
169         if (len <= offsetof(struct BPF_MAP_CREATE_struct, map_flags))
170                 break;
171         PRINT_FIELD_FLAGS(", ", attr, map_flags, bpf_map_flags, "BPF_F_???");
172
173         /*
174          * inner_map_fd field was added in Linux commit
175          * v4.12-rc1~64^3~373^2~2.
176          */
177         if (len <= offsetof(struct BPF_MAP_CREATE_struct, inner_map_fd))
178                 break;
179         PRINT_FIELD_FD(", ", attr, inner_map_fd, tcp);
180
181         /* numa_node field was added in Linux commit v4.14-rc1~130^2~196^2~1. */
182         if (len <= offsetof(struct BPF_MAP_CREATE_struct, numa_node))
183                 break;
184         if (attr.map_flags & BPF_F_NUMA_NODE) {
185                 /*
186                  * Kernel uses the value of -1 as a designation for "no NUMA
187                  * node specified", and even uses NUMA_NO_NODE constant;
188                  * however, the constant definition is not a part of UAPI
189                  * headers, thus we can't simply print this named constant
190                  * instead of the value. Let's force verbose xlat style instead
191                  * in order to provide the information for the user while
192                  * not hampering the availability to derive the actual value
193                  * without the access to the kernel headers.
194                  */
195                 tprints(", numa_node=");
196                 printxvals_ex(attr.numa_node, NULL,
197                               XLAT_STYLE_FMT_U | XLAT_STYLE_VERBOSE,
198                               numa_node, NULL);
199         }
200
201         /* map_name field was added in Linux commit v4.15-rc1~84^2~605^2~3. */
202         if (len <= offsetof(struct BPF_MAP_CREATE_struct, map_name))
203                 break;
204         PRINT_FIELD_CSTRING_SZ(", ", attr, map_name,
205                                MIN(sizeof(attr.map_name),
206                                    len - offsetof(struct BPF_MAP_CREATE_struct,
207                                                   map_name)));
208
209         /*
210          * map_ifindex field was added in Linux commit
211          * v4.16-rc1~123^2~145^2~5^2~8.
212          */
213         if (len <= offsetof(struct BPF_MAP_CREATE_struct, map_ifindex))
214                 break;
215         PRINT_FIELD_IFINDEX(", ", attr, map_ifindex);
216
217         /*
218          * The following three fields were introduced by Linux commits
219          * v4.18-rc1~114^2~417^2~1^2~3 and v4.18-rc1~114^2~148^2~7^2~2.
220          */
221         if (len <= offsetof(struct BPF_MAP_CREATE_struct, btf_fd))
222                 break;
223         PRINT_FIELD_FD(", ", attr, btf_fd, tcp);
224         PRINT_FIELD_U(", ", attr, btf_key_type_id);
225         PRINT_FIELD_U(", ", attr, btf_value_type_id);
226 }
227 END_BPF_CMD_DECODER(RVAL_DECODED | RVAL_FD)
228
229 BEGIN_BPF_CMD_DECODER(BPF_MAP_LOOKUP_ELEM)
230 {
231         PRINT_FIELD_FD("{", attr, map_fd, tcp);
232         PRINT_FIELD_ADDR64(", ", attr, key);
233         PRINT_FIELD_ADDR64(", ", attr, value);
234 }
235 END_BPF_CMD_DECODER(RVAL_DECODED)
236
237 #define decode_BPF_MAP_LOOKUP_AND_DELETE_ELEM decode_BPF_MAP_LOOKUP_ELEM
238
239 BEGIN_BPF_CMD_DECODER(BPF_MAP_UPDATE_ELEM)
240 {
241         PRINT_FIELD_FD("{", attr, map_fd, tcp);
242         PRINT_FIELD_ADDR64(", ", attr, key);
243         PRINT_FIELD_ADDR64(", ", attr, value);
244         PRINT_FIELD_XVAL(", ", attr, flags, bpf_map_update_elem_flags,
245                          "BPF_???");
246 }
247 END_BPF_CMD_DECODER(RVAL_DECODED)
248
249 BEGIN_BPF_CMD_DECODER(BPF_MAP_DELETE_ELEM)
250 {
251         PRINT_FIELD_FD("{", attr, map_fd, tcp);
252         PRINT_FIELD_ADDR64(", ", attr, key);
253 }
254 END_BPF_CMD_DECODER(RVAL_DECODED)
255
256 BEGIN_BPF_CMD_DECODER(BPF_MAP_GET_NEXT_KEY)
257 {
258         PRINT_FIELD_FD("{", attr, map_fd, tcp);
259         PRINT_FIELD_ADDR64(", ", attr, key);
260         PRINT_FIELD_ADDR64(", ", attr, next_key);
261 }
262 END_BPF_CMD_DECODER(RVAL_DECODED)
263
264 BEGIN_BPF_CMD_DECODER(BPF_MAP_FREEZE)
265 {
266         PRINT_FIELD_FD("{", attr, map_fd, tcp);
267 }
268 END_BPF_CMD_DECODER(RVAL_DECODED)
269
270 BEGIN_BPF_CMD_DECODER(BPF_PROG_LOAD)
271 {
272         PRINT_FIELD_XVAL("{", attr, prog_type, bpf_prog_types,
273                          "BPF_PROG_TYPE_???");
274         PRINT_FIELD_U(", ", attr, insn_cnt);
275         tprints(", insns=");
276         print_ebpf_prog(tcp, attr.insns, attr.insn_cnt);
277
278         tprintf(", license=");
279         print_big_u64_addr(attr.license);
280         printstr(tcp, attr.license);
281
282         /* log_* fields were added in Linux commit v3.18-rc1~52^2~1^2~4.  */
283         if (len <= offsetof(struct BPF_PROG_LOAD_struct, log_level))
284                 break;
285         PRINT_FIELD_U(", ", attr, log_level);
286         PRINT_FIELD_U(", ", attr, log_size);
287         tprintf(", log_buf=");
288         print_big_u64_addr(attr.log_buf);
289         printstr_ex(tcp, attr.log_buf, attr.log_size, QUOTE_0_TERMINATED);
290
291         /* kern_version field was added in Linux commit v4.1-rc1~84^2~50.  */
292         if (len <= offsetof(struct BPF_PROG_LOAD_struct, kern_version))
293                 break;
294         tprints(", kern_version=");
295         print_kernel_version(attr.kern_version);
296         /* prog_flags field was added in Linux commit v4.12-rc2~34^2~29^2~2.  */
297         if (len <= offsetof(struct BPF_PROG_LOAD_struct, prog_flags))
298                 break;
299         PRINT_FIELD_FLAGS(", ", attr, prog_flags, bpf_prog_flags, "BPF_F_???");
300
301         /* prog_name field was added in Linux commit v4.15-rc1~84^2~605^2~4. */
302         if (len <= offsetof(struct BPF_PROG_LOAD_struct, prog_name))
303                 break;
304         PRINT_FIELD_CSTRING_SZ(", ", attr, prog_name,
305                                MIN(sizeof(attr.prog_name),
306                                    len - offsetof(struct BPF_PROG_LOAD_struct,
307                                                    prog_name)));
308
309         /*
310          * prog_ifindex field was added as prog_target_ifindex in Linux commit
311          * v4.15-rc1~84^2~127^2~13 and renamed to its current name in
312          * v4.15-rc1~15^2~5^2~3^2~7.
313          */
314         if (len <= offsetof(struct BPF_PROG_LOAD_struct, prog_ifindex))
315                 break;
316         PRINT_FIELD_IFINDEX(", ", attr, prog_ifindex);
317
318         /*
319          * expected_attach_type was added in Linux commit
320          * v4.17-rc1~148^2~19^2^2~8.
321          */
322         if (len <= offsetof(struct BPF_PROG_LOAD_struct, expected_attach_type))
323                 break;
324         PRINT_FIELD_XVAL(", ", attr, expected_attach_type, bpf_attach_type,
325                          "BPF_???");
326
327         /*
328          * The following seven fields were introduced by Linux commits
329          * v5.0-rc1~129^2~209^2~16^2~8 and v5.0-rc1~129^2~114^2~5^2~6.
330          */
331         if (len <= offsetof(struct BPF_PROG_LOAD_struct, prog_btf_fd))
332                 break;
333         PRINT_FIELD_FD(", ", attr, prog_btf_fd, tcp);
334         PRINT_FIELD_U(", ", attr, func_info_rec_size);
335         PRINT_FIELD_ADDR64(", ", attr, func_info);
336         PRINT_FIELD_U(", ", attr, func_info_cnt);
337         PRINT_FIELD_U(", ", attr, line_info_rec_size);
338         PRINT_FIELD_ADDR64(", ", attr, line_info);
339         PRINT_FIELD_U(", ", attr, line_info_cnt);
340 }
341 END_BPF_CMD_DECODER(RVAL_DECODED | RVAL_FD)
342
343 BEGIN_BPF_CMD_DECODER(BPF_OBJ_PIN)
344 {
345         tprintf("{pathname=");
346         print_big_u64_addr(attr.pathname);
347         printpath(tcp, attr.pathname);
348
349         PRINT_FIELD_FD(", ", attr, bpf_fd, tcp);
350
351         /* file_flags field was added in Linux v4.15-rc1~84^2~384^2~4 */
352         if (len <= offsetof(struct BPF_OBJ_PIN_struct, file_flags))
353                 break;
354         PRINT_FIELD_FLAGS(", ", attr, file_flags, bpf_file_mode_flags,
355                           "BPF_F_???");
356 }
357 END_BPF_CMD_DECODER(RVAL_DECODED | RVAL_FD)
358
359 #define decode_BPF_OBJ_GET decode_BPF_OBJ_PIN
360
361 BEGIN_BPF_CMD_DECODER(BPF_PROG_ATTACH)
362 {
363         PRINT_FIELD_FD("{", attr, target_fd, tcp);
364         PRINT_FIELD_FD(", ", attr, attach_bpf_fd, tcp);
365         PRINT_FIELD_XVAL(", ", attr, attach_type, bpf_attach_type, "BPF_???");
366         PRINT_FIELD_FLAGS(", ", attr, attach_flags, bpf_attach_flags,
367                           "BPF_F_???");
368 }
369 END_BPF_CMD_DECODER(RVAL_DECODED)
370
371 BEGIN_BPF_CMD_DECODER(BPF_PROG_DETACH)
372 {
373         PRINT_FIELD_FD("{", attr, target_fd, tcp);
374         PRINT_FIELD_XVAL(", ", attr, attach_type, bpf_attach_type, "BPF_???");
375 }
376 END_BPF_CMD_DECODER(RVAL_DECODED)
377
378 BEGIN_BPF_CMD_DECODER(BPF_PROG_TEST_RUN)
379 {
380         PRINT_FIELD_FD("{test={", attr, prog_fd, tcp);
381         PRINT_FIELD_U(", ", attr, retval);
382         PRINT_FIELD_U(", ", attr, data_size_in);
383         PRINT_FIELD_U(", ", attr, data_size_out);
384         PRINT_FIELD_ADDR64(", ", attr, data_in);
385         PRINT_FIELD_ADDR64(", ", attr, data_out);
386         PRINT_FIELD_U(", ", attr, repeat);
387         PRINT_FIELD_U(", ", attr, duration);
388         /*
389          * The following four fields were introduced by Linux commit
390          * v5.2-rc1~133^2~193^2~6.
391          */
392         if (len > offsetof(struct BPF_PROG_TEST_RUN_struct, ctx_size_in)) {
393                 PRINT_FIELD_U(", ", attr, ctx_size_in);
394                 PRINT_FIELD_U(", ", attr, ctx_size_out);
395                 PRINT_FIELD_ADDR64(", ", attr, ctx_in);
396                 PRINT_FIELD_ADDR64(", ", attr, ctx_out);
397         }
398         tprints("}");
399 }
400 END_BPF_CMD_DECODER(RVAL_DECODED)
401
402 BEGIN_BPF_CMD_DECODER(BPF_PROG_GET_NEXT_ID)
403 {
404         PRINT_FIELD_U("{", attr, start_id);
405         PRINT_FIELD_U(", ", attr, next_id);
406
407         /* open_flags field has been added in Linux v4.15-rc1~84^2~384^2~4 */
408         if (len <= offsetof(struct BPF_PROG_GET_NEXT_ID_struct, open_flags))
409                 break;
410         PRINT_FIELD_FLAGS(", ", attr, open_flags, bpf_file_mode_flags,
411                           "BPF_F_???");
412 }
413 END_BPF_CMD_DECODER(RVAL_DECODED)
414
415 #define decode_BPF_MAP_GET_NEXT_ID decode_BPF_PROG_GET_NEXT_ID
416
417 BEGIN_BPF_CMD_DECODER(BPF_PROG_GET_FD_BY_ID)
418 {
419         PRINT_FIELD_U("{", attr, prog_id);
420         PRINT_FIELD_U(", ", attr, next_id);
421
422         /* open_flags field has been added in Linux v4.15-rc1~84^2~384^2~4 */
423         if (len <= offsetof(struct BPF_PROG_GET_FD_BY_ID_struct, open_flags))
424                 break;
425         PRINT_FIELD_FLAGS(", ", attr, open_flags, bpf_file_mode_flags,
426                           "BPF_F_???");
427 }
428 END_BPF_CMD_DECODER(RVAL_DECODED | RVAL_FD)
429
430 BEGIN_BPF_CMD_DECODER(BPF_MAP_GET_FD_BY_ID)
431 {
432         PRINT_FIELD_U("{", attr, map_id);
433         PRINT_FIELD_U(", ", attr, next_id);
434
435         /* open_flags field has been added in Linux v4.15-rc1~84^2~384^2~4 */
436         if (len <= offsetof(struct BPF_MAP_GET_FD_BY_ID_struct, open_flags))
437                 break;
438         PRINT_FIELD_FLAGS(", ", attr, open_flags, bpf_file_mode_flags,
439                           "BPF_F_???");
440 }
441 END_BPF_CMD_DECODER(RVAL_DECODED | RVAL_FD)
442
443 struct obj_get_info_saved;
444 typedef void (*print_bpf_obj_info_fn)(struct tcb *,
445                                       uint32_t bpf_fd,
446                                       const char *info_buf,
447                                       uint32_t size,
448                                       struct obj_get_info_saved *saved);
449
450 struct obj_get_info_saved {
451         print_bpf_obj_info_fn print_fn;
452
453         uint32_t info_len;
454
455         uint32_t jited_prog_len;
456         uint32_t xlated_prog_len;
457         uint32_t nr_map_ids;
458
459         uint32_t nr_jited_ksyms;
460         uint32_t nr_jited_func_lens;
461         uint64_t jited_ksyms;
462         uint64_t jited_func_lens;
463
464         uint32_t func_info_rec_size;
465         uint32_t nr_func_info;
466         uint32_t nr_line_info;
467         uint32_t nr_jited_line_info;
468         uint64_t jited_line_info;
469         uint32_t line_info_rec_size;
470         uint32_t jited_line_info_rec_size;
471         uint32_t nr_prog_tags;
472 };
473
474 static void
475 print_bpf_map_info(struct tcb * const tcp, uint32_t bpf_fd,
476                    const char *info_buf, uint32_t size,
477                    struct obj_get_info_saved *saved)
478 {
479         if (entering(tcp))
480                 return;
481
482         struct bpf_map_info_struct info = { 0 };
483         const unsigned int len = MIN(size, bpf_map_info_struct_size);
484
485         memcpy(&info, info_buf, len);
486
487         PRINT_FIELD_XVAL("{", info, type, bpf_map_types, "BPF_MAP_TYPE_???");
488         PRINT_FIELD_U(", ", info, id);
489         PRINT_FIELD_U(", ", info, key_size);
490         PRINT_FIELD_U(", ", info, value_size);
491         PRINT_FIELD_U(", ", info, max_entries);
492         PRINT_FIELD_FLAGS(", ", info, map_flags, bpf_map_flags, "BPF_F_???");
493
494         /*
495          * "name" field was introduced by Linux commit v4.15-rc1~84^2~605^2~3.
496          */
497         if (len <= offsetof(struct bpf_map_info_struct, name))
498                 goto print_bpf_map_info_end;
499         PRINT_FIELD_CSTRING(", ", info, name);
500
501         /*
502          * ifindex, netns_dev, and netns_ino fields were introduced
503          * by Linux commit v4.16-rc1~123^2~109^2~5^2~4.
504          */
505         if (len <= offsetof(struct bpf_map_info_struct, ifindex))
506                 goto print_bpf_map_info_end;
507         PRINT_FIELD_IFINDEX(", ", info, ifindex);
508         PRINT_FIELD_DEV(", ", info, netns_dev);
509         PRINT_FIELD_U(", ", info, netns_ino);
510
511         /*
512          * The next three fields were introduced by Linux commits
513          * v4.18-rc1~114^2~223^2~21^2~4 and v4.18-rc1~114^2~148^2~7^2~2.
514          */
515         if (len <= offsetof(struct bpf_map_info_struct, btf_id))
516                 goto print_bpf_map_info_end;
517         PRINT_FIELD_U(", ", info, btf_id);
518         PRINT_FIELD_U(", ", info, btf_key_type_id);
519         PRINT_FIELD_U(", ", info, btf_value_type_id);
520
521         decode_attr_extra_data(tcp, info_buf, size, bpf_map_info_struct_size);
522
523 print_bpf_map_info_end:
524         tprints("}");
525 }
526
527 static void
528 print_bpf_prog_info(struct tcb * const tcp, uint32_t bpf_fd,
529                     const char *info_buf, uint32_t size,
530                     struct obj_get_info_saved *saved)
531 {
532         struct bpf_prog_info_struct info = { 0 };
533         const unsigned int len = MIN(size, bpf_prog_info_struct_size);
534         uint64_t map_id_buf;
535
536         memcpy(&info, info_buf, len);
537
538         if (entering(tcp)) {
539                 saved->jited_prog_len = info.jited_prog_len;
540                 saved->xlated_prog_len = info.xlated_prog_len;
541                 saved->nr_map_ids = info.nr_map_ids;
542                 saved->nr_jited_ksyms = info.nr_jited_ksyms;
543                 saved->nr_jited_func_lens = info.nr_jited_func_lens;
544                 saved->jited_ksyms = info.jited_ksyms;
545                 saved->jited_func_lens = info.jited_func_lens;
546
547                 saved->func_info_rec_size = info.func_info_rec_size;
548                 saved->nr_func_info = info.nr_func_info;
549                 saved->nr_line_info = info.nr_line_info;
550                 saved->nr_jited_line_info = info.nr_jited_line_info;
551                 saved->jited_line_info = info.jited_line_info;
552                 saved->line_info_rec_size = info.line_info_rec_size;
553                 saved->jited_line_info_rec_size = info.jited_line_info_rec_size;
554                 saved->nr_prog_tags = info.nr_prog_tags;
555
556                 return;
557         }
558
559         PRINT_FIELD_XVAL("{", info, type, bpf_prog_types, "BPF_PROG_TYPE_???");
560         PRINT_FIELD_U(", ", info, id);
561         PRINT_FIELD_HEX_ARRAY(", ", info, tag);
562
563         tprints(", jited_prog_len=");
564         if (saved->jited_prog_len != info.jited_prog_len)
565                 tprintf("%" PRIu32 " => ", saved->jited_prog_len);
566         tprintf("%" PRIu32, info.jited_prog_len);
567
568         tprints(", jited_prog_insns=");
569         print_big_u64_addr(info.jited_prog_insns);
570         printstr_ex(tcp, info.jited_prog_insns, info.jited_prog_len,
571                     QUOTE_FORCE_HEX);
572
573         tprints(", xlated_prog_len=");
574         if (saved->xlated_prog_len != info.xlated_prog_len)
575                 tprintf("%" PRIu32 " => ", saved->xlated_prog_len);
576         tprintf("%" PRIu32, info.xlated_prog_len);
577
578         tprints(", xlated_prog_insns=");
579         print_ebpf_prog(tcp, info.xlated_prog_insns,
580                         MIN(saved->xlated_prog_len, info.xlated_prog_len) / 8);
581
582         /*
583          * load_time, created_by_uid, nr_map_ids, map_ids, and name fields
584          * were introduced by Linux commit v4.15-rc1~84^2~605^2~4.
585          */
586         if (len <= offsetof(struct bpf_prog_info_struct, load_time))
587                 goto print_bpf_prog_info_end;
588         PRINT_FIELD_U(", ", info, load_time);
589         PRINT_FIELD_UID(", ", info, created_by_uid);
590
591         tprints(", nr_map_ids=");
592         if (saved->nr_map_ids != info.nr_map_ids)
593                 tprintf("%" PRIu32 " => ", saved->nr_map_ids);
594         tprintf("%" PRIu32, info.nr_map_ids);
595
596         tprints(", map_ids=");
597         print_big_u64_addr(info.map_ids);
598         print_array(tcp, info.map_ids, MIN(saved->nr_map_ids, info.nr_map_ids),
599                     &map_id_buf, sizeof(map_id_buf),
600                     tfetch_mem, print_uint32_array_member, 0);
601
602         PRINT_FIELD_CSTRING(", ", info, name);
603
604         /*
605          * ifindex, netns_dev, and netns_ino fields were introduced
606          * by Linux commit v4.16-rc1~123^2~227^2~5^2~2, and
607          * gpl_compatible was added later by Linux commit
608          * v4.18-rc1~114^2~376^2~6.
609          */
610         if (len <= offsetof(struct bpf_prog_info_struct, ifindex))
611                 goto print_bpf_prog_info_end;
612         PRINT_FIELD_IFINDEX(", ", info, ifindex);
613         tprintf(", gpl_compatible=%u", info.gpl_compatible);
614         PRINT_FIELD_DEV(", ", info, netns_dev);
615         PRINT_FIELD_U(", ", info, netns_ino);
616
617         /*
618          * The next four fields were introduced by Linux commits
619          * v4.18-rc1~114^2~148^2~3^2~6 and v4.18-rc1~114^2~148^2~3^2~2.
620          */
621         if (len <= offsetof(struct bpf_prog_info_struct, nr_jited_ksyms))
622                 goto print_bpf_prog_info_end;
623
624         tprints(", nr_jited_ksyms=");
625         if (saved->nr_jited_ksyms != info.nr_jited_ksyms)
626                 tprintf("%" PRIu32 " => ", saved->nr_jited_ksyms);
627         tprintf("%" PRIu32, info.nr_jited_ksyms);
628
629         tprints(", nr_jited_func_lens=");
630         if (saved->nr_jited_func_lens != info.nr_jited_func_lens)
631                 tprintf("%" PRIu32 " => ", saved->nr_jited_func_lens);
632         tprintf("%" PRIu32, info.nr_jited_func_lens);
633
634         tprints(", jited_ksyms=");
635         if (saved->jited_ksyms != info.jited_ksyms) {
636                 printaddr64(saved->jited_ksyms);
637                 tprints(" => ");
638         }
639         printaddr64(info.jited_ksyms);
640
641         tprints(", jited_func_lens=");
642         if (saved->jited_func_lens != info.jited_func_lens) {
643                 printaddr64(saved->jited_func_lens);
644                 tprints(" => ");
645         }
646         printaddr64(info.jited_func_lens);
647
648         /*
649          * The next twelve fields were introduced by Linux commits
650          * v5.0-rc1~129^2~209^2~16^2~8
651          * v5.0-rc1~129^2~114^2~5^2~6
652          * v5.0-rc1~129^2~114^2^2~2
653          * v5.0-rc1~129^2~15^2~22
654          */
655         if (len <= offsetof(struct bpf_prog_info_struct, btf_id))
656                 goto print_bpf_prog_info_end;
657
658         PRINT_FIELD_U(", ", info, btf_id);
659
660         tprints(", func_info_rec_size=");
661         if (saved->func_info_rec_size != info.func_info_rec_size)
662                 tprintf("%" PRIu32 " => ", saved->func_info_rec_size);
663         tprintf("%" PRIu32, info.func_info_rec_size);
664
665         PRINT_FIELD_ADDR64(", ", info, func_info);
666
667         tprints(", nr_func_info=");
668         if (saved->nr_func_info != info.nr_func_info)
669                 tprintf("%" PRIu32 " => ", saved->nr_func_info);
670         tprintf("%" PRIu32, info.nr_func_info);
671
672         tprints(", nr_line_info=");
673         if (saved->nr_line_info != info.nr_line_info)
674                 tprintf("%" PRIu32 " => ", saved->nr_line_info);
675         tprintf("%" PRIu32, info.nr_line_info);
676
677         PRINT_FIELD_ADDR64(", ", info, line_info);
678
679         tprints(", jited_line_info=");
680         if (saved->jited_line_info != info.jited_line_info) {
681                 printaddr64(saved->jited_line_info);
682                 tprints(" => ");
683         }
684         printaddr64(info.jited_line_info);
685
686         tprints(", nr_jited_line_info=");
687         if (saved->nr_jited_line_info != info.nr_jited_line_info)
688                 tprintf("%" PRIu32 " => ", saved->nr_jited_line_info);
689         tprintf("%" PRIu32, info.nr_jited_line_info);
690
691         tprints(", line_info_rec_size=");
692         if (saved->line_info_rec_size != info.line_info_rec_size)
693                 tprintf("%" PRIu32 " => ", saved->line_info_rec_size);
694         tprintf("%" PRIu32, info.line_info_rec_size);
695
696         tprints(", jited_line_info_rec_size=");
697         if (saved->jited_line_info_rec_size != info.jited_line_info_rec_size)
698                 tprintf("%" PRIu32 " => ", saved->jited_line_info_rec_size);
699         tprintf("%" PRIu32, info.jited_line_info_rec_size);
700
701         tprints(", nr_prog_tags=");
702         if (saved->nr_prog_tags != info.nr_prog_tags)
703                 tprintf("%" PRIu32 " => ", saved->nr_prog_tags);
704         tprintf("%" PRIu32, info.nr_prog_tags);
705
706         PRINT_FIELD_ADDR64(", ", info, prog_tags);
707
708         /*
709          * run_time_ns and run_cnt fields were introduced
710          * by Linux commit v5.1-rc1~178^2~17^2~15^2~2.
711          */
712         if (len <= offsetof(struct bpf_prog_info_struct, run_time_ns))
713                 goto print_bpf_prog_info_end;
714
715         PRINT_FIELD_U(", ", info, run_time_ns);
716         PRINT_FIELD_U(", ", info, run_cnt);
717
718         decode_attr_extra_data(tcp, info_buf, size, bpf_prog_info_struct_size);
719
720 print_bpf_prog_info_end:
721         tprints("}");
722 }
723
724 static const char *
725 fetch_bpf_obj_info(struct tcb * const tcp, uint64_t info, uint32_t size)
726 {
727         static char *info_buf;
728
729         if (!info_buf)
730                 info_buf = xmalloc(get_pagesize());
731
732         memset(info_buf, 0, get_pagesize());
733
734         if (size > 0 && size <= get_pagesize()
735             && !umoven(tcp, info, size, info_buf))
736                 return info_buf;
737
738         return NULL;
739 }
740
741 static void
742 print_bpf_obj_info_addr(struct tcb * const tcp, uint64_t addr)
743 {
744         if (exiting(tcp))
745                 printaddr64(addr);
746 }
747
748 static void
749 print_bpf_obj_info(struct tcb * const tcp, uint32_t bpf_fd, uint64_t info,
750                    uint32_t size, struct obj_get_info_saved *saved)
751 {
752         if (abbrev(tcp)) {
753                 print_bpf_obj_info_addr(tcp, info);
754                 return;
755         }
756
757         static struct {
758                 const char *id;
759                 print_bpf_obj_info_fn print_fn;
760         } obj_printers[] = {
761                 { "anon_inode:bpf-map", print_bpf_map_info },
762                 { "anon_inode:bpf-prog", print_bpf_prog_info }
763         };
764
765         if (entering(tcp)) {
766                 char path[PATH_MAX + 1];
767
768                 if (getfdpath(tcp, bpf_fd, path, sizeof(path)) > 0) {
769                         for (size_t i = 0; i < ARRAY_SIZE(obj_printers); ++i) {
770                                 if (!strcmp(path, obj_printers[i].id)) {
771                                         saved->print_fn =
772                                                 obj_printers[i].print_fn;
773                                         break;
774                                 }
775                         }
776                 }
777         }
778
779         if (!saved || !saved->print_fn) {
780                 print_bpf_obj_info_addr(tcp, info);
781                 return;
782         }
783
784         const char *info_buf = fetch_bpf_obj_info(tcp, info, size);
785
786         if (info_buf)
787                 saved->print_fn(tcp, bpf_fd, info_buf, size, saved);
788         else
789                 print_bpf_obj_info_addr(tcp, info);
790 }
791
792 BEGIN_BPF_CMD_DECODER(BPF_OBJ_GET_INFO_BY_FD)
793 {
794         struct obj_get_info_saved *saved;
795
796         if (entering(tcp)) {
797                 saved = xzalloc(sizeof(*saved));
798                 saved->info_len = attr.info_len;
799                 set_tcb_priv_data(tcp, saved, free);
800
801                 PRINT_FIELD_FD("{info={", attr, bpf_fd, tcp);
802                 PRINT_FIELD_U(", ", attr, info_len);
803         } else {
804                 saved = get_tcb_priv_data(tcp);
805
806                 if (saved && (saved->info_len != attr.info_len))
807                         tprintf(" => %u", attr.info_len);
808
809                 tprintf(", info=");
810         }
811
812         print_bpf_obj_info(tcp, attr.bpf_fd, attr.info, attr.info_len, saved);
813
814         if (entering(tcp))
815                 return 0;
816
817         tprints("}");
818 }
819 END_BPF_CMD_DECODER(RVAL_DECODED)
820
821 BEGIN_BPF_CMD_DECODER(BPF_PROG_QUERY)
822 {
823         uint32_t prog_id_buf;
824
825         if (entering(tcp)) {
826                 PRINT_FIELD_FD("{query={", attr, target_fd, tcp);
827                 PRINT_FIELD_XVAL(", ", attr, attach_type, bpf_attach_type,
828                                  "BPF_???");
829                 PRINT_FIELD_FLAGS(", ", attr, query_flags, bpf_query_flags,
830                                   "BPF_F_QUERY_???");
831                 PRINT_FIELD_FLAGS(", ", attr, attach_flags, bpf_attach_flags,
832                                   "BPF_F_???");
833
834                 tprints(", prog_ids=");
835
836                 set_tcb_priv_ulong(tcp, attr.prog_cnt);
837
838                 return 0;
839         }
840
841         print_big_u64_addr(attr.prog_ids);
842         print_array(tcp, attr.prog_ids, attr.prog_cnt, &prog_id_buf,
843                     sizeof(prog_id_buf), tfetch_mem,
844                     print_uint32_array_member, 0);
845
846         tprints(", prog_cnt=");
847         const uint32_t prog_cnt_entering = get_tcb_priv_ulong(tcp);
848         if (prog_cnt_entering != attr.prog_cnt)
849                 tprintf("%" PRIu32 " => ", prog_cnt_entering);
850         tprintf("%" PRIu32, attr.prog_cnt);
851         tprints("}");
852 }
853 END_BPF_CMD_DECODER(RVAL_DECODED)
854
855 BEGIN_BPF_CMD_DECODER(BPF_RAW_TRACEPOINT_OPEN)
856 {
857         enum { TP_NAME_SIZE = 128 };
858
859         tprintf("{raw_tracepoint={name=");
860         print_big_u64_addr(attr.name);
861         printstr_ex(tcp, attr.name, TP_NAME_SIZE, QUOTE_0_TERMINATED);
862
863         PRINT_FIELD_FD(", ", attr, prog_fd, tcp);
864
865         tprints("}");
866 }
867 END_BPF_CMD_DECODER(RVAL_DECODED)
868
869 BEGIN_BPF_CMD_DECODER(BPF_BTF_LOAD)
870 {
871         tprints("{btf=");
872         print_big_u64_addr(attr.btf);
873         printstrn(tcp, attr.btf, attr.btf_size);
874         PRINT_FIELD_ADDR64(", ", attr, btf_log_buf);
875         PRINT_FIELD_U(", ", attr, btf_size);
876         PRINT_FIELD_U(", ", attr, btf_log_size);
877         PRINT_FIELD_U(", ", attr, btf_log_level);
878 }
879 END_BPF_CMD_DECODER(RVAL_DECODED | RVAL_FD)
880
881 BEGIN_BPF_CMD_DECODER(BPF_BTF_GET_FD_BY_ID)
882 {
883         PRINT_FIELD_U("{", attr, btf_id);
884 }
885 END_BPF_CMD_DECODER(RVAL_DECODED | RVAL_FD)
886
887 BEGIN_BPF_CMD_DECODER(BPF_TASK_FD_QUERY)
888 {
889         if (entering(tcp)) {
890                 set_tcb_priv_ulong(tcp, attr.buf_len);
891
892                 PRINT_FIELD_U("{task_fd_query={", attr, pid);
893                 PRINT_FIELD_FD(", ", attr, fd, tcp);
894                 PRINT_FIELD_U(", ", attr, flags);
895                 PRINT_FIELD_U(", ", attr, buf_len);
896
897                 return 0;
898         }
899
900         unsigned int saved_buf_len = get_tcb_priv_ulong(tcp);
901
902         if (saved_buf_len != attr.buf_len)
903                 tprintf(" => %u", attr.buf_len);
904
905         const unsigned int buf_len = MIN(saved_buf_len, attr.buf_len);
906         tprintf(", buf=");
907         print_big_u64_addr(attr.buf);
908         printstr_ex(tcp, attr.buf, buf_len, QUOTE_0_TERMINATED);
909         PRINT_FIELD_U(", ", attr, prog_id);
910         PRINT_FIELD_XVAL(", ", attr, fd_type, bpf_task_fd_type,
911                          "BPF_FD_TYPE_???");
912         PRINT_FIELD_X(", ", attr, probe_offset);
913         PRINT_FIELD_X(", ", attr, probe_addr);
914
915         tprints("}");
916 }
917 END_BPF_CMD_DECODER(RVAL_DECODED)
918
919 SYS_FUNC(bpf)
920 {
921         static const bpf_cmd_decoder_t bpf_cmd_decoders[] = {
922                 BPF_CMD_ENTRY(BPF_MAP_CREATE),
923                 BPF_CMD_ENTRY(BPF_MAP_LOOKUP_ELEM),
924                 BPF_CMD_ENTRY(BPF_MAP_UPDATE_ELEM),
925                 BPF_CMD_ENTRY(BPF_MAP_DELETE_ELEM),
926                 BPF_CMD_ENTRY(BPF_MAP_GET_NEXT_KEY),
927                 BPF_CMD_ENTRY(BPF_PROG_LOAD),
928                 BPF_CMD_ENTRY(BPF_OBJ_PIN),
929                 BPF_CMD_ENTRY(BPF_OBJ_GET),
930                 BPF_CMD_ENTRY(BPF_PROG_ATTACH),
931                 BPF_CMD_ENTRY(BPF_PROG_DETACH),
932                 BPF_CMD_ENTRY(BPF_PROG_TEST_RUN),
933                 BPF_CMD_ENTRY(BPF_PROG_GET_NEXT_ID),
934                 BPF_CMD_ENTRY(BPF_MAP_GET_NEXT_ID),
935                 BPF_CMD_ENTRY(BPF_PROG_GET_FD_BY_ID),
936                 BPF_CMD_ENTRY(BPF_MAP_GET_FD_BY_ID),
937                 BPF_CMD_ENTRY(BPF_OBJ_GET_INFO_BY_FD),
938                 BPF_CMD_ENTRY(BPF_PROG_QUERY),
939                 BPF_CMD_ENTRY(BPF_RAW_TRACEPOINT_OPEN),
940                 BPF_CMD_ENTRY(BPF_BTF_LOAD),
941                 BPF_CMD_ENTRY(BPF_BTF_GET_FD_BY_ID),
942                 BPF_CMD_ENTRY(BPF_TASK_FD_QUERY),
943                 BPF_CMD_ENTRY(BPF_MAP_LOOKUP_AND_DELETE_ELEM),
944                 BPF_CMD_ENTRY(BPF_MAP_FREEZE),
945         };
946
947         const unsigned int cmd = tcp->u_arg[0];
948         const kernel_ulong_t addr = tcp->u_arg[1];
949         const unsigned int size = tcp->u_arg[2];
950         int rc = RVAL_DECODED;
951
952         if (entering(tcp)) {
953                 printxval(bpf_commands, cmd, "BPF_???");
954                 tprints(", ");
955         }
956
957         if (size > 0
958             && size <= get_pagesize()
959             && cmd < ARRAY_SIZE(bpf_cmd_decoders)
960             && bpf_cmd_decoders[cmd]) {
961                 static char *buf;
962
963                 if (!buf)
964                         buf = xmalloc(get_pagesize());
965
966                 if (!umoven_or_printaddr_ignore_syserror(tcp, addr, size, buf))
967                         rc = bpf_cmd_decoders[cmd](tcp, addr, size, buf);
968         } else {
969                 printaddr(addr);
970         }
971
972         if (exiting(tcp) || (rc & RVAL_DECODED))
973                 tprintf(", %u", size);
974
975         return rc;
976 }