18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * bpf-loader.c 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2015 Wang Nan <wangnan0@huawei.com> 68c2ecf20Sopenharmony_ci * Copyright (C) 2015 Huawei Inc. 78c2ecf20Sopenharmony_ci */ 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ci#include <linux/bpf.h> 108c2ecf20Sopenharmony_ci#include <bpf/libbpf.h> 118c2ecf20Sopenharmony_ci#include <bpf/bpf.h> 128c2ecf20Sopenharmony_ci#include <linux/err.h> 138c2ecf20Sopenharmony_ci#include <linux/kernel.h> 148c2ecf20Sopenharmony_ci#include <linux/string.h> 158c2ecf20Sopenharmony_ci#include <linux/zalloc.h> 168c2ecf20Sopenharmony_ci#include <errno.h> 178c2ecf20Sopenharmony_ci#include <stdlib.h> 188c2ecf20Sopenharmony_ci#include "debug.h" 198c2ecf20Sopenharmony_ci#include "evlist.h" 208c2ecf20Sopenharmony_ci#include "bpf-loader.h" 218c2ecf20Sopenharmony_ci#include "bpf-prologue.h" 228c2ecf20Sopenharmony_ci#include "probe-event.h" 238c2ecf20Sopenharmony_ci#include "probe-finder.h" // for MAX_PROBES 248c2ecf20Sopenharmony_ci#include "parse-events.h" 258c2ecf20Sopenharmony_ci#include "strfilter.h" 268c2ecf20Sopenharmony_ci#include "util.h" 278c2ecf20Sopenharmony_ci#include "llvm-utils.h" 288c2ecf20Sopenharmony_ci#include "c++/clang-c.h" 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ci#include <internal/xyarray.h> 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_cistatic int libbpf_perf_print(enum libbpf_print_level level __attribute__((unused)), 338c2ecf20Sopenharmony_ci const char *fmt, va_list args) 348c2ecf20Sopenharmony_ci{ 358c2ecf20Sopenharmony_ci return veprintf(1, verbose, pr_fmt(fmt), args); 368c2ecf20Sopenharmony_ci} 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_cistruct bpf_prog_priv { 398c2ecf20Sopenharmony_ci bool is_tp; 408c2ecf20Sopenharmony_ci char *sys_name; 418c2ecf20Sopenharmony_ci char *evt_name; 428c2ecf20Sopenharmony_ci struct perf_probe_event pev; 438c2ecf20Sopenharmony_ci bool need_prologue; 448c2ecf20Sopenharmony_ci struct bpf_insn *insns_buf; 458c2ecf20Sopenharmony_ci int nr_types; 468c2ecf20Sopenharmony_ci int *type_mapping; 478c2ecf20Sopenharmony_ci}; 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_cistatic bool libbpf_initialized; 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_cistruct bpf_object * 528c2ecf20Sopenharmony_cibpf__prepare_load_buffer(void *obj_buf, size_t obj_buf_sz, const char *name) 538c2ecf20Sopenharmony_ci{ 548c2ecf20Sopenharmony_ci struct bpf_object *obj; 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ci if (!libbpf_initialized) { 578c2ecf20Sopenharmony_ci libbpf_set_print(libbpf_perf_print); 588c2ecf20Sopenharmony_ci libbpf_initialized = true; 598c2ecf20Sopenharmony_ci } 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_ci obj = bpf_object__open_buffer(obj_buf, obj_buf_sz, name); 628c2ecf20Sopenharmony_ci if (IS_ERR_OR_NULL(obj)) { 638c2ecf20Sopenharmony_ci pr_debug("bpf: failed to load buffer\n"); 648c2ecf20Sopenharmony_ci return ERR_PTR(-EINVAL); 658c2ecf20Sopenharmony_ci } 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_ci return obj; 688c2ecf20Sopenharmony_ci} 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_cistruct bpf_object *bpf__prepare_load(const char *filename, bool source) 718c2ecf20Sopenharmony_ci{ 728c2ecf20Sopenharmony_ci struct bpf_object *obj; 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_ci if (!libbpf_initialized) { 758c2ecf20Sopenharmony_ci libbpf_set_print(libbpf_perf_print); 768c2ecf20Sopenharmony_ci libbpf_initialized = true; 778c2ecf20Sopenharmony_ci } 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_ci if (source) { 808c2ecf20Sopenharmony_ci int err; 818c2ecf20Sopenharmony_ci void *obj_buf; 828c2ecf20Sopenharmony_ci size_t obj_buf_sz; 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_ci perf_clang__init(); 858c2ecf20Sopenharmony_ci err = perf_clang__compile_bpf(filename, &obj_buf, &obj_buf_sz); 868c2ecf20Sopenharmony_ci perf_clang__cleanup(); 878c2ecf20Sopenharmony_ci if (err) { 888c2ecf20Sopenharmony_ci pr_debug("bpf: builtin compilation failed: %d, try external compiler\n", err); 898c2ecf20Sopenharmony_ci err = llvm__compile_bpf(filename, &obj_buf, &obj_buf_sz); 908c2ecf20Sopenharmony_ci if (err) 918c2ecf20Sopenharmony_ci return ERR_PTR(-BPF_LOADER_ERRNO__COMPILE); 928c2ecf20Sopenharmony_ci } else 938c2ecf20Sopenharmony_ci pr_debug("bpf: successful builtin compilation\n"); 948c2ecf20Sopenharmony_ci obj = bpf_object__open_buffer(obj_buf, obj_buf_sz, filename); 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_ci if (!IS_ERR_OR_NULL(obj) && llvm_param.dump_obj) 978c2ecf20Sopenharmony_ci llvm__dump_obj(filename, obj_buf, obj_buf_sz); 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_ci free(obj_buf); 1008c2ecf20Sopenharmony_ci } else 1018c2ecf20Sopenharmony_ci obj = bpf_object__open(filename); 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_ci if (IS_ERR_OR_NULL(obj)) { 1048c2ecf20Sopenharmony_ci pr_debug("bpf: failed to load %s\n", filename); 1058c2ecf20Sopenharmony_ci return obj; 1068c2ecf20Sopenharmony_ci } 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_ci return obj; 1098c2ecf20Sopenharmony_ci} 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_civoid bpf__clear(void) 1128c2ecf20Sopenharmony_ci{ 1138c2ecf20Sopenharmony_ci struct bpf_object *obj, *tmp; 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_ci bpf_object__for_each_safe(obj, tmp) { 1168c2ecf20Sopenharmony_ci bpf__unprobe(obj); 1178c2ecf20Sopenharmony_ci bpf_object__close(obj); 1188c2ecf20Sopenharmony_ci } 1198c2ecf20Sopenharmony_ci} 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_cistatic void 1228c2ecf20Sopenharmony_ciclear_prog_priv(struct bpf_program *prog __maybe_unused, 1238c2ecf20Sopenharmony_ci void *_priv) 1248c2ecf20Sopenharmony_ci{ 1258c2ecf20Sopenharmony_ci struct bpf_prog_priv *priv = _priv; 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_ci cleanup_perf_probe_events(&priv->pev, 1); 1288c2ecf20Sopenharmony_ci zfree(&priv->insns_buf); 1298c2ecf20Sopenharmony_ci zfree(&priv->type_mapping); 1308c2ecf20Sopenharmony_ci zfree(&priv->sys_name); 1318c2ecf20Sopenharmony_ci zfree(&priv->evt_name); 1328c2ecf20Sopenharmony_ci free(priv); 1338c2ecf20Sopenharmony_ci} 1348c2ecf20Sopenharmony_ci 1358c2ecf20Sopenharmony_cistatic int 1368c2ecf20Sopenharmony_ciprog_config__exec(const char *value, struct perf_probe_event *pev) 1378c2ecf20Sopenharmony_ci{ 1388c2ecf20Sopenharmony_ci pev->uprobes = true; 1398c2ecf20Sopenharmony_ci pev->target = strdup(value); 1408c2ecf20Sopenharmony_ci if (!pev->target) 1418c2ecf20Sopenharmony_ci return -ENOMEM; 1428c2ecf20Sopenharmony_ci return 0; 1438c2ecf20Sopenharmony_ci} 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_cistatic int 1468c2ecf20Sopenharmony_ciprog_config__module(const char *value, struct perf_probe_event *pev) 1478c2ecf20Sopenharmony_ci{ 1488c2ecf20Sopenharmony_ci pev->uprobes = false; 1498c2ecf20Sopenharmony_ci pev->target = strdup(value); 1508c2ecf20Sopenharmony_ci if (!pev->target) 1518c2ecf20Sopenharmony_ci return -ENOMEM; 1528c2ecf20Sopenharmony_ci return 0; 1538c2ecf20Sopenharmony_ci} 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_cistatic int 1568c2ecf20Sopenharmony_ciprog_config__bool(const char *value, bool *pbool, bool invert) 1578c2ecf20Sopenharmony_ci{ 1588c2ecf20Sopenharmony_ci int err; 1598c2ecf20Sopenharmony_ci bool bool_value; 1608c2ecf20Sopenharmony_ci 1618c2ecf20Sopenharmony_ci if (!pbool) 1628c2ecf20Sopenharmony_ci return -EINVAL; 1638c2ecf20Sopenharmony_ci 1648c2ecf20Sopenharmony_ci err = strtobool(value, &bool_value); 1658c2ecf20Sopenharmony_ci if (err) 1668c2ecf20Sopenharmony_ci return err; 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_ci *pbool = invert ? !bool_value : bool_value; 1698c2ecf20Sopenharmony_ci return 0; 1708c2ecf20Sopenharmony_ci} 1718c2ecf20Sopenharmony_ci 1728c2ecf20Sopenharmony_cistatic int 1738c2ecf20Sopenharmony_ciprog_config__inlines(const char *value, 1748c2ecf20Sopenharmony_ci struct perf_probe_event *pev __maybe_unused) 1758c2ecf20Sopenharmony_ci{ 1768c2ecf20Sopenharmony_ci return prog_config__bool(value, &probe_conf.no_inlines, true); 1778c2ecf20Sopenharmony_ci} 1788c2ecf20Sopenharmony_ci 1798c2ecf20Sopenharmony_cistatic int 1808c2ecf20Sopenharmony_ciprog_config__force(const char *value, 1818c2ecf20Sopenharmony_ci struct perf_probe_event *pev __maybe_unused) 1828c2ecf20Sopenharmony_ci{ 1838c2ecf20Sopenharmony_ci return prog_config__bool(value, &probe_conf.force_add, false); 1848c2ecf20Sopenharmony_ci} 1858c2ecf20Sopenharmony_ci 1868c2ecf20Sopenharmony_cistatic struct { 1878c2ecf20Sopenharmony_ci const char *key; 1888c2ecf20Sopenharmony_ci const char *usage; 1898c2ecf20Sopenharmony_ci const char *desc; 1908c2ecf20Sopenharmony_ci int (*func)(const char *, struct perf_probe_event *); 1918c2ecf20Sopenharmony_ci} bpf_prog_config_terms[] = { 1928c2ecf20Sopenharmony_ci { 1938c2ecf20Sopenharmony_ci .key = "exec", 1948c2ecf20Sopenharmony_ci .usage = "exec=<full path of file>", 1958c2ecf20Sopenharmony_ci .desc = "Set uprobe target", 1968c2ecf20Sopenharmony_ci .func = prog_config__exec, 1978c2ecf20Sopenharmony_ci }, 1988c2ecf20Sopenharmony_ci { 1998c2ecf20Sopenharmony_ci .key = "module", 2008c2ecf20Sopenharmony_ci .usage = "module=<module name> ", 2018c2ecf20Sopenharmony_ci .desc = "Set kprobe module", 2028c2ecf20Sopenharmony_ci .func = prog_config__module, 2038c2ecf20Sopenharmony_ci }, 2048c2ecf20Sopenharmony_ci { 2058c2ecf20Sopenharmony_ci .key = "inlines", 2068c2ecf20Sopenharmony_ci .usage = "inlines=[yes|no] ", 2078c2ecf20Sopenharmony_ci .desc = "Probe at inline symbol", 2088c2ecf20Sopenharmony_ci .func = prog_config__inlines, 2098c2ecf20Sopenharmony_ci }, 2108c2ecf20Sopenharmony_ci { 2118c2ecf20Sopenharmony_ci .key = "force", 2128c2ecf20Sopenharmony_ci .usage = "force=[yes|no] ", 2138c2ecf20Sopenharmony_ci .desc = "Forcibly add events with existing name", 2148c2ecf20Sopenharmony_ci .func = prog_config__force, 2158c2ecf20Sopenharmony_ci }, 2168c2ecf20Sopenharmony_ci}; 2178c2ecf20Sopenharmony_ci 2188c2ecf20Sopenharmony_cistatic int 2198c2ecf20Sopenharmony_cido_prog_config(const char *key, const char *value, 2208c2ecf20Sopenharmony_ci struct perf_probe_event *pev) 2218c2ecf20Sopenharmony_ci{ 2228c2ecf20Sopenharmony_ci unsigned int i; 2238c2ecf20Sopenharmony_ci 2248c2ecf20Sopenharmony_ci pr_debug("config bpf program: %s=%s\n", key, value); 2258c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(bpf_prog_config_terms); i++) 2268c2ecf20Sopenharmony_ci if (strcmp(key, bpf_prog_config_terms[i].key) == 0) 2278c2ecf20Sopenharmony_ci return bpf_prog_config_terms[i].func(value, pev); 2288c2ecf20Sopenharmony_ci 2298c2ecf20Sopenharmony_ci pr_debug("BPF: ERROR: invalid program config option: %s=%s\n", 2308c2ecf20Sopenharmony_ci key, value); 2318c2ecf20Sopenharmony_ci 2328c2ecf20Sopenharmony_ci pr_debug("\nHint: Valid options are:\n"); 2338c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(bpf_prog_config_terms); i++) 2348c2ecf20Sopenharmony_ci pr_debug("\t%s:\t%s\n", bpf_prog_config_terms[i].usage, 2358c2ecf20Sopenharmony_ci bpf_prog_config_terms[i].desc); 2368c2ecf20Sopenharmony_ci pr_debug("\n"); 2378c2ecf20Sopenharmony_ci 2388c2ecf20Sopenharmony_ci return -BPF_LOADER_ERRNO__PROGCONF_TERM; 2398c2ecf20Sopenharmony_ci} 2408c2ecf20Sopenharmony_ci 2418c2ecf20Sopenharmony_cistatic const char * 2428c2ecf20Sopenharmony_ciparse_prog_config_kvpair(const char *config_str, struct perf_probe_event *pev) 2438c2ecf20Sopenharmony_ci{ 2448c2ecf20Sopenharmony_ci char *text = strdup(config_str); 2458c2ecf20Sopenharmony_ci char *sep, *line; 2468c2ecf20Sopenharmony_ci const char *main_str = NULL; 2478c2ecf20Sopenharmony_ci int err = 0; 2488c2ecf20Sopenharmony_ci 2498c2ecf20Sopenharmony_ci if (!text) { 2508c2ecf20Sopenharmony_ci pr_debug("Not enough memory: dup config_str failed\n"); 2518c2ecf20Sopenharmony_ci return ERR_PTR(-ENOMEM); 2528c2ecf20Sopenharmony_ci } 2538c2ecf20Sopenharmony_ci 2548c2ecf20Sopenharmony_ci line = text; 2558c2ecf20Sopenharmony_ci while ((sep = strchr(line, ';'))) { 2568c2ecf20Sopenharmony_ci char *equ; 2578c2ecf20Sopenharmony_ci 2588c2ecf20Sopenharmony_ci *sep = '\0'; 2598c2ecf20Sopenharmony_ci equ = strchr(line, '='); 2608c2ecf20Sopenharmony_ci if (!equ) { 2618c2ecf20Sopenharmony_ci pr_warning("WARNING: invalid config in BPF object: %s\n", 2628c2ecf20Sopenharmony_ci line); 2638c2ecf20Sopenharmony_ci pr_warning("\tShould be 'key=value'.\n"); 2648c2ecf20Sopenharmony_ci goto nextline; 2658c2ecf20Sopenharmony_ci } 2668c2ecf20Sopenharmony_ci *equ = '\0'; 2678c2ecf20Sopenharmony_ci 2688c2ecf20Sopenharmony_ci err = do_prog_config(line, equ + 1, pev); 2698c2ecf20Sopenharmony_ci if (err) 2708c2ecf20Sopenharmony_ci break; 2718c2ecf20Sopenharmony_cinextline: 2728c2ecf20Sopenharmony_ci line = sep + 1; 2738c2ecf20Sopenharmony_ci } 2748c2ecf20Sopenharmony_ci 2758c2ecf20Sopenharmony_ci if (!err) 2768c2ecf20Sopenharmony_ci main_str = config_str + (line - text); 2778c2ecf20Sopenharmony_ci free(text); 2788c2ecf20Sopenharmony_ci 2798c2ecf20Sopenharmony_ci return err ? ERR_PTR(err) : main_str; 2808c2ecf20Sopenharmony_ci} 2818c2ecf20Sopenharmony_ci 2828c2ecf20Sopenharmony_cistatic int 2838c2ecf20Sopenharmony_ciparse_prog_config(const char *config_str, const char **p_main_str, 2848c2ecf20Sopenharmony_ci bool *is_tp, struct perf_probe_event *pev) 2858c2ecf20Sopenharmony_ci{ 2868c2ecf20Sopenharmony_ci int err; 2878c2ecf20Sopenharmony_ci const char *main_str = parse_prog_config_kvpair(config_str, pev); 2888c2ecf20Sopenharmony_ci 2898c2ecf20Sopenharmony_ci if (IS_ERR(main_str)) 2908c2ecf20Sopenharmony_ci return PTR_ERR(main_str); 2918c2ecf20Sopenharmony_ci 2928c2ecf20Sopenharmony_ci *p_main_str = main_str; 2938c2ecf20Sopenharmony_ci if (!strchr(main_str, '=')) { 2948c2ecf20Sopenharmony_ci /* Is a tracepoint event? */ 2958c2ecf20Sopenharmony_ci const char *s = strchr(main_str, ':'); 2968c2ecf20Sopenharmony_ci 2978c2ecf20Sopenharmony_ci if (!s) { 2988c2ecf20Sopenharmony_ci pr_debug("bpf: '%s' is not a valid tracepoint\n", 2998c2ecf20Sopenharmony_ci config_str); 3008c2ecf20Sopenharmony_ci return -BPF_LOADER_ERRNO__CONFIG; 3018c2ecf20Sopenharmony_ci } 3028c2ecf20Sopenharmony_ci 3038c2ecf20Sopenharmony_ci *is_tp = true; 3048c2ecf20Sopenharmony_ci return 0; 3058c2ecf20Sopenharmony_ci } 3068c2ecf20Sopenharmony_ci 3078c2ecf20Sopenharmony_ci *is_tp = false; 3088c2ecf20Sopenharmony_ci err = parse_perf_probe_command(main_str, pev); 3098c2ecf20Sopenharmony_ci if (err < 0) { 3108c2ecf20Sopenharmony_ci pr_debug("bpf: '%s' is not a valid config string\n", 3118c2ecf20Sopenharmony_ci config_str); 3128c2ecf20Sopenharmony_ci /* parse failed, don't need clear pev. */ 3138c2ecf20Sopenharmony_ci return -BPF_LOADER_ERRNO__CONFIG; 3148c2ecf20Sopenharmony_ci } 3158c2ecf20Sopenharmony_ci return 0; 3168c2ecf20Sopenharmony_ci} 3178c2ecf20Sopenharmony_ci 3188c2ecf20Sopenharmony_cistatic int 3198c2ecf20Sopenharmony_ciconfig_bpf_program(struct bpf_program *prog) 3208c2ecf20Sopenharmony_ci{ 3218c2ecf20Sopenharmony_ci struct perf_probe_event *pev = NULL; 3228c2ecf20Sopenharmony_ci struct bpf_prog_priv *priv = NULL; 3238c2ecf20Sopenharmony_ci const char *config_str, *main_str; 3248c2ecf20Sopenharmony_ci bool is_tp = false; 3258c2ecf20Sopenharmony_ci int err; 3268c2ecf20Sopenharmony_ci 3278c2ecf20Sopenharmony_ci /* Initialize per-program probing setting */ 3288c2ecf20Sopenharmony_ci probe_conf.no_inlines = false; 3298c2ecf20Sopenharmony_ci probe_conf.force_add = false; 3308c2ecf20Sopenharmony_ci 3318c2ecf20Sopenharmony_ci priv = calloc(sizeof(*priv), 1); 3328c2ecf20Sopenharmony_ci if (!priv) { 3338c2ecf20Sopenharmony_ci pr_debug("bpf: failed to alloc priv\n"); 3348c2ecf20Sopenharmony_ci return -ENOMEM; 3358c2ecf20Sopenharmony_ci } 3368c2ecf20Sopenharmony_ci pev = &priv->pev; 3378c2ecf20Sopenharmony_ci 3388c2ecf20Sopenharmony_ci config_str = bpf_program__section_name(prog); 3398c2ecf20Sopenharmony_ci pr_debug("bpf: config program '%s'\n", config_str); 3408c2ecf20Sopenharmony_ci err = parse_prog_config(config_str, &main_str, &is_tp, pev); 3418c2ecf20Sopenharmony_ci if (err) 3428c2ecf20Sopenharmony_ci goto errout; 3438c2ecf20Sopenharmony_ci 3448c2ecf20Sopenharmony_ci if (is_tp) { 3458c2ecf20Sopenharmony_ci char *s = strchr(main_str, ':'); 3468c2ecf20Sopenharmony_ci 3478c2ecf20Sopenharmony_ci priv->is_tp = true; 3488c2ecf20Sopenharmony_ci priv->sys_name = strndup(main_str, s - main_str); 3498c2ecf20Sopenharmony_ci priv->evt_name = strdup(s + 1); 3508c2ecf20Sopenharmony_ci goto set_priv; 3518c2ecf20Sopenharmony_ci } 3528c2ecf20Sopenharmony_ci 3538c2ecf20Sopenharmony_ci if (pev->group && strcmp(pev->group, PERF_BPF_PROBE_GROUP)) { 3548c2ecf20Sopenharmony_ci pr_debug("bpf: '%s': group for event is set and not '%s'.\n", 3558c2ecf20Sopenharmony_ci config_str, PERF_BPF_PROBE_GROUP); 3568c2ecf20Sopenharmony_ci err = -BPF_LOADER_ERRNO__GROUP; 3578c2ecf20Sopenharmony_ci goto errout; 3588c2ecf20Sopenharmony_ci } else if (!pev->group) 3598c2ecf20Sopenharmony_ci pev->group = strdup(PERF_BPF_PROBE_GROUP); 3608c2ecf20Sopenharmony_ci 3618c2ecf20Sopenharmony_ci if (!pev->group) { 3628c2ecf20Sopenharmony_ci pr_debug("bpf: strdup failed\n"); 3638c2ecf20Sopenharmony_ci err = -ENOMEM; 3648c2ecf20Sopenharmony_ci goto errout; 3658c2ecf20Sopenharmony_ci } 3668c2ecf20Sopenharmony_ci 3678c2ecf20Sopenharmony_ci if (!pev->event) { 3688c2ecf20Sopenharmony_ci pr_debug("bpf: '%s': event name is missing. Section name should be 'key=value'\n", 3698c2ecf20Sopenharmony_ci config_str); 3708c2ecf20Sopenharmony_ci err = -BPF_LOADER_ERRNO__EVENTNAME; 3718c2ecf20Sopenharmony_ci goto errout; 3728c2ecf20Sopenharmony_ci } 3738c2ecf20Sopenharmony_ci pr_debug("bpf: config '%s' is ok\n", config_str); 3748c2ecf20Sopenharmony_ci 3758c2ecf20Sopenharmony_ciset_priv: 3768c2ecf20Sopenharmony_ci err = bpf_program__set_priv(prog, priv, clear_prog_priv); 3778c2ecf20Sopenharmony_ci if (err) { 3788c2ecf20Sopenharmony_ci pr_debug("Failed to set priv for program '%s'\n", config_str); 3798c2ecf20Sopenharmony_ci goto errout; 3808c2ecf20Sopenharmony_ci } 3818c2ecf20Sopenharmony_ci 3828c2ecf20Sopenharmony_ci return 0; 3838c2ecf20Sopenharmony_ci 3848c2ecf20Sopenharmony_cierrout: 3858c2ecf20Sopenharmony_ci if (pev) 3868c2ecf20Sopenharmony_ci clear_perf_probe_event(pev); 3878c2ecf20Sopenharmony_ci free(priv); 3888c2ecf20Sopenharmony_ci return err; 3898c2ecf20Sopenharmony_ci} 3908c2ecf20Sopenharmony_ci 3918c2ecf20Sopenharmony_cistatic int bpf__prepare_probe(void) 3928c2ecf20Sopenharmony_ci{ 3938c2ecf20Sopenharmony_ci static int err = 0; 3948c2ecf20Sopenharmony_ci static bool initialized = false; 3958c2ecf20Sopenharmony_ci 3968c2ecf20Sopenharmony_ci /* 3978c2ecf20Sopenharmony_ci * Make err static, so if init failed the first, bpf__prepare_probe() 3988c2ecf20Sopenharmony_ci * fails each time without calling init_probe_symbol_maps multiple 3998c2ecf20Sopenharmony_ci * times. 4008c2ecf20Sopenharmony_ci */ 4018c2ecf20Sopenharmony_ci if (initialized) 4028c2ecf20Sopenharmony_ci return err; 4038c2ecf20Sopenharmony_ci 4048c2ecf20Sopenharmony_ci initialized = true; 4058c2ecf20Sopenharmony_ci err = init_probe_symbol_maps(false); 4068c2ecf20Sopenharmony_ci if (err < 0) 4078c2ecf20Sopenharmony_ci pr_debug("Failed to init_probe_symbol_maps\n"); 4088c2ecf20Sopenharmony_ci probe_conf.max_probes = MAX_PROBES; 4098c2ecf20Sopenharmony_ci return err; 4108c2ecf20Sopenharmony_ci} 4118c2ecf20Sopenharmony_ci 4128c2ecf20Sopenharmony_cistatic int 4138c2ecf20Sopenharmony_cipreproc_gen_prologue(struct bpf_program *prog, int n, 4148c2ecf20Sopenharmony_ci struct bpf_insn *orig_insns, int orig_insns_cnt, 4158c2ecf20Sopenharmony_ci struct bpf_prog_prep_result *res) 4168c2ecf20Sopenharmony_ci{ 4178c2ecf20Sopenharmony_ci struct bpf_prog_priv *priv = bpf_program__priv(prog); 4188c2ecf20Sopenharmony_ci struct probe_trace_event *tev; 4198c2ecf20Sopenharmony_ci struct perf_probe_event *pev; 4208c2ecf20Sopenharmony_ci struct bpf_insn *buf; 4218c2ecf20Sopenharmony_ci size_t prologue_cnt = 0; 4228c2ecf20Sopenharmony_ci int i, err; 4238c2ecf20Sopenharmony_ci 4248c2ecf20Sopenharmony_ci if (IS_ERR(priv) || !priv || priv->is_tp) 4258c2ecf20Sopenharmony_ci goto errout; 4268c2ecf20Sopenharmony_ci 4278c2ecf20Sopenharmony_ci pev = &priv->pev; 4288c2ecf20Sopenharmony_ci 4298c2ecf20Sopenharmony_ci if (n < 0 || n >= priv->nr_types) 4308c2ecf20Sopenharmony_ci goto errout; 4318c2ecf20Sopenharmony_ci 4328c2ecf20Sopenharmony_ci /* Find a tev belongs to that type */ 4338c2ecf20Sopenharmony_ci for (i = 0; i < pev->ntevs; i++) { 4348c2ecf20Sopenharmony_ci if (priv->type_mapping[i] == n) 4358c2ecf20Sopenharmony_ci break; 4368c2ecf20Sopenharmony_ci } 4378c2ecf20Sopenharmony_ci 4388c2ecf20Sopenharmony_ci if (i >= pev->ntevs) { 4398c2ecf20Sopenharmony_ci pr_debug("Internal error: prologue type %d not found\n", n); 4408c2ecf20Sopenharmony_ci return -BPF_LOADER_ERRNO__PROLOGUE; 4418c2ecf20Sopenharmony_ci } 4428c2ecf20Sopenharmony_ci 4438c2ecf20Sopenharmony_ci tev = &pev->tevs[i]; 4448c2ecf20Sopenharmony_ci 4458c2ecf20Sopenharmony_ci buf = priv->insns_buf; 4468c2ecf20Sopenharmony_ci err = bpf__gen_prologue(tev->args, tev->nargs, 4478c2ecf20Sopenharmony_ci buf, &prologue_cnt, 4488c2ecf20Sopenharmony_ci BPF_MAXINSNS - orig_insns_cnt); 4498c2ecf20Sopenharmony_ci if (err) { 4508c2ecf20Sopenharmony_ci const char *title; 4518c2ecf20Sopenharmony_ci 4528c2ecf20Sopenharmony_ci title = bpf_program__section_name(prog); 4538c2ecf20Sopenharmony_ci pr_debug("Failed to generate prologue for program %s\n", 4548c2ecf20Sopenharmony_ci title); 4558c2ecf20Sopenharmony_ci return err; 4568c2ecf20Sopenharmony_ci } 4578c2ecf20Sopenharmony_ci 4588c2ecf20Sopenharmony_ci memcpy(&buf[prologue_cnt], orig_insns, 4598c2ecf20Sopenharmony_ci sizeof(struct bpf_insn) * orig_insns_cnt); 4608c2ecf20Sopenharmony_ci 4618c2ecf20Sopenharmony_ci res->new_insn_ptr = buf; 4628c2ecf20Sopenharmony_ci res->new_insn_cnt = prologue_cnt + orig_insns_cnt; 4638c2ecf20Sopenharmony_ci res->pfd = NULL; 4648c2ecf20Sopenharmony_ci return 0; 4658c2ecf20Sopenharmony_ci 4668c2ecf20Sopenharmony_cierrout: 4678c2ecf20Sopenharmony_ci pr_debug("Internal error in preproc_gen_prologue\n"); 4688c2ecf20Sopenharmony_ci return -BPF_LOADER_ERRNO__PROLOGUE; 4698c2ecf20Sopenharmony_ci} 4708c2ecf20Sopenharmony_ci 4718c2ecf20Sopenharmony_ci/* 4728c2ecf20Sopenharmony_ci * compare_tev_args is reflexive, transitive and antisymmetric. 4738c2ecf20Sopenharmony_ci * I can proof it but this margin is too narrow to contain. 4748c2ecf20Sopenharmony_ci */ 4758c2ecf20Sopenharmony_cistatic int compare_tev_args(const void *ptev1, const void *ptev2) 4768c2ecf20Sopenharmony_ci{ 4778c2ecf20Sopenharmony_ci int i, ret; 4788c2ecf20Sopenharmony_ci const struct probe_trace_event *tev1 = 4798c2ecf20Sopenharmony_ci *(const struct probe_trace_event **)ptev1; 4808c2ecf20Sopenharmony_ci const struct probe_trace_event *tev2 = 4818c2ecf20Sopenharmony_ci *(const struct probe_trace_event **)ptev2; 4828c2ecf20Sopenharmony_ci 4838c2ecf20Sopenharmony_ci ret = tev2->nargs - tev1->nargs; 4848c2ecf20Sopenharmony_ci if (ret) 4858c2ecf20Sopenharmony_ci return ret; 4868c2ecf20Sopenharmony_ci 4878c2ecf20Sopenharmony_ci for (i = 0; i < tev1->nargs; i++) { 4888c2ecf20Sopenharmony_ci struct probe_trace_arg *arg1, *arg2; 4898c2ecf20Sopenharmony_ci struct probe_trace_arg_ref *ref1, *ref2; 4908c2ecf20Sopenharmony_ci 4918c2ecf20Sopenharmony_ci arg1 = &tev1->args[i]; 4928c2ecf20Sopenharmony_ci arg2 = &tev2->args[i]; 4938c2ecf20Sopenharmony_ci 4948c2ecf20Sopenharmony_ci ret = strcmp(arg1->value, arg2->value); 4958c2ecf20Sopenharmony_ci if (ret) 4968c2ecf20Sopenharmony_ci return ret; 4978c2ecf20Sopenharmony_ci 4988c2ecf20Sopenharmony_ci ref1 = arg1->ref; 4998c2ecf20Sopenharmony_ci ref2 = arg2->ref; 5008c2ecf20Sopenharmony_ci 5018c2ecf20Sopenharmony_ci while (ref1 && ref2) { 5028c2ecf20Sopenharmony_ci ret = ref2->offset - ref1->offset; 5038c2ecf20Sopenharmony_ci if (ret) 5048c2ecf20Sopenharmony_ci return ret; 5058c2ecf20Sopenharmony_ci 5068c2ecf20Sopenharmony_ci ref1 = ref1->next; 5078c2ecf20Sopenharmony_ci ref2 = ref2->next; 5088c2ecf20Sopenharmony_ci } 5098c2ecf20Sopenharmony_ci 5108c2ecf20Sopenharmony_ci if (ref1 || ref2) 5118c2ecf20Sopenharmony_ci return ref2 ? 1 : -1; 5128c2ecf20Sopenharmony_ci } 5138c2ecf20Sopenharmony_ci 5148c2ecf20Sopenharmony_ci return 0; 5158c2ecf20Sopenharmony_ci} 5168c2ecf20Sopenharmony_ci 5178c2ecf20Sopenharmony_ci/* 5188c2ecf20Sopenharmony_ci * Assign a type number to each tevs in a pev. 5198c2ecf20Sopenharmony_ci * mapping is an array with same slots as tevs in that pev. 5208c2ecf20Sopenharmony_ci * nr_types will be set to number of types. 5218c2ecf20Sopenharmony_ci */ 5228c2ecf20Sopenharmony_cistatic int map_prologue(struct perf_probe_event *pev, int *mapping, 5238c2ecf20Sopenharmony_ci int *nr_types) 5248c2ecf20Sopenharmony_ci{ 5258c2ecf20Sopenharmony_ci int i, type = 0; 5268c2ecf20Sopenharmony_ci struct probe_trace_event **ptevs; 5278c2ecf20Sopenharmony_ci 5288c2ecf20Sopenharmony_ci size_t array_sz = sizeof(*ptevs) * pev->ntevs; 5298c2ecf20Sopenharmony_ci 5308c2ecf20Sopenharmony_ci ptevs = malloc(array_sz); 5318c2ecf20Sopenharmony_ci if (!ptevs) { 5328c2ecf20Sopenharmony_ci pr_debug("Not enough memory: alloc ptevs failed\n"); 5338c2ecf20Sopenharmony_ci return -ENOMEM; 5348c2ecf20Sopenharmony_ci } 5358c2ecf20Sopenharmony_ci 5368c2ecf20Sopenharmony_ci pr_debug("In map_prologue, ntevs=%d\n", pev->ntevs); 5378c2ecf20Sopenharmony_ci for (i = 0; i < pev->ntevs; i++) 5388c2ecf20Sopenharmony_ci ptevs[i] = &pev->tevs[i]; 5398c2ecf20Sopenharmony_ci 5408c2ecf20Sopenharmony_ci qsort(ptevs, pev->ntevs, sizeof(*ptevs), 5418c2ecf20Sopenharmony_ci compare_tev_args); 5428c2ecf20Sopenharmony_ci 5438c2ecf20Sopenharmony_ci for (i = 0; i < pev->ntevs; i++) { 5448c2ecf20Sopenharmony_ci int n; 5458c2ecf20Sopenharmony_ci 5468c2ecf20Sopenharmony_ci n = ptevs[i] - pev->tevs; 5478c2ecf20Sopenharmony_ci if (i == 0) { 5488c2ecf20Sopenharmony_ci mapping[n] = type; 5498c2ecf20Sopenharmony_ci pr_debug("mapping[%d]=%d\n", n, type); 5508c2ecf20Sopenharmony_ci continue; 5518c2ecf20Sopenharmony_ci } 5528c2ecf20Sopenharmony_ci 5538c2ecf20Sopenharmony_ci if (compare_tev_args(ptevs + i, ptevs + i - 1) == 0) 5548c2ecf20Sopenharmony_ci mapping[n] = type; 5558c2ecf20Sopenharmony_ci else 5568c2ecf20Sopenharmony_ci mapping[n] = ++type; 5578c2ecf20Sopenharmony_ci 5588c2ecf20Sopenharmony_ci pr_debug("mapping[%d]=%d\n", n, mapping[n]); 5598c2ecf20Sopenharmony_ci } 5608c2ecf20Sopenharmony_ci free(ptevs); 5618c2ecf20Sopenharmony_ci *nr_types = type + 1; 5628c2ecf20Sopenharmony_ci 5638c2ecf20Sopenharmony_ci return 0; 5648c2ecf20Sopenharmony_ci} 5658c2ecf20Sopenharmony_ci 5668c2ecf20Sopenharmony_cistatic int hook_load_preprocessor(struct bpf_program *prog) 5678c2ecf20Sopenharmony_ci{ 5688c2ecf20Sopenharmony_ci struct bpf_prog_priv *priv = bpf_program__priv(prog); 5698c2ecf20Sopenharmony_ci struct perf_probe_event *pev; 5708c2ecf20Sopenharmony_ci bool need_prologue = false; 5718c2ecf20Sopenharmony_ci int err, i; 5728c2ecf20Sopenharmony_ci 5738c2ecf20Sopenharmony_ci if (IS_ERR(priv) || !priv) { 5748c2ecf20Sopenharmony_ci pr_debug("Internal error when hook preprocessor\n"); 5758c2ecf20Sopenharmony_ci return -BPF_LOADER_ERRNO__INTERNAL; 5768c2ecf20Sopenharmony_ci } 5778c2ecf20Sopenharmony_ci 5788c2ecf20Sopenharmony_ci if (priv->is_tp) { 5798c2ecf20Sopenharmony_ci priv->need_prologue = false; 5808c2ecf20Sopenharmony_ci return 0; 5818c2ecf20Sopenharmony_ci } 5828c2ecf20Sopenharmony_ci 5838c2ecf20Sopenharmony_ci pev = &priv->pev; 5848c2ecf20Sopenharmony_ci for (i = 0; i < pev->ntevs; i++) { 5858c2ecf20Sopenharmony_ci struct probe_trace_event *tev = &pev->tevs[i]; 5868c2ecf20Sopenharmony_ci 5878c2ecf20Sopenharmony_ci if (tev->nargs > 0) { 5888c2ecf20Sopenharmony_ci need_prologue = true; 5898c2ecf20Sopenharmony_ci break; 5908c2ecf20Sopenharmony_ci } 5918c2ecf20Sopenharmony_ci } 5928c2ecf20Sopenharmony_ci 5938c2ecf20Sopenharmony_ci /* 5948c2ecf20Sopenharmony_ci * Since all tevs don't have argument, we don't need generate 5958c2ecf20Sopenharmony_ci * prologue. 5968c2ecf20Sopenharmony_ci */ 5978c2ecf20Sopenharmony_ci if (!need_prologue) { 5988c2ecf20Sopenharmony_ci priv->need_prologue = false; 5998c2ecf20Sopenharmony_ci return 0; 6008c2ecf20Sopenharmony_ci } 6018c2ecf20Sopenharmony_ci 6028c2ecf20Sopenharmony_ci priv->need_prologue = true; 6038c2ecf20Sopenharmony_ci priv->insns_buf = malloc(sizeof(struct bpf_insn) * BPF_MAXINSNS); 6048c2ecf20Sopenharmony_ci if (!priv->insns_buf) { 6058c2ecf20Sopenharmony_ci pr_debug("Not enough memory: alloc insns_buf failed\n"); 6068c2ecf20Sopenharmony_ci return -ENOMEM; 6078c2ecf20Sopenharmony_ci } 6088c2ecf20Sopenharmony_ci 6098c2ecf20Sopenharmony_ci priv->type_mapping = malloc(sizeof(int) * pev->ntevs); 6108c2ecf20Sopenharmony_ci if (!priv->type_mapping) { 6118c2ecf20Sopenharmony_ci pr_debug("Not enough memory: alloc type_mapping failed\n"); 6128c2ecf20Sopenharmony_ci return -ENOMEM; 6138c2ecf20Sopenharmony_ci } 6148c2ecf20Sopenharmony_ci memset(priv->type_mapping, -1, 6158c2ecf20Sopenharmony_ci sizeof(int) * pev->ntevs); 6168c2ecf20Sopenharmony_ci 6178c2ecf20Sopenharmony_ci err = map_prologue(pev, priv->type_mapping, &priv->nr_types); 6188c2ecf20Sopenharmony_ci if (err) 6198c2ecf20Sopenharmony_ci return err; 6208c2ecf20Sopenharmony_ci 6218c2ecf20Sopenharmony_ci err = bpf_program__set_prep(prog, priv->nr_types, 6228c2ecf20Sopenharmony_ci preproc_gen_prologue); 6238c2ecf20Sopenharmony_ci return err; 6248c2ecf20Sopenharmony_ci} 6258c2ecf20Sopenharmony_ci 6268c2ecf20Sopenharmony_ciint bpf__probe(struct bpf_object *obj) 6278c2ecf20Sopenharmony_ci{ 6288c2ecf20Sopenharmony_ci int err = 0; 6298c2ecf20Sopenharmony_ci struct bpf_program *prog; 6308c2ecf20Sopenharmony_ci struct bpf_prog_priv *priv; 6318c2ecf20Sopenharmony_ci struct perf_probe_event *pev; 6328c2ecf20Sopenharmony_ci 6338c2ecf20Sopenharmony_ci err = bpf__prepare_probe(); 6348c2ecf20Sopenharmony_ci if (err) { 6358c2ecf20Sopenharmony_ci pr_debug("bpf__prepare_probe failed\n"); 6368c2ecf20Sopenharmony_ci return err; 6378c2ecf20Sopenharmony_ci } 6388c2ecf20Sopenharmony_ci 6398c2ecf20Sopenharmony_ci bpf_object__for_each_program(prog, obj) { 6408c2ecf20Sopenharmony_ci err = config_bpf_program(prog); 6418c2ecf20Sopenharmony_ci if (err) 6428c2ecf20Sopenharmony_ci goto out; 6438c2ecf20Sopenharmony_ci 6448c2ecf20Sopenharmony_ci priv = bpf_program__priv(prog); 6458c2ecf20Sopenharmony_ci if (IS_ERR(priv) || !priv) { 6468c2ecf20Sopenharmony_ci err = PTR_ERR(priv); 6478c2ecf20Sopenharmony_ci goto out; 6488c2ecf20Sopenharmony_ci } 6498c2ecf20Sopenharmony_ci 6508c2ecf20Sopenharmony_ci if (priv->is_tp) { 6518c2ecf20Sopenharmony_ci bpf_program__set_tracepoint(prog); 6528c2ecf20Sopenharmony_ci continue; 6538c2ecf20Sopenharmony_ci } 6548c2ecf20Sopenharmony_ci 6558c2ecf20Sopenharmony_ci bpf_program__set_kprobe(prog); 6568c2ecf20Sopenharmony_ci pev = &priv->pev; 6578c2ecf20Sopenharmony_ci 6588c2ecf20Sopenharmony_ci err = convert_perf_probe_events(pev, 1); 6598c2ecf20Sopenharmony_ci if (err < 0) { 6608c2ecf20Sopenharmony_ci pr_debug("bpf_probe: failed to convert perf probe events\n"); 6618c2ecf20Sopenharmony_ci goto out; 6628c2ecf20Sopenharmony_ci } 6638c2ecf20Sopenharmony_ci 6648c2ecf20Sopenharmony_ci err = apply_perf_probe_events(pev, 1); 6658c2ecf20Sopenharmony_ci if (err < 0) { 6668c2ecf20Sopenharmony_ci pr_debug("bpf_probe: failed to apply perf probe events\n"); 6678c2ecf20Sopenharmony_ci goto out; 6688c2ecf20Sopenharmony_ci } 6698c2ecf20Sopenharmony_ci 6708c2ecf20Sopenharmony_ci /* 6718c2ecf20Sopenharmony_ci * After probing, let's consider prologue, which 6728c2ecf20Sopenharmony_ci * adds program fetcher to BPF programs. 6738c2ecf20Sopenharmony_ci * 6748c2ecf20Sopenharmony_ci * hook_load_preprocessorr() hooks pre-processor 6758c2ecf20Sopenharmony_ci * to bpf_program, let it generate prologue 6768c2ecf20Sopenharmony_ci * dynamically during loading. 6778c2ecf20Sopenharmony_ci */ 6788c2ecf20Sopenharmony_ci err = hook_load_preprocessor(prog); 6798c2ecf20Sopenharmony_ci if (err) 6808c2ecf20Sopenharmony_ci goto out; 6818c2ecf20Sopenharmony_ci } 6828c2ecf20Sopenharmony_ciout: 6838c2ecf20Sopenharmony_ci return err < 0 ? err : 0; 6848c2ecf20Sopenharmony_ci} 6858c2ecf20Sopenharmony_ci 6868c2ecf20Sopenharmony_ci#define EVENTS_WRITE_BUFSIZE 4096 6878c2ecf20Sopenharmony_ciint bpf__unprobe(struct bpf_object *obj) 6888c2ecf20Sopenharmony_ci{ 6898c2ecf20Sopenharmony_ci int err, ret = 0; 6908c2ecf20Sopenharmony_ci struct bpf_program *prog; 6918c2ecf20Sopenharmony_ci 6928c2ecf20Sopenharmony_ci bpf_object__for_each_program(prog, obj) { 6938c2ecf20Sopenharmony_ci struct bpf_prog_priv *priv = bpf_program__priv(prog); 6948c2ecf20Sopenharmony_ci int i; 6958c2ecf20Sopenharmony_ci 6968c2ecf20Sopenharmony_ci if (IS_ERR(priv) || !priv || priv->is_tp) 6978c2ecf20Sopenharmony_ci continue; 6988c2ecf20Sopenharmony_ci 6998c2ecf20Sopenharmony_ci for (i = 0; i < priv->pev.ntevs; i++) { 7008c2ecf20Sopenharmony_ci struct probe_trace_event *tev = &priv->pev.tevs[i]; 7018c2ecf20Sopenharmony_ci char name_buf[EVENTS_WRITE_BUFSIZE]; 7028c2ecf20Sopenharmony_ci struct strfilter *delfilter; 7038c2ecf20Sopenharmony_ci 7048c2ecf20Sopenharmony_ci snprintf(name_buf, EVENTS_WRITE_BUFSIZE, 7058c2ecf20Sopenharmony_ci "%s:%s", tev->group, tev->event); 7068c2ecf20Sopenharmony_ci name_buf[EVENTS_WRITE_BUFSIZE - 1] = '\0'; 7078c2ecf20Sopenharmony_ci 7088c2ecf20Sopenharmony_ci delfilter = strfilter__new(name_buf, NULL); 7098c2ecf20Sopenharmony_ci if (!delfilter) { 7108c2ecf20Sopenharmony_ci pr_debug("Failed to create filter for unprobing\n"); 7118c2ecf20Sopenharmony_ci ret = -ENOMEM; 7128c2ecf20Sopenharmony_ci continue; 7138c2ecf20Sopenharmony_ci } 7148c2ecf20Sopenharmony_ci 7158c2ecf20Sopenharmony_ci err = del_perf_probe_events(delfilter); 7168c2ecf20Sopenharmony_ci strfilter__delete(delfilter); 7178c2ecf20Sopenharmony_ci if (err) { 7188c2ecf20Sopenharmony_ci pr_debug("Failed to delete %s\n", name_buf); 7198c2ecf20Sopenharmony_ci ret = err; 7208c2ecf20Sopenharmony_ci continue; 7218c2ecf20Sopenharmony_ci } 7228c2ecf20Sopenharmony_ci } 7238c2ecf20Sopenharmony_ci } 7248c2ecf20Sopenharmony_ci return ret; 7258c2ecf20Sopenharmony_ci} 7268c2ecf20Sopenharmony_ci 7278c2ecf20Sopenharmony_ciint bpf__load(struct bpf_object *obj) 7288c2ecf20Sopenharmony_ci{ 7298c2ecf20Sopenharmony_ci int err; 7308c2ecf20Sopenharmony_ci 7318c2ecf20Sopenharmony_ci err = bpf_object__load(obj); 7328c2ecf20Sopenharmony_ci if (err) { 7338c2ecf20Sopenharmony_ci char bf[128]; 7348c2ecf20Sopenharmony_ci libbpf_strerror(err, bf, sizeof(bf)); 7358c2ecf20Sopenharmony_ci pr_debug("bpf: load objects failed: err=%d: (%s)\n", err, bf); 7368c2ecf20Sopenharmony_ci return err; 7378c2ecf20Sopenharmony_ci } 7388c2ecf20Sopenharmony_ci return 0; 7398c2ecf20Sopenharmony_ci} 7408c2ecf20Sopenharmony_ci 7418c2ecf20Sopenharmony_ciint bpf__foreach_event(struct bpf_object *obj, 7428c2ecf20Sopenharmony_ci bpf_prog_iter_callback_t func, 7438c2ecf20Sopenharmony_ci void *arg) 7448c2ecf20Sopenharmony_ci{ 7458c2ecf20Sopenharmony_ci struct bpf_program *prog; 7468c2ecf20Sopenharmony_ci int err; 7478c2ecf20Sopenharmony_ci 7488c2ecf20Sopenharmony_ci bpf_object__for_each_program(prog, obj) { 7498c2ecf20Sopenharmony_ci struct bpf_prog_priv *priv = bpf_program__priv(prog); 7508c2ecf20Sopenharmony_ci struct probe_trace_event *tev; 7518c2ecf20Sopenharmony_ci struct perf_probe_event *pev; 7528c2ecf20Sopenharmony_ci int i, fd; 7538c2ecf20Sopenharmony_ci 7548c2ecf20Sopenharmony_ci if (IS_ERR(priv) || !priv) { 7558c2ecf20Sopenharmony_ci pr_debug("bpf: failed to get private field\n"); 7568c2ecf20Sopenharmony_ci return -BPF_LOADER_ERRNO__INTERNAL; 7578c2ecf20Sopenharmony_ci } 7588c2ecf20Sopenharmony_ci 7598c2ecf20Sopenharmony_ci if (priv->is_tp) { 7608c2ecf20Sopenharmony_ci fd = bpf_program__fd(prog); 7618c2ecf20Sopenharmony_ci err = (*func)(priv->sys_name, priv->evt_name, fd, obj, arg); 7628c2ecf20Sopenharmony_ci if (err) { 7638c2ecf20Sopenharmony_ci pr_debug("bpf: tracepoint call back failed, stop iterate\n"); 7648c2ecf20Sopenharmony_ci return err; 7658c2ecf20Sopenharmony_ci } 7668c2ecf20Sopenharmony_ci continue; 7678c2ecf20Sopenharmony_ci } 7688c2ecf20Sopenharmony_ci 7698c2ecf20Sopenharmony_ci pev = &priv->pev; 7708c2ecf20Sopenharmony_ci for (i = 0; i < pev->ntevs; i++) { 7718c2ecf20Sopenharmony_ci tev = &pev->tevs[i]; 7728c2ecf20Sopenharmony_ci 7738c2ecf20Sopenharmony_ci if (priv->need_prologue) { 7748c2ecf20Sopenharmony_ci int type = priv->type_mapping[i]; 7758c2ecf20Sopenharmony_ci 7768c2ecf20Sopenharmony_ci fd = bpf_program__nth_fd(prog, type); 7778c2ecf20Sopenharmony_ci } else { 7788c2ecf20Sopenharmony_ci fd = bpf_program__fd(prog); 7798c2ecf20Sopenharmony_ci } 7808c2ecf20Sopenharmony_ci 7818c2ecf20Sopenharmony_ci if (fd < 0) { 7828c2ecf20Sopenharmony_ci pr_debug("bpf: failed to get file descriptor\n"); 7838c2ecf20Sopenharmony_ci return fd; 7848c2ecf20Sopenharmony_ci } 7858c2ecf20Sopenharmony_ci 7868c2ecf20Sopenharmony_ci err = (*func)(tev->group, tev->event, fd, obj, arg); 7878c2ecf20Sopenharmony_ci if (err) { 7888c2ecf20Sopenharmony_ci pr_debug("bpf: call back failed, stop iterate\n"); 7898c2ecf20Sopenharmony_ci return err; 7908c2ecf20Sopenharmony_ci } 7918c2ecf20Sopenharmony_ci } 7928c2ecf20Sopenharmony_ci } 7938c2ecf20Sopenharmony_ci return 0; 7948c2ecf20Sopenharmony_ci} 7958c2ecf20Sopenharmony_ci 7968c2ecf20Sopenharmony_cienum bpf_map_op_type { 7978c2ecf20Sopenharmony_ci BPF_MAP_OP_SET_VALUE, 7988c2ecf20Sopenharmony_ci BPF_MAP_OP_SET_EVSEL, 7998c2ecf20Sopenharmony_ci}; 8008c2ecf20Sopenharmony_ci 8018c2ecf20Sopenharmony_cienum bpf_map_key_type { 8028c2ecf20Sopenharmony_ci BPF_MAP_KEY_ALL, 8038c2ecf20Sopenharmony_ci BPF_MAP_KEY_RANGES, 8048c2ecf20Sopenharmony_ci}; 8058c2ecf20Sopenharmony_ci 8068c2ecf20Sopenharmony_cistruct bpf_map_op { 8078c2ecf20Sopenharmony_ci struct list_head list; 8088c2ecf20Sopenharmony_ci enum bpf_map_op_type op_type; 8098c2ecf20Sopenharmony_ci enum bpf_map_key_type key_type; 8108c2ecf20Sopenharmony_ci union { 8118c2ecf20Sopenharmony_ci struct parse_events_array array; 8128c2ecf20Sopenharmony_ci } k; 8138c2ecf20Sopenharmony_ci union { 8148c2ecf20Sopenharmony_ci u64 value; 8158c2ecf20Sopenharmony_ci struct evsel *evsel; 8168c2ecf20Sopenharmony_ci } v; 8178c2ecf20Sopenharmony_ci}; 8188c2ecf20Sopenharmony_ci 8198c2ecf20Sopenharmony_cistruct bpf_map_priv { 8208c2ecf20Sopenharmony_ci struct list_head ops_list; 8218c2ecf20Sopenharmony_ci}; 8228c2ecf20Sopenharmony_ci 8238c2ecf20Sopenharmony_cistatic void 8248c2ecf20Sopenharmony_cibpf_map_op__delete(struct bpf_map_op *op) 8258c2ecf20Sopenharmony_ci{ 8268c2ecf20Sopenharmony_ci if (!list_empty(&op->list)) 8278c2ecf20Sopenharmony_ci list_del_init(&op->list); 8288c2ecf20Sopenharmony_ci if (op->key_type == BPF_MAP_KEY_RANGES) 8298c2ecf20Sopenharmony_ci parse_events__clear_array(&op->k.array); 8308c2ecf20Sopenharmony_ci free(op); 8318c2ecf20Sopenharmony_ci} 8328c2ecf20Sopenharmony_ci 8338c2ecf20Sopenharmony_cistatic void 8348c2ecf20Sopenharmony_cibpf_map_priv__purge(struct bpf_map_priv *priv) 8358c2ecf20Sopenharmony_ci{ 8368c2ecf20Sopenharmony_ci struct bpf_map_op *pos, *n; 8378c2ecf20Sopenharmony_ci 8388c2ecf20Sopenharmony_ci list_for_each_entry_safe(pos, n, &priv->ops_list, list) { 8398c2ecf20Sopenharmony_ci list_del_init(&pos->list); 8408c2ecf20Sopenharmony_ci bpf_map_op__delete(pos); 8418c2ecf20Sopenharmony_ci } 8428c2ecf20Sopenharmony_ci} 8438c2ecf20Sopenharmony_ci 8448c2ecf20Sopenharmony_cistatic void 8458c2ecf20Sopenharmony_cibpf_map_priv__clear(struct bpf_map *map __maybe_unused, 8468c2ecf20Sopenharmony_ci void *_priv) 8478c2ecf20Sopenharmony_ci{ 8488c2ecf20Sopenharmony_ci struct bpf_map_priv *priv = _priv; 8498c2ecf20Sopenharmony_ci 8508c2ecf20Sopenharmony_ci bpf_map_priv__purge(priv); 8518c2ecf20Sopenharmony_ci free(priv); 8528c2ecf20Sopenharmony_ci} 8538c2ecf20Sopenharmony_ci 8548c2ecf20Sopenharmony_cistatic int 8558c2ecf20Sopenharmony_cibpf_map_op_setkey(struct bpf_map_op *op, struct parse_events_term *term) 8568c2ecf20Sopenharmony_ci{ 8578c2ecf20Sopenharmony_ci op->key_type = BPF_MAP_KEY_ALL; 8588c2ecf20Sopenharmony_ci if (!term) 8598c2ecf20Sopenharmony_ci return 0; 8608c2ecf20Sopenharmony_ci 8618c2ecf20Sopenharmony_ci if (term->array.nr_ranges) { 8628c2ecf20Sopenharmony_ci size_t memsz = term->array.nr_ranges * 8638c2ecf20Sopenharmony_ci sizeof(op->k.array.ranges[0]); 8648c2ecf20Sopenharmony_ci 8658c2ecf20Sopenharmony_ci op->k.array.ranges = memdup(term->array.ranges, memsz); 8668c2ecf20Sopenharmony_ci if (!op->k.array.ranges) { 8678c2ecf20Sopenharmony_ci pr_debug("Not enough memory to alloc indices for map\n"); 8688c2ecf20Sopenharmony_ci return -ENOMEM; 8698c2ecf20Sopenharmony_ci } 8708c2ecf20Sopenharmony_ci op->key_type = BPF_MAP_KEY_RANGES; 8718c2ecf20Sopenharmony_ci op->k.array.nr_ranges = term->array.nr_ranges; 8728c2ecf20Sopenharmony_ci } 8738c2ecf20Sopenharmony_ci return 0; 8748c2ecf20Sopenharmony_ci} 8758c2ecf20Sopenharmony_ci 8768c2ecf20Sopenharmony_cistatic struct bpf_map_op * 8778c2ecf20Sopenharmony_cibpf_map_op__new(struct parse_events_term *term) 8788c2ecf20Sopenharmony_ci{ 8798c2ecf20Sopenharmony_ci struct bpf_map_op *op; 8808c2ecf20Sopenharmony_ci int err; 8818c2ecf20Sopenharmony_ci 8828c2ecf20Sopenharmony_ci op = zalloc(sizeof(*op)); 8838c2ecf20Sopenharmony_ci if (!op) { 8848c2ecf20Sopenharmony_ci pr_debug("Failed to alloc bpf_map_op\n"); 8858c2ecf20Sopenharmony_ci return ERR_PTR(-ENOMEM); 8868c2ecf20Sopenharmony_ci } 8878c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&op->list); 8888c2ecf20Sopenharmony_ci 8898c2ecf20Sopenharmony_ci err = bpf_map_op_setkey(op, term); 8908c2ecf20Sopenharmony_ci if (err) { 8918c2ecf20Sopenharmony_ci free(op); 8928c2ecf20Sopenharmony_ci return ERR_PTR(err); 8938c2ecf20Sopenharmony_ci } 8948c2ecf20Sopenharmony_ci return op; 8958c2ecf20Sopenharmony_ci} 8968c2ecf20Sopenharmony_ci 8978c2ecf20Sopenharmony_cistatic struct bpf_map_op * 8988c2ecf20Sopenharmony_cibpf_map_op__clone(struct bpf_map_op *op) 8998c2ecf20Sopenharmony_ci{ 9008c2ecf20Sopenharmony_ci struct bpf_map_op *newop; 9018c2ecf20Sopenharmony_ci 9028c2ecf20Sopenharmony_ci newop = memdup(op, sizeof(*op)); 9038c2ecf20Sopenharmony_ci if (!newop) { 9048c2ecf20Sopenharmony_ci pr_debug("Failed to alloc bpf_map_op\n"); 9058c2ecf20Sopenharmony_ci return NULL; 9068c2ecf20Sopenharmony_ci } 9078c2ecf20Sopenharmony_ci 9088c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&newop->list); 9098c2ecf20Sopenharmony_ci if (op->key_type == BPF_MAP_KEY_RANGES) { 9108c2ecf20Sopenharmony_ci size_t memsz = op->k.array.nr_ranges * 9118c2ecf20Sopenharmony_ci sizeof(op->k.array.ranges[0]); 9128c2ecf20Sopenharmony_ci 9138c2ecf20Sopenharmony_ci newop->k.array.ranges = memdup(op->k.array.ranges, memsz); 9148c2ecf20Sopenharmony_ci if (!newop->k.array.ranges) { 9158c2ecf20Sopenharmony_ci pr_debug("Failed to alloc indices for map\n"); 9168c2ecf20Sopenharmony_ci free(newop); 9178c2ecf20Sopenharmony_ci return NULL; 9188c2ecf20Sopenharmony_ci } 9198c2ecf20Sopenharmony_ci } 9208c2ecf20Sopenharmony_ci 9218c2ecf20Sopenharmony_ci return newop; 9228c2ecf20Sopenharmony_ci} 9238c2ecf20Sopenharmony_ci 9248c2ecf20Sopenharmony_cistatic struct bpf_map_priv * 9258c2ecf20Sopenharmony_cibpf_map_priv__clone(struct bpf_map_priv *priv) 9268c2ecf20Sopenharmony_ci{ 9278c2ecf20Sopenharmony_ci struct bpf_map_priv *newpriv; 9288c2ecf20Sopenharmony_ci struct bpf_map_op *pos, *newop; 9298c2ecf20Sopenharmony_ci 9308c2ecf20Sopenharmony_ci newpriv = zalloc(sizeof(*newpriv)); 9318c2ecf20Sopenharmony_ci if (!newpriv) { 9328c2ecf20Sopenharmony_ci pr_debug("Not enough memory to alloc map private\n"); 9338c2ecf20Sopenharmony_ci return NULL; 9348c2ecf20Sopenharmony_ci } 9358c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&newpriv->ops_list); 9368c2ecf20Sopenharmony_ci 9378c2ecf20Sopenharmony_ci list_for_each_entry(pos, &priv->ops_list, list) { 9388c2ecf20Sopenharmony_ci newop = bpf_map_op__clone(pos); 9398c2ecf20Sopenharmony_ci if (!newop) { 9408c2ecf20Sopenharmony_ci bpf_map_priv__purge(newpriv); 9418c2ecf20Sopenharmony_ci return NULL; 9428c2ecf20Sopenharmony_ci } 9438c2ecf20Sopenharmony_ci list_add_tail(&newop->list, &newpriv->ops_list); 9448c2ecf20Sopenharmony_ci } 9458c2ecf20Sopenharmony_ci 9468c2ecf20Sopenharmony_ci return newpriv; 9478c2ecf20Sopenharmony_ci} 9488c2ecf20Sopenharmony_ci 9498c2ecf20Sopenharmony_cistatic int 9508c2ecf20Sopenharmony_cibpf_map__add_op(struct bpf_map *map, struct bpf_map_op *op) 9518c2ecf20Sopenharmony_ci{ 9528c2ecf20Sopenharmony_ci const char *map_name = bpf_map__name(map); 9538c2ecf20Sopenharmony_ci struct bpf_map_priv *priv = bpf_map__priv(map); 9548c2ecf20Sopenharmony_ci 9558c2ecf20Sopenharmony_ci if (IS_ERR(priv)) { 9568c2ecf20Sopenharmony_ci pr_debug("Failed to get private from map %s\n", map_name); 9578c2ecf20Sopenharmony_ci return PTR_ERR(priv); 9588c2ecf20Sopenharmony_ci } 9598c2ecf20Sopenharmony_ci 9608c2ecf20Sopenharmony_ci if (!priv) { 9618c2ecf20Sopenharmony_ci priv = zalloc(sizeof(*priv)); 9628c2ecf20Sopenharmony_ci if (!priv) { 9638c2ecf20Sopenharmony_ci pr_debug("Not enough memory to alloc map private\n"); 9648c2ecf20Sopenharmony_ci return -ENOMEM; 9658c2ecf20Sopenharmony_ci } 9668c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&priv->ops_list); 9678c2ecf20Sopenharmony_ci 9688c2ecf20Sopenharmony_ci if (bpf_map__set_priv(map, priv, bpf_map_priv__clear)) { 9698c2ecf20Sopenharmony_ci free(priv); 9708c2ecf20Sopenharmony_ci return -BPF_LOADER_ERRNO__INTERNAL; 9718c2ecf20Sopenharmony_ci } 9728c2ecf20Sopenharmony_ci } 9738c2ecf20Sopenharmony_ci 9748c2ecf20Sopenharmony_ci list_add_tail(&op->list, &priv->ops_list); 9758c2ecf20Sopenharmony_ci return 0; 9768c2ecf20Sopenharmony_ci} 9778c2ecf20Sopenharmony_ci 9788c2ecf20Sopenharmony_cistatic struct bpf_map_op * 9798c2ecf20Sopenharmony_cibpf_map__add_newop(struct bpf_map *map, struct parse_events_term *term) 9808c2ecf20Sopenharmony_ci{ 9818c2ecf20Sopenharmony_ci struct bpf_map_op *op; 9828c2ecf20Sopenharmony_ci int err; 9838c2ecf20Sopenharmony_ci 9848c2ecf20Sopenharmony_ci op = bpf_map_op__new(term); 9858c2ecf20Sopenharmony_ci if (IS_ERR(op)) 9868c2ecf20Sopenharmony_ci return op; 9878c2ecf20Sopenharmony_ci 9888c2ecf20Sopenharmony_ci err = bpf_map__add_op(map, op); 9898c2ecf20Sopenharmony_ci if (err) { 9908c2ecf20Sopenharmony_ci bpf_map_op__delete(op); 9918c2ecf20Sopenharmony_ci return ERR_PTR(err); 9928c2ecf20Sopenharmony_ci } 9938c2ecf20Sopenharmony_ci return op; 9948c2ecf20Sopenharmony_ci} 9958c2ecf20Sopenharmony_ci 9968c2ecf20Sopenharmony_cistatic int 9978c2ecf20Sopenharmony_ci__bpf_map__config_value(struct bpf_map *map, 9988c2ecf20Sopenharmony_ci struct parse_events_term *term) 9998c2ecf20Sopenharmony_ci{ 10008c2ecf20Sopenharmony_ci struct bpf_map_op *op; 10018c2ecf20Sopenharmony_ci const char *map_name = bpf_map__name(map); 10028c2ecf20Sopenharmony_ci const struct bpf_map_def *def = bpf_map__def(map); 10038c2ecf20Sopenharmony_ci 10048c2ecf20Sopenharmony_ci if (IS_ERR(def)) { 10058c2ecf20Sopenharmony_ci pr_debug("Unable to get map definition from '%s'\n", 10068c2ecf20Sopenharmony_ci map_name); 10078c2ecf20Sopenharmony_ci return -BPF_LOADER_ERRNO__INTERNAL; 10088c2ecf20Sopenharmony_ci } 10098c2ecf20Sopenharmony_ci 10108c2ecf20Sopenharmony_ci if (def->type != BPF_MAP_TYPE_ARRAY) { 10118c2ecf20Sopenharmony_ci pr_debug("Map %s type is not BPF_MAP_TYPE_ARRAY\n", 10128c2ecf20Sopenharmony_ci map_name); 10138c2ecf20Sopenharmony_ci return -BPF_LOADER_ERRNO__OBJCONF_MAP_TYPE; 10148c2ecf20Sopenharmony_ci } 10158c2ecf20Sopenharmony_ci if (def->key_size < sizeof(unsigned int)) { 10168c2ecf20Sopenharmony_ci pr_debug("Map %s has incorrect key size\n", map_name); 10178c2ecf20Sopenharmony_ci return -BPF_LOADER_ERRNO__OBJCONF_MAP_KEYSIZE; 10188c2ecf20Sopenharmony_ci } 10198c2ecf20Sopenharmony_ci switch (def->value_size) { 10208c2ecf20Sopenharmony_ci case 1: 10218c2ecf20Sopenharmony_ci case 2: 10228c2ecf20Sopenharmony_ci case 4: 10238c2ecf20Sopenharmony_ci case 8: 10248c2ecf20Sopenharmony_ci break; 10258c2ecf20Sopenharmony_ci default: 10268c2ecf20Sopenharmony_ci pr_debug("Map %s has incorrect value size\n", map_name); 10278c2ecf20Sopenharmony_ci return -BPF_LOADER_ERRNO__OBJCONF_MAP_VALUESIZE; 10288c2ecf20Sopenharmony_ci } 10298c2ecf20Sopenharmony_ci 10308c2ecf20Sopenharmony_ci op = bpf_map__add_newop(map, term); 10318c2ecf20Sopenharmony_ci if (IS_ERR(op)) 10328c2ecf20Sopenharmony_ci return PTR_ERR(op); 10338c2ecf20Sopenharmony_ci op->op_type = BPF_MAP_OP_SET_VALUE; 10348c2ecf20Sopenharmony_ci op->v.value = term->val.num; 10358c2ecf20Sopenharmony_ci return 0; 10368c2ecf20Sopenharmony_ci} 10378c2ecf20Sopenharmony_ci 10388c2ecf20Sopenharmony_cistatic int 10398c2ecf20Sopenharmony_cibpf_map__config_value(struct bpf_map *map, 10408c2ecf20Sopenharmony_ci struct parse_events_term *term, 10418c2ecf20Sopenharmony_ci struct evlist *evlist __maybe_unused) 10428c2ecf20Sopenharmony_ci{ 10438c2ecf20Sopenharmony_ci if (!term->err_val) { 10448c2ecf20Sopenharmony_ci pr_debug("Config value not set\n"); 10458c2ecf20Sopenharmony_ci return -BPF_LOADER_ERRNO__OBJCONF_CONF; 10468c2ecf20Sopenharmony_ci } 10478c2ecf20Sopenharmony_ci 10488c2ecf20Sopenharmony_ci if (term->type_val != PARSE_EVENTS__TERM_TYPE_NUM) { 10498c2ecf20Sopenharmony_ci pr_debug("ERROR: wrong value type for 'value'\n"); 10508c2ecf20Sopenharmony_ci return -BPF_LOADER_ERRNO__OBJCONF_MAP_VALUE; 10518c2ecf20Sopenharmony_ci } 10528c2ecf20Sopenharmony_ci 10538c2ecf20Sopenharmony_ci return __bpf_map__config_value(map, term); 10548c2ecf20Sopenharmony_ci} 10558c2ecf20Sopenharmony_ci 10568c2ecf20Sopenharmony_cistatic int 10578c2ecf20Sopenharmony_ci__bpf_map__config_event(struct bpf_map *map, 10588c2ecf20Sopenharmony_ci struct parse_events_term *term, 10598c2ecf20Sopenharmony_ci struct evlist *evlist) 10608c2ecf20Sopenharmony_ci{ 10618c2ecf20Sopenharmony_ci struct evsel *evsel; 10628c2ecf20Sopenharmony_ci const struct bpf_map_def *def; 10638c2ecf20Sopenharmony_ci struct bpf_map_op *op; 10648c2ecf20Sopenharmony_ci const char *map_name = bpf_map__name(map); 10658c2ecf20Sopenharmony_ci 10668c2ecf20Sopenharmony_ci evsel = perf_evlist__find_evsel_by_str(evlist, term->val.str); 10678c2ecf20Sopenharmony_ci if (!evsel) { 10688c2ecf20Sopenharmony_ci pr_debug("Event (for '%s') '%s' doesn't exist\n", 10698c2ecf20Sopenharmony_ci map_name, term->val.str); 10708c2ecf20Sopenharmony_ci return -BPF_LOADER_ERRNO__OBJCONF_MAP_NOEVT; 10718c2ecf20Sopenharmony_ci } 10728c2ecf20Sopenharmony_ci 10738c2ecf20Sopenharmony_ci def = bpf_map__def(map); 10748c2ecf20Sopenharmony_ci if (IS_ERR(def)) { 10758c2ecf20Sopenharmony_ci pr_debug("Unable to get map definition from '%s'\n", 10768c2ecf20Sopenharmony_ci map_name); 10778c2ecf20Sopenharmony_ci return PTR_ERR(def); 10788c2ecf20Sopenharmony_ci } 10798c2ecf20Sopenharmony_ci 10808c2ecf20Sopenharmony_ci /* 10818c2ecf20Sopenharmony_ci * No need to check key_size and value_size: 10828c2ecf20Sopenharmony_ci * kernel has already checked them. 10838c2ecf20Sopenharmony_ci */ 10848c2ecf20Sopenharmony_ci if (def->type != BPF_MAP_TYPE_PERF_EVENT_ARRAY) { 10858c2ecf20Sopenharmony_ci pr_debug("Map %s type is not BPF_MAP_TYPE_PERF_EVENT_ARRAY\n", 10868c2ecf20Sopenharmony_ci map_name); 10878c2ecf20Sopenharmony_ci return -BPF_LOADER_ERRNO__OBJCONF_MAP_TYPE; 10888c2ecf20Sopenharmony_ci } 10898c2ecf20Sopenharmony_ci 10908c2ecf20Sopenharmony_ci op = bpf_map__add_newop(map, term); 10918c2ecf20Sopenharmony_ci if (IS_ERR(op)) 10928c2ecf20Sopenharmony_ci return PTR_ERR(op); 10938c2ecf20Sopenharmony_ci op->op_type = BPF_MAP_OP_SET_EVSEL; 10948c2ecf20Sopenharmony_ci op->v.evsel = evsel; 10958c2ecf20Sopenharmony_ci return 0; 10968c2ecf20Sopenharmony_ci} 10978c2ecf20Sopenharmony_ci 10988c2ecf20Sopenharmony_cistatic int 10998c2ecf20Sopenharmony_cibpf_map__config_event(struct bpf_map *map, 11008c2ecf20Sopenharmony_ci struct parse_events_term *term, 11018c2ecf20Sopenharmony_ci struct evlist *evlist) 11028c2ecf20Sopenharmony_ci{ 11038c2ecf20Sopenharmony_ci if (!term->err_val) { 11048c2ecf20Sopenharmony_ci pr_debug("Config value not set\n"); 11058c2ecf20Sopenharmony_ci return -BPF_LOADER_ERRNO__OBJCONF_CONF; 11068c2ecf20Sopenharmony_ci } 11078c2ecf20Sopenharmony_ci 11088c2ecf20Sopenharmony_ci if (term->type_val != PARSE_EVENTS__TERM_TYPE_STR) { 11098c2ecf20Sopenharmony_ci pr_debug("ERROR: wrong value type for 'event'\n"); 11108c2ecf20Sopenharmony_ci return -BPF_LOADER_ERRNO__OBJCONF_MAP_VALUE; 11118c2ecf20Sopenharmony_ci } 11128c2ecf20Sopenharmony_ci 11138c2ecf20Sopenharmony_ci return __bpf_map__config_event(map, term, evlist); 11148c2ecf20Sopenharmony_ci} 11158c2ecf20Sopenharmony_ci 11168c2ecf20Sopenharmony_cistruct bpf_obj_config__map_func { 11178c2ecf20Sopenharmony_ci const char *config_opt; 11188c2ecf20Sopenharmony_ci int (*config_func)(struct bpf_map *, struct parse_events_term *, 11198c2ecf20Sopenharmony_ci struct evlist *); 11208c2ecf20Sopenharmony_ci}; 11218c2ecf20Sopenharmony_ci 11228c2ecf20Sopenharmony_cistruct bpf_obj_config__map_func bpf_obj_config__map_funcs[] = { 11238c2ecf20Sopenharmony_ci {"value", bpf_map__config_value}, 11248c2ecf20Sopenharmony_ci {"event", bpf_map__config_event}, 11258c2ecf20Sopenharmony_ci}; 11268c2ecf20Sopenharmony_ci 11278c2ecf20Sopenharmony_cistatic int 11288c2ecf20Sopenharmony_ciconfig_map_indices_range_check(struct parse_events_term *term, 11298c2ecf20Sopenharmony_ci struct bpf_map *map, 11308c2ecf20Sopenharmony_ci const char *map_name) 11318c2ecf20Sopenharmony_ci{ 11328c2ecf20Sopenharmony_ci struct parse_events_array *array = &term->array; 11338c2ecf20Sopenharmony_ci const struct bpf_map_def *def; 11348c2ecf20Sopenharmony_ci unsigned int i; 11358c2ecf20Sopenharmony_ci 11368c2ecf20Sopenharmony_ci if (!array->nr_ranges) 11378c2ecf20Sopenharmony_ci return 0; 11388c2ecf20Sopenharmony_ci if (!array->ranges) { 11398c2ecf20Sopenharmony_ci pr_debug("ERROR: map %s: array->nr_ranges is %d but range array is NULL\n", 11408c2ecf20Sopenharmony_ci map_name, (int)array->nr_ranges); 11418c2ecf20Sopenharmony_ci return -BPF_LOADER_ERRNO__INTERNAL; 11428c2ecf20Sopenharmony_ci } 11438c2ecf20Sopenharmony_ci 11448c2ecf20Sopenharmony_ci def = bpf_map__def(map); 11458c2ecf20Sopenharmony_ci if (IS_ERR(def)) { 11468c2ecf20Sopenharmony_ci pr_debug("ERROR: Unable to get map definition from '%s'\n", 11478c2ecf20Sopenharmony_ci map_name); 11488c2ecf20Sopenharmony_ci return -BPF_LOADER_ERRNO__INTERNAL; 11498c2ecf20Sopenharmony_ci } 11508c2ecf20Sopenharmony_ci 11518c2ecf20Sopenharmony_ci for (i = 0; i < array->nr_ranges; i++) { 11528c2ecf20Sopenharmony_ci unsigned int start = array->ranges[i].start; 11538c2ecf20Sopenharmony_ci size_t length = array->ranges[i].length; 11548c2ecf20Sopenharmony_ci unsigned int idx = start + length - 1; 11558c2ecf20Sopenharmony_ci 11568c2ecf20Sopenharmony_ci if (idx >= def->max_entries) { 11578c2ecf20Sopenharmony_ci pr_debug("ERROR: index %d too large\n", idx); 11588c2ecf20Sopenharmony_ci return -BPF_LOADER_ERRNO__OBJCONF_MAP_IDX2BIG; 11598c2ecf20Sopenharmony_ci } 11608c2ecf20Sopenharmony_ci } 11618c2ecf20Sopenharmony_ci return 0; 11628c2ecf20Sopenharmony_ci} 11638c2ecf20Sopenharmony_ci 11648c2ecf20Sopenharmony_cistatic int 11658c2ecf20Sopenharmony_cibpf__obj_config_map(struct bpf_object *obj, 11668c2ecf20Sopenharmony_ci struct parse_events_term *term, 11678c2ecf20Sopenharmony_ci struct evlist *evlist, 11688c2ecf20Sopenharmony_ci int *key_scan_pos) 11698c2ecf20Sopenharmony_ci{ 11708c2ecf20Sopenharmony_ci /* key is "map:<mapname>.<config opt>" */ 11718c2ecf20Sopenharmony_ci char *map_name = strdup(term->config + sizeof("map:") - 1); 11728c2ecf20Sopenharmony_ci struct bpf_map *map; 11738c2ecf20Sopenharmony_ci int err = -BPF_LOADER_ERRNO__OBJCONF_OPT; 11748c2ecf20Sopenharmony_ci char *map_opt; 11758c2ecf20Sopenharmony_ci size_t i; 11768c2ecf20Sopenharmony_ci 11778c2ecf20Sopenharmony_ci if (!map_name) 11788c2ecf20Sopenharmony_ci return -ENOMEM; 11798c2ecf20Sopenharmony_ci 11808c2ecf20Sopenharmony_ci map_opt = strchr(map_name, '.'); 11818c2ecf20Sopenharmony_ci if (!map_opt) { 11828c2ecf20Sopenharmony_ci pr_debug("ERROR: Invalid map config: %s\n", map_name); 11838c2ecf20Sopenharmony_ci goto out; 11848c2ecf20Sopenharmony_ci } 11858c2ecf20Sopenharmony_ci 11868c2ecf20Sopenharmony_ci *map_opt++ = '\0'; 11878c2ecf20Sopenharmony_ci if (*map_opt == '\0') { 11888c2ecf20Sopenharmony_ci pr_debug("ERROR: Invalid map option: %s\n", term->config); 11898c2ecf20Sopenharmony_ci goto out; 11908c2ecf20Sopenharmony_ci } 11918c2ecf20Sopenharmony_ci 11928c2ecf20Sopenharmony_ci map = bpf_object__find_map_by_name(obj, map_name); 11938c2ecf20Sopenharmony_ci if (!map) { 11948c2ecf20Sopenharmony_ci pr_debug("ERROR: Map %s doesn't exist\n", map_name); 11958c2ecf20Sopenharmony_ci err = -BPF_LOADER_ERRNO__OBJCONF_MAP_NOTEXIST; 11968c2ecf20Sopenharmony_ci goto out; 11978c2ecf20Sopenharmony_ci } 11988c2ecf20Sopenharmony_ci 11998c2ecf20Sopenharmony_ci *key_scan_pos += strlen(map_opt); 12008c2ecf20Sopenharmony_ci err = config_map_indices_range_check(term, map, map_name); 12018c2ecf20Sopenharmony_ci if (err) 12028c2ecf20Sopenharmony_ci goto out; 12038c2ecf20Sopenharmony_ci *key_scan_pos -= strlen(map_opt); 12048c2ecf20Sopenharmony_ci 12058c2ecf20Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(bpf_obj_config__map_funcs); i++) { 12068c2ecf20Sopenharmony_ci struct bpf_obj_config__map_func *func = 12078c2ecf20Sopenharmony_ci &bpf_obj_config__map_funcs[i]; 12088c2ecf20Sopenharmony_ci 12098c2ecf20Sopenharmony_ci if (strcmp(map_opt, func->config_opt) == 0) { 12108c2ecf20Sopenharmony_ci err = func->config_func(map, term, evlist); 12118c2ecf20Sopenharmony_ci goto out; 12128c2ecf20Sopenharmony_ci } 12138c2ecf20Sopenharmony_ci } 12148c2ecf20Sopenharmony_ci 12158c2ecf20Sopenharmony_ci pr_debug("ERROR: Invalid map config option '%s'\n", map_opt); 12168c2ecf20Sopenharmony_ci err = -BPF_LOADER_ERRNO__OBJCONF_MAP_OPT; 12178c2ecf20Sopenharmony_ciout: 12188c2ecf20Sopenharmony_ci if (!err) 12198c2ecf20Sopenharmony_ci *key_scan_pos += strlen(map_opt); 12208c2ecf20Sopenharmony_ci 12218c2ecf20Sopenharmony_ci free(map_name); 12228c2ecf20Sopenharmony_ci return err; 12238c2ecf20Sopenharmony_ci} 12248c2ecf20Sopenharmony_ci 12258c2ecf20Sopenharmony_ciint bpf__config_obj(struct bpf_object *obj, 12268c2ecf20Sopenharmony_ci struct parse_events_term *term, 12278c2ecf20Sopenharmony_ci struct evlist *evlist, 12288c2ecf20Sopenharmony_ci int *error_pos) 12298c2ecf20Sopenharmony_ci{ 12308c2ecf20Sopenharmony_ci int key_scan_pos = 0; 12318c2ecf20Sopenharmony_ci int err; 12328c2ecf20Sopenharmony_ci 12338c2ecf20Sopenharmony_ci if (!obj || !term || !term->config) 12348c2ecf20Sopenharmony_ci return -EINVAL; 12358c2ecf20Sopenharmony_ci 12368c2ecf20Sopenharmony_ci if (strstarts(term->config, "map:")) { 12378c2ecf20Sopenharmony_ci key_scan_pos = sizeof("map:") - 1; 12388c2ecf20Sopenharmony_ci err = bpf__obj_config_map(obj, term, evlist, &key_scan_pos); 12398c2ecf20Sopenharmony_ci goto out; 12408c2ecf20Sopenharmony_ci } 12418c2ecf20Sopenharmony_ci err = -BPF_LOADER_ERRNO__OBJCONF_OPT; 12428c2ecf20Sopenharmony_ciout: 12438c2ecf20Sopenharmony_ci if (error_pos) 12448c2ecf20Sopenharmony_ci *error_pos = key_scan_pos; 12458c2ecf20Sopenharmony_ci return err; 12468c2ecf20Sopenharmony_ci 12478c2ecf20Sopenharmony_ci} 12488c2ecf20Sopenharmony_ci 12498c2ecf20Sopenharmony_citypedef int (*map_config_func_t)(const char *name, int map_fd, 12508c2ecf20Sopenharmony_ci const struct bpf_map_def *pdef, 12518c2ecf20Sopenharmony_ci struct bpf_map_op *op, 12528c2ecf20Sopenharmony_ci void *pkey, void *arg); 12538c2ecf20Sopenharmony_ci 12548c2ecf20Sopenharmony_cistatic int 12558c2ecf20Sopenharmony_ciforeach_key_array_all(map_config_func_t func, 12568c2ecf20Sopenharmony_ci void *arg, const char *name, 12578c2ecf20Sopenharmony_ci int map_fd, const struct bpf_map_def *pdef, 12588c2ecf20Sopenharmony_ci struct bpf_map_op *op) 12598c2ecf20Sopenharmony_ci{ 12608c2ecf20Sopenharmony_ci unsigned int i; 12618c2ecf20Sopenharmony_ci int err; 12628c2ecf20Sopenharmony_ci 12638c2ecf20Sopenharmony_ci for (i = 0; i < pdef->max_entries; i++) { 12648c2ecf20Sopenharmony_ci err = func(name, map_fd, pdef, op, &i, arg); 12658c2ecf20Sopenharmony_ci if (err) { 12668c2ecf20Sopenharmony_ci pr_debug("ERROR: failed to insert value to %s[%u]\n", 12678c2ecf20Sopenharmony_ci name, i); 12688c2ecf20Sopenharmony_ci return err; 12698c2ecf20Sopenharmony_ci } 12708c2ecf20Sopenharmony_ci } 12718c2ecf20Sopenharmony_ci return 0; 12728c2ecf20Sopenharmony_ci} 12738c2ecf20Sopenharmony_ci 12748c2ecf20Sopenharmony_cistatic int 12758c2ecf20Sopenharmony_ciforeach_key_array_ranges(map_config_func_t func, void *arg, 12768c2ecf20Sopenharmony_ci const char *name, int map_fd, 12778c2ecf20Sopenharmony_ci const struct bpf_map_def *pdef, 12788c2ecf20Sopenharmony_ci struct bpf_map_op *op) 12798c2ecf20Sopenharmony_ci{ 12808c2ecf20Sopenharmony_ci unsigned int i, j; 12818c2ecf20Sopenharmony_ci int err; 12828c2ecf20Sopenharmony_ci 12838c2ecf20Sopenharmony_ci for (i = 0; i < op->k.array.nr_ranges; i++) { 12848c2ecf20Sopenharmony_ci unsigned int start = op->k.array.ranges[i].start; 12858c2ecf20Sopenharmony_ci size_t length = op->k.array.ranges[i].length; 12868c2ecf20Sopenharmony_ci 12878c2ecf20Sopenharmony_ci for (j = 0; j < length; j++) { 12888c2ecf20Sopenharmony_ci unsigned int idx = start + j; 12898c2ecf20Sopenharmony_ci 12908c2ecf20Sopenharmony_ci err = func(name, map_fd, pdef, op, &idx, arg); 12918c2ecf20Sopenharmony_ci if (err) { 12928c2ecf20Sopenharmony_ci pr_debug("ERROR: failed to insert value to %s[%u]\n", 12938c2ecf20Sopenharmony_ci name, idx); 12948c2ecf20Sopenharmony_ci return err; 12958c2ecf20Sopenharmony_ci } 12968c2ecf20Sopenharmony_ci } 12978c2ecf20Sopenharmony_ci } 12988c2ecf20Sopenharmony_ci return 0; 12998c2ecf20Sopenharmony_ci} 13008c2ecf20Sopenharmony_ci 13018c2ecf20Sopenharmony_cistatic int 13028c2ecf20Sopenharmony_cibpf_map_config_foreach_key(struct bpf_map *map, 13038c2ecf20Sopenharmony_ci map_config_func_t func, 13048c2ecf20Sopenharmony_ci void *arg) 13058c2ecf20Sopenharmony_ci{ 13068c2ecf20Sopenharmony_ci int err, map_fd; 13078c2ecf20Sopenharmony_ci struct bpf_map_op *op; 13088c2ecf20Sopenharmony_ci const struct bpf_map_def *def; 13098c2ecf20Sopenharmony_ci const char *name = bpf_map__name(map); 13108c2ecf20Sopenharmony_ci struct bpf_map_priv *priv = bpf_map__priv(map); 13118c2ecf20Sopenharmony_ci 13128c2ecf20Sopenharmony_ci if (IS_ERR(priv)) { 13138c2ecf20Sopenharmony_ci pr_debug("ERROR: failed to get private from map %s\n", name); 13148c2ecf20Sopenharmony_ci return -BPF_LOADER_ERRNO__INTERNAL; 13158c2ecf20Sopenharmony_ci } 13168c2ecf20Sopenharmony_ci if (!priv || list_empty(&priv->ops_list)) { 13178c2ecf20Sopenharmony_ci pr_debug("INFO: nothing to config for map %s\n", name); 13188c2ecf20Sopenharmony_ci return 0; 13198c2ecf20Sopenharmony_ci } 13208c2ecf20Sopenharmony_ci 13218c2ecf20Sopenharmony_ci def = bpf_map__def(map); 13228c2ecf20Sopenharmony_ci if (IS_ERR(def)) { 13238c2ecf20Sopenharmony_ci pr_debug("ERROR: failed to get definition from map %s\n", name); 13248c2ecf20Sopenharmony_ci return -BPF_LOADER_ERRNO__INTERNAL; 13258c2ecf20Sopenharmony_ci } 13268c2ecf20Sopenharmony_ci map_fd = bpf_map__fd(map); 13278c2ecf20Sopenharmony_ci if (map_fd < 0) { 13288c2ecf20Sopenharmony_ci pr_debug("ERROR: failed to get fd from map %s\n", name); 13298c2ecf20Sopenharmony_ci return map_fd; 13308c2ecf20Sopenharmony_ci } 13318c2ecf20Sopenharmony_ci 13328c2ecf20Sopenharmony_ci list_for_each_entry(op, &priv->ops_list, list) { 13338c2ecf20Sopenharmony_ci switch (def->type) { 13348c2ecf20Sopenharmony_ci case BPF_MAP_TYPE_ARRAY: 13358c2ecf20Sopenharmony_ci case BPF_MAP_TYPE_PERF_EVENT_ARRAY: 13368c2ecf20Sopenharmony_ci switch (op->key_type) { 13378c2ecf20Sopenharmony_ci case BPF_MAP_KEY_ALL: 13388c2ecf20Sopenharmony_ci err = foreach_key_array_all(func, arg, name, 13398c2ecf20Sopenharmony_ci map_fd, def, op); 13408c2ecf20Sopenharmony_ci break; 13418c2ecf20Sopenharmony_ci case BPF_MAP_KEY_RANGES: 13428c2ecf20Sopenharmony_ci err = foreach_key_array_ranges(func, arg, name, 13438c2ecf20Sopenharmony_ci map_fd, def, 13448c2ecf20Sopenharmony_ci op); 13458c2ecf20Sopenharmony_ci break; 13468c2ecf20Sopenharmony_ci default: 13478c2ecf20Sopenharmony_ci pr_debug("ERROR: keytype for map '%s' invalid\n", 13488c2ecf20Sopenharmony_ci name); 13498c2ecf20Sopenharmony_ci return -BPF_LOADER_ERRNO__INTERNAL; 13508c2ecf20Sopenharmony_ci } 13518c2ecf20Sopenharmony_ci if (err) 13528c2ecf20Sopenharmony_ci return err; 13538c2ecf20Sopenharmony_ci break; 13548c2ecf20Sopenharmony_ci default: 13558c2ecf20Sopenharmony_ci pr_debug("ERROR: type of '%s' incorrect\n", name); 13568c2ecf20Sopenharmony_ci return -BPF_LOADER_ERRNO__OBJCONF_MAP_TYPE; 13578c2ecf20Sopenharmony_ci } 13588c2ecf20Sopenharmony_ci } 13598c2ecf20Sopenharmony_ci 13608c2ecf20Sopenharmony_ci return 0; 13618c2ecf20Sopenharmony_ci} 13628c2ecf20Sopenharmony_ci 13638c2ecf20Sopenharmony_cistatic int 13648c2ecf20Sopenharmony_ciapply_config_value_for_key(int map_fd, void *pkey, 13658c2ecf20Sopenharmony_ci size_t val_size, u64 val) 13668c2ecf20Sopenharmony_ci{ 13678c2ecf20Sopenharmony_ci int err = 0; 13688c2ecf20Sopenharmony_ci 13698c2ecf20Sopenharmony_ci switch (val_size) { 13708c2ecf20Sopenharmony_ci case 1: { 13718c2ecf20Sopenharmony_ci u8 _val = (u8)(val); 13728c2ecf20Sopenharmony_ci err = bpf_map_update_elem(map_fd, pkey, &_val, BPF_ANY); 13738c2ecf20Sopenharmony_ci break; 13748c2ecf20Sopenharmony_ci } 13758c2ecf20Sopenharmony_ci case 2: { 13768c2ecf20Sopenharmony_ci u16 _val = (u16)(val); 13778c2ecf20Sopenharmony_ci err = bpf_map_update_elem(map_fd, pkey, &_val, BPF_ANY); 13788c2ecf20Sopenharmony_ci break; 13798c2ecf20Sopenharmony_ci } 13808c2ecf20Sopenharmony_ci case 4: { 13818c2ecf20Sopenharmony_ci u32 _val = (u32)(val); 13828c2ecf20Sopenharmony_ci err = bpf_map_update_elem(map_fd, pkey, &_val, BPF_ANY); 13838c2ecf20Sopenharmony_ci break; 13848c2ecf20Sopenharmony_ci } 13858c2ecf20Sopenharmony_ci case 8: { 13868c2ecf20Sopenharmony_ci err = bpf_map_update_elem(map_fd, pkey, &val, BPF_ANY); 13878c2ecf20Sopenharmony_ci break; 13888c2ecf20Sopenharmony_ci } 13898c2ecf20Sopenharmony_ci default: 13908c2ecf20Sopenharmony_ci pr_debug("ERROR: invalid value size\n"); 13918c2ecf20Sopenharmony_ci return -BPF_LOADER_ERRNO__OBJCONF_MAP_VALUESIZE; 13928c2ecf20Sopenharmony_ci } 13938c2ecf20Sopenharmony_ci if (err && errno) 13948c2ecf20Sopenharmony_ci err = -errno; 13958c2ecf20Sopenharmony_ci return err; 13968c2ecf20Sopenharmony_ci} 13978c2ecf20Sopenharmony_ci 13988c2ecf20Sopenharmony_cistatic int 13998c2ecf20Sopenharmony_ciapply_config_evsel_for_key(const char *name, int map_fd, void *pkey, 14008c2ecf20Sopenharmony_ci struct evsel *evsel) 14018c2ecf20Sopenharmony_ci{ 14028c2ecf20Sopenharmony_ci struct xyarray *xy = evsel->core.fd; 14038c2ecf20Sopenharmony_ci struct perf_event_attr *attr; 14048c2ecf20Sopenharmony_ci unsigned int key, events; 14058c2ecf20Sopenharmony_ci bool check_pass = false; 14068c2ecf20Sopenharmony_ci int *evt_fd; 14078c2ecf20Sopenharmony_ci int err; 14088c2ecf20Sopenharmony_ci 14098c2ecf20Sopenharmony_ci if (!xy) { 14108c2ecf20Sopenharmony_ci pr_debug("ERROR: evsel not ready for map %s\n", name); 14118c2ecf20Sopenharmony_ci return -BPF_LOADER_ERRNO__INTERNAL; 14128c2ecf20Sopenharmony_ci } 14138c2ecf20Sopenharmony_ci 14148c2ecf20Sopenharmony_ci if (xy->row_size / xy->entry_size != 1) { 14158c2ecf20Sopenharmony_ci pr_debug("ERROR: Dimension of target event is incorrect for map %s\n", 14168c2ecf20Sopenharmony_ci name); 14178c2ecf20Sopenharmony_ci return -BPF_LOADER_ERRNO__OBJCONF_MAP_EVTDIM; 14188c2ecf20Sopenharmony_ci } 14198c2ecf20Sopenharmony_ci 14208c2ecf20Sopenharmony_ci attr = &evsel->core.attr; 14218c2ecf20Sopenharmony_ci if (attr->inherit) { 14228c2ecf20Sopenharmony_ci pr_debug("ERROR: Can't put inherit event into map %s\n", name); 14238c2ecf20Sopenharmony_ci return -BPF_LOADER_ERRNO__OBJCONF_MAP_EVTINH; 14248c2ecf20Sopenharmony_ci } 14258c2ecf20Sopenharmony_ci 14268c2ecf20Sopenharmony_ci if (evsel__is_bpf_output(evsel)) 14278c2ecf20Sopenharmony_ci check_pass = true; 14288c2ecf20Sopenharmony_ci if (attr->type == PERF_TYPE_RAW) 14298c2ecf20Sopenharmony_ci check_pass = true; 14308c2ecf20Sopenharmony_ci if (attr->type == PERF_TYPE_HARDWARE) 14318c2ecf20Sopenharmony_ci check_pass = true; 14328c2ecf20Sopenharmony_ci if (!check_pass) { 14338c2ecf20Sopenharmony_ci pr_debug("ERROR: Event type is wrong for map %s\n", name); 14348c2ecf20Sopenharmony_ci return -BPF_LOADER_ERRNO__OBJCONF_MAP_EVTTYPE; 14358c2ecf20Sopenharmony_ci } 14368c2ecf20Sopenharmony_ci 14378c2ecf20Sopenharmony_ci events = xy->entries / (xy->row_size / xy->entry_size); 14388c2ecf20Sopenharmony_ci key = *((unsigned int *)pkey); 14398c2ecf20Sopenharmony_ci if (key >= events) { 14408c2ecf20Sopenharmony_ci pr_debug("ERROR: there is no event %d for map %s\n", 14418c2ecf20Sopenharmony_ci key, name); 14428c2ecf20Sopenharmony_ci return -BPF_LOADER_ERRNO__OBJCONF_MAP_MAPSIZE; 14438c2ecf20Sopenharmony_ci } 14448c2ecf20Sopenharmony_ci evt_fd = xyarray__entry(xy, key, 0); 14458c2ecf20Sopenharmony_ci err = bpf_map_update_elem(map_fd, pkey, evt_fd, BPF_ANY); 14468c2ecf20Sopenharmony_ci if (err && errno) 14478c2ecf20Sopenharmony_ci err = -errno; 14488c2ecf20Sopenharmony_ci return err; 14498c2ecf20Sopenharmony_ci} 14508c2ecf20Sopenharmony_ci 14518c2ecf20Sopenharmony_cistatic int 14528c2ecf20Sopenharmony_ciapply_obj_config_map_for_key(const char *name, int map_fd, 14538c2ecf20Sopenharmony_ci const struct bpf_map_def *pdef, 14548c2ecf20Sopenharmony_ci struct bpf_map_op *op, 14558c2ecf20Sopenharmony_ci void *pkey, void *arg __maybe_unused) 14568c2ecf20Sopenharmony_ci{ 14578c2ecf20Sopenharmony_ci int err; 14588c2ecf20Sopenharmony_ci 14598c2ecf20Sopenharmony_ci switch (op->op_type) { 14608c2ecf20Sopenharmony_ci case BPF_MAP_OP_SET_VALUE: 14618c2ecf20Sopenharmony_ci err = apply_config_value_for_key(map_fd, pkey, 14628c2ecf20Sopenharmony_ci pdef->value_size, 14638c2ecf20Sopenharmony_ci op->v.value); 14648c2ecf20Sopenharmony_ci break; 14658c2ecf20Sopenharmony_ci case BPF_MAP_OP_SET_EVSEL: 14668c2ecf20Sopenharmony_ci err = apply_config_evsel_for_key(name, map_fd, pkey, 14678c2ecf20Sopenharmony_ci op->v.evsel); 14688c2ecf20Sopenharmony_ci break; 14698c2ecf20Sopenharmony_ci default: 14708c2ecf20Sopenharmony_ci pr_debug("ERROR: unknown value type for '%s'\n", name); 14718c2ecf20Sopenharmony_ci err = -BPF_LOADER_ERRNO__INTERNAL; 14728c2ecf20Sopenharmony_ci } 14738c2ecf20Sopenharmony_ci return err; 14748c2ecf20Sopenharmony_ci} 14758c2ecf20Sopenharmony_ci 14768c2ecf20Sopenharmony_cistatic int 14778c2ecf20Sopenharmony_ciapply_obj_config_map(struct bpf_map *map) 14788c2ecf20Sopenharmony_ci{ 14798c2ecf20Sopenharmony_ci return bpf_map_config_foreach_key(map, 14808c2ecf20Sopenharmony_ci apply_obj_config_map_for_key, 14818c2ecf20Sopenharmony_ci NULL); 14828c2ecf20Sopenharmony_ci} 14838c2ecf20Sopenharmony_ci 14848c2ecf20Sopenharmony_cistatic int 14858c2ecf20Sopenharmony_ciapply_obj_config_object(struct bpf_object *obj) 14868c2ecf20Sopenharmony_ci{ 14878c2ecf20Sopenharmony_ci struct bpf_map *map; 14888c2ecf20Sopenharmony_ci int err; 14898c2ecf20Sopenharmony_ci 14908c2ecf20Sopenharmony_ci bpf_object__for_each_map(map, obj) { 14918c2ecf20Sopenharmony_ci err = apply_obj_config_map(map); 14928c2ecf20Sopenharmony_ci if (err) 14938c2ecf20Sopenharmony_ci return err; 14948c2ecf20Sopenharmony_ci } 14958c2ecf20Sopenharmony_ci return 0; 14968c2ecf20Sopenharmony_ci} 14978c2ecf20Sopenharmony_ci 14988c2ecf20Sopenharmony_ciint bpf__apply_obj_config(void) 14998c2ecf20Sopenharmony_ci{ 15008c2ecf20Sopenharmony_ci struct bpf_object *obj, *tmp; 15018c2ecf20Sopenharmony_ci int err; 15028c2ecf20Sopenharmony_ci 15038c2ecf20Sopenharmony_ci bpf_object__for_each_safe(obj, tmp) { 15048c2ecf20Sopenharmony_ci err = apply_obj_config_object(obj); 15058c2ecf20Sopenharmony_ci if (err) 15068c2ecf20Sopenharmony_ci return err; 15078c2ecf20Sopenharmony_ci } 15088c2ecf20Sopenharmony_ci 15098c2ecf20Sopenharmony_ci return 0; 15108c2ecf20Sopenharmony_ci} 15118c2ecf20Sopenharmony_ci 15128c2ecf20Sopenharmony_ci#define bpf__for_each_map(pos, obj, objtmp) \ 15138c2ecf20Sopenharmony_ci bpf_object__for_each_safe(obj, objtmp) \ 15148c2ecf20Sopenharmony_ci bpf_object__for_each_map(pos, obj) 15158c2ecf20Sopenharmony_ci 15168c2ecf20Sopenharmony_ci#define bpf__for_each_map_named(pos, obj, objtmp, name) \ 15178c2ecf20Sopenharmony_ci bpf__for_each_map(pos, obj, objtmp) \ 15188c2ecf20Sopenharmony_ci if (bpf_map__name(pos) && \ 15198c2ecf20Sopenharmony_ci (strcmp(name, \ 15208c2ecf20Sopenharmony_ci bpf_map__name(pos)) == 0)) 15218c2ecf20Sopenharmony_ci 15228c2ecf20Sopenharmony_cistruct evsel *bpf__setup_output_event(struct evlist *evlist, const char *name) 15238c2ecf20Sopenharmony_ci{ 15248c2ecf20Sopenharmony_ci struct bpf_map_priv *tmpl_priv = NULL; 15258c2ecf20Sopenharmony_ci struct bpf_object *obj, *tmp; 15268c2ecf20Sopenharmony_ci struct evsel *evsel = NULL; 15278c2ecf20Sopenharmony_ci struct bpf_map *map; 15288c2ecf20Sopenharmony_ci int err; 15298c2ecf20Sopenharmony_ci bool need_init = false; 15308c2ecf20Sopenharmony_ci 15318c2ecf20Sopenharmony_ci bpf__for_each_map_named(map, obj, tmp, name) { 15328c2ecf20Sopenharmony_ci struct bpf_map_priv *priv = bpf_map__priv(map); 15338c2ecf20Sopenharmony_ci 15348c2ecf20Sopenharmony_ci if (IS_ERR(priv)) 15358c2ecf20Sopenharmony_ci return ERR_PTR(-BPF_LOADER_ERRNO__INTERNAL); 15368c2ecf20Sopenharmony_ci 15378c2ecf20Sopenharmony_ci /* 15388c2ecf20Sopenharmony_ci * No need to check map type: type should have been 15398c2ecf20Sopenharmony_ci * verified by kernel. 15408c2ecf20Sopenharmony_ci */ 15418c2ecf20Sopenharmony_ci if (!need_init && !priv) 15428c2ecf20Sopenharmony_ci need_init = !priv; 15438c2ecf20Sopenharmony_ci if (!tmpl_priv && priv) 15448c2ecf20Sopenharmony_ci tmpl_priv = priv; 15458c2ecf20Sopenharmony_ci } 15468c2ecf20Sopenharmony_ci 15478c2ecf20Sopenharmony_ci if (!need_init) 15488c2ecf20Sopenharmony_ci return NULL; 15498c2ecf20Sopenharmony_ci 15508c2ecf20Sopenharmony_ci if (!tmpl_priv) { 15518c2ecf20Sopenharmony_ci char *event_definition = NULL; 15528c2ecf20Sopenharmony_ci 15538c2ecf20Sopenharmony_ci if (asprintf(&event_definition, "bpf-output/no-inherit=1,name=%s/", name) < 0) 15548c2ecf20Sopenharmony_ci return ERR_PTR(-ENOMEM); 15558c2ecf20Sopenharmony_ci 15568c2ecf20Sopenharmony_ci err = parse_events(evlist, event_definition, NULL); 15578c2ecf20Sopenharmony_ci free(event_definition); 15588c2ecf20Sopenharmony_ci 15598c2ecf20Sopenharmony_ci if (err) { 15608c2ecf20Sopenharmony_ci pr_debug("ERROR: failed to create the \"%s\" bpf-output event\n", name); 15618c2ecf20Sopenharmony_ci return ERR_PTR(-err); 15628c2ecf20Sopenharmony_ci } 15638c2ecf20Sopenharmony_ci 15648c2ecf20Sopenharmony_ci evsel = evlist__last(evlist); 15658c2ecf20Sopenharmony_ci } 15668c2ecf20Sopenharmony_ci 15678c2ecf20Sopenharmony_ci bpf__for_each_map_named(map, obj, tmp, name) { 15688c2ecf20Sopenharmony_ci struct bpf_map_priv *priv = bpf_map__priv(map); 15698c2ecf20Sopenharmony_ci 15708c2ecf20Sopenharmony_ci if (IS_ERR(priv)) 15718c2ecf20Sopenharmony_ci return ERR_PTR(-BPF_LOADER_ERRNO__INTERNAL); 15728c2ecf20Sopenharmony_ci if (priv) 15738c2ecf20Sopenharmony_ci continue; 15748c2ecf20Sopenharmony_ci 15758c2ecf20Sopenharmony_ci if (tmpl_priv) { 15768c2ecf20Sopenharmony_ci priv = bpf_map_priv__clone(tmpl_priv); 15778c2ecf20Sopenharmony_ci if (!priv) 15788c2ecf20Sopenharmony_ci return ERR_PTR(-ENOMEM); 15798c2ecf20Sopenharmony_ci 15808c2ecf20Sopenharmony_ci err = bpf_map__set_priv(map, priv, bpf_map_priv__clear); 15818c2ecf20Sopenharmony_ci if (err) { 15828c2ecf20Sopenharmony_ci bpf_map_priv__clear(map, priv); 15838c2ecf20Sopenharmony_ci return ERR_PTR(err); 15848c2ecf20Sopenharmony_ci } 15858c2ecf20Sopenharmony_ci } else if (evsel) { 15868c2ecf20Sopenharmony_ci struct bpf_map_op *op; 15878c2ecf20Sopenharmony_ci 15888c2ecf20Sopenharmony_ci op = bpf_map__add_newop(map, NULL); 15898c2ecf20Sopenharmony_ci if (IS_ERR(op)) 15908c2ecf20Sopenharmony_ci return ERR_CAST(op); 15918c2ecf20Sopenharmony_ci op->op_type = BPF_MAP_OP_SET_EVSEL; 15928c2ecf20Sopenharmony_ci op->v.evsel = evsel; 15938c2ecf20Sopenharmony_ci } 15948c2ecf20Sopenharmony_ci } 15958c2ecf20Sopenharmony_ci 15968c2ecf20Sopenharmony_ci return evsel; 15978c2ecf20Sopenharmony_ci} 15988c2ecf20Sopenharmony_ci 15998c2ecf20Sopenharmony_ciint bpf__setup_stdout(struct evlist *evlist) 16008c2ecf20Sopenharmony_ci{ 16018c2ecf20Sopenharmony_ci struct evsel *evsel = bpf__setup_output_event(evlist, "__bpf_stdout__"); 16028c2ecf20Sopenharmony_ci return PTR_ERR_OR_ZERO(evsel); 16038c2ecf20Sopenharmony_ci} 16048c2ecf20Sopenharmony_ci 16058c2ecf20Sopenharmony_ci#define ERRNO_OFFSET(e) ((e) - __BPF_LOADER_ERRNO__START) 16068c2ecf20Sopenharmony_ci#define ERRCODE_OFFSET(c) ERRNO_OFFSET(BPF_LOADER_ERRNO__##c) 16078c2ecf20Sopenharmony_ci#define NR_ERRNO (__BPF_LOADER_ERRNO__END - __BPF_LOADER_ERRNO__START) 16088c2ecf20Sopenharmony_ci 16098c2ecf20Sopenharmony_cistatic const char *bpf_loader_strerror_table[NR_ERRNO] = { 16108c2ecf20Sopenharmony_ci [ERRCODE_OFFSET(CONFIG)] = "Invalid config string", 16118c2ecf20Sopenharmony_ci [ERRCODE_OFFSET(GROUP)] = "Invalid group name", 16128c2ecf20Sopenharmony_ci [ERRCODE_OFFSET(EVENTNAME)] = "No event name found in config string", 16138c2ecf20Sopenharmony_ci [ERRCODE_OFFSET(INTERNAL)] = "BPF loader internal error", 16148c2ecf20Sopenharmony_ci [ERRCODE_OFFSET(COMPILE)] = "Error when compiling BPF scriptlet", 16158c2ecf20Sopenharmony_ci [ERRCODE_OFFSET(PROGCONF_TERM)] = "Invalid program config term in config string", 16168c2ecf20Sopenharmony_ci [ERRCODE_OFFSET(PROLOGUE)] = "Failed to generate prologue", 16178c2ecf20Sopenharmony_ci [ERRCODE_OFFSET(PROLOGUE2BIG)] = "Prologue too big for program", 16188c2ecf20Sopenharmony_ci [ERRCODE_OFFSET(PROLOGUEOOB)] = "Offset out of bound for prologue", 16198c2ecf20Sopenharmony_ci [ERRCODE_OFFSET(OBJCONF_OPT)] = "Invalid object config option", 16208c2ecf20Sopenharmony_ci [ERRCODE_OFFSET(OBJCONF_CONF)] = "Config value not set (missing '=')", 16218c2ecf20Sopenharmony_ci [ERRCODE_OFFSET(OBJCONF_MAP_OPT)] = "Invalid object map config option", 16228c2ecf20Sopenharmony_ci [ERRCODE_OFFSET(OBJCONF_MAP_NOTEXIST)] = "Target map doesn't exist", 16238c2ecf20Sopenharmony_ci [ERRCODE_OFFSET(OBJCONF_MAP_VALUE)] = "Incorrect value type for map", 16248c2ecf20Sopenharmony_ci [ERRCODE_OFFSET(OBJCONF_MAP_TYPE)] = "Incorrect map type", 16258c2ecf20Sopenharmony_ci [ERRCODE_OFFSET(OBJCONF_MAP_KEYSIZE)] = "Incorrect map key size", 16268c2ecf20Sopenharmony_ci [ERRCODE_OFFSET(OBJCONF_MAP_VALUESIZE)] = "Incorrect map value size", 16278c2ecf20Sopenharmony_ci [ERRCODE_OFFSET(OBJCONF_MAP_NOEVT)] = "Event not found for map setting", 16288c2ecf20Sopenharmony_ci [ERRCODE_OFFSET(OBJCONF_MAP_MAPSIZE)] = "Invalid map size for event setting", 16298c2ecf20Sopenharmony_ci [ERRCODE_OFFSET(OBJCONF_MAP_EVTDIM)] = "Event dimension too large", 16308c2ecf20Sopenharmony_ci [ERRCODE_OFFSET(OBJCONF_MAP_EVTINH)] = "Doesn't support inherit event", 16318c2ecf20Sopenharmony_ci [ERRCODE_OFFSET(OBJCONF_MAP_EVTTYPE)] = "Wrong event type for map", 16328c2ecf20Sopenharmony_ci [ERRCODE_OFFSET(OBJCONF_MAP_IDX2BIG)] = "Index too large", 16338c2ecf20Sopenharmony_ci}; 16348c2ecf20Sopenharmony_ci 16358c2ecf20Sopenharmony_cistatic int 16368c2ecf20Sopenharmony_cibpf_loader_strerror(int err, char *buf, size_t size) 16378c2ecf20Sopenharmony_ci{ 16388c2ecf20Sopenharmony_ci char sbuf[STRERR_BUFSIZE]; 16398c2ecf20Sopenharmony_ci const char *msg; 16408c2ecf20Sopenharmony_ci 16418c2ecf20Sopenharmony_ci if (!buf || !size) 16428c2ecf20Sopenharmony_ci return -1; 16438c2ecf20Sopenharmony_ci 16448c2ecf20Sopenharmony_ci err = err > 0 ? err : -err; 16458c2ecf20Sopenharmony_ci 16468c2ecf20Sopenharmony_ci if (err >= __LIBBPF_ERRNO__START) 16478c2ecf20Sopenharmony_ci return libbpf_strerror(err, buf, size); 16488c2ecf20Sopenharmony_ci 16498c2ecf20Sopenharmony_ci if (err >= __BPF_LOADER_ERRNO__START && err < __BPF_LOADER_ERRNO__END) { 16508c2ecf20Sopenharmony_ci msg = bpf_loader_strerror_table[ERRNO_OFFSET(err)]; 16518c2ecf20Sopenharmony_ci snprintf(buf, size, "%s", msg); 16528c2ecf20Sopenharmony_ci buf[size - 1] = '\0'; 16538c2ecf20Sopenharmony_ci return 0; 16548c2ecf20Sopenharmony_ci } 16558c2ecf20Sopenharmony_ci 16568c2ecf20Sopenharmony_ci if (err >= __BPF_LOADER_ERRNO__END) 16578c2ecf20Sopenharmony_ci snprintf(buf, size, "Unknown bpf loader error %d", err); 16588c2ecf20Sopenharmony_ci else 16598c2ecf20Sopenharmony_ci snprintf(buf, size, "%s", 16608c2ecf20Sopenharmony_ci str_error_r(err, sbuf, sizeof(sbuf))); 16618c2ecf20Sopenharmony_ci 16628c2ecf20Sopenharmony_ci buf[size - 1] = '\0'; 16638c2ecf20Sopenharmony_ci return -1; 16648c2ecf20Sopenharmony_ci} 16658c2ecf20Sopenharmony_ci 16668c2ecf20Sopenharmony_ci#define bpf__strerror_head(err, buf, size) \ 16678c2ecf20Sopenharmony_ci char sbuf[STRERR_BUFSIZE], *emsg;\ 16688c2ecf20Sopenharmony_ci if (!size)\ 16698c2ecf20Sopenharmony_ci return 0;\ 16708c2ecf20Sopenharmony_ci if (err < 0)\ 16718c2ecf20Sopenharmony_ci err = -err;\ 16728c2ecf20Sopenharmony_ci bpf_loader_strerror(err, sbuf, sizeof(sbuf));\ 16738c2ecf20Sopenharmony_ci emsg = sbuf;\ 16748c2ecf20Sopenharmony_ci switch (err) {\ 16758c2ecf20Sopenharmony_ci default:\ 16768c2ecf20Sopenharmony_ci scnprintf(buf, size, "%s", emsg);\ 16778c2ecf20Sopenharmony_ci break; 16788c2ecf20Sopenharmony_ci 16798c2ecf20Sopenharmony_ci#define bpf__strerror_entry(val, fmt...)\ 16808c2ecf20Sopenharmony_ci case val: {\ 16818c2ecf20Sopenharmony_ci scnprintf(buf, size, fmt);\ 16828c2ecf20Sopenharmony_ci break;\ 16838c2ecf20Sopenharmony_ci } 16848c2ecf20Sopenharmony_ci 16858c2ecf20Sopenharmony_ci#define bpf__strerror_end(buf, size)\ 16868c2ecf20Sopenharmony_ci }\ 16878c2ecf20Sopenharmony_ci buf[size - 1] = '\0'; 16888c2ecf20Sopenharmony_ci 16898c2ecf20Sopenharmony_ciint bpf__strerror_prepare_load(const char *filename, bool source, 16908c2ecf20Sopenharmony_ci int err, char *buf, size_t size) 16918c2ecf20Sopenharmony_ci{ 16928c2ecf20Sopenharmony_ci size_t n; 16938c2ecf20Sopenharmony_ci int ret; 16948c2ecf20Sopenharmony_ci 16958c2ecf20Sopenharmony_ci n = snprintf(buf, size, "Failed to load %s%s: ", 16968c2ecf20Sopenharmony_ci filename, source ? " from source" : ""); 16978c2ecf20Sopenharmony_ci if (n >= size) { 16988c2ecf20Sopenharmony_ci buf[size - 1] = '\0'; 16998c2ecf20Sopenharmony_ci return 0; 17008c2ecf20Sopenharmony_ci } 17018c2ecf20Sopenharmony_ci buf += n; 17028c2ecf20Sopenharmony_ci size -= n; 17038c2ecf20Sopenharmony_ci 17048c2ecf20Sopenharmony_ci ret = bpf_loader_strerror(err, buf, size); 17058c2ecf20Sopenharmony_ci buf[size - 1] = '\0'; 17068c2ecf20Sopenharmony_ci return ret; 17078c2ecf20Sopenharmony_ci} 17088c2ecf20Sopenharmony_ci 17098c2ecf20Sopenharmony_ciint bpf__strerror_probe(struct bpf_object *obj __maybe_unused, 17108c2ecf20Sopenharmony_ci int err, char *buf, size_t size) 17118c2ecf20Sopenharmony_ci{ 17128c2ecf20Sopenharmony_ci bpf__strerror_head(err, buf, size); 17138c2ecf20Sopenharmony_ci case BPF_LOADER_ERRNO__PROGCONF_TERM: { 17148c2ecf20Sopenharmony_ci scnprintf(buf, size, "%s (add -v to see detail)", emsg); 17158c2ecf20Sopenharmony_ci break; 17168c2ecf20Sopenharmony_ci } 17178c2ecf20Sopenharmony_ci bpf__strerror_entry(EEXIST, "Probe point exist. Try 'perf probe -d \"*\"' and set 'force=yes'"); 17188c2ecf20Sopenharmony_ci bpf__strerror_entry(EACCES, "You need to be root"); 17198c2ecf20Sopenharmony_ci bpf__strerror_entry(EPERM, "You need to be root, and /proc/sys/kernel/kptr_restrict should be 0"); 17208c2ecf20Sopenharmony_ci bpf__strerror_entry(ENOENT, "You need to check probing points in BPF file"); 17218c2ecf20Sopenharmony_ci bpf__strerror_end(buf, size); 17228c2ecf20Sopenharmony_ci return 0; 17238c2ecf20Sopenharmony_ci} 17248c2ecf20Sopenharmony_ci 17258c2ecf20Sopenharmony_ciint bpf__strerror_load(struct bpf_object *obj, 17268c2ecf20Sopenharmony_ci int err, char *buf, size_t size) 17278c2ecf20Sopenharmony_ci{ 17288c2ecf20Sopenharmony_ci bpf__strerror_head(err, buf, size); 17298c2ecf20Sopenharmony_ci case LIBBPF_ERRNO__KVER: { 17308c2ecf20Sopenharmony_ci unsigned int obj_kver = bpf_object__kversion(obj); 17318c2ecf20Sopenharmony_ci unsigned int real_kver; 17328c2ecf20Sopenharmony_ci 17338c2ecf20Sopenharmony_ci if (fetch_kernel_version(&real_kver, NULL, 0)) { 17348c2ecf20Sopenharmony_ci scnprintf(buf, size, "Unable to fetch kernel version"); 17358c2ecf20Sopenharmony_ci break; 17368c2ecf20Sopenharmony_ci } 17378c2ecf20Sopenharmony_ci 17388c2ecf20Sopenharmony_ci if (obj_kver != real_kver) { 17398c2ecf20Sopenharmony_ci scnprintf(buf, size, 17408c2ecf20Sopenharmony_ci "'version' ("KVER_FMT") doesn't match running kernel ("KVER_FMT")", 17418c2ecf20Sopenharmony_ci KVER_PARAM(obj_kver), 17428c2ecf20Sopenharmony_ci KVER_PARAM(real_kver)); 17438c2ecf20Sopenharmony_ci break; 17448c2ecf20Sopenharmony_ci } 17458c2ecf20Sopenharmony_ci 17468c2ecf20Sopenharmony_ci scnprintf(buf, size, "Failed to load program for unknown reason"); 17478c2ecf20Sopenharmony_ci break; 17488c2ecf20Sopenharmony_ci } 17498c2ecf20Sopenharmony_ci bpf__strerror_end(buf, size); 17508c2ecf20Sopenharmony_ci return 0; 17518c2ecf20Sopenharmony_ci} 17528c2ecf20Sopenharmony_ci 17538c2ecf20Sopenharmony_ciint bpf__strerror_config_obj(struct bpf_object *obj __maybe_unused, 17548c2ecf20Sopenharmony_ci struct parse_events_term *term __maybe_unused, 17558c2ecf20Sopenharmony_ci struct evlist *evlist __maybe_unused, 17568c2ecf20Sopenharmony_ci int *error_pos __maybe_unused, int err, 17578c2ecf20Sopenharmony_ci char *buf, size_t size) 17588c2ecf20Sopenharmony_ci{ 17598c2ecf20Sopenharmony_ci bpf__strerror_head(err, buf, size); 17608c2ecf20Sopenharmony_ci bpf__strerror_entry(BPF_LOADER_ERRNO__OBJCONF_MAP_TYPE, 17618c2ecf20Sopenharmony_ci "Can't use this config term with this map type"); 17628c2ecf20Sopenharmony_ci bpf__strerror_end(buf, size); 17638c2ecf20Sopenharmony_ci return 0; 17648c2ecf20Sopenharmony_ci} 17658c2ecf20Sopenharmony_ci 17668c2ecf20Sopenharmony_ciint bpf__strerror_apply_obj_config(int err, char *buf, size_t size) 17678c2ecf20Sopenharmony_ci{ 17688c2ecf20Sopenharmony_ci bpf__strerror_head(err, buf, size); 17698c2ecf20Sopenharmony_ci bpf__strerror_entry(BPF_LOADER_ERRNO__OBJCONF_MAP_EVTDIM, 17708c2ecf20Sopenharmony_ci "Cannot set event to BPF map in multi-thread tracing"); 17718c2ecf20Sopenharmony_ci bpf__strerror_entry(BPF_LOADER_ERRNO__OBJCONF_MAP_EVTINH, 17728c2ecf20Sopenharmony_ci "%s (Hint: use -i to turn off inherit)", emsg); 17738c2ecf20Sopenharmony_ci bpf__strerror_entry(BPF_LOADER_ERRNO__OBJCONF_MAP_EVTTYPE, 17748c2ecf20Sopenharmony_ci "Can only put raw, hardware and BPF output event into a BPF map"); 17758c2ecf20Sopenharmony_ci bpf__strerror_end(buf, size); 17768c2ecf20Sopenharmony_ci return 0; 17778c2ecf20Sopenharmony_ci} 17788c2ecf20Sopenharmony_ci 17798c2ecf20Sopenharmony_ciint bpf__strerror_setup_output_event(struct evlist *evlist __maybe_unused, 17808c2ecf20Sopenharmony_ci int err, char *buf, size_t size) 17818c2ecf20Sopenharmony_ci{ 17828c2ecf20Sopenharmony_ci bpf__strerror_head(err, buf, size); 17838c2ecf20Sopenharmony_ci bpf__strerror_end(buf, size); 17848c2ecf20Sopenharmony_ci return 0; 17858c2ecf20Sopenharmony_ci} 1786