| // SPDX-License-Identifier: GPL-2.0 |
| /* Copyright (c) 2020 Facebook */ |
| #include <linux/bpf.h> |
| #include <bpf/bpf_helpers.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 *dst_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; |
| } |
| |
| __s64 bpf_map_sum_elem_count(struct bpf_map *map) __ksym; |
| |
| 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 cur_entries\n"); |
| |
| BPF_SEQ_PRINTF(seq, "%4u %-16s %10d %10lld\n", |
| map->id, map->name, map->max_entries, |
| bpf_map_sum_elem_count(map)); |
| |
| 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->dst_prog->aux->name); |
| return 0; |
| } |
| char LICENSE[] SEC("license") = "GPL"; |