1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (c) 2020 Facebook */
3 #include <linux/bpf.h>
4 #include <bpf/bpf_helpers.h>
5 #include <bpf/bpf_tracing.h>
6 #include <bpf/bpf_core_read.h>
7 
8 #pragma clang attribute push (__attribute__((preserve_access_index)), apply_to = record)
9 struct seq_file;
10 struct bpf_iter_meta {
11 	struct seq_file *seq;
12 	__u64 session_id;
13 	__u64 seq_num;
14 };
15 
16 struct bpf_map {
17 	__u32 id;
18 	char name[16];
19 	__u32 max_entries;
20 };
21 
22 struct bpf_iter__bpf_map {
23 	struct bpf_iter_meta *meta;
24 	struct bpf_map *map;
25 };
26 
27 struct btf_type {
28 	__u32 name_off;
29 };
30 
31 struct btf_header {
32 	__u32   str_len;
33 };
34 
35 struct btf {
36 	const char *strings;
37 	struct btf_type **types;
38 	struct btf_header hdr;
39 };
40 
41 struct bpf_prog_aux {
42 	__u32 id;
43 	char name[16];
44 	const char *attach_func_name;
45 	struct bpf_prog *dst_prog;
46 	struct bpf_func_info *func_info;
47 	struct btf *btf;
48 };
49 
50 struct bpf_prog {
51 	struct bpf_prog_aux *aux;
52 };
53 
54 struct bpf_iter__bpf_prog {
55 	struct bpf_iter_meta *meta;
56 	struct bpf_prog *prog;
57 };
58 #pragma clang attribute pop
59 
60 static const char *get_name(struct btf *btf, long btf_id, const char *fallback)
61 {
62 	struct btf_type **types, *t;
63 	unsigned int name_off;
64 	const char *str;
65 
66 	if (!btf)
67 		return fallback;
68 	str = btf->strings;
69 	types = btf->types;
70 	bpf_probe_read_kernel(&t, sizeof(t), types + btf_id);
71 	name_off = BPF_CORE_READ(t, name_off);
72 	if (name_off >= btf->hdr.str_len)
73 		return fallback;
74 	return str + name_off;
75 }
76 
77 SEC("iter/bpf_map")
78 int dump_bpf_map(struct bpf_iter__bpf_map *ctx)
79 {
80 	struct seq_file *seq = ctx->meta->seq;
81 	__u64 seq_num = ctx->meta->seq_num;
82 	struct bpf_map *map = ctx->map;
83 
84 	if (!map)
85 		return 0;
86 
87 	if (seq_num == 0)
88 		BPF_SEQ_PRINTF(seq, "  id name             max_entries\n");
89 
90 	BPF_SEQ_PRINTF(seq, "%4u %-16s%6d\n", map->id, map->name, map->max_entries);
91 	return 0;
92 }
93 
94 SEC("iter/bpf_prog")
95 int dump_bpf_prog(struct bpf_iter__bpf_prog *ctx)
96 {
97 	struct seq_file *seq = ctx->meta->seq;
98 	__u64 seq_num = ctx->meta->seq_num;
99 	struct bpf_prog *prog = ctx->prog;
100 	struct bpf_prog_aux *aux;
101 
102 	if (!prog)
103 		return 0;
104 
105 	aux = prog->aux;
106 	if (seq_num == 0)
107 		BPF_SEQ_PRINTF(seq, "  id name             attached\n");
108 
109 	BPF_SEQ_PRINTF(seq, "%4u %-16s %s %s\n", aux->id,
110 		       get_name(aux->btf, aux->func_info[0].type_id, aux->name),
111 		       aux->attach_func_name, aux->dst_prog->aux->name);
112 	return 0;
113 }
114 char LICENSE[] SEC("license") = "GPL";
115