Context |
Check |
Description |
bpf/vmtest-bpf-next-PR |
success
|
PR summary
|
bpf/vmtest-bpf-next-VM_Test-1 |
success
|
Logs for ShellCheck
|
bpf/vmtest-bpf-next-VM_Test-0 |
success
|
Logs for Lint
|
bpf/vmtest-bpf-next-VM_Test-2 |
success
|
Logs for Unittests
|
bpf/vmtest-bpf-next-VM_Test-3 |
success
|
Logs for Validate matrix.py
|
bpf/vmtest-bpf-next-VM_Test-5 |
success
|
Logs for aarch64-gcc / build-release
|
bpf/vmtest-bpf-next-VM_Test-7 |
success
|
Logs for s390x-gcc / build-release
|
bpf/vmtest-bpf-next-VM_Test-8 |
success
|
Logs for set-matrix
|
bpf/vmtest-bpf-next-VM_Test-4 |
success
|
Logs for aarch64-gcc / build / build for aarch64 with gcc
|
bpf/vmtest-bpf-next-VM_Test-6 |
pending
|
Logs for aarch64-gcc / test (test_maps, false, 360) / test_maps on aarch64 with gcc
|
bpf/vmtest-bpf-next-VM_Test-9 |
pending
|
Logs for aarch64-gcc / test (test_verifier, false, 360) / test_verifier on aarch64 with gcc
|
bpf/vmtest-bpf-next-VM_Test-10 |
success
|
Logs for aarch64-gcc / veristat
|
bpf/vmtest-bpf-next-VM_Test-11 |
success
|
Logs for s390x-gcc / build / build for s390x with gcc
|
bpf/vmtest-bpf-next-VM_Test-12 |
success
|
Logs for s390x-gcc / build-release
|
bpf/vmtest-bpf-next-VM_Test-13 |
fail
|
Logs for s390x-gcc / test (test_maps, false, 360) / test_maps on s390x with gcc
|
bpf/vmtest-bpf-next-VM_Test-17 |
success
|
Logs for s390x-gcc / veristat
|
bpf/vmtest-bpf-next-VM_Test-18 |
success
|
Logs for set-matrix
|
bpf/vmtest-bpf-next-VM_Test-19 |
success
|
Logs for x86_64-gcc / build / build for x86_64 with gcc
|
bpf/vmtest-bpf-next-VM_Test-20 |
success
|
Logs for x86_64-gcc / build-release
|
bpf/vmtest-bpf-next-VM_Test-28 |
success
|
Logs for x86_64-llvm-17 / build / build for x86_64 with llvm-17
|
bpf/vmtest-bpf-next-VM_Test-29 |
success
|
Logs for x86_64-llvm-17 / build-release / build for x86_64 with llvm-17-O2
|
bpf/vmtest-bpf-next-VM_Test-34 |
success
|
Logs for x86_64-llvm-17 / veristat
|
bpf/vmtest-bpf-next-VM_Test-14 |
fail
|
Logs for s390x-gcc / test (test_progs, false, 360) / test_progs on s390x with gcc
|
bpf/vmtest-bpf-next-VM_Test-15 |
fail
|
Logs for s390x-gcc / test (test_progs_no_alu32, false, 360) / test_progs_no_alu32 on s390x with gcc
|
bpf/vmtest-bpf-next-VM_Test-16 |
success
|
Logs for s390x-gcc / test (test_verifier, false, 360) / test_verifier on s390x with gcc
|
bpf/vmtest-bpf-next-VM_Test-35 |
success
|
Logs for x86_64-llvm-18 / build / build for x86_64 with llvm-18
|
bpf/vmtest-bpf-next-VM_Test-36 |
success
|
Logs for x86_64-llvm-18 / build-release / build for x86_64 with llvm-18-O2
|
bpf/vmtest-bpf-next-VM_Test-42 |
success
|
Logs for x86_64-llvm-18 / veristat
|
bpf/vmtest-bpf-next-VM_Test-21 |
success
|
Logs for x86_64-gcc / test (test_maps, false, 360) / test_maps on x86_64 with gcc
|
bpf/vmtest-bpf-next-VM_Test-22 |
fail
|
Logs for x86_64-gcc / test (test_progs, false, 360) / test_progs on x86_64 with gcc
|
bpf/vmtest-bpf-next-VM_Test-23 |
fail
|
Logs for x86_64-gcc / test (test_progs_no_alu32, false, 360) / test_progs_no_alu32 on x86_64 with gcc
|
bpf/vmtest-bpf-next-VM_Test-24 |
success
|
Logs for x86_64-gcc / test (test_progs_no_alu32_parallel, true, 30) / test_progs_no_alu32_parallel on x86_64 with gcc
|
bpf/vmtest-bpf-next-VM_Test-25 |
success
|
Logs for x86_64-gcc / test (test_progs_parallel, true, 30) / test_progs_parallel on x86_64 with gcc
|
bpf/vmtest-bpf-next-VM_Test-26 |
success
|
Logs for x86_64-gcc / test (test_verifier, false, 360) / test_verifier on x86_64 with gcc
|
bpf/vmtest-bpf-next-VM_Test-27 |
success
|
Logs for x86_64-gcc / veristat / veristat on x86_64 with gcc
|
bpf/vmtest-bpf-next-VM_Test-30 |
success
|
Logs for x86_64-llvm-17 / test (test_maps, false, 360) / test_maps on x86_64 with llvm-17
|
bpf/vmtest-bpf-next-VM_Test-31 |
fail
|
Logs for x86_64-llvm-17 / test (test_progs, false, 360) / test_progs on x86_64 with llvm-17
|
bpf/vmtest-bpf-next-VM_Test-32 |
fail
|
Logs for x86_64-llvm-17 / test (test_progs_no_alu32, false, 360) / test_progs_no_alu32 on x86_64 with llvm-17
|
bpf/vmtest-bpf-next-VM_Test-33 |
success
|
Logs for x86_64-llvm-17 / test (test_verifier, false, 360) / test_verifier on x86_64 with llvm-17
|
bpf/vmtest-bpf-next-VM_Test-37 |
success
|
Logs for x86_64-llvm-18 / test (test_maps, false, 360) / test_maps on x86_64 with llvm-18
|
bpf/vmtest-bpf-next-VM_Test-38 |
fail
|
Logs for x86_64-llvm-18 / test (test_progs, false, 360) / test_progs on x86_64 with llvm-18
|
bpf/vmtest-bpf-next-VM_Test-39 |
fail
|
Logs for x86_64-llvm-18 / test (test_progs_cpuv4, false, 360) / test_progs_cpuv4 on x86_64 with llvm-18
|
bpf/vmtest-bpf-next-VM_Test-40 |
fail
|
Logs for x86_64-llvm-18 / test (test_progs_no_alu32, false, 360) / test_progs_no_alu32 on x86_64 with llvm-18
|
bpf/vmtest-bpf-next-VM_Test-41 |
success
|
Logs for x86_64-llvm-18 / test (test_verifier, false, 360) / test_verifier on x86_64 with llvm-18
|
netdev/series_format |
fail
|
Series longer than 15 patches
|
netdev/tree_selection |
success
|
Guessed tree name to be net-next, async
|
netdev/ynl |
success
|
Generated files up to date;
no warnings/errors;
no diff in generated;
|
netdev/fixes_present |
success
|
Fixes tag not required for -next series
|
netdev/header_inline |
success
|
No static functions without inline keyword in header files
|
netdev/build_32bit |
fail
|
Errors and warnings before: 18 this patch: 18
|
netdev/build_tools |
success
|
Errors and warnings before: 0 this patch: 0
|
netdev/cc_maintainers |
warning
|
11 maintainers not CCed: shuah@kernel.org nathan@kernel.org llvm@lists.linux.dev justinstitt@google.com linux-kselftest@vger.kernel.org aou@eecs.berkeley.edu paul.walmsley@sifive.com morbo@google.com ndesaulniers@google.com linux-riscv@lists.infradead.org palmer@dabbelt.com
|
netdev/build_clang |
success
|
Errors and warnings before: 821 this patch: 821
|
netdev/verify_signedoff |
success
|
Signed-off-by tag matches author and committer
|
netdev/deprecated_api |
success
|
None detected
|
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: 826 this patch: 826
|
netdev/checkpatch |
fail
|
CHECK: Alignment should match open parenthesis
ERROR: while should follow close brace '}'
WARNING: Improper SPDX comment style for 'tools/testing/selftests/crib/test_dump_task.h', please use '/*' instead
WARNING: Missing a blank line after declarations
WARNING: Missing or malformed SPDX-License-Identifier tag in line 1
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
WARNING: externs should be avoided in .c files
WARNING: line length of 82 exceeds 80 columns
WARNING: line length of 83 exceeds 80 columns
WARNING: line length of 85 exceeds 80 columns
WARNING: line length of 86 exceeds 80 columns
WARNING: line length of 89 exceeds 80 columns
WARNING: line length of 90 exceeds 80 columns
WARNING: line length of 91 exceeds 80 columns
WARNING: line length of 96 exceeds 80 columns
WARNING: quoted string split across lines
WARNING: unchecked sscanf return value
|
netdev/build_clang_rust |
success
|
No Rust files in patch. Skipping build
|
netdev/kdoc |
success
|
Errors and warnings before: 0 this patch: 0
|
netdev/source_inline |
success
|
Was 0 now: 0
|
new file mode 100644
@@ -0,0 +1 @@
+build
new file mode 100644
@@ -0,0 +1,136 @@
+# SPDX-License-Identifier: GPL-2.0
+include ../../../build/Build.include
+include ../../../scripts/Makefile.arch
+include ../../../scripts/Makefile.include
+include ../lib.mk
+
+CUR_DIR := $(abspath .)
+REPO_ROOT := $(abspath ../../../..)
+TOOLS_DIR := $(REPO_ROOT)/tools
+TOOLSINC_DIR := $(TOOLS_DIR)/include
+BPFTOOL_DIR := $(TOOLS_DIR)/bpf/bpftool
+UAPI_DIR := $(TOOLSINC_DIR)/uapi
+LIB_DIR := $(TOOLS_DIR)/lib
+LIBBPF_DIR := $(LIB_DIR)/bpf
+GEN_DIR := $(REPO_ROOT)/include/generated
+GEN_HDR := $(GEN_DIR)/autoconf.h
+
+OUTPUT_DIR := $(CUR_DIR)/build
+INCLUDE_DIR := $(OUTPUT_DIR)/include
+SBIN_DIR:= $(OUTPUT_DIR)/sbin
+OBJ_DIR := $(OUTPUT_DIR)/obj
+CRIBOBJ_DIR := $(OBJ_DIR)/crib
+LIBBPF_OUTPUT := $(OBJ_DIR)/libbpf/libbpf.a
+LIBBPF_OBJ_DIR := $(OBJ_DIR)/libbpf
+LIBBPF_OBJ := $(LIBBPF_OBJ_DIR)/libbpf.a
+
+DEFAULT_BPFTOOL := $(SBIN_DIR)/bpftool
+BPFTOOL ?= $(DEFAULT_BPFTOOL)
+
+VMLINUX_BTF_PATHS ?= ../../../../vmlinux \
+ /sys/kernel/btf/vmlinux \
+ /boot/vmlinux-$(shell uname -r)
+VMLINUX_BTF ?= $(abspath $(firstword $(wildcard $(VMLINUX_BTF_PATHS))))
+ifeq ($(VMLINUX_BTF),)
+$(error Cannot find a vmlinux for VMLINUX_BTF at any of "$(VMLINUX_BTF_PATHS)")
+endif
+
+ifneq ($(wildcard $(GEN_HDR)),)
+ GENFLAGS := -DHAVE_GENHDR
+endif
+
+CFLAGS += -g -O2 -rdynamic -pthread -Wall -Werror $(GENFLAGS) \
+ -I$(INCLUDE_DIR) -I$(GEN_DIR) -I$(LIB_DIR) \
+ -I$(TOOLSINC_DIR) -I$(UAPI_DIR) -I$(CUR_DIR)/include \
+ -Wno-unused-command-line-argument
+
+LDFLAGS = -lelf -lz
+
+IS_LITTLE_ENDIAN = $(shell $(CC) -dM -E - </dev/null | \
+ grep 'define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__')
+
+define get_sys_includes
+$(shell $(1) -v -E - </dev/null 2>&1 \
+ | sed -n '/<...> search starts here:/,/End of search list./{ s| \(/.*\)|-idirafter \1|p }') \
+$(shell $(1) -dM -E - </dev/null | grep '__riscv_xlen ' | awk '{printf("-D__riscv_xlen=%d -D__BITS_PER_LONG=%d", $$3, $$3)}')
+endef
+
+BPF_CFLAGS = -g -D__TARGET_ARCH_$(SRCARCH) \
+ $(if $(IS_LITTLE_ENDIAN),-mlittle-endian,-mbig-endian) \
+ -I$(CUR_DIR)/include -I$(CUR_DIR)/include/bpf-compat \
+ -I$(INCLUDE_DIR) -I$(UAPI_DIR) \
+ -I$(REPO_ROOT)/include \
+ $(call get_sys_includes,$(CLANG)) \
+ -Wall -Wno-compare-distinct-pointer-types \
+ -Wno-incompatible-function-pointer-types \
+ -O2 -mcpu=v3
+
+MAKE_DIRS := $(sort $(OBJ_DIR)/libbpf $(OBJ_DIR)/libbpf \
+ $(OBJ_DIR)/bpftool $(OBJ_DIR)/resolve_btfids \
+ $(INCLUDE_DIR) $(CRIBOBJ_DIR) $(SBIN_DIR))
+
+TEST_GEN_BPF_PROGS_SKEL := $(foreach prog,$(wildcard *.bpf.c),$(INCLUDE_DIR)/$(patsubst %.c,%.skel.h,$(prog)))
+
+TEST_GEN_PROGS := $(addprefix $(SBIN_DIR)/, $(basename $(filter-out $(wildcard *.bpf.c), $(wildcard *.c))))
+
+TEST_GEN_PROGS_OBJ := $(addsuffix .o,$(addprefix $(CRIBOBJ_DIR)/, $(notdir $(TEST_GEN_PROGS))))
+
+$(MAKE_DIRS):
+ $(call msg,MKDIR,,$@)
+ $(Q)mkdir -p $@
+
+$(LIBBPF_OBJ): $(wildcard $(LIBBPF_DIR)/*.[ch] $(LIBBPF_DIR)/Makefile) \
+ $(UAPI_DIR)/linux/bpf.h \
+ | $(OBJ_DIR)/libbpf
+ $(Q)$(MAKE) $(submake_extras) -C $(LIBBPF_DIR) OUTPUT=$(OBJ_DIR)/libbpf/ \
+ EXTRA_CFLAGS='-g -O0 -fPIC' \
+ DESTDIR=$(OUTPUT_DIR) prefix= all install_headers
+
+$(DEFAULT_BPFTOOL): $(wildcard $(BPFTOOL_DIR)/*.[ch] $(BPFTOOL_DIR)/Makefile) \
+ $(LIBBPF_OUTPUT) | $(OBJ_DIR)/bpftool
+ $(Q)$(MAKE) $(submake_extras) -C $(BPFTOOL_DIR) \
+ ARCH= CROSS_COMPILE= CC=$(HOSTCC) LD=$(HOSTLD) \
+ EXTRA_CFLAGS='-g -O0' \
+ OUTPUT=$(OBJ_DIR)/bpftool/ \
+ LIBBPF_OUTPUT=$(OBJ_DIR)/libbpf/ \
+ LIBBPF_DESTDIR=$(OUTPUT_DIR)/ \
+ prefix= DESTDIR=$(OUTPUT_DIR)/ install-bin
+
+$(INCLUDE_DIR)/vmlinux.h: $(VMLINUX_BTF) $(BPFTOOL) | $(INCLUDE_DIR)
+ifeq ($(VMLINUX_H),)
+ $(call msg,GEN,,$@)
+ $(Q)$(BPFTOOL) btf dump file $(VMLINUX_BTF) format c > $@
+else
+ $(call msg,CP,,$@)
+ $(Q)cp "$(VMLINUX_H)" $@
+endif
+
+$(CRIBOBJ_DIR)/%.bpf.o: %.bpf.c %.h $(INCLUDE_DIR)/vmlinux.h | $(LIBBPF_OBJ) $(CRIBOBJ_DIR)
+ $(call msg,CLANG-BPF,,$(notdir $@))
+ $(Q)$(CLANG) $(BPF_CFLAGS) -target bpf -c $< -o $@
+
+$(INCLUDE_DIR)/%.bpf.skel.h: $(CRIBOBJ_DIR)/%.bpf.o $(INCLUDE_DIR)/vmlinux.h $(BPFTOOL) | $(INCLUDE_DIR)
+ $(call msg,GEN-SKEL,,$(notdir $@))
+ $(Q)$(BPFTOOL) gen skeleton $< > $@
+
+$(TEST_GEN_PROGS_OBJ): $(CRIBOBJ_DIR)/%.o: %.c %.h $(INCLUDE_DIR)/%.bpf.skel.h | $(CRIBOBJ_DIR)
+ $(call msg,CLANG,,$(notdir $@))
+ $(Q)$(CLANG) $(CFLAGS) -c $< -o $@
+
+$(TEST_GEN_PROGS): $(SBIN_DIR)/%: $(CRIBOBJ_DIR)/%.o $(LIBBPF_OBJ) | $(SBIN_DIR)
+ $(call msg,CLANG-LINK,,$(notdir $@))
+ $(Q)$(CLANG) $(CFLAGS) $(LDFLAGS) $^ -o $@
+
+override define CLEAN
+ rm -rf $(OUTPUT_DIR)
+endef
+
+all: $(TEST_GEN_PROGS)
+
+.PHONY: all clean help
+
+.DEFAULT_GOAL := all
+
+.DELETE_ON_ERROR:
+
+.SECONDARY:
new file mode 100644
@@ -0,0 +1,7 @@
+CONFIG_BPF=y
+CONFIG_BPF_EVENTS=y
+CONFIG_BPF_JIT=y
+CONFIG_BPF_CRIB=y
+CONFIG_DEBUG_INFO_BTF=y
+CONFIG_IPV6=y
+CONFIG_NET=y
new file mode 100644
@@ -0,0 +1,125 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Author:
+ * Juntong Deng <juntong.deng@outlook.com>
+ */
+
+#include "vmlinux.h"
+
+#include <bpf/bpf_helpers.h>
+#include <bpf/bpf_tracing.h>
+#include <bpf/bpf_core_read.h>
+
+#include "test_dump_task.h"
+
+char LICENSE[] SEC("license") = "Dual BSD/GPL";
+
+struct {
+ __uint(type, BPF_MAP_TYPE_RINGBUF);
+ __uint(max_entries, 100000);
+} rb SEC(".maps");
+
+extern struct task_struct *bpf_task_from_vpid(pid_t vpid) __ksym;
+extern void bpf_task_release(struct task_struct *p) __ksym;
+
+extern int bpf_iter_task_vma_new(struct bpf_iter_task_vma *it,
+ struct task_struct *task,
+ unsigned long addr) __ksym;
+extern struct vm_area_struct *bpf_iter_task_vma_next(struct bpf_iter_task_vma *it) __ksym;
+extern void bpf_iter_task_vma_destroy(struct bpf_iter_task_vma *it) __ksym;
+
+SEC("crib")
+int dump_all_vma(struct prog_args *arg)
+{
+ int err = 0;
+
+ struct task_struct *task = bpf_task_from_vpid(arg->pid);
+ if (!task) {
+ err = -1;
+ goto error;
+ }
+
+ struct vm_area_struct *cur_vma;
+ struct bpf_iter_task_vma vma_it;
+
+ bpf_iter_task_vma_new(&vma_it, task, 0);
+ while ((cur_vma = bpf_iter_task_vma_next(&vma_it))) {
+ struct event_vma *e_vma = bpf_ringbuf_reserve(&rb, sizeof(struct event_vma), 0);
+ if (!e_vma) {
+ err = -2;
+ goto error_buf;
+ }
+
+ e_vma->hdr.type = EVENT_TYPE_VMA;
+ e_vma->vm_start = BPF_CORE_READ(cur_vma, vm_start);
+ e_vma->vm_end = BPF_CORE_READ(cur_vma, vm_end);
+ e_vma->vm_flags = BPF_CORE_READ(cur_vma, vm_flags);
+
+ if (cur_vma->vm_file)
+ e_vma->vm_pgoff = BPF_CORE_READ(cur_vma, vm_pgoff);
+
+ bpf_ringbuf_submit(e_vma, 0);
+ }
+
+error_buf:
+ bpf_iter_task_vma_destroy(&vma_it);
+ bpf_task_release(task);
+error:
+ return err;
+}
+
+SEC("crib")
+int dump_task_stat(struct prog_args *arg)
+{
+ int err = 0;
+
+ struct task_struct *task = bpf_task_from_vpid(arg->pid);
+ if (!task) {
+ err = -1;
+ goto error;
+ }
+
+ struct event_task *e_task = bpf_ringbuf_reserve(&rb, sizeof(struct event_task), 0);
+ if (!e_task) {
+ err = -2;
+ goto error_buf;
+ }
+
+ e_task->hdr.type = EVENT_TYPE_TASK;
+ e_task->pid = BPF_CORE_READ(task, pid);
+ e_task->prio = BPF_CORE_READ(task, prio);
+ e_task->policy = BPF_CORE_READ(task, policy);
+ e_task->flags = BPF_CORE_READ(task, flags);
+ e_task->exit_code = BPF_CORE_READ(task, exit_code);
+ BPF_CORE_READ_STR_INTO(&e_task->comm, task, comm);
+
+ bpf_ringbuf_submit(e_task, 0);
+
+ struct event_mm *e_mm = bpf_ringbuf_reserve(&rb, sizeof(struct event_mm), 0);
+ if (!e_mm) {
+ err = -2;
+ goto error_buf;
+ }
+
+ struct mm_struct *mm = BPF_CORE_READ(task, mm);
+ e_mm->hdr.type = EVENT_TYPE_MM;
+ e_mm->start_code = BPF_CORE_READ(mm, start_code);
+ e_mm->end_code = BPF_CORE_READ(mm, end_code);
+ e_mm->start_data = BPF_CORE_READ(mm, start_data);
+ e_mm->end_data = BPF_CORE_READ(mm, end_data);
+ e_mm->start_brk = BPF_CORE_READ(mm, start_brk);
+ e_mm->brk = BPF_CORE_READ(mm, brk);
+ e_mm->start_stack = BPF_CORE_READ(mm, start_stack);
+ e_mm->arg_start = BPF_CORE_READ(mm, arg_start);
+ e_mm->arg_end = BPF_CORE_READ(mm, arg_end);
+ e_mm->env_start = BPF_CORE_READ(mm, env_start);
+ e_mm->env_end = BPF_CORE_READ(mm, env_end);
+ e_mm->map_count = BPF_CORE_READ(mm, map_count);
+
+ bpf_ringbuf_submit(e_mm, 0);
+
+error_buf:
+ bpf_task_release(task);
+error:
+ return err;
+}
new file mode 100644
@@ -0,0 +1,337 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Author:
+ * Juntong Deng <juntong.deng@outlook.com>
+ */
+
+#include <argp.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <time.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include <bpf/libbpf.h>
+#include <bpf/bpf.h>
+#include <autoconf.h>
+
+#include "../kselftest_harness.h"
+
+#include "test_dump_task.h"
+#include "test_dump_task.bpf.skel.h"
+
+struct task {
+ int pid;
+ unsigned int flags;
+ int prio;
+ unsigned int policy;
+ int exit_code;
+ char comm[16];
+};
+
+struct mm {
+ unsigned long start_code;
+ unsigned long end_code;
+ unsigned long start_data;
+ unsigned long end_data;
+ unsigned long start_brk;
+ unsigned long brk;
+ unsigned long start_stack;
+ unsigned long arg_start;
+ unsigned long arg_end;
+ unsigned long env_start;
+ unsigned long env_end;
+ int map_count;
+};
+
+struct vma {
+ unsigned long vm_start;
+ unsigned long vm_end;
+ unsigned long vm_flags;
+ unsigned long vm_pgoff;
+};
+
+struct dump_info {
+ struct task task;
+ struct mm mm;
+ struct vma *vma;
+ unsigned int vma_count;
+};
+
+static int handle_vma_event(struct dump_info *info, struct event_vma *e_vma)
+{
+ struct vma *vma = &info->vma[info->vma_count];
+ vma->vm_start = e_vma->vm_start;
+ vma->vm_end = e_vma->vm_end;
+ vma->vm_flags = e_vma->vm_flags;
+ vma->vm_pgoff = e_vma->vm_pgoff;
+ info->vma_count++;
+ return 0;
+}
+
+static int handle_mm_event(struct dump_info *info, struct event_mm *e_mm)
+{
+ info->mm.start_code = e_mm->start_code;
+ info->mm.end_code = e_mm->end_code;
+ info->mm.start_data = e_mm->start_data;
+ info->mm.end_data = e_mm->end_data;
+ info->mm.start_brk = e_mm->start_brk;
+ info->mm.brk = e_mm->brk;
+ info->mm.start_stack = e_mm->start_stack;
+ info->mm.arg_start = e_mm->arg_start;
+ info->mm.arg_end = e_mm->arg_end;
+ info->mm.env_start = e_mm->env_start;
+ info->mm.env_end = e_mm->env_end;
+ info->mm.map_count = e_mm->map_count;
+ info->vma = (struct vma *)malloc(sizeof(struct vma) * e_mm->map_count);
+ info->vma_count = 0;
+ return 0;
+}
+
+static int handle_task_event(struct dump_info *info, struct event_task *e_task)
+{
+ info->task.pid = e_task->pid;
+ info->task.flags = e_task->flags;
+ info->task.prio = e_task->prio;
+ info->task.policy = e_task->policy;
+ info->task.exit_code = e_task->exit_code;
+ memcpy(info->task.comm, e_task->comm, sizeof(info->task.comm));
+ return 0;
+}
+
+static int handle_event(void *ctx, void *data, size_t data_sz)
+{
+ struct dump_info *info = (struct dump_info *)ctx;
+ const struct event_hdr *e_hdr = data;
+ int err = 0;
+
+ switch (e_hdr->type) {
+ case EVENT_TYPE_TASK:
+ handle_task_event(info, (struct event_task *)data);
+ break;
+ case EVENT_TYPE_VMA:
+ handle_vma_event(info, (struct event_vma *)data);
+ break;
+ case EVENT_TYPE_MM:
+ handle_mm_event(info, (struct event_mm *)data);
+ break;
+ default:
+ err = -1;
+ printf("Unknown event type!\n");
+ break;
+ }
+ return err;
+}
+
+static int dump_task_and_mm_struct_from_proc(struct dump_info *info)
+{
+ FILE *file = fopen("/proc/self/stat", "r");
+ if (!file)
+ return -1;
+
+ fscanf(file, "%d %s %*c %*d %*d %*d %*d %*d %u %*lu %*lu %*lu %*lu "
+ "%*lu %*lu %*ld %*ld %d %*ld %*d %*d %*llu %*lu %*ld %*lu %lu %lu %lu "
+ "%*lu %*lu %*lu %*lu %*lu %*lu %*lu %*lu %*lu %*d %*d %*u %u %*llu %*lu %*ld "
+ "%lu %lu %lu %lu %lu %lu %lu %d",
+ &info->task.pid, info->task.comm, &info->task.flags, &info->task.prio,
+ &info->mm.start_code, &info->mm.end_code, &info->mm.start_stack,
+ &info->task.policy, &info->mm.start_data, &info->mm.end_data,
+ &info->mm.start_brk, &info->mm.arg_start, &info->mm.arg_end,
+ &info->mm.env_start, &info->mm.env_end, &info->task.exit_code);
+
+ fclose(file);
+ return 0;
+}
+
+static void parse_vma_vmflags(char *buf, struct vma *vma)
+{
+ vma->vm_flags = 0;
+ char *token = strtok(buf, " ");
+ do {
+ if (!strncmp(token, "rd", 2))
+ vma->vm_flags |= VM_READ;
+ else if (!strncmp(token, "wr", 2))
+ vma->vm_flags |= VM_WRITE;
+ else if (!strncmp(token, "ex", 2))
+ vma->vm_flags |= VM_EXEC;
+ else if (!strncmp(token, "sh", 2))
+ vma->vm_flags |= VM_SHARED;
+ else if (!strncmp(token, "mr", 2))
+ vma->vm_flags |= VM_MAYREAD;
+ else if (!strncmp(token, "mw", 2))
+ vma->vm_flags |= VM_MAYWRITE;
+ else if (!strncmp(token, "me", 2))
+ vma->vm_flags |= VM_MAYEXEC;
+ else if (!strncmp(token, "ms", 2))
+ vma->vm_flags |= VM_MAYSHARE;
+ else if (!strncmp(token, "gd", 2))
+ vma->vm_flags |= VM_GROWSDOWN;
+ else if (!strncmp(token, "pf", 2))
+ vma->vm_flags |= VM_PFNMAP;
+ else if (!strncmp(token, "lo", 2))
+ vma->vm_flags |= VM_LOCKED;
+ else if (!strncmp(token, "io", 2))
+ vma->vm_flags |= VM_IO;
+ else if (!strncmp(token, "sr", 2))
+ vma->vm_flags |= VM_SEQ_READ;
+ else if (!strncmp(token, "rr", 2))
+ vma->vm_flags |= VM_RAND_READ;
+ else if (!strncmp(token, "dc", 2))
+ vma->vm_flags |= VM_DONTCOPY;
+ else if (!strncmp(token, "de", 2))
+ vma->vm_flags |= VM_DONTEXPAND;
+ else if (!strncmp(token, "lf", 2))
+ vma->vm_flags |= VM_LOCKONFAULT;
+ else if (!strncmp(token, "ac", 2))
+ vma->vm_flags |= VM_ACCOUNT;
+ else if (!strncmp(token, "nr", 2))
+ vma->vm_flags |= VM_NORESERVE;
+ else if (!strncmp(token, "ht", 2))
+ vma->vm_flags |= VM_HUGETLB;
+ else if (!strncmp(token, "sf", 2))
+ vma->vm_flags |= VM_SYNC;
+ else if (!strncmp(token, "ar", 2))
+ vma->vm_flags |= VM_ARCH_1;
+ else if (!strncmp(token, "wf", 2))
+ vma->vm_flags |= VM_WIPEONFORK;
+ else if (!strncmp(token, "dd", 2))
+ vma->vm_flags |= VM_DONTDUMP;
+ else if (!strncmp(token, "sd", 2))
+ vma->vm_flags |= VM_SOFTDIRTY;
+ else if (!strncmp(token, "mm", 2))
+ vma->vm_flags |= VM_MIXEDMAP;
+ else if (!strncmp(token, "hg", 2))
+ vma->vm_flags |= VM_HUGEPAGE;
+ else if (!strncmp(token, "nh", 2))
+ vma->vm_flags |= VM_NOHUGEPAGE;
+ else if (!strncmp(token, "mg", 2))
+ vma->vm_flags |= VM_MERGEABLE;
+ else if (!strncmp(token, "um", 2))
+ vma->vm_flags |= VM_UFFD_MISSING;
+ else if (!strncmp(token, "uw", 2))
+ vma->vm_flags |= VM_UFFD_WP;
+ }
+ while ((token = strtok(NULL, " ")) != NULL);
+}
+
+static int dump_vma_from_proc(struct dump_info *info)
+{
+ FILE *file = fopen("/proc/self/smaps", "r");
+ if (!file)
+ return -1;
+
+ char *line = NULL;
+ size_t len = 0;
+ ssize_t nread;
+ while ((nread = getline(&line, &len, file)) != -1) {
+ struct vma *vma = &info->vma[info->vma_count];
+ if (isupper(*line)) {
+ if (!strncmp(line, "VmFlags: ", 9)) {
+ parse_vma_vmflags(&line[9], vma);
+ info->vma_count++;
+ }
+ } else {
+ sscanf(line, "%lx-%lx %*c%*c%*c%*c %lx",
+ &vma->vm_start, &vma->vm_end, &vma->vm_pgoff);
+ }
+ }
+
+ fclose(file);
+ return 0;
+}
+
+static int check_dump_info_correctness(struct dump_info *crib_info, struct dump_info *proc_info)
+{
+ if (crib_info->task.pid != proc_info->task.pid ||
+ crib_info->task.flags != proc_info->task.flags ||
+ crib_info->task.prio - 100 != proc_info->task.prio ||
+ crib_info->task.policy != proc_info->task.policy ||
+ crib_info->task.exit_code != proc_info->task.exit_code ||
+ strncmp(crib_info->task.comm, proc_info->task.comm + 1,
+ strlen(crib_info->task.comm)))
+ return -1;
+
+ if (crib_info->mm.start_code != proc_info->mm.start_code ||
+ crib_info->mm.end_code != proc_info->mm.end_code ||
+ crib_info->mm.start_data != proc_info->mm.start_data ||
+ crib_info->mm.end_data != proc_info->mm.end_data ||
+ crib_info->mm.start_brk != proc_info->mm.start_brk ||
+ crib_info->mm.arg_start != proc_info->mm.arg_start ||
+ crib_info->mm.arg_end != proc_info->mm.arg_end ||
+ crib_info->mm.env_start != proc_info->mm.env_start ||
+ crib_info->mm.env_end != proc_info->mm.env_end ||
+ crib_info->mm.start_stack != proc_info->mm.start_stack)
+ return -1;
+
+ struct vma *crib_vma, *proc_vma;
+ for (int i = 0; i < crib_info->mm.map_count; i++) {
+ crib_vma = &crib_info->vma[i];
+ proc_vma = &proc_info->vma[i];
+ if (crib_vma->vm_start != proc_vma->vm_start ||
+ crib_vma->vm_end != proc_vma->vm_end ||
+ crib_vma->vm_flags != proc_vma->vm_flags ||
+ crib_vma->vm_pgoff << CONFIG_PAGE_SHIFT != proc_vma->vm_pgoff)
+ return -1;
+ }
+ return 0;
+}
+
+TEST(dump_task)
+{
+ struct prog_args args = {
+ .pid = getpid(),
+ };
+ ASSERT_GT(args.pid, 0);
+
+ DECLARE_LIBBPF_OPTS(bpf_test_run_opts, opts,
+ .ctx_in = &args,
+ .ctx_size_in = sizeof(args),
+ );
+
+ struct test_dump_task_bpf *skel = test_dump_task_bpf__open_and_load();
+ ASSERT_NE(skel, NULL);
+
+ int dump_task_stat_fd = bpf_program__fd(skel->progs.dump_task_stat);
+ ASSERT_GT(dump_task_stat_fd, 0);
+
+ int dump_all_vma_fd = bpf_program__fd(skel->progs.dump_all_vma);
+ ASSERT_GT(dump_all_vma_fd, 0);
+
+ struct dump_info crib_info, proc_info;
+ memset(&crib_info, 0, sizeof(struct dump_info));
+ memset(&proc_info, 0, sizeof(struct dump_info));
+
+ struct ring_buffer *rb = ring_buffer__new(bpf_map__fd(skel->maps.rb), handle_event,
+ &crib_info, NULL);
+ ASSERT_NE(rb, NULL);
+
+ clock_t crib_begin = clock();
+
+ ASSERT_EQ(bpf_prog_test_run_opts(dump_task_stat_fd, &opts), 0);
+ ASSERT_EQ(bpf_prog_test_run_opts(dump_all_vma_fd, &opts), 0);
+
+ ASSERT_GT(ring_buffer__poll(rb, 100), 0);
+
+ clock_t crib_end = clock();
+
+ printf("CRIB dump took %f seconds\n", (double)(crib_end - crib_begin) / CLOCKS_PER_SEC);
+
+ clock_t proc_begin = clock();
+
+ proc_info.vma = (struct vma *)malloc(sizeof(struct vma) * (crib_info.mm.map_count + 1));
+ ASSERT_EQ(dump_task_and_mm_struct_from_proc(&proc_info), 0);
+ ASSERT_EQ(dump_vma_from_proc(&proc_info), 0);
+
+ clock_t proc_end = clock();
+
+ printf("PROC dump took %f seconds\n", (double)(proc_end - proc_begin) / CLOCKS_PER_SEC);
+
+ ASSERT_EQ(check_dump_info_correctness(&crib_info, &proc_info), 0);
+
+ free(crib_info.vma);
+ free(proc_info.vma);
+ ring_buffer__free(rb);
+ test_dump_task_bpf__destroy(skel);
+}
+
+TEST_HARNESS_MAIN
new file mode 100644
@@ -0,0 +1,90 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Author:
+ * Juntong Deng <juntong.deng@outlook.com>
+ */
+
+#ifndef __TEST_DUMP_TASK_H
+#define __TEST_DUMP_TASK_H
+
+#define EVENT_TYPE_VMA 0
+#define EVENT_TYPE_TASK 1
+#define EVENT_TYPE_MM 2
+
+#define VM_READ 0x00000001
+#define VM_WRITE 0x00000002
+#define VM_EXEC 0x00000004
+#define VM_SHARED 0x00000008
+#define VM_MAYREAD 0x00000010
+#define VM_MAYWRITE 0x00000020
+#define VM_MAYEXEC 0x00000040
+#define VM_MAYSHARE 0x00000080
+#define VM_GROWSDOWN 0x00000100
+#define VM_UFFD_MISSING 0x00000200
+#define VM_MAYOVERLAY 0x00000200
+#define VM_PFNMAP 0x00000400
+#define VM_UFFD_WP 0x00001000
+#define VM_LOCKED 0x00002000
+#define VM_IO 0x00004000
+#define VM_SEQ_READ 0x00008000
+#define VM_RAND_READ 0x00010000
+#define VM_DONTCOPY 0x00020000
+#define VM_DONTEXPAND 0x00040000
+#define VM_LOCKONFAULT 0x00080000
+#define VM_ACCOUNT 0x00100000
+#define VM_NORESERVE 0x00200000
+#define VM_HUGETLB 0x00400000
+#define VM_SYNC 0x00800000
+#define VM_ARCH_1 0x01000000
+#define VM_WIPEONFORK 0x02000000
+#define VM_DONTDUMP 0x04000000
+#define VM_SOFTDIRTY 0x08000000
+#define VM_MIXEDMAP 0x10000000
+#define VM_HUGEPAGE 0x20000000
+#define VM_NOHUGEPAGE 0x40000000
+#define VM_MERGEABLE 0x80000000
+
+struct prog_args {
+ int pid;
+};
+
+struct event_hdr {
+ int type;
+ int subtype;
+};
+
+struct event_task {
+ struct event_hdr hdr;
+ int pid;
+ unsigned int flags;
+ int prio;
+ unsigned int policy;
+ int exit_code;
+ char comm[16];
+};
+
+struct event_vma {
+ struct event_hdr hdr;
+ unsigned long vm_start;
+ unsigned long vm_end;
+ unsigned long vm_flags;
+ unsigned long vm_pgoff;
+};
+
+struct event_mm {
+ struct event_hdr hdr;
+ unsigned long start_code;
+ unsigned long end_code;
+ unsigned long start_data;
+ unsigned long end_data;
+ unsigned long start_brk;
+ unsigned long brk;
+ unsigned long start_stack;
+ unsigned long arg_start;
+ unsigned long arg_end;
+ unsigned long env_start;
+ unsigned long env_end;
+ int map_count;
+};
+
+#endif /* __TEST_DUMP_TASK_H */
In this test, the basic information of the process is obtained through CRIB, including priority, comm, address space, all VMAs, etc. The process information obtained through CRIB will be compared with the process information obtained through procfs to verify the correctness of the information. In addition, the performance of CRIB and procfs will be compared in this test, usually CRIB takes only 20-30% of the time of procfs. The following is an example of test results: CRIB dump took 0.001349 seconds PROC dump took 0.005516 seconds Signed-off-by: Juntong Deng <juntong.deng@outlook.com> --- tools/testing/selftests/crib/.gitignore | 1 + tools/testing/selftests/crib/Makefile | 136 +++++++ tools/testing/selftests/crib/config | 7 + .../selftests/crib/test_dump_task.bpf.c | 125 +++++++ tools/testing/selftests/crib/test_dump_task.c | 337 ++++++++++++++++++ tools/testing/selftests/crib/test_dump_task.h | 90 +++++ 6 files changed, 696 insertions(+) create mode 100644 tools/testing/selftests/crib/.gitignore create mode 100644 tools/testing/selftests/crib/Makefile create mode 100644 tools/testing/selftests/crib/config create mode 100644 tools/testing/selftests/crib/test_dump_task.bpf.c create mode 100644 tools/testing/selftests/crib/test_dump_task.c create mode 100644 tools/testing/selftests/crib/test_dump_task.h