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
6char _license[] SEC("license") = "GPL";
7
8unsigned long last_sym_value = 0;
9
10static inline char to_lower(char c)
11{
12 if (c >= 'A' && c <= 'Z')
13 c += ('a' - 'A');
14 return c;
15}
16
17static 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 */
28SEC("iter/ksym")
29int 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
37 if (!iter)
38 return 0;
39
40 if (seq_num == 0) {
41 BPF_SEQ_PRINTF(seq, "ADDR TYPE NAME MODULE_NAME KIND MAX_SIZE\n");
42 return 0;
43 }
44 if (last_sym_value)
45 BPF_SEQ_PRINTF(seq, "0x%x\n", iter->value - last_sym_value);
46 else
47 BPF_SEQ_PRINTF(seq, "\n");
48
49 value = iter->show_value ? iter->value : 0;
50
51 last_sym_value = value;
52
53 type = iter->type;
54
55 if (iter->module_name[0]) {
56 type = iter->exported ? to_upper(c: type) : to_lower(c: type);
57 BPF_SEQ_PRINTF(seq, "0x%llx %c %s [ %s ] ",
58 value, type, iter->name, iter->module_name);
59 } else {
60 BPF_SEQ_PRINTF(seq, "0x%llx %c %s ", value, type, iter->name);
61 }
62 if (!iter->pos_mod_end || iter->pos_mod_end > iter->pos)
63 BPF_SEQ_PRINTF(seq, "MOD ");
64 else if (!iter->pos_ftrace_mod_end || iter->pos_ftrace_mod_end > iter->pos)
65 BPF_SEQ_PRINTF(seq, "FTRACE_MOD ");
66 else if (!iter->pos_bpf_end || iter->pos_bpf_end > iter->pos)
67 BPF_SEQ_PRINTF(seq, "BPF ");
68 else
69 BPF_SEQ_PRINTF(seq, "KPROBE ");
70 return 0;
71}
72

source code of linux/tools/testing/selftests/bpf/progs/bpf_iter_ksym.c