This patch adds new DejaGnu target board for BPF for runtime testing of
BPF programs using the `bpf-vmtest-tool` script in the contrib directory.
The kernel version used for the tests can be specified via KERNEL_VERSION,
for example:
make check-gcc RUNTESTFLAGS="--target_board=bpf bpf-torture.exp
KERNEL_VERSION=6.14"
If not specified, the default kernel version used is 6.15.
It also adds a new torture subdirectory for running torture tests on BPF
programs.
Passed tests covered in bpf.exp and bpf-torture.exp
gcc/ChangeLog:
* Makefile.in: Append boards directory to target boards search path.
gcc/testsuite/ChangeLog:
* boards/bpf.exp: New board for bpf-unknown-none target
* gcc.target/bpf/torture/bpf-testool-demo.c: New test.
* gcc.target/bpf/torture/bpf-torture.exp: New test.
Signed-off-by: Piyush Raj <[email protected]>
---
gcc/Makefile.in | 1 +
gcc/testsuite/boards/bpf.exp | 69 +++++++++++++++++++
.../gcc.target/bpf/torture/bpf-torture.exp | 46 +++++++++++++
.../bpf/torture/invalid-memory-access.c | 18 +++++
.../gcc.target/bpf/torture/trace_openat.c | 23 +++++++
5 files changed, 157 insertions(+)
create mode 100644 gcc/testsuite/boards/bpf.exp
create mode 100644 gcc/testsuite/gcc.target/bpf/torture/bpf-torture.exp
create mode 100644 gcc/testsuite/gcc.target/bpf/torture/invalid-memory-access.c
create mode 100644 gcc/testsuite/gcc.target/bpf/torture/trace_openat.c
diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index cf1408d56e2..10b1b3baee6 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -4615,6 +4615,7 @@ site.exp: ./config.status Makefile
fi
echo "set tmpdir $(objdir)/testsuite" >> ./site.tmp
@echo "set srcdir \"\$${srcdir}/testsuite\"" >> ./site.tmp
+ @echo "lappend boards_dir \"\$${srcdir}/boards\"" >> ./site.tmp
@if [ "X$(ALT_CC_UNDER_TEST)" != "X" ] ; then \
echo "set ALT_CC_UNDER_TEST \"$(ALT_CC_UNDER_TEST)\"" >> ./site.tmp; \
else true; \
diff --git a/gcc/testsuite/boards/bpf.exp b/gcc/testsuite/boards/bpf.exp
new file mode 100644
index 00000000000..2c85daca58e
--- /dev/null
+++ b/gcc/testsuite/boards/bpf.exp
@@ -0,0 +1,69 @@
+load_lib "standard.exp"
+set_board_info target_install {bpf-unknown-none}
+set_board_info generic_name bpf
+set_board_info mathlib ""
+unset_board_info isremote
+set_board_info isremote "0"
+
+set BPF_GCC_FLAGS "-D__TARGET_ARCH_x86_64 -gbtf -std=gnu17
-I/usr/local/include -I/usr/include"
+
+if {![info exists KERNEL_VERSION]} {
+ set KERNEL_VERSION 6.15
+ verbose -log "Using default kernel version: $KERNEL_VERSION" 1
+}
+
+proc bpf_compile {source destfile type options} {
+ global BPF_GCC_FLAGS
+
+ if { $type == "executable" } {
+ # We don't actually link now; we just need the object file
+ set type "object"
+ lappend options "additional_flags=$BPF_GCC_FLAGS"
+ return [default_target_compile $source $destfile $type $options]
+ }
+ return [default_target_compile $source $destfile $type $options]
+}
+
+proc bpf_load {dest prog args} {
+ global srcdir
+ global KERNEL_VERSION
+ # Construct command
+ set python3 [find_python3]
+ if {$python3 == ""} {
+ error "Cannot find python3 in $PATH"
+ }
+ set script_path "$srcdir/../../contrib/bpf-vmtest-tool/main.py"
+ set bpf_object $prog
+
+ set args [list $script_path -k $KERNEL_VERSION --bpf-obj $prog ]
+ set status [remote_exec $dest $python3 $args]
+ set exit_code [lindex $status 0]
+ set output [lindex $status 1]
+
+ if { $exit_code < 0 } {
+ verbose -log "Couldn't execute $prog: $output"
+ return "unresolved"
+ }
+
+ verbose -log "Executed $prog, exit_code $exit_code"
+ if {$output ne ""} {
+ verbose -log -- $output 2
+ }
+
+ if { $exit_code == 0 } {
+ return [list "pass" $output]
+ } else {
+ return [list "fail" $output]
+ }
+}
+
+
+proc find_python3 {} {
+ foreach candidate {python3 python} {
+ set path [which $candidate]
+ if {$path != ""} {
+ return $path
+ }
+ }
+ return ""
+}
\ No newline at end of file
diff --git a/gcc/testsuite/gcc.target/bpf/torture/bpf-torture.exp
b/gcc/testsuite/gcc.target/bpf/torture/bpf-torture.exp
new file mode 100644
index 00000000000..08d909c400b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/bpf/torture/bpf-torture.exp
@@ -0,0 +1,46 @@
+# Copyright (C) 2019-2025 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3. If not see
+# <http://www.gnu.org/licenses/>.
+
+# GCC testsuite that uses the `dg.exp' driver.
+
+# Exit immediately if this isn't an eBPF target.
+if ![istarget bpf-*-*] then {
+ return
+}
+
+# Default values for torture testing
+set TORTURE_OPTIONS [ list {-O1 -g} {-O2 -g} {-O3 -g} ]
+set LTO_TORTURE_OPTIONS ""
+
+# Load support procs.
+load_lib gcc-dg.exp
+
+# If a testcase doesn't have special options, use these.
+global DEFAULT_CFLAGS
+if ![info exists DEFAULT_CFLAGS] then {
+ set DEFAULT_CFLAGS ""
+}
+
+# Initialize `dg'.
+dg-init
+
+
+# Main loop.
+gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.\[cS\]]] \
+ "" $DEFAULT_CFLAGS
+
+# All done.
+dg-finish
diff --git a/gcc/testsuite/gcc.target/bpf/torture/invalid-memory-access.c
b/gcc/testsuite/gcc.target/bpf/torture/invalid-memory-access.c
new file mode 100644
index 00000000000..d0bfe8a0009
--- /dev/null
+++ b/gcc/testsuite/gcc.target/bpf/torture/invalid-memory-access.c
@@ -0,0 +1,18 @@
+// { dg-do run { xfail *-*-* } }
+
+#include "vmlinux.h"
+#include <bpf/bpf_helpers.h>
+#include <bpf/bpf_tracing.h>
+
+char LICENSE[] SEC("license") = "GPL";
+
+SEC("tracepoint/syscalls/sys_enter_openat")
+int bpf_prog(struct trace_event_raw_sys_enter *ctx) {
+ int arr[4] = {1, 2, 3, 4};
+
+ // Invalid memory access: out-of-bounds
+ int val = arr[5]; // This causes the verifier to fail
+
+ return val;
+}
+
diff --git a/gcc/testsuite/gcc.target/bpf/torture/trace_openat.c
b/gcc/testsuite/gcc.target/bpf/torture/trace_openat.c
new file mode 100644
index 00000000000..78a6d7b7145
--- /dev/null
+++ b/gcc/testsuite/gcc.target/bpf/torture/trace_openat.c
@@ -0,0 +1,23 @@
+// { dg-do run }
+
+#include "vmlinux.h"
+#include <bpf/bpf_helpers.h>
+#include <bpf/bpf_tracing.h>
+#include <bpf/bpf_core_read.h>
+
+char LICENSE[] SEC("license") = "GPL";
+
+int example_pid = 0;
+
+SEC("tracepoint/syscalls/sys_enter_openat")
+int handle_openat(struct trace_event_raw_sys_enter *ctx)
+{
+ int pid = bpf_get_current_pid_tgid() >> 32;
+ char filename[256]; // filename buffer
+ bpf_probe_read_user(&filename, sizeof(filename), (void *)ctx->args[1]);
+ bpf_printk("sys_enter_openat() called from PID %d for file: %s\n", pid,
filename);
+
+ return 0;
+}
+
+/* { dg-output "BPF programs succesfully loaded" } */
--
2.51.0