xref: /linux/tools/testing/selftests/bpf/progs/bpf_iter_ksym.c (revision 9f2c9170934eace462499ba0bfe042cc72900173)
1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (c) 2022, Oracle and/or its affiliates. */
3 #include "bpf_iter.h"
4 #include <bpf/bpf_helpers.h>
5 
6 char _license[] SEC("license") = "GPL";
7 
8 unsigned long last_sym_value = 0;
9 
10 static inline char to_lower(char c)
11 {
12 	if (c >= 'A' && c <= 'Z')
13 		c += ('a' - 'A');
14 	return c;
15 }
16 
17 static inline char to_upper(char c)
18 {
19 	if (c >= 'a' && c <= 'z')
20 		c -= ('a' - 'A');
21 	return c;
22 }
23 
24 /* Dump symbols with max size; the latter is calculated by caching symbol N value
25  * and when iterating on symbol N+1, we can print max size of symbol N via
26  * address of N+1 - address of N.
27  */
28 SEC("iter/ksym")
29 int dump_ksym(struct bpf_iter__ksym *ctx)
30 {
31 	struct seq_file *seq = ctx->meta->seq;
32 	struct kallsym_iter *iter = ctx->ksym;
33 	__u32 seq_num = ctx->meta->seq_num;
34 	unsigned long value;
35 	char type;
36 	int ret;
37 
38 	if (!iter)
39 		return 0;
40 
41 	if (seq_num == 0) {
42 		BPF_SEQ_PRINTF(seq, "ADDR TYPE NAME MODULE_NAME KIND MAX_SIZE\n");
43 		return 0;
44 	}
45 	if (last_sym_value)
46 		BPF_SEQ_PRINTF(seq, "0x%x\n", iter->value - last_sym_value);
47 	else
48 		BPF_SEQ_PRINTF(seq, "\n");
49 
50 	value = iter->show_value ? iter->value : 0;
51 
52 	last_sym_value = value;
53 
54 	type = iter->type;
55 
56 	if (iter->module_name[0]) {
57 		type = iter->exported ? to_upper(type) : to_lower(type);
58 		BPF_SEQ_PRINTF(seq, "0x%llx %c %s [ %s ] ",
59 			       value, type, iter->name, iter->module_name);
60 	} else {
61 		BPF_SEQ_PRINTF(seq, "0x%llx %c %s ", value, type, iter->name);
62 	}
63 	if (!iter->pos_arch_end || iter->pos_arch_end > iter->pos)
64 		BPF_SEQ_PRINTF(seq, "CORE ");
65 	else if (!iter->pos_mod_end || iter->pos_mod_end > iter->pos)
66 		BPF_SEQ_PRINTF(seq, "MOD ");
67 	else if (!iter->pos_ftrace_mod_end || iter->pos_ftrace_mod_end > iter->pos)
68 		BPF_SEQ_PRINTF(seq, "FTRACE_MOD ");
69 	else if (!iter->pos_bpf_end || iter->pos_bpf_end > iter->pos)
70 		BPF_SEQ_PRINTF(seq, "BPF ");
71 	else
72 		BPF_SEQ_PRINTF(seq, "KPROBE ");
73 	return 0;
74 }
75