162306a36Sopenharmony_ci/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ 262306a36Sopenharmony_ci/* Copyright (C) 2017-2018 Netronome Systems, Inc. */ 362306a36Sopenharmony_ci 462306a36Sopenharmony_ci#ifndef __BPF_TOOL_H 562306a36Sopenharmony_ci#define __BPF_TOOL_H 662306a36Sopenharmony_ci 762306a36Sopenharmony_ci/* BFD and kernel.h both define GCC_VERSION, differently */ 862306a36Sopenharmony_ci#undef GCC_VERSION 962306a36Sopenharmony_ci#include <stdbool.h> 1062306a36Sopenharmony_ci#include <stdio.h> 1162306a36Sopenharmony_ci#include <stdlib.h> 1262306a36Sopenharmony_ci#include <linux/bpf.h> 1362306a36Sopenharmony_ci#include <linux/compiler.h> 1462306a36Sopenharmony_ci#include <linux/kernel.h> 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ci#include <bpf/hashmap.h> 1762306a36Sopenharmony_ci#include <bpf/libbpf.h> 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci#include "json_writer.h" 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ci/* Make sure we do not use kernel-only integer typedefs */ 2262306a36Sopenharmony_ci#pragma GCC poison u8 u16 u32 u64 s8 s16 s32 s64 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_cistatic inline __u64 ptr_to_u64(const void *ptr) 2562306a36Sopenharmony_ci{ 2662306a36Sopenharmony_ci return (__u64)(unsigned long)ptr; 2762306a36Sopenharmony_ci} 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_cistatic inline void *u64_to_ptr(__u64 ptr) 3062306a36Sopenharmony_ci{ 3162306a36Sopenharmony_ci return (void *)(unsigned long)ptr; 3262306a36Sopenharmony_ci} 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci#define NEXT_ARG() ({ argc--; argv++; if (argc < 0) usage(); }) 3562306a36Sopenharmony_ci#define NEXT_ARGP() ({ (*argc)--; (*argv)++; if (*argc < 0) usage(); }) 3662306a36Sopenharmony_ci#define BAD_ARG() ({ p_err("what is '%s'?", *argv); -1; }) 3762306a36Sopenharmony_ci#define GET_ARG() ({ argc--; *argv++; }) 3862306a36Sopenharmony_ci#define REQ_ARGS(cnt) \ 3962306a36Sopenharmony_ci ({ \ 4062306a36Sopenharmony_ci int _cnt = (cnt); \ 4162306a36Sopenharmony_ci bool _res; \ 4262306a36Sopenharmony_ci \ 4362306a36Sopenharmony_ci if (argc < _cnt) { \ 4462306a36Sopenharmony_ci p_err("'%s' needs at least %d arguments, %d found", \ 4562306a36Sopenharmony_ci argv[-1], _cnt, argc); \ 4662306a36Sopenharmony_ci _res = false; \ 4762306a36Sopenharmony_ci } else { \ 4862306a36Sopenharmony_ci _res = true; \ 4962306a36Sopenharmony_ci } \ 5062306a36Sopenharmony_ci _res; \ 5162306a36Sopenharmony_ci }) 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ci#define ERR_MAX_LEN 1024 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci#define BPF_TAG_FMT "%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx" 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci#define HELP_SPEC_PROGRAM \ 5862306a36Sopenharmony_ci "PROG := { id PROG_ID | pinned FILE | tag PROG_TAG | name PROG_NAME }" 5962306a36Sopenharmony_ci#define HELP_SPEC_OPTIONS \ 6062306a36Sopenharmony_ci "OPTIONS := { {-j|--json} [{-p|--pretty}] | {-d|--debug}" 6162306a36Sopenharmony_ci#define HELP_SPEC_MAP \ 6262306a36Sopenharmony_ci "MAP := { id MAP_ID | pinned FILE | name MAP_NAME }" 6362306a36Sopenharmony_ci#define HELP_SPEC_LINK \ 6462306a36Sopenharmony_ci "LINK := { id LINK_ID | pinned FILE }" 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci/* keep in sync with the definition in skeleton/pid_iter.bpf.c */ 6762306a36Sopenharmony_cienum bpf_obj_type { 6862306a36Sopenharmony_ci BPF_OBJ_UNKNOWN, 6962306a36Sopenharmony_ci BPF_OBJ_PROG, 7062306a36Sopenharmony_ci BPF_OBJ_MAP, 7162306a36Sopenharmony_ci BPF_OBJ_LINK, 7262306a36Sopenharmony_ci BPF_OBJ_BTF, 7362306a36Sopenharmony_ci}; 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_ciextern const char *bin_name; 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ciextern json_writer_t *json_wtr; 7862306a36Sopenharmony_ciextern bool json_output; 7962306a36Sopenharmony_ciextern bool show_pinned; 8062306a36Sopenharmony_ciextern bool show_pids; 8162306a36Sopenharmony_ciextern bool block_mount; 8262306a36Sopenharmony_ciextern bool verifier_logs; 8362306a36Sopenharmony_ciextern bool relaxed_maps; 8462306a36Sopenharmony_ciextern bool use_loader; 8562306a36Sopenharmony_ciextern struct btf *base_btf; 8662306a36Sopenharmony_ciextern struct hashmap *refs_table; 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_civoid __printf(1, 2) p_err(const char *fmt, ...); 8962306a36Sopenharmony_civoid __printf(1, 2) p_info(const char *fmt, ...); 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_cibool is_prefix(const char *pfx, const char *str); 9262306a36Sopenharmony_ciint detect_common_prefix(const char *arg, ...); 9362306a36Sopenharmony_civoid fprint_hex(FILE *f, void *arg, unsigned int n, const char *sep); 9462306a36Sopenharmony_civoid usage(void) __noreturn; 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_civoid set_max_rlimit(void); 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_ciint mount_tracefs(const char *target); 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_cistruct obj_ref { 10162306a36Sopenharmony_ci int pid; 10262306a36Sopenharmony_ci char comm[16]; 10362306a36Sopenharmony_ci}; 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_cistruct obj_refs { 10662306a36Sopenharmony_ci int ref_cnt; 10762306a36Sopenharmony_ci bool has_bpf_cookie; 10862306a36Sopenharmony_ci struct obj_ref *refs; 10962306a36Sopenharmony_ci __u64 bpf_cookie; 11062306a36Sopenharmony_ci}; 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_cistruct btf; 11362306a36Sopenharmony_cistruct bpf_line_info; 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_ciint build_pinned_obj_table(struct hashmap *table, 11662306a36Sopenharmony_ci enum bpf_obj_type type); 11762306a36Sopenharmony_civoid delete_pinned_obj_table(struct hashmap *table); 11862306a36Sopenharmony_ci__weak int build_obj_refs_table(struct hashmap **table, 11962306a36Sopenharmony_ci enum bpf_obj_type type); 12062306a36Sopenharmony_ci__weak void delete_obj_refs_table(struct hashmap *table); 12162306a36Sopenharmony_ci__weak void emit_obj_refs_json(struct hashmap *table, __u32 id, 12262306a36Sopenharmony_ci json_writer_t *json_wtr); 12362306a36Sopenharmony_ci__weak void emit_obj_refs_plain(struct hashmap *table, __u32 id, 12462306a36Sopenharmony_ci const char *prefix); 12562306a36Sopenharmony_civoid print_dev_plain(__u32 ifindex, __u64 ns_dev, __u64 ns_inode); 12662306a36Sopenharmony_civoid print_dev_json(__u32 ifindex, __u64 ns_dev, __u64 ns_inode); 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_cistruct cmd { 12962306a36Sopenharmony_ci const char *cmd; 13062306a36Sopenharmony_ci int (*func)(int argc, char **argv); 13162306a36Sopenharmony_ci}; 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ciint cmd_select(const struct cmd *cmds, int argc, char **argv, 13462306a36Sopenharmony_ci int (*help)(int argc, char **argv)); 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_ci#define MAX_PROG_FULL_NAME 128 13762306a36Sopenharmony_civoid get_prog_full_name(const struct bpf_prog_info *prog_info, int prog_fd, 13862306a36Sopenharmony_ci char *name_buff, size_t buff_len); 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ciint get_fd_type(int fd); 14162306a36Sopenharmony_ciconst char *get_fd_type_name(enum bpf_obj_type type); 14262306a36Sopenharmony_cichar *get_fdinfo(int fd, const char *key); 14362306a36Sopenharmony_ciint open_obj_pinned(const char *path, bool quiet); 14462306a36Sopenharmony_ciint open_obj_pinned_any(const char *path, enum bpf_obj_type exp_type); 14562306a36Sopenharmony_ciint mount_bpffs_for_pin(const char *name, bool is_dir); 14662306a36Sopenharmony_ciint do_pin_any(int argc, char **argv, int (*get_fd_by_id)(int *, char ***)); 14762306a36Sopenharmony_ciint do_pin_fd(int fd, const char *name); 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_ci/* commands available in bootstrap mode */ 15062306a36Sopenharmony_ciint do_gen(int argc, char **argv); 15162306a36Sopenharmony_ciint do_btf(int argc, char **argv); 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ci/* non-bootstrap only commands */ 15462306a36Sopenharmony_ciint do_prog(int argc, char **arg) __weak; 15562306a36Sopenharmony_ciint do_map(int argc, char **arg) __weak; 15662306a36Sopenharmony_ciint do_link(int argc, char **arg) __weak; 15762306a36Sopenharmony_ciint do_event_pipe(int argc, char **argv) __weak; 15862306a36Sopenharmony_ciint do_cgroup(int argc, char **arg) __weak; 15962306a36Sopenharmony_ciint do_perf(int argc, char **arg) __weak; 16062306a36Sopenharmony_ciint do_net(int argc, char **arg) __weak; 16162306a36Sopenharmony_ciint do_tracelog(int argc, char **arg) __weak; 16262306a36Sopenharmony_ciint do_feature(int argc, char **argv) __weak; 16362306a36Sopenharmony_ciint do_struct_ops(int argc, char **argv) __weak; 16462306a36Sopenharmony_ciint do_iter(int argc, char **argv) __weak; 16562306a36Sopenharmony_ci 16662306a36Sopenharmony_ciint parse_u32_arg(int *argc, char ***argv, __u32 *val, const char *what); 16762306a36Sopenharmony_ciint prog_parse_fd(int *argc, char ***argv); 16862306a36Sopenharmony_ciint prog_parse_fds(int *argc, char ***argv, int **fds); 16962306a36Sopenharmony_ciint map_parse_fd(int *argc, char ***argv); 17062306a36Sopenharmony_ciint map_parse_fds(int *argc, char ***argv, int **fds); 17162306a36Sopenharmony_ciint map_parse_fd_and_info(int *argc, char ***argv, struct bpf_map_info *info, 17262306a36Sopenharmony_ci __u32 *info_len); 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_cistruct bpf_prog_linfo; 17562306a36Sopenharmony_ci#if defined(HAVE_LLVM_SUPPORT) || defined(HAVE_LIBBFD_SUPPORT) 17662306a36Sopenharmony_ciint disasm_print_insn(unsigned char *image, ssize_t len, int opcodes, 17762306a36Sopenharmony_ci const char *arch, const char *disassembler_options, 17862306a36Sopenharmony_ci const struct btf *btf, 17962306a36Sopenharmony_ci const struct bpf_prog_linfo *prog_linfo, 18062306a36Sopenharmony_ci __u64 func_ksym, unsigned int func_idx, 18162306a36Sopenharmony_ci bool linum); 18262306a36Sopenharmony_ciint disasm_init(void); 18362306a36Sopenharmony_ci#else 18462306a36Sopenharmony_cistatic inline 18562306a36Sopenharmony_ciint disasm_print_insn(unsigned char *image, ssize_t len, int opcodes, 18662306a36Sopenharmony_ci const char *arch, const char *disassembler_options, 18762306a36Sopenharmony_ci const struct btf *btf, 18862306a36Sopenharmony_ci const struct bpf_prog_linfo *prog_linfo, 18962306a36Sopenharmony_ci __u64 func_ksym, unsigned int func_idx, 19062306a36Sopenharmony_ci bool linum) 19162306a36Sopenharmony_ci{ 19262306a36Sopenharmony_ci return 0; 19362306a36Sopenharmony_ci} 19462306a36Sopenharmony_cistatic inline int disasm_init(void) 19562306a36Sopenharmony_ci{ 19662306a36Sopenharmony_ci p_err("No JIT disassembly support"); 19762306a36Sopenharmony_ci return -1; 19862306a36Sopenharmony_ci} 19962306a36Sopenharmony_ci#endif 20062306a36Sopenharmony_civoid print_data_json(uint8_t *data, size_t len); 20162306a36Sopenharmony_civoid print_hex_data_json(uint8_t *data, size_t len); 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_ciunsigned int get_page_size(void); 20462306a36Sopenharmony_ciunsigned int get_possible_cpus(void); 20562306a36Sopenharmony_ciconst char * 20662306a36Sopenharmony_ciifindex_to_arch(__u32 ifindex, __u64 ns_dev, __u64 ns_ino, const char **opt); 20762306a36Sopenharmony_ci 20862306a36Sopenharmony_cistruct btf_dumper { 20962306a36Sopenharmony_ci const struct btf *btf; 21062306a36Sopenharmony_ci json_writer_t *jw; 21162306a36Sopenharmony_ci bool is_plain_text; 21262306a36Sopenharmony_ci bool prog_id_as_func_ptr; 21362306a36Sopenharmony_ci}; 21462306a36Sopenharmony_ci 21562306a36Sopenharmony_ci/* btf_dumper_type - print data along with type information 21662306a36Sopenharmony_ci * @d: an instance containing context for dumping types 21762306a36Sopenharmony_ci * @type_id: index in btf->types array. this points to the type to be dumped 21862306a36Sopenharmony_ci * @data: pointer the actual data, i.e. the values to be printed 21962306a36Sopenharmony_ci * 22062306a36Sopenharmony_ci * Returns zero on success and negative error code otherwise 22162306a36Sopenharmony_ci */ 22262306a36Sopenharmony_ciint btf_dumper_type(const struct btf_dumper *d, __u32 type_id, 22362306a36Sopenharmony_ci const void *data); 22462306a36Sopenharmony_civoid btf_dumper_type_only(const struct btf *btf, __u32 func_type_id, 22562306a36Sopenharmony_ci char *func_only, int size); 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_civoid btf_dump_linfo_plain(const struct btf *btf, 22862306a36Sopenharmony_ci const struct bpf_line_info *linfo, 22962306a36Sopenharmony_ci const char *prefix, bool linum); 23062306a36Sopenharmony_civoid btf_dump_linfo_json(const struct btf *btf, 23162306a36Sopenharmony_ci const struct bpf_line_info *linfo, bool linum); 23262306a36Sopenharmony_civoid btf_dump_linfo_dotlabel(const struct btf *btf, 23362306a36Sopenharmony_ci const struct bpf_line_info *linfo, bool linum); 23462306a36Sopenharmony_ci 23562306a36Sopenharmony_cistruct nlattr; 23662306a36Sopenharmony_cistruct ifinfomsg; 23762306a36Sopenharmony_cistruct tcmsg; 23862306a36Sopenharmony_ciint do_xdp_dump(struct ifinfomsg *ifinfo, struct nlattr **tb); 23962306a36Sopenharmony_ciint do_filter_dump(struct tcmsg *ifinfo, struct nlattr **tb, const char *kind, 24062306a36Sopenharmony_ci const char *devname, int ifindex); 24162306a36Sopenharmony_ci 24262306a36Sopenharmony_ciint print_all_levels(__maybe_unused enum libbpf_print_level level, 24362306a36Sopenharmony_ci const char *format, va_list args); 24462306a36Sopenharmony_ci 24562306a36Sopenharmony_cisize_t hash_fn_for_key_as_id(long key, void *ctx); 24662306a36Sopenharmony_cibool equal_fn_for_key_as_id(long k1, long k2, void *ctx); 24762306a36Sopenharmony_ci 24862306a36Sopenharmony_ci/* bpf_attach_type_input_str - convert the provided attach type value into a 24962306a36Sopenharmony_ci * textual representation that we accept for input purposes. 25062306a36Sopenharmony_ci * 25162306a36Sopenharmony_ci * This function is similar in nature to libbpf_bpf_attach_type_str, but 25262306a36Sopenharmony_ci * recognizes some attach type names that have been used by the program in the 25362306a36Sopenharmony_ci * past and which do not follow the string inference scheme that libbpf uses. 25462306a36Sopenharmony_ci * These textual representations should only be used for user input. 25562306a36Sopenharmony_ci * 25662306a36Sopenharmony_ci * @t: The attach type 25762306a36Sopenharmony_ci * Returns a pointer to a static string identifying the attach type. NULL is 25862306a36Sopenharmony_ci * returned for unknown bpf_attach_type values. 25962306a36Sopenharmony_ci */ 26062306a36Sopenharmony_ciconst char *bpf_attach_type_input_str(enum bpf_attach_type t); 26162306a36Sopenharmony_ci 26262306a36Sopenharmony_cistatic inline bool hashmap__empty(struct hashmap *map) 26362306a36Sopenharmony_ci{ 26462306a36Sopenharmony_ci return map ? hashmap__size(map) == 0 : true; 26562306a36Sopenharmony_ci} 26662306a36Sopenharmony_ci 26762306a36Sopenharmony_ciint pathname_concat(char *buf, int buf_sz, const char *path, 26862306a36Sopenharmony_ci const char *name); 26962306a36Sopenharmony_ci 27062306a36Sopenharmony_ci/* print netfilter bpf_link info */ 27162306a36Sopenharmony_civoid netfilter_dump_plain(const struct bpf_link_info *info); 27262306a36Sopenharmony_civoid netfilter_dump_json(const struct bpf_link_info *info, json_writer_t *wtr); 27362306a36Sopenharmony_ci#endif 274