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