The program and map iterators work similar to seq_file-s. Once the program is pinned in bpffs it can be read with "cat" tool to print human readable output. In this case about BPF programs and maps. For example: $ cat /sys/fs/bpf/progs.debug id name attached 5 dump_bpf_map bpf_iter_bpf_map 6 dump_bpf_prog bpf_iter_bpf_prog $ cat /sys/fs/bpf/maps.debug id name max_entries 3 iterator.rodata 1 To avoid kernel build dependency on clang 10 separate bpf skeleton generation into manual "make" step and instead check-in generated .skel.h into git. Unlike 'bpftool prog show' in-kernel BTF name is used (when available) to print full name of BPF program instead of 16-byte truncated name. Signed-off-by: Alexei Starovoitov <ast@kernel.org> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net> Acked-by: Andrii Nakryiko <andriin@fb.com> Link: https://lore.kernel.org/bpf/20200819042759.51280-3-alexei.starovoitov@gmail.com
114 lines
2.3 KiB
C
114 lines
2.3 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
/* Copyright (c) 2020 Facebook */
|
|
#include <linux/bpf.h>
|
|
#include <bpf/bpf_helpers.h>
|
|
#include <bpf/bpf_tracing.h>
|
|
#include <bpf/bpf_core_read.h>
|
|
|
|
#pragma clang attribute push (__attribute__((preserve_access_index)), apply_to = record)
|
|
struct seq_file;
|
|
struct bpf_iter_meta {
|
|
struct seq_file *seq;
|
|
__u64 session_id;
|
|
__u64 seq_num;
|
|
};
|
|
|
|
struct bpf_map {
|
|
__u32 id;
|
|
char name[16];
|
|
__u32 max_entries;
|
|
};
|
|
|
|
struct bpf_iter__bpf_map {
|
|
struct bpf_iter_meta *meta;
|
|
struct bpf_map *map;
|
|
};
|
|
|
|
struct btf_type {
|
|
__u32 name_off;
|
|
};
|
|
|
|
struct btf_header {
|
|
__u32 str_len;
|
|
};
|
|
|
|
struct btf {
|
|
const char *strings;
|
|
struct btf_type **types;
|
|
struct btf_header hdr;
|
|
};
|
|
|
|
struct bpf_prog_aux {
|
|
__u32 id;
|
|
char name[16];
|
|
const char *attach_func_name;
|
|
struct bpf_prog *linked_prog;
|
|
struct bpf_func_info *func_info;
|
|
struct btf *btf;
|
|
};
|
|
|
|
struct bpf_prog {
|
|
struct bpf_prog_aux *aux;
|
|
};
|
|
|
|
struct bpf_iter__bpf_prog {
|
|
struct bpf_iter_meta *meta;
|
|
struct bpf_prog *prog;
|
|
};
|
|
#pragma clang attribute pop
|
|
|
|
static const char *get_name(struct btf *btf, long btf_id, const char *fallback)
|
|
{
|
|
struct btf_type **types, *t;
|
|
unsigned int name_off;
|
|
const char *str;
|
|
|
|
if (!btf)
|
|
return fallback;
|
|
str = btf->strings;
|
|
types = btf->types;
|
|
bpf_probe_read_kernel(&t, sizeof(t), types + btf_id);
|
|
name_off = BPF_CORE_READ(t, name_off);
|
|
if (name_off >= btf->hdr.str_len)
|
|
return fallback;
|
|
return str + name_off;
|
|
}
|
|
|
|
SEC("iter/bpf_map")
|
|
int dump_bpf_map(struct bpf_iter__bpf_map *ctx)
|
|
{
|
|
struct seq_file *seq = ctx->meta->seq;
|
|
__u64 seq_num = ctx->meta->seq_num;
|
|
struct bpf_map *map = ctx->map;
|
|
|
|
if (!map)
|
|
return 0;
|
|
|
|
if (seq_num == 0)
|
|
BPF_SEQ_PRINTF(seq, " id name max_entries\n");
|
|
|
|
BPF_SEQ_PRINTF(seq, "%4u %-16s%6d\n", map->id, map->name, map->max_entries);
|
|
return 0;
|
|
}
|
|
|
|
SEC("iter/bpf_prog")
|
|
int dump_bpf_prog(struct bpf_iter__bpf_prog *ctx)
|
|
{
|
|
struct seq_file *seq = ctx->meta->seq;
|
|
__u64 seq_num = ctx->meta->seq_num;
|
|
struct bpf_prog *prog = ctx->prog;
|
|
struct bpf_prog_aux *aux;
|
|
|
|
if (!prog)
|
|
return 0;
|
|
|
|
aux = prog->aux;
|
|
if (seq_num == 0)
|
|
BPF_SEQ_PRINTF(seq, " id name attached\n");
|
|
|
|
BPF_SEQ_PRINTF(seq, "%4u %-16s %s %s\n", aux->id,
|
|
get_name(aux->btf, aux->func_info[0].type_id, aux->name),
|
|
aux->attach_func_name, aux->linked_prog->aux->name);
|
|
return 0;
|
|
}
|
|
char LICENSE[] SEC("license") = "GPL";
|