Home | History | Annotate | Download | only in strace
      1 /*
      2  * Copyright (c) 2015-2017 Dmitry V. Levin <ldv (at) altlinux.org>
      3  * Copyright (c) 2017 Quentin Monnet <quentin.monnet (at) 6wind.com>
      4  * Copyright (c) 2015-2018 The strace developers.
      5  * All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  * 3. The name of the author may not be used to endorse or promote products
     16  *    derived from this software without specific prior written permission.
     17  *
     18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     19  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     20  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     21  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     22  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     23  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     24  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     25  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     28  */
     29 
     30 #include "defs.h"
     31 #include "print_fields.h"
     32 
     33 #ifdef HAVE_LINUX_BPF_H
     34 # include <linux/bpf.h>
     35 #endif
     36 #include <linux/filter.h>
     37 
     38 #include "bpf_attr.h"
     39 
     40 #include "xlat/bpf_commands.h"
     41 #include "xlat/bpf_file_mode_flags.h"
     42 #include "xlat/bpf_map_types.h"
     43 #include "xlat/bpf_map_flags.h"
     44 #include "xlat/bpf_prog_types.h"
     45 #include "xlat/bpf_prog_flags.h"
     46 #include "xlat/bpf_map_update_elem_flags.h"
     47 #include "xlat/bpf_attach_type.h"
     48 #include "xlat/bpf_attach_flags.h"
     49 #include "xlat/bpf_query_flags.h"
     50 #include "xlat/ebpf_regs.h"
     51 #include "xlat/numa_node.h"
     52 
     53 #define DECL_BPF_CMD_DECODER(bpf_cmd_decoder)				\
     54 int									\
     55 bpf_cmd_decoder(struct tcb *const tcp,					\
     56 		const kernel_ulong_t addr,				\
     57 		const unsigned int size,				\
     58 		void *const data)					\
     59 /* End of DECL_BPF_CMD_DECODER definition. */
     60 
     61 #define BEGIN_BPF_CMD_DECODER(bpf_cmd)					\
     62 	static DECL_BPF_CMD_DECODER(decode_ ## bpf_cmd)			\
     63 	{								\
     64 		struct bpf_cmd ## _struct attr = {};			\
     65 		const size_t attr_size = bpf_cmd ## _struct_size;	\
     66 		const unsigned int len = MIN(size, attr_size);		\
     67 		memcpy(&attr, data, len);				\
     68 		do {							\
     69 /* End of BEGIN_BPF_CMD_DECODER definition. */
     70 
     71 #define END_BPF_CMD_DECODER(rval)					\
     72 			decode_attr_extra_data(tcp, data, size, attr_size); \
     73 		} while (0);						\
     74 		tprints("}");						\
     75 		return (rval);						\
     76 	}								\
     77 /* End of END_BPF_CMD_DECODER definition. */
     78 
     79 #define BPF_CMD_ENTRY(bpf_cmd)						\
     80 	[bpf_cmd] = decode_ ## bpf_cmd
     81 
     82 typedef DECL_BPF_CMD_DECODER((*bpf_cmd_decoder_t));
     83 
     84 /*
     85  * A note about bpf syscall decoder: it doesn't perform any size sanity checks,
     86  * so even if it leads to partial copying of one of the fields, the command
     87  * handler will still use the (partially-copied-from-userspace, partially
     88  * zeroed) field value.  That's why we stop decoding and check for known sizes
     89  * that correspond to released versions of the structure used by the specific
     90  * command - it looks like the most sensible way to parse this insanity.
     91  */
     92 
     93 static int
     94 decode_attr_extra_data(struct tcb *const tcp,
     95 		       const char *data,
     96 		       unsigned int size,
     97 		       const size_t attr_size)
     98 {
     99 	if (size <= attr_size)
    100 		return 0;
    101 
    102 	data += attr_size;
    103 	size -= attr_size;
    104 
    105 	unsigned int i;
    106 	for (i = 0; i < size; ++i) {
    107 		if (data[i]) {
    108 			tprints(", ");
    109 			if (abbrev(tcp)) {
    110 				tprints("...");
    111 			} else {
    112 				tprintf("/* bytes %zu..%zu */ ",
    113 					attr_size, attr_size + size - 1);
    114 				print_quoted_string(data, size,
    115 						    QUOTE_FORCE_HEX);
    116 			}
    117 			return RVAL_DECODED;
    118 		}
    119 	}
    120 
    121 	return 0;
    122 }
    123 
    124 struct ebpf_insn {
    125 	uint8_t code;
    126 	uint8_t dst_reg:4;
    127 	uint8_t src_reg:4;
    128 	int16_t off;
    129 	int32_t imm;
    130 };
    131 
    132 struct ebpf_insns_data {
    133 	unsigned int count;
    134 };
    135 
    136 static bool
    137 print_ebpf_insn(struct tcb * const tcp, void * const elem_buf,
    138 		const size_t elem_size, void * const data)
    139 {
    140 	struct ebpf_insns_data *eid = data;
    141 	struct ebpf_insn *insn = elem_buf;
    142 
    143 	if (eid->count++ >= BPF_MAXINSNS) {
    144 		tprints("...");
    145 		return false;
    146 	}
    147 
    148 	tprints("{code=");
    149 	print_bpf_filter_code(insn->code, true);
    150 
    151 	/* We can't use PRINT_FIELD_XVAL on bit fields */
    152 	tprints(", dst_reg=");
    153 	printxval_index(ebpf_regs, insn->dst_reg, "BPF_REG_???");
    154 	tprints(", src_reg=");
    155 	printxval_index(ebpf_regs, insn->src_reg, "BPF_REG_???");
    156 
    157 	PRINT_FIELD_D(", ", *insn, off);
    158 	PRINT_FIELD_X(", ", *insn, imm);
    159 	tprints("}");
    160 
    161 	return true;
    162 }
    163 
    164 static void
    165 print_ebpf_prog(struct tcb *const tcp, const uint64_t addr, const uint32_t len)
    166 {
    167 	print_big_u64_addr(addr);
    168 	if (abbrev(tcp)) {
    169 		printaddr(addr);
    170 	} else {
    171 		struct ebpf_insns_data eid = {};
    172 		struct ebpf_insn insn;
    173 
    174 		print_array(tcp, addr, len, &insn, sizeof(insn),
    175 			    tfetch_mem, print_ebpf_insn, &eid);
    176 	}
    177 }
    178 
    179 BEGIN_BPF_CMD_DECODER(BPF_MAP_CREATE)
    180 {
    181 	PRINT_FIELD_XVAL_INDEX("{", attr, map_type, bpf_map_types,
    182 			       "BPF_MAP_TYPE_???");
    183 	PRINT_FIELD_U(", ", attr, key_size);
    184 	PRINT_FIELD_U(", ", attr, value_size);
    185 	PRINT_FIELD_U(", ", attr, max_entries);
    186 
    187 	/* map_flags field was added in Linux commit v4.6-rc1~91^2~108^2~6. */
    188 	if (len <= offsetof(struct BPF_MAP_CREATE_struct, map_flags))
    189 		break;
    190 	PRINT_FIELD_FLAGS(", ", attr, map_flags, bpf_map_flags, "BPF_F_???");
    191 
    192 	/*
    193 	 * inner_map_fd field was added in Linux commit
    194 	 * v4.12-rc1~64^3~373^2~2.
    195 	 */
    196 	if (len <= offsetof(struct BPF_MAP_CREATE_struct, inner_map_fd))
    197 		break;
    198 	PRINT_FIELD_FD(", ", attr, inner_map_fd, tcp);
    199 
    200 	/* numa_node field was added in Linux commit v4.14-rc1~130^2~196^2~1. */
    201 	if (len <= offsetof(struct BPF_MAP_CREATE_struct, numa_node))
    202 		break;
    203 	if (attr.map_flags & BPF_F_NUMA_NODE) {
    204 		/*
    205 		 * Kernel uses the value of -1 as a designation for "no NUMA
    206 		 * node specified", and even uses NUMA_NO_NODE constant;
    207 		 * however, the constant definition is not a part of UAPI
    208 		 * headers, thus we can't simply print this named constant
    209 		 * instead of the value. Let's force verbose xlat style instead
    210 		 * in order to provide the information for the user while
    211 		 * not hampering the availability to derive the actual value
    212 		 * without the access to the kernel headers.
    213 		 */
    214 		tprints(", numa_node=");
    215 		printxvals_ex(attr.numa_node, NULL,
    216 			      XLAT_STYLE_FMT_U | XLAT_STYLE_VERBOSE,
    217 			      numa_node, NULL);
    218 	}
    219 
    220 	/* map_name field was added in Linux commit v4.15-rc1~84^2~605^2~3. */
    221 	if (len <= offsetof(struct BPF_MAP_CREATE_struct, map_name))
    222 		break;
    223 	PRINT_FIELD_CSTRING_SZ(", ", attr, map_name,
    224 			       MIN(sizeof(attr.map_name),
    225 				   len - offsetof(struct BPF_MAP_CREATE_struct,
    226 						  map_name)));
    227 
    228 	/*
    229 	 * map_ifindex field was added in Linux commit
    230 	 * v4.16-rc1~123^2~145^2~5^2~8.
    231 	 */
    232 	if (len <= offsetof(struct BPF_MAP_CREATE_struct, map_ifindex))
    233 		break;
    234 	PRINT_FIELD_IFINDEX(", ", attr, map_ifindex);
    235 }
    236 END_BPF_CMD_DECODER(RVAL_DECODED | RVAL_FD)
    237 
    238 BEGIN_BPF_CMD_DECODER(BPF_MAP_LOOKUP_ELEM)
    239 {
    240 	PRINT_FIELD_FD("{", attr, map_fd, tcp);
    241 	PRINT_FIELD_ADDR64(", ", attr, key);
    242 	PRINT_FIELD_ADDR64(", ", attr, value);
    243 }
    244 END_BPF_CMD_DECODER(RVAL_DECODED)
    245 
    246 BEGIN_BPF_CMD_DECODER(BPF_MAP_UPDATE_ELEM)
    247 {
    248 	PRINT_FIELD_FD("{", attr, map_fd, tcp);
    249 	PRINT_FIELD_ADDR64(", ", attr, key);
    250 	PRINT_FIELD_ADDR64(", ", attr, value);
    251 	PRINT_FIELD_XVAL_INDEX(", ", attr, flags, bpf_map_update_elem_flags,
    252 			       "BPF_???");
    253 }
    254 END_BPF_CMD_DECODER(RVAL_DECODED)
    255 
    256 BEGIN_BPF_CMD_DECODER(BPF_MAP_DELETE_ELEM)
    257 {
    258 	PRINT_FIELD_FD("{", attr, map_fd, tcp);
    259 	PRINT_FIELD_ADDR64(", ", attr, key);
    260 }
    261 END_BPF_CMD_DECODER(RVAL_DECODED)
    262 
    263 BEGIN_BPF_CMD_DECODER(BPF_MAP_GET_NEXT_KEY)
    264 {
    265 	PRINT_FIELD_FD("{", attr, map_fd, tcp);
    266 	PRINT_FIELD_ADDR64(", ", attr, key);
    267 	PRINT_FIELD_ADDR64(", ", attr, next_key);
    268 }
    269 END_BPF_CMD_DECODER(RVAL_DECODED)
    270 
    271 BEGIN_BPF_CMD_DECODER(BPF_PROG_LOAD)
    272 {
    273 	PRINT_FIELD_XVAL_INDEX("{", attr, prog_type, bpf_prog_types,
    274 			       "BPF_PROG_TYPE_???");
    275 	PRINT_FIELD_U(", ", attr, insn_cnt);
    276 	tprints(", insns=");
    277 	print_ebpf_prog(tcp, attr.insns, attr.insn_cnt);
    278 
    279 	tprintf(", license=");
    280 	print_big_u64_addr(attr.license);
    281 	printstr(tcp, attr.license);
    282 
    283 	/* log_* fields were added in Linux commit v3.18-rc1~52^2~1^2~4.  */
    284 	if (len <= offsetof(struct BPF_PROG_LOAD_struct, log_level))
    285 		break;
    286 	PRINT_FIELD_U(", ", attr, log_level);
    287 	PRINT_FIELD_U(", ", attr, log_size);
    288 	tprintf(", log_buf=");
    289 	print_big_u64_addr(attr.log_buf);
    290 	printstr_ex(tcp, attr.log_buf, attr.log_size, QUOTE_0_TERMINATED);
    291 
    292 	/* kern_version field was added in Linux commit v4.1-rc1~84^2~50.  */
    293 	if (len <= offsetof(struct BPF_PROG_LOAD_struct, kern_version))
    294 		break;
    295 	tprintf(", kern_version=KERNEL_VERSION(%u, %u, %u)",
    296 		attr.kern_version >> 16,
    297 		(attr.kern_version >> 8) & 0xFF,
    298 		attr.kern_version & 0xFF);
    299 
    300 	/* prog_flags field was added in Linux commit v4.12-rc2~34^2~29^2~2.  */
    301 	if (len <= offsetof(struct BPF_PROG_LOAD_struct, prog_flags))
    302 		break;
    303 	PRINT_FIELD_FLAGS(", ", attr, prog_flags, bpf_prog_flags, "BPF_F_???");
    304 
    305 	/* prog_name field was added in Linux commit v4.15-rc1~84^2~605^2~4. */
    306 	if (len <= offsetof(struct BPF_PROG_LOAD_struct, prog_name))
    307 		break;
    308 	PRINT_FIELD_CSTRING_SZ(", ", attr, prog_name,
    309 			       MIN(sizeof(attr.prog_name),
    310 				   len - offsetof(struct BPF_PROG_LOAD_struct,
    311 						   prog_name)));
    312 
    313 	/*
    314 	 * prog_ifindex field was added as prog_target_ifindex in Linux commit
    315 	 * v4.15-rc1~84^2~127^2~13 and renamed to its current name in
    316 	 * v4.15-rc1~15^2~5^2~3^2~7.
    317 	 */
    318 	if (len <= offsetof(struct BPF_PROG_LOAD_struct, prog_ifindex))
    319 		break;
    320 	PRINT_FIELD_IFINDEX(", ", attr, prog_ifindex);
    321 
    322 	/*
    323 	 * expected_attach_type was added in Linux commit
    324 	 * v4.17-rc1~148^2~19^2^2~8.
    325 	 */
    326 	if (len <= offsetof(struct BPF_PROG_LOAD_struct, expected_attach_type))
    327 		break;
    328 	PRINT_FIELD_XVAL(", ", attr, expected_attach_type, bpf_attach_type,
    329 			 "BPF_???");
    330 }
    331 END_BPF_CMD_DECODER(RVAL_DECODED | RVAL_FD)
    332 
    333 BEGIN_BPF_CMD_DECODER(BPF_OBJ_PIN)
    334 {
    335 	tprintf("{pathname=");
    336 	print_big_u64_addr(attr.pathname);
    337 	printpath(tcp, attr.pathname);
    338 
    339 	PRINT_FIELD_FD(", ", attr, bpf_fd, tcp);
    340 
    341 	/* file_flags field was added in Linux v4.15-rc1~84^2~384^2~4 */
    342 	if (len <= offsetof(struct BPF_OBJ_PIN_struct, file_flags))
    343 		break;
    344 	PRINT_FIELD_FLAGS(", ", attr, file_flags, bpf_file_mode_flags,
    345 			  "BPF_F_???");
    346 }
    347 END_BPF_CMD_DECODER(RVAL_DECODED | RVAL_FD)
    348 
    349 #define decode_BPF_OBJ_GET decode_BPF_OBJ_PIN
    350 
    351 BEGIN_BPF_CMD_DECODER(BPF_PROG_ATTACH)
    352 {
    353 	PRINT_FIELD_FD("{", attr, target_fd, tcp);
    354 	PRINT_FIELD_FD(", ", attr, attach_bpf_fd, tcp);
    355 	PRINT_FIELD_XVAL_INDEX(", ", attr, attach_type, bpf_attach_type,
    356 			       "BPF_???");
    357 	PRINT_FIELD_FLAGS(", ", attr, attach_flags, bpf_attach_flags,
    358 			  "BPF_F_???");
    359 }
    360 END_BPF_CMD_DECODER(RVAL_DECODED)
    361 
    362 BEGIN_BPF_CMD_DECODER(BPF_PROG_DETACH)
    363 {
    364 	PRINT_FIELD_FD("{", attr, target_fd, tcp);
    365 	PRINT_FIELD_XVAL_INDEX(", ", attr, attach_type, bpf_attach_type,
    366 			       "BPF_???");
    367 }
    368 END_BPF_CMD_DECODER(RVAL_DECODED)
    369 
    370 BEGIN_BPF_CMD_DECODER(BPF_PROG_TEST_RUN)
    371 {
    372 	PRINT_FIELD_FD("{test={", attr, prog_fd, tcp);
    373 	PRINT_FIELD_U(", ", attr, retval);
    374 	PRINT_FIELD_U(", ", attr, data_size_in);
    375 	PRINT_FIELD_U(", ", attr, data_size_out);
    376 	PRINT_FIELD_ADDR64(", ", attr, data_in);
    377 	PRINT_FIELD_ADDR64(", ", attr, data_out);
    378 	PRINT_FIELD_U(", ", attr, repeat);
    379 	PRINT_FIELD_U(", ", attr, duration);
    380 	tprints("}");
    381 }
    382 END_BPF_CMD_DECODER(RVAL_DECODED)
    383 
    384 BEGIN_BPF_CMD_DECODER(BPF_PROG_GET_NEXT_ID)
    385 {
    386 	PRINT_FIELD_U("{", attr, start_id);
    387 	PRINT_FIELD_U(", ", attr, next_id);
    388 
    389 	/* open_flags field has been added in Linux v4.15-rc1~84^2~384^2~4 */
    390 	if (len <= offsetof(struct BPF_PROG_GET_NEXT_ID_struct, open_flags))
    391 		break;
    392 	PRINT_FIELD_FLAGS(", ", attr, open_flags, bpf_file_mode_flags,
    393 			  "BPF_F_???");
    394 }
    395 END_BPF_CMD_DECODER(RVAL_DECODED)
    396 
    397 #define decode_BPF_MAP_GET_NEXT_ID decode_BPF_PROG_GET_NEXT_ID
    398 
    399 BEGIN_BPF_CMD_DECODER(BPF_PROG_GET_FD_BY_ID)
    400 {
    401 	PRINT_FIELD_U("{", attr, prog_id);
    402 	PRINT_FIELD_U(", ", attr, next_id);
    403 
    404 	/* open_flags field has been added in Linux v4.15-rc1~84^2~384^2~4 */
    405 	if (len <= offsetof(struct BPF_PROG_GET_FD_BY_ID_struct, open_flags))
    406 		break;
    407 	PRINT_FIELD_FLAGS(", ", attr, open_flags, bpf_file_mode_flags,
    408 			  "BPF_F_???");
    409 }
    410 END_BPF_CMD_DECODER(RVAL_DECODED)
    411 
    412 BEGIN_BPF_CMD_DECODER(BPF_MAP_GET_FD_BY_ID)
    413 {
    414 	PRINT_FIELD_U("{", attr, map_id);
    415 	PRINT_FIELD_U(", ", attr, next_id);
    416 
    417 	/* open_flags field has been added in Linux v4.15-rc1~84^2~384^2~4 */
    418 	if (len <= offsetof(struct BPF_MAP_GET_FD_BY_ID_struct, open_flags))
    419 		break;
    420 	PRINT_FIELD_FLAGS(", ", attr, open_flags, bpf_file_mode_flags,
    421 			  "BPF_F_???");
    422 }
    423 END_BPF_CMD_DECODER(RVAL_DECODED)
    424 
    425 struct obj_get_info_saved;
    426 typedef void (*print_bpf_obj_info_fn)(struct tcb *,
    427 				      uint32_t bpf_fd,
    428 				      const char *info_buf,
    429 				      uint32_t size,
    430 				      struct obj_get_info_saved *saved);
    431 
    432 struct obj_get_info_saved {
    433 	print_bpf_obj_info_fn print_fn;
    434 
    435 	uint32_t info_len;
    436 
    437 	uint32_t jited_prog_len;
    438 	uint32_t xlated_prog_len;
    439 	uint32_t nr_map_ids;
    440 };
    441 
    442 static void
    443 print_bpf_map_info(struct tcb * const tcp, uint32_t bpf_fd,
    444 		   const char *info_buf, uint32_t size,
    445 		   struct obj_get_info_saved *saved)
    446 {
    447 	if (entering(tcp))
    448 		return;
    449 
    450 	struct bpf_map_info_struct info = { 0 };
    451 	const unsigned int len = MIN(size, bpf_map_info_struct_size);
    452 
    453 	memcpy(&info, info_buf, len);
    454 
    455 	PRINT_FIELD_XVAL("{", info, type, bpf_map_types, "BPF_MAP_TYPE_???");
    456 	PRINT_FIELD_U(", ", info, id);
    457 	PRINT_FIELD_U(", ", info, key_size);
    458 	PRINT_FIELD_U(", ", info, value_size);
    459 	PRINT_FIELD_U(", ", info, max_entries);
    460 	PRINT_FIELD_FLAGS(", ", info, map_flags, bpf_map_flags, "BPF_F_???");
    461 
    462 	/*
    463 	 * "name" field was introduced by Linux commit v4.15-rc1~84^2~605^2~3.
    464 	 */
    465 	if (len <= offsetof(struct bpf_map_info_struct, name))
    466 		goto print_bpf_map_info_end;
    467 	PRINT_FIELD_CSTRING(", ", info, name);
    468 
    469 	/*
    470 	 * ifindex, netns_dev, and netns_ino fields were introduced
    471 	 * by Linux commit v4.16-rc1~123^2~109^2~5^2~4.
    472 	 */
    473 	if (len <= offsetof(struct bpf_map_info_struct, ifindex))
    474 		goto print_bpf_map_info_end;
    475 	PRINT_FIELD_IFINDEX(", ", info, ifindex);
    476 	PRINT_FIELD_DEV(", ", info, netns_dev);
    477 	PRINT_FIELD_U(", ", info, netns_ino);
    478 
    479 	decode_attr_extra_data(tcp, info_buf, size, bpf_map_info_struct_size);
    480 
    481 print_bpf_map_info_end:
    482 	tprints("}");
    483 }
    484 
    485 static void
    486 print_bpf_prog_info(struct tcb * const tcp, uint32_t bpf_fd,
    487 		    const char *info_buf, uint32_t size,
    488 		    struct obj_get_info_saved *saved)
    489 {
    490 	struct bpf_prog_info_struct info = { 0 };
    491 	const unsigned int len = MIN(size, bpf_prog_info_struct_size);
    492 	uint64_t map_id_buf;
    493 
    494 	memcpy(&info, info_buf, len);
    495 
    496 	if (entering(tcp)) {
    497 		saved->jited_prog_len = info.jited_prog_len;
    498 		saved->xlated_prog_len = info.xlated_prog_len;
    499 		saved->nr_map_ids = info.nr_map_ids;
    500 
    501 		return;
    502 	}
    503 
    504 	PRINT_FIELD_XVAL("{", info, type, bpf_prog_types, "BPF_PROG_TYPE_???");
    505 	PRINT_FIELD_U(", ", info, id);
    506 	PRINT_FIELD_HEX_ARRAY(", ", info, tag);
    507 
    508 	tprints(", jited_prog_len=");
    509 	if (saved->jited_prog_len != info.jited_prog_len)
    510 		tprintf("%" PRIu32 " => ", saved->jited_prog_len);
    511 	tprintf("%" PRIu32, info.jited_prog_len);
    512 
    513 	tprints(", jited_prog_insns=");
    514 	print_big_u64_addr(info.jited_prog_insns);
    515 	printstr_ex(tcp, info.jited_prog_insns, info.jited_prog_len,
    516 		    QUOTE_FORCE_HEX);
    517 
    518 	tprints(", xlated_prog_len=");
    519 	if (saved->xlated_prog_len != info.xlated_prog_len)
    520 		tprintf("%" PRIu32 " => ", saved->xlated_prog_len);
    521 	tprintf("%" PRIu32, info.xlated_prog_len);
    522 
    523 	tprints(", xlated_prog_insns=");
    524 	print_ebpf_prog(tcp, info.xlated_prog_insns,
    525 			MIN(saved->xlated_prog_len, info.xlated_prog_len) / 8);
    526 
    527 	/*
    528 	 * load_time, created_by_uid, nr_map_ids, map_ids, and name fields
    529 	 * were introduced by Linux commit v4.15-rc1~84^2~605^2~4.
    530 	 */
    531 	if (len <= offsetof(struct bpf_prog_info_struct, load_time))
    532 		goto print_bpf_prog_info_end;
    533 	PRINT_FIELD_U(", ", info, load_time);
    534 	PRINT_FIELD_UID(", ", info, created_by_uid);
    535 
    536 	tprints(", nr_map_ids=");
    537 	if (saved->nr_map_ids != info.nr_map_ids)
    538 		tprintf("%" PRIu32 " => ", saved->nr_map_ids);
    539 	tprintf("%" PRIu32, info.nr_map_ids);
    540 
    541 	tprints(", map_ids=");
    542 	print_big_u64_addr(info.map_ids);
    543 	print_array(tcp, info.map_ids, MIN(saved->nr_map_ids, info.nr_map_ids),
    544 		    &map_id_buf, sizeof(map_id_buf),
    545 		    tfetch_mem, print_uint32_array_member, 0);
    546 
    547 	PRINT_FIELD_CSTRING(", ", info, name);
    548 
    549 	/*
    550 	 * ifindex, netns_dev, and netns_ino fields were introduced
    551 	 * by Linux commit v4.16-rc1~123^2~227^2~5^2~2.
    552 	 */
    553 	if (len <= offsetof(struct bpf_prog_info_struct, ifindex))
    554 		goto print_bpf_prog_info_end;
    555 	PRINT_FIELD_IFINDEX(", ", info, ifindex);
    556 	PRINT_FIELD_DEV(", ", info, netns_dev);
    557 	PRINT_FIELD_U(", ", info, netns_ino);
    558 
    559 	decode_attr_extra_data(tcp, info_buf, size, bpf_prog_info_struct_size);
    560 
    561 print_bpf_prog_info_end:
    562 	tprints("}");
    563 }
    564 
    565 static const char *
    566 fetch_bpf_obj_info(struct tcb * const tcp, uint64_t info, uint32_t size)
    567 {
    568 	static char *info_buf;
    569 
    570 	if (!info_buf)
    571 		info_buf = xmalloc(get_pagesize());
    572 
    573 	memset(info_buf, 0, get_pagesize());
    574 
    575 	if (size > 0 && size <= get_pagesize()
    576 	    && !umoven(tcp, info, size, info_buf))
    577 		return info_buf;
    578 
    579 	return NULL;
    580 }
    581 
    582 static void
    583 print_bpf_obj_info_addr(struct tcb * const tcp, uint64_t addr)
    584 {
    585 	if (exiting(tcp))
    586 		printaddr64(addr);
    587 }
    588 
    589 static void
    590 print_bpf_obj_info(struct tcb * const tcp, uint32_t bpf_fd, uint64_t info,
    591 		   uint32_t size, struct obj_get_info_saved *saved)
    592 {
    593 	if (abbrev(tcp)) {
    594 		print_bpf_obj_info_addr(tcp, info);
    595 		return;
    596 	}
    597 
    598 	static struct {
    599 		const char *id;
    600 		print_bpf_obj_info_fn print_fn;
    601 	} obj_printers[] = {
    602 		{ "anon_inode:bpf-map", print_bpf_map_info },
    603 		{ "anon_inode:bpf-prog", print_bpf_prog_info }
    604 	};
    605 
    606 	if (entering(tcp)) {
    607 		char path[PATH_MAX + 1];
    608 
    609 		if (getfdpath(tcp, bpf_fd, path, sizeof(path)) > 0) {
    610 			for (size_t i = 0; i < ARRAY_SIZE(obj_printers); ++i) {
    611 				if (!strcmp(path, obj_printers[i].id)) {
    612 					saved->print_fn =
    613 						obj_printers[i].print_fn;
    614 					break;
    615 				}
    616 			}
    617 		}
    618 	}
    619 
    620 	if (!saved || !saved->print_fn) {
    621 		print_bpf_obj_info_addr(tcp, info);
    622 		return;
    623 	}
    624 
    625 	const char *info_buf = fetch_bpf_obj_info(tcp, info, size);
    626 
    627 	if (info_buf)
    628 		saved->print_fn(tcp, bpf_fd, info_buf, size, saved);
    629 	else
    630 		print_bpf_obj_info_addr(tcp, info);
    631 }
    632 
    633 BEGIN_BPF_CMD_DECODER(BPF_OBJ_GET_INFO_BY_FD)
    634 {
    635 	struct obj_get_info_saved *saved;
    636 
    637 	if (entering(tcp)) {
    638 		saved = xcalloc(1, sizeof(*saved));
    639 		saved->info_len = attr.info_len;
    640 		set_tcb_priv_data(tcp, saved, free);
    641 
    642 		PRINT_FIELD_FD("{info={", attr, bpf_fd, tcp);
    643 		PRINT_FIELD_U(", ", attr, info_len);
    644 	} else {
    645 		saved = get_tcb_priv_data(tcp);
    646 
    647 		if (saved && (saved->info_len != attr.info_len))
    648 			tprintf(" => %u", attr.info_len);
    649 
    650 		tprintf(", info=");
    651 	}
    652 
    653 	print_bpf_obj_info(tcp, attr.bpf_fd, attr.info, attr.info_len, saved);
    654 
    655 	if (entering(tcp))
    656 		return 0;
    657 
    658 	tprints("}");
    659 }
    660 END_BPF_CMD_DECODER(RVAL_DECODED)
    661 
    662 BEGIN_BPF_CMD_DECODER(BPF_PROG_QUERY)
    663 {
    664 	uint32_t prog_id_buf;
    665 
    666 	if (entering(tcp)) {
    667 		PRINT_FIELD_FD("{query={", attr, target_fd, tcp);
    668 		PRINT_FIELD_XVAL_INDEX(", ", attr, attach_type, bpf_attach_type,
    669 				       "BPF_???");
    670 		PRINT_FIELD_FLAGS(", ", attr, query_flags, bpf_query_flags,
    671 				  "BPF_F_QUERY_???");
    672 		PRINT_FIELD_FLAGS(", ", attr, attach_flags, bpf_attach_flags,
    673 				  "BPF_F_???");
    674 
    675 		tprints(", prog_ids=");
    676 
    677 		set_tcb_priv_ulong(tcp, attr.prog_cnt);
    678 
    679 		return 0;
    680 	}
    681 
    682 	print_big_u64_addr(attr.prog_ids);
    683 	print_array(tcp, attr.prog_ids, attr.prog_cnt, &prog_id_buf,
    684 		    sizeof(prog_id_buf), tfetch_mem,
    685 		    print_uint32_array_member, 0);
    686 
    687 	tprints(", prog_cnt=");
    688 	const uint32_t prog_cnt_entering = get_tcb_priv_ulong(tcp);
    689 	if (prog_cnt_entering != attr.prog_cnt)
    690 		tprintf("%" PRIu32 " => ", prog_cnt_entering);
    691 	tprintf("%" PRIu32, attr.prog_cnt);
    692 	tprints("}");
    693 }
    694 END_BPF_CMD_DECODER(RVAL_DECODED)
    695 
    696 BEGIN_BPF_CMD_DECODER(BPF_RAW_TRACEPOINT_OPEN)
    697 {
    698 	enum { TP_NAME_SIZE = 128 };
    699 
    700 	tprintf("{raw_tracepoint={name=");
    701 	print_big_u64_addr(attr.name);
    702 	printstr_ex(tcp, attr.name, TP_NAME_SIZE, QUOTE_0_TERMINATED);
    703 
    704 	PRINT_FIELD_FD(", ", attr, prog_fd, tcp);
    705 
    706 	tprints("}");
    707 }
    708 END_BPF_CMD_DECODER(RVAL_DECODED)
    709 
    710 SYS_FUNC(bpf)
    711 {
    712 	static const bpf_cmd_decoder_t bpf_cmd_decoders[] = {
    713 		BPF_CMD_ENTRY(BPF_MAP_CREATE),
    714 		BPF_CMD_ENTRY(BPF_MAP_LOOKUP_ELEM),
    715 		BPF_CMD_ENTRY(BPF_MAP_UPDATE_ELEM),
    716 		BPF_CMD_ENTRY(BPF_MAP_DELETE_ELEM),
    717 		BPF_CMD_ENTRY(BPF_MAP_GET_NEXT_KEY),
    718 		BPF_CMD_ENTRY(BPF_PROG_LOAD),
    719 		BPF_CMD_ENTRY(BPF_OBJ_PIN),
    720 		BPF_CMD_ENTRY(BPF_OBJ_GET),
    721 		BPF_CMD_ENTRY(BPF_PROG_ATTACH),
    722 		BPF_CMD_ENTRY(BPF_PROG_DETACH),
    723 		BPF_CMD_ENTRY(BPF_PROG_TEST_RUN),
    724 		BPF_CMD_ENTRY(BPF_PROG_GET_NEXT_ID),
    725 		BPF_CMD_ENTRY(BPF_MAP_GET_NEXT_ID),
    726 		BPF_CMD_ENTRY(BPF_PROG_GET_FD_BY_ID),
    727 		BPF_CMD_ENTRY(BPF_MAP_GET_FD_BY_ID),
    728 		BPF_CMD_ENTRY(BPF_OBJ_GET_INFO_BY_FD),
    729 		BPF_CMD_ENTRY(BPF_PROG_QUERY),
    730 		BPF_CMD_ENTRY(BPF_RAW_TRACEPOINT_OPEN),
    731 	};
    732 
    733 	const unsigned int cmd = tcp->u_arg[0];
    734 	const kernel_ulong_t addr = tcp->u_arg[1];
    735 	const unsigned int size = tcp->u_arg[2];
    736 	int rc = RVAL_DECODED;
    737 
    738 	if (entering(tcp)) {
    739 		printxval_index(bpf_commands, cmd, "BPF_???");
    740 		tprints(", ");
    741 	}
    742 
    743 	if (size > 0
    744 	    && size <= get_pagesize()
    745 	    && cmd < ARRAY_SIZE(bpf_cmd_decoders)
    746 	    && bpf_cmd_decoders[cmd]) {
    747 		static char *buf;
    748 
    749 		if (!buf)
    750 			buf = xmalloc(get_pagesize());
    751 
    752 		if (!umoven_or_printaddr_ignore_syserror(tcp, addr, size, buf))
    753 			rc = bpf_cmd_decoders[cmd](tcp, addr, size, buf);
    754 	} else {
    755 		printaddr(addr);
    756 	}
    757 
    758 	if (exiting(tcp) || (rc & RVAL_DECODED))
    759 		tprintf(", %u", size);
    760 
    761 	return rc;
    762 }
    763