1
0
Fork 0
mirror of synced 2025-03-06 20:59:54 +01:00
linux/tools/testing/selftests/bpf/progs/bpf_iter_ksym.c
Alan Maguire a9d2fae89f selftests/bpf: add a ksym iter subtest
add subtest verifying BPF ksym iter behaviour.  The BPF ksym
iter program shows an example of dumping a format different to
/proc/kallsyms.  It adds KIND and MAX_SIZE fields which represent the
kind of symbol (core kernel, module, ftrace, bpf, or kprobe) and
the maximum size the symbol can be.  The latter is calculated from
the difference between current symbol value and the next symbol
value.

The key benefit for this iterator will likely be supporting in-kernel
data-gathering rather than dumping symbol details to userspace and
parsing the results.

Signed-off-by: Alan Maguire <alan.maguire@oracle.com>
Acked-by: Yonghong Song <yhs@fb.com>
Link: https://lore.kernel.org/r/1657629105-7812-3-git-send-email-alan.maguire@oracle.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
2022-07-12 15:27:19 -07:00

74 lines
1.8 KiB
C

// SPDX-License-Identifier: GPL-2.0
/* Copyright (c) 2022, Oracle and/or its affiliates. */
#include "bpf_iter.h"
#include <bpf/bpf_helpers.h>
char _license[] SEC("license") = "GPL";
unsigned long last_sym_value = 0;
static inline char tolower(char c)
{
if (c >= 'A' && c <= 'Z')
c += ('a' - 'A');
return c;
}
static inline char toupper(char c)
{
if (c >= 'a' && c <= 'z')
c -= ('a' - 'A');
return c;
}
/* Dump symbols with max size; the latter is calculated by caching symbol N value
* and when iterating on symbol N+1, we can print max size of symbol N via
* address of N+1 - address of N.
*/
SEC("iter/ksym")
int dump_ksym(struct bpf_iter__ksym *ctx)
{
struct seq_file *seq = ctx->meta->seq;
struct kallsym_iter *iter = ctx->ksym;
__u32 seq_num = ctx->meta->seq_num;
unsigned long value;
char type;
int ret;
if (!iter)
return 0;
if (seq_num == 0) {
BPF_SEQ_PRINTF(seq, "ADDR TYPE NAME MODULE_NAME KIND MAX_SIZE\n");
return 0;
}
if (last_sym_value)
BPF_SEQ_PRINTF(seq, "0x%x\n", iter->value - last_sym_value);
else
BPF_SEQ_PRINTF(seq, "\n");
value = iter->show_value ? iter->value : 0;
last_sym_value = value;
type = iter->type;
if (iter->module_name[0]) {
type = iter->exported ? toupper(type) : tolower(type);
BPF_SEQ_PRINTF(seq, "0x%llx %c %s [ %s ] ",
value, type, iter->name, iter->module_name);
} else {
BPF_SEQ_PRINTF(seq, "0x%llx %c %s ", value, type, iter->name);
}
if (!iter->pos_arch_end || iter->pos_arch_end > iter->pos)
BPF_SEQ_PRINTF(seq, "CORE ");
else if (!iter->pos_mod_end || iter->pos_mod_end > iter->pos)
BPF_SEQ_PRINTF(seq, "MOD ");
else if (!iter->pos_ftrace_mod_end || iter->pos_ftrace_mod_end > iter->pos)
BPF_SEQ_PRINTF(seq, "FTRACE_MOD ");
else if (!iter->pos_bpf_end || iter->pos_bpf_end > iter->pos)
BPF_SEQ_PRINTF(seq, "BPF ");
else
BPF_SEQ_PRINTF(seq, "KPROBE ");
return 0;
}