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