diff mbox series

[v5,bpf-next,2/2] selftests/bpf: add a ksym iter subtest

Message ID 1657490998-31468-3-git-send-email-alan.maguire@oracle.com (mailing list archive)
State Superseded
Delegated to: BPF
Headers show
Series bpf: add a ksym BPF iterator | expand

Checks

Context Check Description
bpf/vmtest-bpf-next-PR success PR summary
netdev/tree_selection success Clearly marked for bpf-next
netdev/fixes_present success Fixes tag not required for -next series
netdev/subject_prefix success Link
netdev/cover_letter success Series has a cover letter
netdev/patch_count success Link
netdev/header_inline success No static functions without inline keyword in header files
netdev/build_32bit success Errors and warnings before: 0 this patch: 0
netdev/cc_maintainers warning 6 maintainers not CCed: song@kernel.org linux-kselftest@vger.kernel.org martin.lau@linux.dev mykolal@fb.com sdf@google.com shuah@kernel.org
netdev/build_clang success Errors and warnings before: 0 this patch: 0
netdev/module_param success Was 0 now: 0
netdev/verify_signedoff success Signed-off-by tag matches author and committer
netdev/check_selftest success No net selftest shell script
netdev/verify_fixes success No Fixes tag
netdev/build_allmodconfig_warn success Errors and warnings before: 0 this patch: 0
netdev/checkpatch warning WARNING: added, moved or deleted file(s), does MAINTAINERS need updating? WARNING: line length of 81 exceeds 80 columns WARNING: line length of 82 exceeds 80 columns WARNING: line length of 83 exceeds 80 columns
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/source_inline fail Was 0 now: 2
bpf/vmtest-bpf-next-VM_Test-3 success Logs for Kernel LATEST on z15 with gcc
bpf/vmtest-bpf-next-VM_Test-1 success Logs for Kernel LATEST on ubuntu-latest with gcc
bpf/vmtest-bpf-next-VM_Test-2 success Logs for Kernel LATEST on ubuntu-latest with llvm-15

Commit Message

Alan Maguire July 10, 2022, 10:09 p.m. UTC
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>
---
 tools/testing/selftests/bpf/prog_tests/bpf_iter.c | 16 +++++
 tools/testing/selftests/bpf/progs/bpf_iter.h      | 32 ++++++++++
 tools/testing/selftests/bpf/progs/bpf_iter_ksym.c | 74 +++++++++++++++++++++++
 3 files changed, 122 insertions(+)
 create mode 100644 tools/testing/selftests/bpf/progs/bpf_iter_ksym.c

Comments

Yonghong Song July 11, 2022, 12:30 a.m. UTC | #1
On 7/10/22 3:09 PM, Alan Maguire wrote:
> 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>
> ---
>   tools/testing/selftests/bpf/prog_tests/bpf_iter.c | 16 +++++
>   tools/testing/selftests/bpf/progs/bpf_iter.h      | 32 ++++++++++
>   tools/testing/selftests/bpf/progs/bpf_iter_ksym.c | 74 +++++++++++++++++++++++
>   3 files changed, 122 insertions(+)
>   create mode 100644 tools/testing/selftests/bpf/progs/bpf_iter_ksym.c
> 
> diff --git a/tools/testing/selftests/bpf/prog_tests/bpf_iter.c b/tools/testing/selftests/bpf/prog_tests/bpf_iter.c
> index 7ff5fa9..a33874b 100644
> --- a/tools/testing/selftests/bpf/prog_tests/bpf_iter.c
> +++ b/tools/testing/selftests/bpf/prog_tests/bpf_iter.c
> @@ -27,6 +27,7 @@
>   #include "bpf_iter_test_kern5.skel.h"
>   #include "bpf_iter_test_kern6.skel.h"
>   #include "bpf_iter_bpf_link.skel.h"
> +#include "bpf_iter_ksym.skel.h"
>   
>   static int duration;
>   
> @@ -1120,6 +1121,19 @@ static void test_link_iter(void)
>   	bpf_iter_bpf_link__destroy(skel);
>   }
>   
> +static void test_ksym_iter(void)
> +{
> +	struct bpf_iter_ksym *skel;
> +
> +	skel = bpf_iter_ksym__open_and_load();
> +	if (!ASSERT_OK_PTR(skel, "bpf_iter_ksym__open_and_load"))
> +		return;
> +
> +	do_dummy_read(skel->progs.dump_ksym);
> +
> +	bpf_iter_ksym__destroy(skel);
> +}
> +
>   #define CMP_BUFFER_SIZE 1024
>   static char task_vma_output[CMP_BUFFER_SIZE];
>   static char proc_maps_output[CMP_BUFFER_SIZE];
> @@ -1267,4 +1281,6 @@ void test_bpf_iter(void)
>   		test_buf_neg_offset();
>   	if (test__start_subtest("link-iter"))
>   		test_link_iter();
> +	if (test__start_subtest("ksym"))
> +		test_ksym_iter();
>   }
> diff --git a/tools/testing/selftests/bpf/progs/bpf_iter.h b/tools/testing/selftests/bpf/progs/bpf_iter.h
> index 97ec8bc..4b23a08 100644
> --- a/tools/testing/selftests/bpf/progs/bpf_iter.h
> +++ b/tools/testing/selftests/bpf/progs/bpf_iter.h
> @@ -22,6 +22,8 @@
>   #define BTF_F_NONAME BTF_F_NONAME___not_used
>   #define BTF_F_PTR_RAW BTF_F_PTR_RAW___not_used
>   #define BTF_F_ZERO BTF_F_ZERO___not_used
> +#define bpf_iter__ksym bpf_iter__ksym___not_used
> +#define kallsym_iter kallsym_iter___not_used

There is no need to do kallsym_iter. This structure
should appear in vmlinux.h for all supporting bpf kernels.

>   #include "vmlinux.h"
>   #undef bpf_iter_meta
>   #undef bpf_iter__bpf_map
> @@ -44,6 +46,8 @@
>   #undef BTF_F_NONAME
>   #undef BTF_F_PTR_RAW
>   #undef BTF_F_ZERO
> +#undef bpf_iter__ksym
> +#undef kallsym_iter
>   
>   struct bpf_iter_meta {
>   	struct seq_file *seq;
> @@ -151,3 +155,31 @@ enum {
>   	BTF_F_PTR_RAW	=	(1ULL << 2),
>   	BTF_F_ZERO	=	(1ULL << 3),
>   };
> +
> +#ifndef KSYM_NAME_LEN
> +#define KSYM_NAME_LEN 128
> +#endif
> +
> +#ifndef MODULE_NAME_LEN
> +#define MODULE_NAME_LEN (64 - sizeof(unsigned long))
> +#endif
> +
> +struct kallsym_iter {
> +	loff_t pos;
> +	loff_t pos_arch_end;
> +	loff_t pos_mod_end;
> +	loff_t pos_ftrace_mod_end;
> +	loff_t pos_bpf_end;
> +	unsigned long value;
> +	unsigned int nameoff; /* If iterating in core kernel symbols. */
> +	char type;
> +	char name[KSYM_NAME_LEN];
> +	char module_name[MODULE_NAME_LEN];
> +	int exported;
> +	int show_value;
> +};
> +
> +struct bpf_iter__ksym {
> +	struct bpf_iter_meta *meta;
> +	struct kallsym_iter *ksym;
> +};
[...]
diff mbox series

Patch

diff --git a/tools/testing/selftests/bpf/prog_tests/bpf_iter.c b/tools/testing/selftests/bpf/prog_tests/bpf_iter.c
index 7ff5fa9..a33874b 100644
--- a/tools/testing/selftests/bpf/prog_tests/bpf_iter.c
+++ b/tools/testing/selftests/bpf/prog_tests/bpf_iter.c
@@ -27,6 +27,7 @@ 
 #include "bpf_iter_test_kern5.skel.h"
 #include "bpf_iter_test_kern6.skel.h"
 #include "bpf_iter_bpf_link.skel.h"
+#include "bpf_iter_ksym.skel.h"
 
 static int duration;
 
@@ -1120,6 +1121,19 @@  static void test_link_iter(void)
 	bpf_iter_bpf_link__destroy(skel);
 }
 
+static void test_ksym_iter(void)
+{
+	struct bpf_iter_ksym *skel;
+
+	skel = bpf_iter_ksym__open_and_load();
+	if (!ASSERT_OK_PTR(skel, "bpf_iter_ksym__open_and_load"))
+		return;
+
+	do_dummy_read(skel->progs.dump_ksym);
+
+	bpf_iter_ksym__destroy(skel);
+}
+
 #define CMP_BUFFER_SIZE 1024
 static char task_vma_output[CMP_BUFFER_SIZE];
 static char proc_maps_output[CMP_BUFFER_SIZE];
@@ -1267,4 +1281,6 @@  void test_bpf_iter(void)
 		test_buf_neg_offset();
 	if (test__start_subtest("link-iter"))
 		test_link_iter();
+	if (test__start_subtest("ksym"))
+		test_ksym_iter();
 }
diff --git a/tools/testing/selftests/bpf/progs/bpf_iter.h b/tools/testing/selftests/bpf/progs/bpf_iter.h
index 97ec8bc..4b23a08 100644
--- a/tools/testing/selftests/bpf/progs/bpf_iter.h
+++ b/tools/testing/selftests/bpf/progs/bpf_iter.h
@@ -22,6 +22,8 @@ 
 #define BTF_F_NONAME BTF_F_NONAME___not_used
 #define BTF_F_PTR_RAW BTF_F_PTR_RAW___not_used
 #define BTF_F_ZERO BTF_F_ZERO___not_used
+#define bpf_iter__ksym bpf_iter__ksym___not_used
+#define kallsym_iter kallsym_iter___not_used
 #include "vmlinux.h"
 #undef bpf_iter_meta
 #undef bpf_iter__bpf_map
@@ -44,6 +46,8 @@ 
 #undef BTF_F_NONAME
 #undef BTF_F_PTR_RAW
 #undef BTF_F_ZERO
+#undef bpf_iter__ksym
+#undef kallsym_iter
 
 struct bpf_iter_meta {
 	struct seq_file *seq;
@@ -151,3 +155,31 @@  enum {
 	BTF_F_PTR_RAW	=	(1ULL << 2),
 	BTF_F_ZERO	=	(1ULL << 3),
 };
+
+#ifndef KSYM_NAME_LEN
+#define KSYM_NAME_LEN 128
+#endif
+
+#ifndef MODULE_NAME_LEN
+#define MODULE_NAME_LEN (64 - sizeof(unsigned long))
+#endif
+
+struct kallsym_iter {
+	loff_t pos;
+	loff_t pos_arch_end;
+	loff_t pos_mod_end;
+	loff_t pos_ftrace_mod_end;
+	loff_t pos_bpf_end;
+	unsigned long value;
+	unsigned int nameoff; /* If iterating in core kernel symbols. */
+	char type;
+	char name[KSYM_NAME_LEN];
+	char module_name[MODULE_NAME_LEN];
+	int exported;
+	int show_value;
+};
+
+struct bpf_iter__ksym {
+	struct bpf_iter_meta *meta;
+	struct kallsym_iter *ksym;
+};
diff --git a/tools/testing/selftests/bpf/progs/bpf_iter_ksym.c b/tools/testing/selftests/bpf/progs/bpf_iter_ksym.c
new file mode 100644
index 0000000..285c008
--- /dev/null
+++ b/tools/testing/selftests/bpf/progs/bpf_iter_ksym.c
@@ -0,0 +1,74 @@ 
+// 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;
+}