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 <piyushraj92...@gmail.com>
---
 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 d2744db843d..c02375dc2be 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -4579,6 +4579,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

Reply via email to