cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

prog.c (56782B)


      1// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
      2/* Copyright (C) 2017-2018 Netronome Systems, Inc. */
      3
      4#define _GNU_SOURCE
      5#include <errno.h>
      6#include <fcntl.h>
      7#include <signal.h>
      8#include <stdarg.h>
      9#include <stdio.h>
     10#include <stdlib.h>
     11#include <string.h>
     12#include <time.h>
     13#include <unistd.h>
     14#include <net/if.h>
     15#include <sys/ioctl.h>
     16#include <sys/types.h>
     17#include <sys/stat.h>
     18#include <sys/syscall.h>
     19#include <dirent.h>
     20
     21#include <linux/err.h>
     22#include <linux/perf_event.h>
     23#include <linux/sizes.h>
     24
     25#include <bpf/bpf.h>
     26#include <bpf/btf.h>
     27#include <bpf/hashmap.h>
     28#include <bpf/libbpf.h>
     29#include <bpf/libbpf_internal.h>
     30#include <bpf/skel_internal.h>
     31
     32#include "cfg.h"
     33#include "main.h"
     34#include "xlated_dumper.h"
     35
     36#define BPF_METADATA_PREFIX "bpf_metadata_"
     37#define BPF_METADATA_PREFIX_LEN (sizeof(BPF_METADATA_PREFIX) - 1)
     38
     39const char * const prog_type_name[] = {
     40	[BPF_PROG_TYPE_UNSPEC]			= "unspec",
     41	[BPF_PROG_TYPE_SOCKET_FILTER]		= "socket_filter",
     42	[BPF_PROG_TYPE_KPROBE]			= "kprobe",
     43	[BPF_PROG_TYPE_SCHED_CLS]		= "sched_cls",
     44	[BPF_PROG_TYPE_SCHED_ACT]		= "sched_act",
     45	[BPF_PROG_TYPE_TRACEPOINT]		= "tracepoint",
     46	[BPF_PROG_TYPE_XDP]			= "xdp",
     47	[BPF_PROG_TYPE_PERF_EVENT]		= "perf_event",
     48	[BPF_PROG_TYPE_CGROUP_SKB]		= "cgroup_skb",
     49	[BPF_PROG_TYPE_CGROUP_SOCK]		= "cgroup_sock",
     50	[BPF_PROG_TYPE_LWT_IN]			= "lwt_in",
     51	[BPF_PROG_TYPE_LWT_OUT]			= "lwt_out",
     52	[BPF_PROG_TYPE_LWT_XMIT]		= "lwt_xmit",
     53	[BPF_PROG_TYPE_SOCK_OPS]		= "sock_ops",
     54	[BPF_PROG_TYPE_SK_SKB]			= "sk_skb",
     55	[BPF_PROG_TYPE_CGROUP_DEVICE]		= "cgroup_device",
     56	[BPF_PROG_TYPE_SK_MSG]			= "sk_msg",
     57	[BPF_PROG_TYPE_RAW_TRACEPOINT]		= "raw_tracepoint",
     58	[BPF_PROG_TYPE_CGROUP_SOCK_ADDR]	= "cgroup_sock_addr",
     59	[BPF_PROG_TYPE_LWT_SEG6LOCAL]		= "lwt_seg6local",
     60	[BPF_PROG_TYPE_LIRC_MODE2]		= "lirc_mode2",
     61	[BPF_PROG_TYPE_SK_REUSEPORT]		= "sk_reuseport",
     62	[BPF_PROG_TYPE_FLOW_DISSECTOR]		= "flow_dissector",
     63	[BPF_PROG_TYPE_CGROUP_SYSCTL]		= "cgroup_sysctl",
     64	[BPF_PROG_TYPE_RAW_TRACEPOINT_WRITABLE]	= "raw_tracepoint_writable",
     65	[BPF_PROG_TYPE_CGROUP_SOCKOPT]		= "cgroup_sockopt",
     66	[BPF_PROG_TYPE_TRACING]			= "tracing",
     67	[BPF_PROG_TYPE_STRUCT_OPS]		= "struct_ops",
     68	[BPF_PROG_TYPE_EXT]			= "ext",
     69	[BPF_PROG_TYPE_LSM]			= "lsm",
     70	[BPF_PROG_TYPE_SK_LOOKUP]		= "sk_lookup",
     71	[BPF_PROG_TYPE_SYSCALL]			= "syscall",
     72};
     73
     74const size_t prog_type_name_size = ARRAY_SIZE(prog_type_name);
     75
     76enum dump_mode {
     77	DUMP_JITED,
     78	DUMP_XLATED,
     79};
     80
     81static const char * const attach_type_strings[] = {
     82	[BPF_SK_SKB_STREAM_PARSER] = "stream_parser",
     83	[BPF_SK_SKB_STREAM_VERDICT] = "stream_verdict",
     84	[BPF_SK_SKB_VERDICT] = "skb_verdict",
     85	[BPF_SK_MSG_VERDICT] = "msg_verdict",
     86	[BPF_FLOW_DISSECTOR] = "flow_dissector",
     87	[__MAX_BPF_ATTACH_TYPE] = NULL,
     88};
     89
     90static struct hashmap *prog_table;
     91
     92static enum bpf_attach_type parse_attach_type(const char *str)
     93{
     94	enum bpf_attach_type type;
     95
     96	for (type = 0; type < __MAX_BPF_ATTACH_TYPE; type++) {
     97		if (attach_type_strings[type] &&
     98		    is_prefix(str, attach_type_strings[type]))
     99			return type;
    100	}
    101
    102	return __MAX_BPF_ATTACH_TYPE;
    103}
    104
    105static int prep_prog_info(struct bpf_prog_info *const info, enum dump_mode mode,
    106			  void **info_data, size_t *const info_data_sz)
    107{
    108	struct bpf_prog_info holder = {};
    109	size_t needed = 0;
    110	void *ptr;
    111
    112	if (mode == DUMP_JITED) {
    113		holder.jited_prog_len = info->jited_prog_len;
    114		needed += info->jited_prog_len;
    115	} else {
    116		holder.xlated_prog_len = info->xlated_prog_len;
    117		needed += info->xlated_prog_len;
    118	}
    119
    120	holder.nr_jited_ksyms = info->nr_jited_ksyms;
    121	needed += info->nr_jited_ksyms * sizeof(__u64);
    122
    123	holder.nr_jited_func_lens = info->nr_jited_func_lens;
    124	needed += info->nr_jited_func_lens * sizeof(__u32);
    125
    126	holder.nr_func_info = info->nr_func_info;
    127	holder.func_info_rec_size = info->func_info_rec_size;
    128	needed += info->nr_func_info * info->func_info_rec_size;
    129
    130	holder.nr_line_info = info->nr_line_info;
    131	holder.line_info_rec_size = info->line_info_rec_size;
    132	needed += info->nr_line_info * info->line_info_rec_size;
    133
    134	holder.nr_jited_line_info = info->nr_jited_line_info;
    135	holder.jited_line_info_rec_size = info->jited_line_info_rec_size;
    136	needed += info->nr_jited_line_info * info->jited_line_info_rec_size;
    137
    138	if (needed > *info_data_sz) {
    139		ptr = realloc(*info_data, needed);
    140		if (!ptr)
    141			return -1;
    142
    143		*info_data = ptr;
    144		*info_data_sz = needed;
    145	}
    146	ptr = *info_data;
    147
    148	if (mode == DUMP_JITED) {
    149		holder.jited_prog_insns = ptr_to_u64(ptr);
    150		ptr += holder.jited_prog_len;
    151	} else {
    152		holder.xlated_prog_insns = ptr_to_u64(ptr);
    153		ptr += holder.xlated_prog_len;
    154	}
    155
    156	holder.jited_ksyms = ptr_to_u64(ptr);
    157	ptr += holder.nr_jited_ksyms * sizeof(__u64);
    158
    159	holder.jited_func_lens = ptr_to_u64(ptr);
    160	ptr += holder.nr_jited_func_lens * sizeof(__u32);
    161
    162	holder.func_info = ptr_to_u64(ptr);
    163	ptr += holder.nr_func_info * holder.func_info_rec_size;
    164
    165	holder.line_info = ptr_to_u64(ptr);
    166	ptr += holder.nr_line_info * holder.line_info_rec_size;
    167
    168	holder.jited_line_info = ptr_to_u64(ptr);
    169	ptr += holder.nr_jited_line_info * holder.jited_line_info_rec_size;
    170
    171	*info = holder;
    172	return 0;
    173}
    174
    175static void print_boot_time(__u64 nsecs, char *buf, unsigned int size)
    176{
    177	struct timespec real_time_ts, boot_time_ts;
    178	time_t wallclock_secs;
    179	struct tm load_tm;
    180
    181	buf[--size] = '\0';
    182
    183	if (clock_gettime(CLOCK_REALTIME, &real_time_ts) ||
    184	    clock_gettime(CLOCK_BOOTTIME, &boot_time_ts)) {
    185		perror("Can't read clocks");
    186		snprintf(buf, size, "%llu", nsecs / 1000000000);
    187		return;
    188	}
    189
    190	wallclock_secs = (real_time_ts.tv_sec - boot_time_ts.tv_sec) +
    191		(real_time_ts.tv_nsec - boot_time_ts.tv_nsec + nsecs) /
    192		1000000000;
    193
    194
    195	if (!localtime_r(&wallclock_secs, &load_tm)) {
    196		snprintf(buf, size, "%llu", nsecs / 1000000000);
    197		return;
    198	}
    199
    200	if (json_output)
    201		strftime(buf, size, "%s", &load_tm);
    202	else
    203		strftime(buf, size, "%FT%T%z", &load_tm);
    204}
    205
    206static void show_prog_maps(int fd, __u32 num_maps)
    207{
    208	struct bpf_prog_info info = {};
    209	__u32 len = sizeof(info);
    210	__u32 map_ids[num_maps];
    211	unsigned int i;
    212	int err;
    213
    214	info.nr_map_ids = num_maps;
    215	info.map_ids = ptr_to_u64(map_ids);
    216
    217	err = bpf_obj_get_info_by_fd(fd, &info, &len);
    218	if (err || !info.nr_map_ids)
    219		return;
    220
    221	if (json_output) {
    222		jsonw_name(json_wtr, "map_ids");
    223		jsonw_start_array(json_wtr);
    224		for (i = 0; i < info.nr_map_ids; i++)
    225			jsonw_uint(json_wtr, map_ids[i]);
    226		jsonw_end_array(json_wtr);
    227	} else {
    228		printf("  map_ids ");
    229		for (i = 0; i < info.nr_map_ids; i++)
    230			printf("%u%s", map_ids[i],
    231			       i == info.nr_map_ids - 1 ? "" : ",");
    232	}
    233}
    234
    235static void *find_metadata(int prog_fd, struct bpf_map_info *map_info)
    236{
    237	struct bpf_prog_info prog_info;
    238	__u32 prog_info_len;
    239	__u32 map_info_len;
    240	void *value = NULL;
    241	__u32 *map_ids;
    242	int nr_maps;
    243	int key = 0;
    244	int map_fd;
    245	int ret;
    246	__u32 i;
    247
    248	memset(&prog_info, 0, sizeof(prog_info));
    249	prog_info_len = sizeof(prog_info);
    250	ret = bpf_obj_get_info_by_fd(prog_fd, &prog_info, &prog_info_len);
    251	if (ret)
    252		return NULL;
    253
    254	if (!prog_info.nr_map_ids)
    255		return NULL;
    256
    257	map_ids = calloc(prog_info.nr_map_ids, sizeof(__u32));
    258	if (!map_ids)
    259		return NULL;
    260
    261	nr_maps = prog_info.nr_map_ids;
    262	memset(&prog_info, 0, sizeof(prog_info));
    263	prog_info.nr_map_ids = nr_maps;
    264	prog_info.map_ids = ptr_to_u64(map_ids);
    265	prog_info_len = sizeof(prog_info);
    266
    267	ret = bpf_obj_get_info_by_fd(prog_fd, &prog_info, &prog_info_len);
    268	if (ret)
    269		goto free_map_ids;
    270
    271	for (i = 0; i < prog_info.nr_map_ids; i++) {
    272		map_fd = bpf_map_get_fd_by_id(map_ids[i]);
    273		if (map_fd < 0)
    274			goto free_map_ids;
    275
    276		memset(map_info, 0, sizeof(*map_info));
    277		map_info_len = sizeof(*map_info);
    278		ret = bpf_obj_get_info_by_fd(map_fd, map_info, &map_info_len);
    279		if (ret < 0) {
    280			close(map_fd);
    281			goto free_map_ids;
    282		}
    283
    284		if (map_info->type != BPF_MAP_TYPE_ARRAY ||
    285		    map_info->key_size != sizeof(int) ||
    286		    map_info->max_entries != 1 ||
    287		    !map_info->btf_value_type_id ||
    288		    !strstr(map_info->name, ".rodata")) {
    289			close(map_fd);
    290			continue;
    291		}
    292
    293		value = malloc(map_info->value_size);
    294		if (!value) {
    295			close(map_fd);
    296			goto free_map_ids;
    297		}
    298
    299		if (bpf_map_lookup_elem(map_fd, &key, value)) {
    300			close(map_fd);
    301			free(value);
    302			value = NULL;
    303			goto free_map_ids;
    304		}
    305
    306		close(map_fd);
    307		break;
    308	}
    309
    310free_map_ids:
    311	free(map_ids);
    312	return value;
    313}
    314
    315static bool has_metadata_prefix(const char *s)
    316{
    317	return strncmp(s, BPF_METADATA_PREFIX, BPF_METADATA_PREFIX_LEN) == 0;
    318}
    319
    320static void show_prog_metadata(int fd, __u32 num_maps)
    321{
    322	const struct btf_type *t_datasec, *t_var;
    323	struct bpf_map_info map_info;
    324	struct btf_var_secinfo *vsi;
    325	bool printed_header = false;
    326	unsigned int i, vlen;
    327	void *value = NULL;
    328	const char *name;
    329	struct btf *btf;
    330	int err;
    331
    332	if (!num_maps)
    333		return;
    334
    335	memset(&map_info, 0, sizeof(map_info));
    336	value = find_metadata(fd, &map_info);
    337	if (!value)
    338		return;
    339
    340	btf = btf__load_from_kernel_by_id(map_info.btf_id);
    341	if (libbpf_get_error(btf))
    342		goto out_free;
    343
    344	t_datasec = btf__type_by_id(btf, map_info.btf_value_type_id);
    345	if (!btf_is_datasec(t_datasec))
    346		goto out_free;
    347
    348	vlen = btf_vlen(t_datasec);
    349	vsi = btf_var_secinfos(t_datasec);
    350
    351	/* We don't proceed to check the kinds of the elements of the DATASEC.
    352	 * The verifier enforces them to be BTF_KIND_VAR.
    353	 */
    354
    355	if (json_output) {
    356		struct btf_dumper d = {
    357			.btf = btf,
    358			.jw = json_wtr,
    359			.is_plain_text = false,
    360		};
    361
    362		for (i = 0; i < vlen; i++, vsi++) {
    363			t_var = btf__type_by_id(btf, vsi->type);
    364			name = btf__name_by_offset(btf, t_var->name_off);
    365
    366			if (!has_metadata_prefix(name))
    367				continue;
    368
    369			if (!printed_header) {
    370				jsonw_name(json_wtr, "metadata");
    371				jsonw_start_object(json_wtr);
    372				printed_header = true;
    373			}
    374
    375			jsonw_name(json_wtr, name + BPF_METADATA_PREFIX_LEN);
    376			err = btf_dumper_type(&d, t_var->type, value + vsi->offset);
    377			if (err) {
    378				p_err("btf dump failed: %d", err);
    379				break;
    380			}
    381		}
    382		if (printed_header)
    383			jsonw_end_object(json_wtr);
    384	} else {
    385		json_writer_t *btf_wtr;
    386		struct btf_dumper d = {
    387			.btf = btf,
    388			.is_plain_text = true,
    389		};
    390
    391		for (i = 0; i < vlen; i++, vsi++) {
    392			t_var = btf__type_by_id(btf, vsi->type);
    393			name = btf__name_by_offset(btf, t_var->name_off);
    394
    395			if (!has_metadata_prefix(name))
    396				continue;
    397
    398			if (!printed_header) {
    399				printf("\tmetadata:");
    400
    401				btf_wtr = jsonw_new(stdout);
    402				if (!btf_wtr) {
    403					p_err("jsonw alloc failed");
    404					goto out_free;
    405				}
    406				d.jw = btf_wtr,
    407
    408				printed_header = true;
    409			}
    410
    411			printf("\n\t\t%s = ", name + BPF_METADATA_PREFIX_LEN);
    412
    413			jsonw_reset(btf_wtr);
    414			err = btf_dumper_type(&d, t_var->type, value + vsi->offset);
    415			if (err) {
    416				p_err("btf dump failed: %d", err);
    417				break;
    418			}
    419		}
    420		if (printed_header)
    421			jsonw_destroy(&btf_wtr);
    422	}
    423
    424out_free:
    425	btf__free(btf);
    426	free(value);
    427}
    428
    429static void print_prog_header_json(struct bpf_prog_info *info, int fd)
    430{
    431	char prog_name[MAX_PROG_FULL_NAME];
    432
    433	jsonw_uint_field(json_wtr, "id", info->id);
    434	if (info->type < ARRAY_SIZE(prog_type_name))
    435		jsonw_string_field(json_wtr, "type",
    436				   prog_type_name[info->type]);
    437	else
    438		jsonw_uint_field(json_wtr, "type", info->type);
    439
    440	if (*info->name) {
    441		get_prog_full_name(info, fd, prog_name, sizeof(prog_name));
    442		jsonw_string_field(json_wtr, "name", prog_name);
    443	}
    444
    445	jsonw_name(json_wtr, "tag");
    446	jsonw_printf(json_wtr, "\"" BPF_TAG_FMT "\"",
    447		     info->tag[0], info->tag[1], info->tag[2], info->tag[3],
    448		     info->tag[4], info->tag[5], info->tag[6], info->tag[7]);
    449
    450	jsonw_bool_field(json_wtr, "gpl_compatible", info->gpl_compatible);
    451	if (info->run_time_ns) {
    452		jsonw_uint_field(json_wtr, "run_time_ns", info->run_time_ns);
    453		jsonw_uint_field(json_wtr, "run_cnt", info->run_cnt);
    454	}
    455	if (info->recursion_misses)
    456		jsonw_uint_field(json_wtr, "recursion_misses", info->recursion_misses);
    457}
    458
    459static void print_prog_json(struct bpf_prog_info *info, int fd)
    460{
    461	char *memlock;
    462
    463	jsonw_start_object(json_wtr);
    464	print_prog_header_json(info, fd);
    465	print_dev_json(info->ifindex, info->netns_dev, info->netns_ino);
    466
    467	if (info->load_time) {
    468		char buf[32];
    469
    470		print_boot_time(info->load_time, buf, sizeof(buf));
    471
    472		/* Piggy back on load_time, since 0 uid is a valid one */
    473		jsonw_name(json_wtr, "loaded_at");
    474		jsonw_printf(json_wtr, "%s", buf);
    475		jsonw_uint_field(json_wtr, "uid", info->created_by_uid);
    476	}
    477
    478	jsonw_uint_field(json_wtr, "bytes_xlated", info->xlated_prog_len);
    479
    480	if (info->jited_prog_len) {
    481		jsonw_bool_field(json_wtr, "jited", true);
    482		jsonw_uint_field(json_wtr, "bytes_jited", info->jited_prog_len);
    483	} else {
    484		jsonw_bool_field(json_wtr, "jited", false);
    485	}
    486
    487	memlock = get_fdinfo(fd, "memlock");
    488	if (memlock)
    489		jsonw_int_field(json_wtr, "bytes_memlock", atoll(memlock));
    490	free(memlock);
    491
    492	if (info->nr_map_ids)
    493		show_prog_maps(fd, info->nr_map_ids);
    494
    495	if (info->btf_id)
    496		jsonw_int_field(json_wtr, "btf_id", info->btf_id);
    497
    498	if (!hashmap__empty(prog_table)) {
    499		struct hashmap_entry *entry;
    500
    501		jsonw_name(json_wtr, "pinned");
    502		jsonw_start_array(json_wtr);
    503		hashmap__for_each_key_entry(prog_table, entry,
    504					    u32_as_hash_field(info->id))
    505			jsonw_string(json_wtr, entry->value);
    506		jsonw_end_array(json_wtr);
    507	}
    508
    509	emit_obj_refs_json(refs_table, info->id, json_wtr);
    510
    511	show_prog_metadata(fd, info->nr_map_ids);
    512
    513	jsonw_end_object(json_wtr);
    514}
    515
    516static void print_prog_header_plain(struct bpf_prog_info *info, int fd)
    517{
    518	char prog_name[MAX_PROG_FULL_NAME];
    519
    520	printf("%u: ", info->id);
    521	if (info->type < ARRAY_SIZE(prog_type_name))
    522		printf("%s  ", prog_type_name[info->type]);
    523	else
    524		printf("type %u  ", info->type);
    525
    526	if (*info->name) {
    527		get_prog_full_name(info, fd, prog_name, sizeof(prog_name));
    528		printf("name %s  ", prog_name);
    529	}
    530
    531	printf("tag ");
    532	fprint_hex(stdout, info->tag, BPF_TAG_SIZE, "");
    533	print_dev_plain(info->ifindex, info->netns_dev, info->netns_ino);
    534	printf("%s", info->gpl_compatible ? "  gpl" : "");
    535	if (info->run_time_ns)
    536		printf(" run_time_ns %lld run_cnt %lld",
    537		       info->run_time_ns, info->run_cnt);
    538	if (info->recursion_misses)
    539		printf(" recursion_misses %lld", info->recursion_misses);
    540	printf("\n");
    541}
    542
    543static void print_prog_plain(struct bpf_prog_info *info, int fd)
    544{
    545	char *memlock;
    546
    547	print_prog_header_plain(info, fd);
    548
    549	if (info->load_time) {
    550		char buf[32];
    551
    552		print_boot_time(info->load_time, buf, sizeof(buf));
    553
    554		/* Piggy back on load_time, since 0 uid is a valid one */
    555		printf("\tloaded_at %s  uid %u\n", buf, info->created_by_uid);
    556	}
    557
    558	printf("\txlated %uB", info->xlated_prog_len);
    559
    560	if (info->jited_prog_len)
    561		printf("  jited %uB", info->jited_prog_len);
    562	else
    563		printf("  not jited");
    564
    565	memlock = get_fdinfo(fd, "memlock");
    566	if (memlock)
    567		printf("  memlock %sB", memlock);
    568	free(memlock);
    569
    570	if (info->nr_map_ids)
    571		show_prog_maps(fd, info->nr_map_ids);
    572
    573	if (!hashmap__empty(prog_table)) {
    574		struct hashmap_entry *entry;
    575
    576		hashmap__for_each_key_entry(prog_table, entry,
    577					    u32_as_hash_field(info->id))
    578			printf("\n\tpinned %s", (char *)entry->value);
    579	}
    580
    581	if (info->btf_id)
    582		printf("\n\tbtf_id %d", info->btf_id);
    583
    584	emit_obj_refs_plain(refs_table, info->id, "\n\tpids ");
    585
    586	printf("\n");
    587
    588	show_prog_metadata(fd, info->nr_map_ids);
    589}
    590
    591static int show_prog(int fd)
    592{
    593	struct bpf_prog_info info = {};
    594	__u32 len = sizeof(info);
    595	int err;
    596
    597	err = bpf_obj_get_info_by_fd(fd, &info, &len);
    598	if (err) {
    599		p_err("can't get prog info: %s", strerror(errno));
    600		return -1;
    601	}
    602
    603	if (json_output)
    604		print_prog_json(&info, fd);
    605	else
    606		print_prog_plain(&info, fd);
    607
    608	return 0;
    609}
    610
    611static int do_show_subset(int argc, char **argv)
    612{
    613	int *fds = NULL;
    614	int nb_fds, i;
    615	int err = -1;
    616
    617	fds = malloc(sizeof(int));
    618	if (!fds) {
    619		p_err("mem alloc failed");
    620		return -1;
    621	}
    622	nb_fds = prog_parse_fds(&argc, &argv, &fds);
    623	if (nb_fds < 1)
    624		goto exit_free;
    625
    626	if (json_output && nb_fds > 1)
    627		jsonw_start_array(json_wtr);	/* root array */
    628	for (i = 0; i < nb_fds; i++) {
    629		err = show_prog(fds[i]);
    630		if (err) {
    631			for (; i < nb_fds; i++)
    632				close(fds[i]);
    633			break;
    634		}
    635		close(fds[i]);
    636	}
    637	if (json_output && nb_fds > 1)
    638		jsonw_end_array(json_wtr);	/* root array */
    639
    640exit_free:
    641	free(fds);
    642	return err;
    643}
    644
    645static int do_show(int argc, char **argv)
    646{
    647	__u32 id = 0;
    648	int err;
    649	int fd;
    650
    651	if (show_pinned) {
    652		prog_table = hashmap__new(hash_fn_for_key_as_id,
    653					  equal_fn_for_key_as_id, NULL);
    654		if (IS_ERR(prog_table)) {
    655			p_err("failed to create hashmap for pinned paths");
    656			return -1;
    657		}
    658		build_pinned_obj_table(prog_table, BPF_OBJ_PROG);
    659	}
    660	build_obj_refs_table(&refs_table, BPF_OBJ_PROG);
    661
    662	if (argc == 2)
    663		return do_show_subset(argc, argv);
    664
    665	if (argc)
    666		return BAD_ARG();
    667
    668	if (json_output)
    669		jsonw_start_array(json_wtr);
    670	while (true) {
    671		err = bpf_prog_get_next_id(id, &id);
    672		if (err) {
    673			if (errno == ENOENT) {
    674				err = 0;
    675				break;
    676			}
    677			p_err("can't get next program: %s%s", strerror(errno),
    678			      errno == EINVAL ? " -- kernel too old?" : "");
    679			err = -1;
    680			break;
    681		}
    682
    683		fd = bpf_prog_get_fd_by_id(id);
    684		if (fd < 0) {
    685			if (errno == ENOENT)
    686				continue;
    687			p_err("can't get prog by id (%u): %s",
    688			      id, strerror(errno));
    689			err = -1;
    690			break;
    691		}
    692
    693		err = show_prog(fd);
    694		close(fd);
    695		if (err)
    696			break;
    697	}
    698
    699	if (json_output)
    700		jsonw_end_array(json_wtr);
    701
    702	delete_obj_refs_table(refs_table);
    703
    704	if (show_pinned)
    705		delete_pinned_obj_table(prog_table);
    706
    707	return err;
    708}
    709
    710static int
    711prog_dump(struct bpf_prog_info *info, enum dump_mode mode,
    712	  char *filepath, bool opcodes, bool visual, bool linum)
    713{
    714	struct bpf_prog_linfo *prog_linfo = NULL;
    715	const char *disasm_opt = NULL;
    716	struct dump_data dd = {};
    717	void *func_info = NULL;
    718	struct btf *btf = NULL;
    719	char func_sig[1024];
    720	unsigned char *buf;
    721	__u32 member_len;
    722	int fd, err = -1;
    723	ssize_t n;
    724
    725	if (mode == DUMP_JITED) {
    726		if (info->jited_prog_len == 0 || !info->jited_prog_insns) {
    727			p_info("no instructions returned");
    728			return -1;
    729		}
    730		buf = u64_to_ptr(info->jited_prog_insns);
    731		member_len = info->jited_prog_len;
    732	} else {	/* DUMP_XLATED */
    733		if (info->xlated_prog_len == 0 || !info->xlated_prog_insns) {
    734			p_err("error retrieving insn dump: kernel.kptr_restrict set?");
    735			return -1;
    736		}
    737		buf = u64_to_ptr(info->xlated_prog_insns);
    738		member_len = info->xlated_prog_len;
    739	}
    740
    741	if (info->btf_id) {
    742		btf = btf__load_from_kernel_by_id(info->btf_id);
    743		if (libbpf_get_error(btf)) {
    744			p_err("failed to get btf");
    745			return -1;
    746		}
    747	}
    748
    749	func_info = u64_to_ptr(info->func_info);
    750
    751	if (info->nr_line_info) {
    752		prog_linfo = bpf_prog_linfo__new(info);
    753		if (!prog_linfo)
    754			p_info("error in processing bpf_line_info.  continue without it.");
    755	}
    756
    757	if (filepath) {
    758		fd = open(filepath, O_WRONLY | O_CREAT | O_TRUNC, 0600);
    759		if (fd < 0) {
    760			p_err("can't open file %s: %s", filepath,
    761			      strerror(errno));
    762			goto exit_free;
    763		}
    764
    765		n = write(fd, buf, member_len);
    766		close(fd);
    767		if (n != (ssize_t)member_len) {
    768			p_err("error writing output file: %s",
    769			      n < 0 ? strerror(errno) : "short write");
    770			goto exit_free;
    771		}
    772
    773		if (json_output)
    774			jsonw_null(json_wtr);
    775	} else if (mode == DUMP_JITED) {
    776		const char *name = NULL;
    777
    778		if (info->ifindex) {
    779			name = ifindex_to_bfd_params(info->ifindex,
    780						     info->netns_dev,
    781						     info->netns_ino,
    782						     &disasm_opt);
    783			if (!name)
    784				goto exit_free;
    785		}
    786
    787		if (info->nr_jited_func_lens && info->jited_func_lens) {
    788			struct kernel_sym *sym = NULL;
    789			struct bpf_func_info *record;
    790			char sym_name[SYM_MAX_NAME];
    791			unsigned char *img = buf;
    792			__u64 *ksyms = NULL;
    793			__u32 *lens;
    794			__u32 i;
    795			if (info->nr_jited_ksyms) {
    796				kernel_syms_load(&dd);
    797				ksyms = u64_to_ptr(info->jited_ksyms);
    798			}
    799
    800			if (json_output)
    801				jsonw_start_array(json_wtr);
    802
    803			lens = u64_to_ptr(info->jited_func_lens);
    804			for (i = 0; i < info->nr_jited_func_lens; i++) {
    805				if (ksyms) {
    806					sym = kernel_syms_search(&dd, ksyms[i]);
    807					if (sym)
    808						sprintf(sym_name, "%s", sym->name);
    809					else
    810						sprintf(sym_name, "0x%016llx", ksyms[i]);
    811				} else {
    812					strcpy(sym_name, "unknown");
    813				}
    814
    815				if (func_info) {
    816					record = func_info + i * info->func_info_rec_size;
    817					btf_dumper_type_only(btf, record->type_id,
    818							     func_sig,
    819							     sizeof(func_sig));
    820				}
    821
    822				if (json_output) {
    823					jsonw_start_object(json_wtr);
    824					if (func_info && func_sig[0] != '\0') {
    825						jsonw_name(json_wtr, "proto");
    826						jsonw_string(json_wtr, func_sig);
    827					}
    828					jsonw_name(json_wtr, "name");
    829					jsonw_string(json_wtr, sym_name);
    830					jsonw_name(json_wtr, "insns");
    831				} else {
    832					if (func_info && func_sig[0] != '\0')
    833						printf("%s:\n", func_sig);
    834					printf("%s:\n", sym_name);
    835				}
    836
    837				disasm_print_insn(img, lens[i], opcodes,
    838						  name, disasm_opt, btf,
    839						  prog_linfo, ksyms[i], i,
    840						  linum);
    841
    842				img += lens[i];
    843
    844				if (json_output)
    845					jsonw_end_object(json_wtr);
    846				else
    847					printf("\n");
    848			}
    849
    850			if (json_output)
    851				jsonw_end_array(json_wtr);
    852		} else {
    853			disasm_print_insn(buf, member_len, opcodes, name,
    854					  disasm_opt, btf, NULL, 0, 0, false);
    855		}
    856	} else if (visual) {
    857		if (json_output)
    858			jsonw_null(json_wtr);
    859		else
    860			dump_xlated_cfg(buf, member_len);
    861	} else {
    862		kernel_syms_load(&dd);
    863		dd.nr_jited_ksyms = info->nr_jited_ksyms;
    864		dd.jited_ksyms = u64_to_ptr(info->jited_ksyms);
    865		dd.btf = btf;
    866		dd.func_info = func_info;
    867		dd.finfo_rec_size = info->func_info_rec_size;
    868		dd.prog_linfo = prog_linfo;
    869
    870		if (json_output)
    871			dump_xlated_json(&dd, buf, member_len, opcodes,
    872					 linum);
    873		else
    874			dump_xlated_plain(&dd, buf, member_len, opcodes,
    875					  linum);
    876		kernel_syms_destroy(&dd);
    877	}
    878
    879	err = 0;
    880
    881exit_free:
    882	btf__free(btf);
    883	bpf_prog_linfo__free(prog_linfo);
    884	return err;
    885}
    886
    887static int do_dump(int argc, char **argv)
    888{
    889	struct bpf_prog_info info;
    890	__u32 info_len = sizeof(info);
    891	size_t info_data_sz = 0;
    892	void *info_data = NULL;
    893	char *filepath = NULL;
    894	bool opcodes = false;
    895	bool visual = false;
    896	enum dump_mode mode;
    897	bool linum = false;
    898	int nb_fds, i = 0;
    899	int *fds = NULL;
    900	int err = -1;
    901
    902	if (is_prefix(*argv, "jited")) {
    903		if (disasm_init())
    904			return -1;
    905		mode = DUMP_JITED;
    906	} else if (is_prefix(*argv, "xlated")) {
    907		mode = DUMP_XLATED;
    908	} else {
    909		p_err("expected 'xlated' or 'jited', got: %s", *argv);
    910		return -1;
    911	}
    912	NEXT_ARG();
    913
    914	if (argc < 2)
    915		usage();
    916
    917	fds = malloc(sizeof(int));
    918	if (!fds) {
    919		p_err("mem alloc failed");
    920		return -1;
    921	}
    922	nb_fds = prog_parse_fds(&argc, &argv, &fds);
    923	if (nb_fds < 1)
    924		goto exit_free;
    925
    926	if (is_prefix(*argv, "file")) {
    927		NEXT_ARG();
    928		if (!argc) {
    929			p_err("expected file path");
    930			goto exit_close;
    931		}
    932		if (nb_fds > 1) {
    933			p_err("several programs matched");
    934			goto exit_close;
    935		}
    936
    937		filepath = *argv;
    938		NEXT_ARG();
    939	} else if (is_prefix(*argv, "opcodes")) {
    940		opcodes = true;
    941		NEXT_ARG();
    942	} else if (is_prefix(*argv, "visual")) {
    943		if (nb_fds > 1) {
    944			p_err("several programs matched");
    945			goto exit_close;
    946		}
    947
    948		visual = true;
    949		NEXT_ARG();
    950	} else if (is_prefix(*argv, "linum")) {
    951		linum = true;
    952		NEXT_ARG();
    953	}
    954
    955	if (argc) {
    956		usage();
    957		goto exit_close;
    958	}
    959
    960	if (json_output && nb_fds > 1)
    961		jsonw_start_array(json_wtr);	/* root array */
    962	for (i = 0; i < nb_fds; i++) {
    963		memset(&info, 0, sizeof(info));
    964
    965		err = bpf_obj_get_info_by_fd(fds[i], &info, &info_len);
    966		if (err) {
    967			p_err("can't get prog info: %s", strerror(errno));
    968			break;
    969		}
    970
    971		err = prep_prog_info(&info, mode, &info_data, &info_data_sz);
    972		if (err) {
    973			p_err("can't grow prog info_data");
    974			break;
    975		}
    976
    977		err = bpf_obj_get_info_by_fd(fds[i], &info, &info_len);
    978		if (err) {
    979			p_err("can't get prog info: %s", strerror(errno));
    980			break;
    981		}
    982
    983		if (json_output && nb_fds > 1) {
    984			jsonw_start_object(json_wtr);	/* prog object */
    985			print_prog_header_json(&info, fds[i]);
    986			jsonw_name(json_wtr, "insns");
    987		} else if (nb_fds > 1) {
    988			print_prog_header_plain(&info, fds[i]);
    989		}
    990
    991		err = prog_dump(&info, mode, filepath, opcodes, visual, linum);
    992
    993		if (json_output && nb_fds > 1)
    994			jsonw_end_object(json_wtr);	/* prog object */
    995		else if (i != nb_fds - 1 && nb_fds > 1)
    996			printf("\n");
    997
    998		if (err)
    999			break;
   1000		close(fds[i]);
   1001	}
   1002	if (json_output && nb_fds > 1)
   1003		jsonw_end_array(json_wtr);	/* root array */
   1004
   1005exit_close:
   1006	for (; i < nb_fds; i++)
   1007		close(fds[i]);
   1008exit_free:
   1009	free(info_data);
   1010	free(fds);
   1011	return err;
   1012}
   1013
   1014static int do_pin(int argc, char **argv)
   1015{
   1016	int err;
   1017
   1018	err = do_pin_any(argc, argv, prog_parse_fd);
   1019	if (!err && json_output)
   1020		jsonw_null(json_wtr);
   1021	return err;
   1022}
   1023
   1024struct map_replace {
   1025	int idx;
   1026	int fd;
   1027	char *name;
   1028};
   1029
   1030static int map_replace_compar(const void *p1, const void *p2)
   1031{
   1032	const struct map_replace *a = p1, *b = p2;
   1033
   1034	return a->idx - b->idx;
   1035}
   1036
   1037static int parse_attach_detach_args(int argc, char **argv, int *progfd,
   1038				    enum bpf_attach_type *attach_type,
   1039				    int *mapfd)
   1040{
   1041	if (!REQ_ARGS(3))
   1042		return -EINVAL;
   1043
   1044	*progfd = prog_parse_fd(&argc, &argv);
   1045	if (*progfd < 0)
   1046		return *progfd;
   1047
   1048	*attach_type = parse_attach_type(*argv);
   1049	if (*attach_type == __MAX_BPF_ATTACH_TYPE) {
   1050		p_err("invalid attach/detach type");
   1051		return -EINVAL;
   1052	}
   1053
   1054	if (*attach_type == BPF_FLOW_DISSECTOR) {
   1055		*mapfd = 0;
   1056		return 0;
   1057	}
   1058
   1059	NEXT_ARG();
   1060	if (!REQ_ARGS(2))
   1061		return -EINVAL;
   1062
   1063	*mapfd = map_parse_fd(&argc, &argv);
   1064	if (*mapfd < 0)
   1065		return *mapfd;
   1066
   1067	return 0;
   1068}
   1069
   1070static int do_attach(int argc, char **argv)
   1071{
   1072	enum bpf_attach_type attach_type;
   1073	int err, progfd;
   1074	int mapfd;
   1075
   1076	err = parse_attach_detach_args(argc, argv,
   1077				       &progfd, &attach_type, &mapfd);
   1078	if (err)
   1079		return err;
   1080
   1081	err = bpf_prog_attach(progfd, mapfd, attach_type, 0);
   1082	if (err) {
   1083		p_err("failed prog attach to map");
   1084		return -EINVAL;
   1085	}
   1086
   1087	if (json_output)
   1088		jsonw_null(json_wtr);
   1089	return 0;
   1090}
   1091
   1092static int do_detach(int argc, char **argv)
   1093{
   1094	enum bpf_attach_type attach_type;
   1095	int err, progfd;
   1096	int mapfd;
   1097
   1098	err = parse_attach_detach_args(argc, argv,
   1099				       &progfd, &attach_type, &mapfd);
   1100	if (err)
   1101		return err;
   1102
   1103	err = bpf_prog_detach2(progfd, mapfd, attach_type);
   1104	if (err) {
   1105		p_err("failed prog detach from map");
   1106		return -EINVAL;
   1107	}
   1108
   1109	if (json_output)
   1110		jsonw_null(json_wtr);
   1111	return 0;
   1112}
   1113
   1114static int check_single_stdin(char *file_data_in, char *file_ctx_in)
   1115{
   1116	if (file_data_in && file_ctx_in &&
   1117	    !strcmp(file_data_in, "-") && !strcmp(file_ctx_in, "-")) {
   1118		p_err("cannot use standard input for both data_in and ctx_in");
   1119		return -1;
   1120	}
   1121
   1122	return 0;
   1123}
   1124
   1125static int get_run_data(const char *fname, void **data_ptr, unsigned int *size)
   1126{
   1127	size_t block_size = 256;
   1128	size_t buf_size = block_size;
   1129	size_t nb_read = 0;
   1130	void *tmp;
   1131	FILE *f;
   1132
   1133	if (!fname) {
   1134		*data_ptr = NULL;
   1135		*size = 0;
   1136		return 0;
   1137	}
   1138
   1139	if (!strcmp(fname, "-"))
   1140		f = stdin;
   1141	else
   1142		f = fopen(fname, "r");
   1143	if (!f) {
   1144		p_err("failed to open %s: %s", fname, strerror(errno));
   1145		return -1;
   1146	}
   1147
   1148	*data_ptr = malloc(block_size);
   1149	if (!*data_ptr) {
   1150		p_err("failed to allocate memory for data_in/ctx_in: %s",
   1151		      strerror(errno));
   1152		goto err_fclose;
   1153	}
   1154
   1155	while ((nb_read += fread(*data_ptr + nb_read, 1, block_size, f))) {
   1156		if (feof(f))
   1157			break;
   1158		if (ferror(f)) {
   1159			p_err("failed to read data_in/ctx_in from %s: %s",
   1160			      fname, strerror(errno));
   1161			goto err_free;
   1162		}
   1163		if (nb_read > buf_size - block_size) {
   1164			if (buf_size == UINT32_MAX) {
   1165				p_err("data_in/ctx_in is too long (max: %d)",
   1166				      UINT32_MAX);
   1167				goto err_free;
   1168			}
   1169			/* No space for fread()-ing next chunk; realloc() */
   1170			buf_size *= 2;
   1171			tmp = realloc(*data_ptr, buf_size);
   1172			if (!tmp) {
   1173				p_err("failed to reallocate data_in/ctx_in: %s",
   1174				      strerror(errno));
   1175				goto err_free;
   1176			}
   1177			*data_ptr = tmp;
   1178		}
   1179	}
   1180	if (f != stdin)
   1181		fclose(f);
   1182
   1183	*size = nb_read;
   1184	return 0;
   1185
   1186err_free:
   1187	free(*data_ptr);
   1188	*data_ptr = NULL;
   1189err_fclose:
   1190	if (f != stdin)
   1191		fclose(f);
   1192	return -1;
   1193}
   1194
   1195static void hex_print(void *data, unsigned int size, FILE *f)
   1196{
   1197	size_t i, j;
   1198	char c;
   1199
   1200	for (i = 0; i < size; i += 16) {
   1201		/* Row offset */
   1202		fprintf(f, "%07zx\t", i);
   1203
   1204		/* Hexadecimal values */
   1205		for (j = i; j < i + 16 && j < size; j++)
   1206			fprintf(f, "%02x%s", *(uint8_t *)(data + j),
   1207				j % 2 ? " " : "");
   1208		for (; j < i + 16; j++)
   1209			fprintf(f, "  %s", j % 2 ? " " : "");
   1210
   1211		/* ASCII values (if relevant), '.' otherwise */
   1212		fprintf(f, "| ");
   1213		for (j = i; j < i + 16 && j < size; j++) {
   1214			c = *(char *)(data + j);
   1215			if (c < ' ' || c > '~')
   1216				c = '.';
   1217			fprintf(f, "%c%s", c, j == i + 7 ? " " : "");
   1218		}
   1219
   1220		fprintf(f, "\n");
   1221	}
   1222}
   1223
   1224static int
   1225print_run_output(void *data, unsigned int size, const char *fname,
   1226		 const char *json_key)
   1227{
   1228	size_t nb_written;
   1229	FILE *f;
   1230
   1231	if (!fname)
   1232		return 0;
   1233
   1234	if (!strcmp(fname, "-")) {
   1235		f = stdout;
   1236		if (json_output) {
   1237			jsonw_name(json_wtr, json_key);
   1238			print_data_json(data, size);
   1239		} else {
   1240			hex_print(data, size, f);
   1241		}
   1242		return 0;
   1243	}
   1244
   1245	f = fopen(fname, "w");
   1246	if (!f) {
   1247		p_err("failed to open %s: %s", fname, strerror(errno));
   1248		return -1;
   1249	}
   1250
   1251	nb_written = fwrite(data, 1, size, f);
   1252	fclose(f);
   1253	if (nb_written != size) {
   1254		p_err("failed to write output data/ctx: %s", strerror(errno));
   1255		return -1;
   1256	}
   1257
   1258	return 0;
   1259}
   1260
   1261static int alloc_run_data(void **data_ptr, unsigned int size_out)
   1262{
   1263	*data_ptr = calloc(size_out, 1);
   1264	if (!*data_ptr) {
   1265		p_err("failed to allocate memory for output data/ctx: %s",
   1266		      strerror(errno));
   1267		return -1;
   1268	}
   1269
   1270	return 0;
   1271}
   1272
   1273static int do_run(int argc, char **argv)
   1274{
   1275	char *data_fname_in = NULL, *data_fname_out = NULL;
   1276	char *ctx_fname_in = NULL, *ctx_fname_out = NULL;
   1277	const unsigned int default_size = SZ_32K;
   1278	void *data_in = NULL, *data_out = NULL;
   1279	void *ctx_in = NULL, *ctx_out = NULL;
   1280	unsigned int repeat = 1;
   1281	int fd, err;
   1282	LIBBPF_OPTS(bpf_test_run_opts, test_attr);
   1283
   1284	if (!REQ_ARGS(4))
   1285		return -1;
   1286
   1287	fd = prog_parse_fd(&argc, &argv);
   1288	if (fd < 0)
   1289		return -1;
   1290
   1291	while (argc) {
   1292		if (detect_common_prefix(*argv, "data_in", "data_out",
   1293					 "data_size_out", NULL))
   1294			return -1;
   1295		if (detect_common_prefix(*argv, "ctx_in", "ctx_out",
   1296					 "ctx_size_out", NULL))
   1297			return -1;
   1298
   1299		if (is_prefix(*argv, "data_in")) {
   1300			NEXT_ARG();
   1301			if (!REQ_ARGS(1))
   1302				return -1;
   1303
   1304			data_fname_in = GET_ARG();
   1305			if (check_single_stdin(data_fname_in, ctx_fname_in))
   1306				return -1;
   1307		} else if (is_prefix(*argv, "data_out")) {
   1308			NEXT_ARG();
   1309			if (!REQ_ARGS(1))
   1310				return -1;
   1311
   1312			data_fname_out = GET_ARG();
   1313		} else if (is_prefix(*argv, "data_size_out")) {
   1314			char *endptr;
   1315
   1316			NEXT_ARG();
   1317			if (!REQ_ARGS(1))
   1318				return -1;
   1319
   1320			test_attr.data_size_out = strtoul(*argv, &endptr, 0);
   1321			if (*endptr) {
   1322				p_err("can't parse %s as output data size",
   1323				      *argv);
   1324				return -1;
   1325			}
   1326			NEXT_ARG();
   1327		} else if (is_prefix(*argv, "ctx_in")) {
   1328			NEXT_ARG();
   1329			if (!REQ_ARGS(1))
   1330				return -1;
   1331
   1332			ctx_fname_in = GET_ARG();
   1333			if (check_single_stdin(data_fname_in, ctx_fname_in))
   1334				return -1;
   1335		} else if (is_prefix(*argv, "ctx_out")) {
   1336			NEXT_ARG();
   1337			if (!REQ_ARGS(1))
   1338				return -1;
   1339
   1340			ctx_fname_out = GET_ARG();
   1341		} else if (is_prefix(*argv, "ctx_size_out")) {
   1342			char *endptr;
   1343
   1344			NEXT_ARG();
   1345			if (!REQ_ARGS(1))
   1346				return -1;
   1347
   1348			test_attr.ctx_size_out = strtoul(*argv, &endptr, 0);
   1349			if (*endptr) {
   1350				p_err("can't parse %s as output context size",
   1351				      *argv);
   1352				return -1;
   1353			}
   1354			NEXT_ARG();
   1355		} else if (is_prefix(*argv, "repeat")) {
   1356			char *endptr;
   1357
   1358			NEXT_ARG();
   1359			if (!REQ_ARGS(1))
   1360				return -1;
   1361
   1362			repeat = strtoul(*argv, &endptr, 0);
   1363			if (*endptr) {
   1364				p_err("can't parse %s as repeat number",
   1365				      *argv);
   1366				return -1;
   1367			}
   1368			NEXT_ARG();
   1369		} else {
   1370			p_err("expected no more arguments, 'data_in', 'data_out', 'data_size_out', 'ctx_in', 'ctx_out', 'ctx_size_out' or 'repeat', got: '%s'?",
   1371			      *argv);
   1372			return -1;
   1373		}
   1374	}
   1375
   1376	err = get_run_data(data_fname_in, &data_in, &test_attr.data_size_in);
   1377	if (err)
   1378		return -1;
   1379
   1380	if (data_in) {
   1381		if (!test_attr.data_size_out)
   1382			test_attr.data_size_out = default_size;
   1383		err = alloc_run_data(&data_out, test_attr.data_size_out);
   1384		if (err)
   1385			goto free_data_in;
   1386	}
   1387
   1388	err = get_run_data(ctx_fname_in, &ctx_in, &test_attr.ctx_size_in);
   1389	if (err)
   1390		goto free_data_out;
   1391
   1392	if (ctx_in) {
   1393		if (!test_attr.ctx_size_out)
   1394			test_attr.ctx_size_out = default_size;
   1395		err = alloc_run_data(&ctx_out, test_attr.ctx_size_out);
   1396		if (err)
   1397			goto free_ctx_in;
   1398	}
   1399
   1400	test_attr.repeat	= repeat;
   1401	test_attr.data_in	= data_in;
   1402	test_attr.data_out	= data_out;
   1403	test_attr.ctx_in	= ctx_in;
   1404	test_attr.ctx_out	= ctx_out;
   1405
   1406	err = bpf_prog_test_run_opts(fd, &test_attr);
   1407	if (err) {
   1408		p_err("failed to run program: %s", strerror(errno));
   1409		goto free_ctx_out;
   1410	}
   1411
   1412	err = 0;
   1413
   1414	if (json_output)
   1415		jsonw_start_object(json_wtr);	/* root */
   1416
   1417	/* Do not exit on errors occurring when printing output data/context,
   1418	 * we still want to print return value and duration for program run.
   1419	 */
   1420	if (test_attr.data_size_out)
   1421		err += print_run_output(test_attr.data_out,
   1422					test_attr.data_size_out,
   1423					data_fname_out, "data_out");
   1424	if (test_attr.ctx_size_out)
   1425		err += print_run_output(test_attr.ctx_out,
   1426					test_attr.ctx_size_out,
   1427					ctx_fname_out, "ctx_out");
   1428
   1429	if (json_output) {
   1430		jsonw_uint_field(json_wtr, "retval", test_attr.retval);
   1431		jsonw_uint_field(json_wtr, "duration", test_attr.duration);
   1432		jsonw_end_object(json_wtr);	/* root */
   1433	} else {
   1434		fprintf(stdout, "Return value: %u, duration%s: %uns\n",
   1435			test_attr.retval,
   1436			repeat > 1 ? " (average)" : "", test_attr.duration);
   1437	}
   1438
   1439free_ctx_out:
   1440	free(ctx_out);
   1441free_ctx_in:
   1442	free(ctx_in);
   1443free_data_out:
   1444	free(data_out);
   1445free_data_in:
   1446	free(data_in);
   1447
   1448	return err;
   1449}
   1450
   1451static int
   1452get_prog_type_by_name(const char *name, enum bpf_prog_type *prog_type,
   1453		      enum bpf_attach_type *expected_attach_type)
   1454{
   1455	libbpf_print_fn_t print_backup;
   1456	int ret;
   1457
   1458	ret = libbpf_prog_type_by_name(name, prog_type, expected_attach_type);
   1459	if (!ret)
   1460		return ret;
   1461
   1462	/* libbpf_prog_type_by_name() failed, let's re-run with debug level */
   1463	print_backup = libbpf_set_print(print_all_levels);
   1464	ret = libbpf_prog_type_by_name(name, prog_type, expected_attach_type);
   1465	libbpf_set_print(print_backup);
   1466
   1467	return ret;
   1468}
   1469
   1470static int load_with_options(int argc, char **argv, bool first_prog_only)
   1471{
   1472	enum bpf_prog_type common_prog_type = BPF_PROG_TYPE_UNSPEC;
   1473	DECLARE_LIBBPF_OPTS(bpf_object_open_opts, open_opts,
   1474		.relaxed_maps = relaxed_maps,
   1475	);
   1476	enum bpf_attach_type expected_attach_type;
   1477	struct map_replace *map_replace = NULL;
   1478	struct bpf_program *prog = NULL, *pos;
   1479	unsigned int old_map_fds = 0;
   1480	const char *pinmaps = NULL;
   1481	struct bpf_object *obj;
   1482	struct bpf_map *map;
   1483	const char *pinfile;
   1484	unsigned int i, j;
   1485	__u32 ifindex = 0;
   1486	const char *file;
   1487	int idx, err;
   1488
   1489
   1490	if (!REQ_ARGS(2))
   1491		return -1;
   1492	file = GET_ARG();
   1493	pinfile = GET_ARG();
   1494
   1495	while (argc) {
   1496		if (is_prefix(*argv, "type")) {
   1497			NEXT_ARG();
   1498
   1499			if (common_prog_type != BPF_PROG_TYPE_UNSPEC) {
   1500				p_err("program type already specified");
   1501				goto err_free_reuse_maps;
   1502			}
   1503			if (!REQ_ARGS(1))
   1504				goto err_free_reuse_maps;
   1505
   1506			err = libbpf_prog_type_by_name(*argv, &common_prog_type,
   1507						       &expected_attach_type);
   1508			if (err < 0) {
   1509				/* Put a '/' at the end of type to appease libbpf */
   1510				char *type = malloc(strlen(*argv) + 2);
   1511
   1512				if (!type) {
   1513					p_err("mem alloc failed");
   1514					goto err_free_reuse_maps;
   1515				}
   1516				*type = 0;
   1517				strcat(type, *argv);
   1518				strcat(type, "/");
   1519
   1520				err = get_prog_type_by_name(type, &common_prog_type,
   1521							    &expected_attach_type);
   1522				free(type);
   1523				if (err < 0)
   1524					goto err_free_reuse_maps;
   1525			}
   1526
   1527			NEXT_ARG();
   1528		} else if (is_prefix(*argv, "map")) {
   1529			void *new_map_replace;
   1530			char *endptr, *name;
   1531			int fd;
   1532
   1533			NEXT_ARG();
   1534
   1535			if (!REQ_ARGS(4))
   1536				goto err_free_reuse_maps;
   1537
   1538			if (is_prefix(*argv, "idx")) {
   1539				NEXT_ARG();
   1540
   1541				idx = strtoul(*argv, &endptr, 0);
   1542				if (*endptr) {
   1543					p_err("can't parse %s as IDX", *argv);
   1544					goto err_free_reuse_maps;
   1545				}
   1546				name = NULL;
   1547			} else if (is_prefix(*argv, "name")) {
   1548				NEXT_ARG();
   1549
   1550				name = *argv;
   1551				idx = -1;
   1552			} else {
   1553				p_err("expected 'idx' or 'name', got: '%s'?",
   1554				      *argv);
   1555				goto err_free_reuse_maps;
   1556			}
   1557			NEXT_ARG();
   1558
   1559			fd = map_parse_fd(&argc, &argv);
   1560			if (fd < 0)
   1561				goto err_free_reuse_maps;
   1562
   1563			new_map_replace = libbpf_reallocarray(map_replace,
   1564							      old_map_fds + 1,
   1565							      sizeof(*map_replace));
   1566			if (!new_map_replace) {
   1567				p_err("mem alloc failed");
   1568				goto err_free_reuse_maps;
   1569			}
   1570			map_replace = new_map_replace;
   1571
   1572			map_replace[old_map_fds].idx = idx;
   1573			map_replace[old_map_fds].name = name;
   1574			map_replace[old_map_fds].fd = fd;
   1575			old_map_fds++;
   1576		} else if (is_prefix(*argv, "dev")) {
   1577			NEXT_ARG();
   1578
   1579			if (ifindex) {
   1580				p_err("offload device already specified");
   1581				goto err_free_reuse_maps;
   1582			}
   1583			if (!REQ_ARGS(1))
   1584				goto err_free_reuse_maps;
   1585
   1586			ifindex = if_nametoindex(*argv);
   1587			if (!ifindex) {
   1588				p_err("unrecognized netdevice '%s': %s",
   1589				      *argv, strerror(errno));
   1590				goto err_free_reuse_maps;
   1591			}
   1592			NEXT_ARG();
   1593		} else if (is_prefix(*argv, "pinmaps")) {
   1594			NEXT_ARG();
   1595
   1596			if (!REQ_ARGS(1))
   1597				goto err_free_reuse_maps;
   1598
   1599			pinmaps = GET_ARG();
   1600		} else {
   1601			p_err("expected no more arguments, 'type', 'map' or 'dev', got: '%s'?",
   1602			      *argv);
   1603			goto err_free_reuse_maps;
   1604		}
   1605	}
   1606
   1607	if (verifier_logs)
   1608		/* log_level1 + log_level2 + stats, but not stable UAPI */
   1609		open_opts.kernel_log_level = 1 + 2 + 4;
   1610
   1611	obj = bpf_object__open_file(file, &open_opts);
   1612	if (libbpf_get_error(obj)) {
   1613		p_err("failed to open object file");
   1614		goto err_free_reuse_maps;
   1615	}
   1616
   1617	bpf_object__for_each_program(pos, obj) {
   1618		enum bpf_prog_type prog_type = common_prog_type;
   1619
   1620		if (prog_type == BPF_PROG_TYPE_UNSPEC) {
   1621			const char *sec_name = bpf_program__section_name(pos);
   1622
   1623			err = get_prog_type_by_name(sec_name, &prog_type,
   1624						    &expected_attach_type);
   1625			if (err < 0)
   1626				goto err_close_obj;
   1627		}
   1628
   1629		bpf_program__set_ifindex(pos, ifindex);
   1630		bpf_program__set_type(pos, prog_type);
   1631		bpf_program__set_expected_attach_type(pos, expected_attach_type);
   1632	}
   1633
   1634	qsort(map_replace, old_map_fds, sizeof(*map_replace),
   1635	      map_replace_compar);
   1636
   1637	/* After the sort maps by name will be first on the list, because they
   1638	 * have idx == -1.  Resolve them.
   1639	 */
   1640	j = 0;
   1641	while (j < old_map_fds && map_replace[j].name) {
   1642		i = 0;
   1643		bpf_object__for_each_map(map, obj) {
   1644			if (!strcmp(bpf_map__name(map), map_replace[j].name)) {
   1645				map_replace[j].idx = i;
   1646				break;
   1647			}
   1648			i++;
   1649		}
   1650		if (map_replace[j].idx == -1) {
   1651			p_err("unable to find map '%s'", map_replace[j].name);
   1652			goto err_close_obj;
   1653		}
   1654		j++;
   1655	}
   1656	/* Resort if any names were resolved */
   1657	if (j)
   1658		qsort(map_replace, old_map_fds, sizeof(*map_replace),
   1659		      map_replace_compar);
   1660
   1661	/* Set ifindex and name reuse */
   1662	j = 0;
   1663	idx = 0;
   1664	bpf_object__for_each_map(map, obj) {
   1665		if (bpf_map__type(map) != BPF_MAP_TYPE_PERF_EVENT_ARRAY)
   1666			bpf_map__set_ifindex(map, ifindex);
   1667
   1668		if (j < old_map_fds && idx == map_replace[j].idx) {
   1669			err = bpf_map__reuse_fd(map, map_replace[j++].fd);
   1670			if (err) {
   1671				p_err("unable to set up map reuse: %d", err);
   1672				goto err_close_obj;
   1673			}
   1674
   1675			/* Next reuse wants to apply to the same map */
   1676			if (j < old_map_fds && map_replace[j].idx == idx) {
   1677				p_err("replacement for map idx %d specified more than once",
   1678				      idx);
   1679				goto err_close_obj;
   1680			}
   1681		}
   1682
   1683		idx++;
   1684	}
   1685	if (j < old_map_fds) {
   1686		p_err("map idx '%d' not used", map_replace[j].idx);
   1687		goto err_close_obj;
   1688	}
   1689
   1690	err = bpf_object__load(obj);
   1691	if (err) {
   1692		p_err("failed to load object file");
   1693		goto err_close_obj;
   1694	}
   1695
   1696	err = mount_bpffs_for_pin(pinfile);
   1697	if (err)
   1698		goto err_close_obj;
   1699
   1700	if (first_prog_only) {
   1701		prog = bpf_object__next_program(obj, NULL);
   1702		if (!prog) {
   1703			p_err("object file doesn't contain any bpf program");
   1704			goto err_close_obj;
   1705		}
   1706
   1707		err = bpf_obj_pin(bpf_program__fd(prog), pinfile);
   1708		if (err) {
   1709			p_err("failed to pin program %s",
   1710			      bpf_program__section_name(prog));
   1711			goto err_close_obj;
   1712		}
   1713	} else {
   1714		err = bpf_object__pin_programs(obj, pinfile);
   1715		if (err) {
   1716			p_err("failed to pin all programs");
   1717			goto err_close_obj;
   1718		}
   1719	}
   1720
   1721	if (pinmaps) {
   1722		err = bpf_object__pin_maps(obj, pinmaps);
   1723		if (err) {
   1724			p_err("failed to pin all maps");
   1725			goto err_unpin;
   1726		}
   1727	}
   1728
   1729	if (json_output)
   1730		jsonw_null(json_wtr);
   1731
   1732	bpf_object__close(obj);
   1733	for (i = 0; i < old_map_fds; i++)
   1734		close(map_replace[i].fd);
   1735	free(map_replace);
   1736
   1737	return 0;
   1738
   1739err_unpin:
   1740	if (first_prog_only)
   1741		unlink(pinfile);
   1742	else
   1743		bpf_object__unpin_programs(obj, pinfile);
   1744err_close_obj:
   1745	if (!legacy_libbpf) {
   1746		p_info("Warning: bpftool is now running in libbpf strict mode and has more stringent requirements about BPF programs.\n"
   1747		       "If it used to work for this object file but now doesn't, see --legacy option for more details.\n");
   1748	}
   1749
   1750	bpf_object__close(obj);
   1751err_free_reuse_maps:
   1752	for (i = 0; i < old_map_fds; i++)
   1753		close(map_replace[i].fd);
   1754	free(map_replace);
   1755	return -1;
   1756}
   1757
   1758static int count_open_fds(void)
   1759{
   1760	DIR *dp = opendir("/proc/self/fd");
   1761	struct dirent *de;
   1762	int cnt = -3;
   1763
   1764	if (!dp)
   1765		return -1;
   1766
   1767	while ((de = readdir(dp)))
   1768		cnt++;
   1769
   1770	closedir(dp);
   1771	return cnt;
   1772}
   1773
   1774static int try_loader(struct gen_loader_opts *gen)
   1775{
   1776	struct bpf_load_and_run_opts opts = {};
   1777	struct bpf_loader_ctx *ctx;
   1778	int ctx_sz = sizeof(*ctx) + 64 * max(sizeof(struct bpf_map_desc),
   1779					     sizeof(struct bpf_prog_desc));
   1780	int log_buf_sz = (1u << 24) - 1;
   1781	int err, fds_before, fd_delta;
   1782	char *log_buf = NULL;
   1783
   1784	ctx = alloca(ctx_sz);
   1785	memset(ctx, 0, ctx_sz);
   1786	ctx->sz = ctx_sz;
   1787	if (verifier_logs) {
   1788		ctx->log_level = 1 + 2 + 4;
   1789		ctx->log_size = log_buf_sz;
   1790		log_buf = malloc(log_buf_sz);
   1791		if (!log_buf)
   1792			return -ENOMEM;
   1793		ctx->log_buf = (long) log_buf;
   1794	}
   1795	opts.ctx = ctx;
   1796	opts.data = gen->data;
   1797	opts.data_sz = gen->data_sz;
   1798	opts.insns = gen->insns;
   1799	opts.insns_sz = gen->insns_sz;
   1800	fds_before = count_open_fds();
   1801	err = bpf_load_and_run(&opts);
   1802	fd_delta = count_open_fds() - fds_before;
   1803	if (err < 0 || verifier_logs) {
   1804		fprintf(stderr, "err %d\n%s\n%s", err, opts.errstr, log_buf);
   1805		if (fd_delta && err < 0)
   1806			fprintf(stderr, "loader prog leaked %d FDs\n",
   1807				fd_delta);
   1808	}
   1809	free(log_buf);
   1810	return err;
   1811}
   1812
   1813static int do_loader(int argc, char **argv)
   1814{
   1815	DECLARE_LIBBPF_OPTS(bpf_object_open_opts, open_opts);
   1816	DECLARE_LIBBPF_OPTS(gen_loader_opts, gen);
   1817	struct bpf_object *obj;
   1818	const char *file;
   1819	int err = 0;
   1820
   1821	if (!REQ_ARGS(1))
   1822		return -1;
   1823	file = GET_ARG();
   1824
   1825	if (verifier_logs)
   1826		/* log_level1 + log_level2 + stats, but not stable UAPI */
   1827		open_opts.kernel_log_level = 1 + 2 + 4;
   1828
   1829	obj = bpf_object__open_file(file, &open_opts);
   1830	if (libbpf_get_error(obj)) {
   1831		p_err("failed to open object file");
   1832		goto err_close_obj;
   1833	}
   1834
   1835	err = bpf_object__gen_loader(obj, &gen);
   1836	if (err)
   1837		goto err_close_obj;
   1838
   1839	err = bpf_object__load(obj);
   1840	if (err) {
   1841		p_err("failed to load object file");
   1842		goto err_close_obj;
   1843	}
   1844
   1845	if (verifier_logs) {
   1846		struct dump_data dd = {};
   1847
   1848		kernel_syms_load(&dd);
   1849		dump_xlated_plain(&dd, (void *)gen.insns, gen.insns_sz, false, false);
   1850		kernel_syms_destroy(&dd);
   1851	}
   1852	err = try_loader(&gen);
   1853err_close_obj:
   1854	bpf_object__close(obj);
   1855	return err;
   1856}
   1857
   1858static int do_load(int argc, char **argv)
   1859{
   1860	if (use_loader)
   1861		return do_loader(argc, argv);
   1862	return load_with_options(argc, argv, true);
   1863}
   1864
   1865static int do_loadall(int argc, char **argv)
   1866{
   1867	return load_with_options(argc, argv, false);
   1868}
   1869
   1870#ifdef BPFTOOL_WITHOUT_SKELETONS
   1871
   1872static int do_profile(int argc, char **argv)
   1873{
   1874	p_err("bpftool prog profile command is not supported. Please build bpftool with clang >= 10.0.0");
   1875	return 0;
   1876}
   1877
   1878#else /* BPFTOOL_WITHOUT_SKELETONS */
   1879
   1880#include "profiler.skel.h"
   1881
   1882struct profile_metric {
   1883	const char *name;
   1884	struct bpf_perf_event_value val;
   1885	struct perf_event_attr attr;
   1886	bool selected;
   1887
   1888	/* calculate ratios like instructions per cycle */
   1889	const int ratio_metric; /* 0 for N/A, 1 for index 0 (cycles) */
   1890	const char *ratio_desc;
   1891	const float ratio_mul;
   1892} metrics[] = {
   1893	{
   1894		.name = "cycles",
   1895		.attr = {
   1896			.type = PERF_TYPE_HARDWARE,
   1897			.config = PERF_COUNT_HW_CPU_CYCLES,
   1898			.exclude_user = 1,
   1899		},
   1900	},
   1901	{
   1902		.name = "instructions",
   1903		.attr = {
   1904			.type = PERF_TYPE_HARDWARE,
   1905			.config = PERF_COUNT_HW_INSTRUCTIONS,
   1906			.exclude_user = 1,
   1907		},
   1908		.ratio_metric = 1,
   1909		.ratio_desc = "insns per cycle",
   1910		.ratio_mul = 1.0,
   1911	},
   1912	{
   1913		.name = "l1d_loads",
   1914		.attr = {
   1915			.type = PERF_TYPE_HW_CACHE,
   1916			.config =
   1917				PERF_COUNT_HW_CACHE_L1D |
   1918				(PERF_COUNT_HW_CACHE_OP_READ << 8) |
   1919				(PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16),
   1920			.exclude_user = 1,
   1921		},
   1922	},
   1923	{
   1924		.name = "llc_misses",
   1925		.attr = {
   1926			.type = PERF_TYPE_HW_CACHE,
   1927			.config =
   1928				PERF_COUNT_HW_CACHE_LL |
   1929				(PERF_COUNT_HW_CACHE_OP_READ << 8) |
   1930				(PERF_COUNT_HW_CACHE_RESULT_MISS << 16),
   1931			.exclude_user = 1
   1932		},
   1933		.ratio_metric = 2,
   1934		.ratio_desc = "LLC misses per million insns",
   1935		.ratio_mul = 1e6,
   1936	},
   1937	{
   1938		.name = "itlb_misses",
   1939		.attr = {
   1940			.type = PERF_TYPE_HW_CACHE,
   1941			.config =
   1942				PERF_COUNT_HW_CACHE_ITLB |
   1943				(PERF_COUNT_HW_CACHE_OP_READ << 8) |
   1944				(PERF_COUNT_HW_CACHE_RESULT_MISS << 16),
   1945			.exclude_user = 1
   1946		},
   1947		.ratio_metric = 2,
   1948		.ratio_desc = "itlb misses per million insns",
   1949		.ratio_mul = 1e6,
   1950	},
   1951	{
   1952		.name = "dtlb_misses",
   1953		.attr = {
   1954			.type = PERF_TYPE_HW_CACHE,
   1955			.config =
   1956				PERF_COUNT_HW_CACHE_DTLB |
   1957				(PERF_COUNT_HW_CACHE_OP_READ << 8) |
   1958				(PERF_COUNT_HW_CACHE_RESULT_MISS << 16),
   1959			.exclude_user = 1
   1960		},
   1961		.ratio_metric = 2,
   1962		.ratio_desc = "dtlb misses per million insns",
   1963		.ratio_mul = 1e6,
   1964	},
   1965};
   1966
   1967static __u64 profile_total_count;
   1968
   1969#define MAX_NUM_PROFILE_METRICS 4
   1970
   1971static int profile_parse_metrics(int argc, char **argv)
   1972{
   1973	unsigned int metric_cnt;
   1974	int selected_cnt = 0;
   1975	unsigned int i;
   1976
   1977	metric_cnt = sizeof(metrics) / sizeof(struct profile_metric);
   1978
   1979	while (argc > 0) {
   1980		for (i = 0; i < metric_cnt; i++) {
   1981			if (is_prefix(argv[0], metrics[i].name)) {
   1982				if (!metrics[i].selected)
   1983					selected_cnt++;
   1984				metrics[i].selected = true;
   1985				break;
   1986			}
   1987		}
   1988		if (i == metric_cnt) {
   1989			p_err("unknown metric %s", argv[0]);
   1990			return -1;
   1991		}
   1992		NEXT_ARG();
   1993	}
   1994	if (selected_cnt > MAX_NUM_PROFILE_METRICS) {
   1995		p_err("too many (%d) metrics, please specify no more than %d metrics at at time",
   1996		      selected_cnt, MAX_NUM_PROFILE_METRICS);
   1997		return -1;
   1998	}
   1999	return selected_cnt;
   2000}
   2001
   2002static void profile_read_values(struct profiler_bpf *obj)
   2003{
   2004	__u32 m, cpu, num_cpu = obj->rodata->num_cpu;
   2005	int reading_map_fd, count_map_fd;
   2006	__u64 counts[num_cpu];
   2007	__u32 key = 0;
   2008	int err;
   2009
   2010	reading_map_fd = bpf_map__fd(obj->maps.accum_readings);
   2011	count_map_fd = bpf_map__fd(obj->maps.counts);
   2012	if (reading_map_fd < 0 || count_map_fd < 0) {
   2013		p_err("failed to get fd for map");
   2014		return;
   2015	}
   2016
   2017	err = bpf_map_lookup_elem(count_map_fd, &key, counts);
   2018	if (err) {
   2019		p_err("failed to read count_map: %s", strerror(errno));
   2020		return;
   2021	}
   2022
   2023	profile_total_count = 0;
   2024	for (cpu = 0; cpu < num_cpu; cpu++)
   2025		profile_total_count += counts[cpu];
   2026
   2027	for (m = 0; m < ARRAY_SIZE(metrics); m++) {
   2028		struct bpf_perf_event_value values[num_cpu];
   2029
   2030		if (!metrics[m].selected)
   2031			continue;
   2032
   2033		err = bpf_map_lookup_elem(reading_map_fd, &key, values);
   2034		if (err) {
   2035			p_err("failed to read reading_map: %s",
   2036			      strerror(errno));
   2037			return;
   2038		}
   2039		for (cpu = 0; cpu < num_cpu; cpu++) {
   2040			metrics[m].val.counter += values[cpu].counter;
   2041			metrics[m].val.enabled += values[cpu].enabled;
   2042			metrics[m].val.running += values[cpu].running;
   2043		}
   2044		key++;
   2045	}
   2046}
   2047
   2048static void profile_print_readings_json(void)
   2049{
   2050	__u32 m;
   2051
   2052	jsonw_start_array(json_wtr);
   2053	for (m = 0; m < ARRAY_SIZE(metrics); m++) {
   2054		if (!metrics[m].selected)
   2055			continue;
   2056		jsonw_start_object(json_wtr);
   2057		jsonw_string_field(json_wtr, "metric", metrics[m].name);
   2058		jsonw_lluint_field(json_wtr, "run_cnt", profile_total_count);
   2059		jsonw_lluint_field(json_wtr, "value", metrics[m].val.counter);
   2060		jsonw_lluint_field(json_wtr, "enabled", metrics[m].val.enabled);
   2061		jsonw_lluint_field(json_wtr, "running", metrics[m].val.running);
   2062
   2063		jsonw_end_object(json_wtr);
   2064	}
   2065	jsonw_end_array(json_wtr);
   2066}
   2067
   2068static void profile_print_readings_plain(void)
   2069{
   2070	__u32 m;
   2071
   2072	printf("\n%18llu %-20s\n", profile_total_count, "run_cnt");
   2073	for (m = 0; m < ARRAY_SIZE(metrics); m++) {
   2074		struct bpf_perf_event_value *val = &metrics[m].val;
   2075		int r;
   2076
   2077		if (!metrics[m].selected)
   2078			continue;
   2079		printf("%18llu %-20s", val->counter, metrics[m].name);
   2080
   2081		r = metrics[m].ratio_metric - 1;
   2082		if (r >= 0 && metrics[r].selected &&
   2083		    metrics[r].val.counter > 0) {
   2084			printf("# %8.2f %-30s",
   2085			       val->counter * metrics[m].ratio_mul /
   2086			       metrics[r].val.counter,
   2087			       metrics[m].ratio_desc);
   2088		} else {
   2089			printf("%-41s", "");
   2090		}
   2091
   2092		if (val->enabled > val->running)
   2093			printf("(%4.2f%%)",
   2094			       val->running * 100.0 / val->enabled);
   2095		printf("\n");
   2096	}
   2097}
   2098
   2099static void profile_print_readings(void)
   2100{
   2101	if (json_output)
   2102		profile_print_readings_json();
   2103	else
   2104		profile_print_readings_plain();
   2105}
   2106
   2107static char *profile_target_name(int tgt_fd)
   2108{
   2109	struct bpf_func_info func_info;
   2110	struct bpf_prog_info info = {};
   2111	__u32 info_len = sizeof(info);
   2112	const struct btf_type *t;
   2113	__u32 func_info_rec_size;
   2114	struct btf *btf = NULL;
   2115	char *name = NULL;
   2116	int err;
   2117
   2118	err = bpf_obj_get_info_by_fd(tgt_fd, &info, &info_len);
   2119	if (err) {
   2120		p_err("failed to bpf_obj_get_info_by_fd for prog FD %d", tgt_fd);
   2121		goto out;
   2122	}
   2123
   2124	if (info.btf_id == 0) {
   2125		p_err("prog FD %d doesn't have valid btf", tgt_fd);
   2126		goto out;
   2127	}
   2128
   2129	func_info_rec_size = info.func_info_rec_size;
   2130	if (info.nr_func_info == 0) {
   2131		p_err("bpf_obj_get_info_by_fd for prog FD %d found 0 func_info", tgt_fd);
   2132		goto out;
   2133	}
   2134
   2135	memset(&info, 0, sizeof(info));
   2136	info.nr_func_info = 1;
   2137	info.func_info_rec_size = func_info_rec_size;
   2138	info.func_info = ptr_to_u64(&func_info);
   2139
   2140	err = bpf_obj_get_info_by_fd(tgt_fd, &info, &info_len);
   2141	if (err) {
   2142		p_err("failed to get func_info for prog FD %d", tgt_fd);
   2143		goto out;
   2144	}
   2145
   2146	btf = btf__load_from_kernel_by_id(info.btf_id);
   2147	if (libbpf_get_error(btf)) {
   2148		p_err("failed to load btf for prog FD %d", tgt_fd);
   2149		goto out;
   2150	}
   2151
   2152	t = btf__type_by_id(btf, func_info.type_id);
   2153	if (!t) {
   2154		p_err("btf %d doesn't have type %d",
   2155		      info.btf_id, func_info.type_id);
   2156		goto out;
   2157	}
   2158	name = strdup(btf__name_by_offset(btf, t->name_off));
   2159out:
   2160	btf__free(btf);
   2161	return name;
   2162}
   2163
   2164static struct profiler_bpf *profile_obj;
   2165static int profile_tgt_fd = -1;
   2166static char *profile_tgt_name;
   2167static int *profile_perf_events;
   2168static int profile_perf_event_cnt;
   2169
   2170static void profile_close_perf_events(struct profiler_bpf *obj)
   2171{
   2172	int i;
   2173
   2174	for (i = profile_perf_event_cnt - 1; i >= 0; i--)
   2175		close(profile_perf_events[i]);
   2176
   2177	free(profile_perf_events);
   2178	profile_perf_event_cnt = 0;
   2179}
   2180
   2181static int profile_open_perf_events(struct profiler_bpf *obj)
   2182{
   2183	unsigned int cpu, m;
   2184	int map_fd, pmu_fd;
   2185
   2186	profile_perf_events = calloc(
   2187		sizeof(int), obj->rodata->num_cpu * obj->rodata->num_metric);
   2188	if (!profile_perf_events) {
   2189		p_err("failed to allocate memory for perf_event array: %s",
   2190		      strerror(errno));
   2191		return -1;
   2192	}
   2193	map_fd = bpf_map__fd(obj->maps.events);
   2194	if (map_fd < 0) {
   2195		p_err("failed to get fd for events map");
   2196		return -1;
   2197	}
   2198
   2199	for (m = 0; m < ARRAY_SIZE(metrics); m++) {
   2200		if (!metrics[m].selected)
   2201			continue;
   2202		for (cpu = 0; cpu < obj->rodata->num_cpu; cpu++) {
   2203			pmu_fd = syscall(__NR_perf_event_open, &metrics[m].attr,
   2204					 -1/*pid*/, cpu, -1/*group_fd*/, 0);
   2205			if (pmu_fd < 0 ||
   2206			    bpf_map_update_elem(map_fd, &profile_perf_event_cnt,
   2207						&pmu_fd, BPF_ANY) ||
   2208			    ioctl(pmu_fd, PERF_EVENT_IOC_ENABLE, 0)) {
   2209				p_err("failed to create event %s on cpu %d",
   2210				      metrics[m].name, cpu);
   2211				return -1;
   2212			}
   2213			profile_perf_events[profile_perf_event_cnt++] = pmu_fd;
   2214		}
   2215	}
   2216	return 0;
   2217}
   2218
   2219static void profile_print_and_cleanup(void)
   2220{
   2221	profile_close_perf_events(profile_obj);
   2222	profile_read_values(profile_obj);
   2223	profile_print_readings();
   2224	profiler_bpf__destroy(profile_obj);
   2225
   2226	close(profile_tgt_fd);
   2227	free(profile_tgt_name);
   2228}
   2229
   2230static void int_exit(int signo)
   2231{
   2232	profile_print_and_cleanup();
   2233	exit(0);
   2234}
   2235
   2236static int do_profile(int argc, char **argv)
   2237{
   2238	int num_metric, num_cpu, err = -1;
   2239	struct bpf_program *prog;
   2240	unsigned long duration;
   2241	char *endptr;
   2242
   2243	/* we at least need two args for the prog and one metric */
   2244	if (!REQ_ARGS(3))
   2245		return -EINVAL;
   2246
   2247	/* parse target fd */
   2248	profile_tgt_fd = prog_parse_fd(&argc, &argv);
   2249	if (profile_tgt_fd < 0) {
   2250		p_err("failed to parse fd");
   2251		return -1;
   2252	}
   2253
   2254	/* parse profiling optional duration */
   2255	if (argc > 2 && is_prefix(argv[0], "duration")) {
   2256		NEXT_ARG();
   2257		duration = strtoul(*argv, &endptr, 0);
   2258		if (*endptr)
   2259			usage();
   2260		NEXT_ARG();
   2261	} else {
   2262		duration = UINT_MAX;
   2263	}
   2264
   2265	num_metric = profile_parse_metrics(argc, argv);
   2266	if (num_metric <= 0)
   2267		goto out;
   2268
   2269	num_cpu = libbpf_num_possible_cpus();
   2270	if (num_cpu <= 0) {
   2271		p_err("failed to identify number of CPUs");
   2272		goto out;
   2273	}
   2274
   2275	profile_obj = profiler_bpf__open();
   2276	if (!profile_obj) {
   2277		p_err("failed to open and/or load BPF object");
   2278		goto out;
   2279	}
   2280
   2281	profile_obj->rodata->num_cpu = num_cpu;
   2282	profile_obj->rodata->num_metric = num_metric;
   2283
   2284	/* adjust map sizes */
   2285	bpf_map__set_max_entries(profile_obj->maps.events, num_metric * num_cpu);
   2286	bpf_map__set_max_entries(profile_obj->maps.fentry_readings, num_metric);
   2287	bpf_map__set_max_entries(profile_obj->maps.accum_readings, num_metric);
   2288	bpf_map__set_max_entries(profile_obj->maps.counts, 1);
   2289
   2290	/* change target name */
   2291	profile_tgt_name = profile_target_name(profile_tgt_fd);
   2292	if (!profile_tgt_name)
   2293		goto out;
   2294
   2295	bpf_object__for_each_program(prog, profile_obj->obj) {
   2296		err = bpf_program__set_attach_target(prog, profile_tgt_fd,
   2297						     profile_tgt_name);
   2298		if (err) {
   2299			p_err("failed to set attach target\n");
   2300			goto out;
   2301		}
   2302	}
   2303
   2304	err = profiler_bpf__load(profile_obj);
   2305	if (err) {
   2306		p_err("failed to load profile_obj");
   2307		goto out;
   2308	}
   2309
   2310	err = profile_open_perf_events(profile_obj);
   2311	if (err)
   2312		goto out;
   2313
   2314	err = profiler_bpf__attach(profile_obj);
   2315	if (err) {
   2316		p_err("failed to attach profile_obj");
   2317		goto out;
   2318	}
   2319	signal(SIGINT, int_exit);
   2320
   2321	sleep(duration);
   2322	profile_print_and_cleanup();
   2323	return 0;
   2324
   2325out:
   2326	profile_close_perf_events(profile_obj);
   2327	if (profile_obj)
   2328		profiler_bpf__destroy(profile_obj);
   2329	close(profile_tgt_fd);
   2330	free(profile_tgt_name);
   2331	return err;
   2332}
   2333
   2334#endif /* BPFTOOL_WITHOUT_SKELETONS */
   2335
   2336static int do_help(int argc, char **argv)
   2337{
   2338	if (json_output) {
   2339		jsonw_null(json_wtr);
   2340		return 0;
   2341	}
   2342
   2343	fprintf(stderr,
   2344		"Usage: %1$s %2$s { show | list } [PROG]\n"
   2345		"       %1$s %2$s dump xlated PROG [{ file FILE | opcodes | visual | linum }]\n"
   2346		"       %1$s %2$s dump jited  PROG [{ file FILE | opcodes | linum }]\n"
   2347		"       %1$s %2$s pin   PROG FILE\n"
   2348		"       %1$s %2$s { load | loadall } OBJ  PATH \\\n"
   2349		"                         [type TYPE] [dev NAME] \\\n"
   2350		"                         [map { idx IDX | name NAME } MAP]\\\n"
   2351		"                         [pinmaps MAP_DIR]\n"
   2352		"       %1$s %2$s attach PROG ATTACH_TYPE [MAP]\n"
   2353		"       %1$s %2$s detach PROG ATTACH_TYPE [MAP]\n"
   2354		"       %1$s %2$s run PROG \\\n"
   2355		"                         data_in FILE \\\n"
   2356		"                         [data_out FILE [data_size_out L]] \\\n"
   2357		"                         [ctx_in FILE [ctx_out FILE [ctx_size_out M]]] \\\n"
   2358		"                         [repeat N]\n"
   2359		"       %1$s %2$s profile PROG [duration DURATION] METRICs\n"
   2360		"       %1$s %2$s tracelog\n"
   2361		"       %1$s %2$s help\n"
   2362		"\n"
   2363		"       " HELP_SPEC_MAP "\n"
   2364		"       " HELP_SPEC_PROGRAM "\n"
   2365		"       TYPE := { socket | kprobe | kretprobe | classifier | action |\n"
   2366		"                 tracepoint | raw_tracepoint | xdp | perf_event | cgroup/skb |\n"
   2367		"                 cgroup/sock | cgroup/dev | lwt_in | lwt_out | lwt_xmit |\n"
   2368		"                 lwt_seg6local | sockops | sk_skb | sk_msg | lirc_mode2 |\n"
   2369		"                 sk_reuseport | flow_dissector | cgroup/sysctl |\n"
   2370		"                 cgroup/bind4 | cgroup/bind6 | cgroup/post_bind4 |\n"
   2371		"                 cgroup/post_bind6 | cgroup/connect4 | cgroup/connect6 |\n"
   2372		"                 cgroup/getpeername4 | cgroup/getpeername6 |\n"
   2373		"                 cgroup/getsockname4 | cgroup/getsockname6 | cgroup/sendmsg4 |\n"
   2374		"                 cgroup/sendmsg6 | cgroup/recvmsg4 | cgroup/recvmsg6 |\n"
   2375		"                 cgroup/getsockopt | cgroup/setsockopt | cgroup/sock_release |\n"
   2376		"                 struct_ops | fentry | fexit | freplace | sk_lookup }\n"
   2377		"       ATTACH_TYPE := { msg_verdict | skb_verdict | stream_verdict |\n"
   2378		"                        stream_parser | flow_dissector }\n"
   2379		"       METRIC := { cycles | instructions | l1d_loads | llc_misses | itlb_misses | dtlb_misses }\n"
   2380		"       " HELP_SPEC_OPTIONS " |\n"
   2381		"                    {-f|--bpffs} | {-m|--mapcompat} | {-n|--nomount} |\n"
   2382		"                    {-L|--use-loader} }\n"
   2383		"",
   2384		bin_name, argv[-2]);
   2385
   2386	return 0;
   2387}
   2388
   2389static const struct cmd cmds[] = {
   2390	{ "show",	do_show },
   2391	{ "list",	do_show },
   2392	{ "help",	do_help },
   2393	{ "dump",	do_dump },
   2394	{ "pin",	do_pin },
   2395	{ "load",	do_load },
   2396	{ "loadall",	do_loadall },
   2397	{ "attach",	do_attach },
   2398	{ "detach",	do_detach },
   2399	{ "tracelog",	do_tracelog },
   2400	{ "run",	do_run },
   2401	{ "profile",	do_profile },
   2402	{ 0 }
   2403};
   2404
   2405int do_prog(int argc, char **argv)
   2406{
   2407	return cmd_select(cmds, argc, argv, do_help);
   2408}