#ifdef HAVE_LINUX_BPF_H
# include <linux/bpf.h>
#endif
+#include <linux/filter.h>
#include "bpf_attr.h"
#include "xlat/bpf_attach_type.h"
#include "xlat/bpf_attach_flags.h"
#include "xlat/bpf_query_flags.h"
+#include "xlat/ebpf_regs.h"
#include "xlat/numa_node.h"
/** Storage for all the data that is needed to be stored on entering. */
return 0;
}
+struct ebpf_insn {
+ uint8_t code;
+ uint8_t dst_reg:4;
+ uint8_t src_reg:4;
+ int16_t off;
+ int32_t imm;
+};
+
+struct ebpf_insns_data {
+ unsigned int count;
+};
+
+static bool
+print_ebpf_insn(struct tcb * const tcp, void * const elem_buf,
+ const size_t elem_size, void * const data)
+{
+ struct ebpf_insns_data *eid = data;
+ struct ebpf_insn *insn = elem_buf;
+
+ if (eid->count++ >= BPF_MAXINSNS) {
+ tprints("...");
+ return false;
+ }
+
+ tprints("{code=");
+ print_bpf_filter_code(insn->code, true);
+
+ /* We can't use PRINT_FIELD_XVAL on bit fields */
+ tprints(", dst_reg=");
+ printxval_index(ebpf_regs, insn->dst_reg, "BPF_REG_???");
+ tprints(", src_reg=");
+ printxval_index(ebpf_regs, insn->src_reg, "BPF_REG_???");
+
+ PRINT_FIELD_D(", ", *insn, off);
+ PRINT_FIELD_X(", ", *insn, imm);
+ tprints("}");
+
+ return true;
+}
+
+void
+print_ebpf_prog(struct tcb *const tcp, const kernel_ulong_t addr,
+ const uint32_t len)
+{
+ if (abbrev(tcp)) {
+ printaddr(addr);
+ } else {
+ struct ebpf_insns_data eid = {};
+ struct ebpf_insn insn;
+
+ print_array(tcp, addr, len, &insn, sizeof(insn),
+ umoven_or_printaddr, print_ebpf_insn, &eid);
+ }
+}
+
BEGIN_BPF_CMD_DECODER(BPF_MAP_CREATE)
{
PRINT_FIELD_XVAL_INDEX("{", attr, map_type, bpf_map_types,
PRINT_FIELD_XVAL_INDEX("{", attr, prog_type, bpf_prog_types,
"BPF_PROG_TYPE_???");
PRINT_FIELD_U(", ", attr, insn_cnt);
- PRINT_FIELD_ADDR64(", ", attr, insns);
+ tprints(", insns=");
+ print_big_u64_addr(attr.insns);
+ print_ebpf_prog(tcp, attr.insns, attr.insn_cnt);
tprintf(", license=");
print_big_u64_addr(attr.license);
};
static const struct bpf_insn insns[] = {
- { .code = 0x95 }
+ {
+ .code = 0x95,
+ .dst_reg = 10,
+ .src_reg = 11,
+ .off = 0xdead,
+ .imm = 0xbadc0ded,
+ },
};
static const char license[] = "GPL";
static char log_buf[4096];
static const char pathname[] = "/sys/fs/bpf/foo/bar";
+#if VERBOSE
+# define INSNS_FMT \
+ "[{code=BPF_JMP|BPF_K|BPF_EXIT, dst_reg=BPF_REG_10" \
+ ", src_reg=0xb /* BPF_REG_??? */, off=%d, imm=%#x}]"
+# define INSNS_ARG insns[0].off, insns[0].imm
+#else
+# define INSNS_FMT "%p"
+# define INSNS_ARG insns
+#endif
+
static void
init_BPF_PROG_LOAD_attr3(struct bpf_attr_check *check)
{
static void
print_BPF_PROG_LOAD_attr3(const struct bpf_attr_check *check, unsigned long addr)
{
- printf("prog_type=BPF_PROG_TYPE_SOCKET_FILTER, insn_cnt=%u, insns=%p"
- ", license=\"%s\", log_level=2718281828, log_size=4096"
- ", log_buf=%p, kern_version=KERNEL_VERSION(51966, 240, 13)"
+ printf("prog_type=BPF_PROG_TYPE_SOCKET_FILTER, insn_cnt=%u"
+ ", insns=" INSNS_FMT ", license=\"%s\", log_level=2718281828"
+ ", log_size=4096, log_buf=%p"
+ ", kern_version=KERNEL_VERSION(51966, 240, 13)"
", prog_flags=0x2 /* BPF_F_??? */"
", prog_name=\"0123456789abcde\"..., prog_ifindex=3203399405",
- (unsigned int) ARRAY_SIZE(insns), insns,
- license, log_buf);
+ (unsigned int) ARRAY_SIZE(insns), INSNS_ARG, license, log_buf);
}
static void
static void
print_BPF_PROG_LOAD_attr4(const struct bpf_attr_check *check, unsigned long addr)
{
- printf("prog_type=BPF_PROG_TYPE_UNSPEC, insn_cnt=%u, insns=%p"
+ printf("prog_type=BPF_PROG_TYPE_UNSPEC, insn_cnt=%u, insns=" INSNS_FMT
", license=\"%s\", log_level=2718281828, log_size=4096"
", log_buf=%p, kern_version=KERNEL_VERSION(51966, 240, 13)"
", prog_flags=BPF_F_STRICT_ALIGNMENT|0x2"
", prog_name=\"0123456789abcde\"..., prog_ifindex=%s"
", expected_attach_type=BPF_CGROUP_INET6_BIND",
- (unsigned int) ARRAY_SIZE(insns), insns,
+ (unsigned int) ARRAY_SIZE(insns), INSNS_ARG,
license, log_buf, IFINDEX_LO_STR);
}
} },
.size = offsetofend(struct BPF_PROG_LOAD_struct, prog_name),
.str = "prog_type=BPF_PROG_TYPE_RAW_TRACEPOINT"
- ", insn_cnt=3134983661, insns=0xffffffff00000000"
+ ", insn_cnt=3134983661"
+ ", insns=" BIG_ADDR("0xffffffff00000000", "NULL")
", license=" BIG_ADDR("0xffffffff00000000", "NULL")
", log_level=2718281828, log_size=4096"
", log_buf=0xffffffff00000000"