Hi Piyush.

> 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.


The board should be contributed to dejagnu rather than GCC.
We already have a bpf-sim.exp board there.

Project page: https://www.gnu.org/s/dejagnu

Send patches to list: [email protected] (please CC me and David).

Git repo: https://git.savannah.gnu.org/git/dejagnu.git
          or
          git://git.sv.gnu.org/dejagnu.git


> Signed-off-by: Piyush Raj <[email protected]>
> ---
>  gcc/Makefile.in                               |   1 +
>  gcc/testsuite/boards/bpf.exp                  | 123 ++++++++++++++++++
>  .../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, 211 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 abf98aabac8..660ec3e0e78 100644
> --- a/gcc/Makefile.in
> +++ b/gcc/Makefile.in
> @@ -4653,6 +4653,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..73722c778a5
> --- /dev/null
> +++ b/gcc/testsuite/boards/bpf.exp
> @@ -0,0 +1,123 @@
> +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"
> +
> +
> +if {![info exists KERNEL_VERSION]} {
> +    set KERNEL_VERSION 6.15
> +    verbose -log "Using default kernel version: $KERNEL_VERSION" 1
> +}
> +
> +if {![info exists LOG_LEVEL]} {
> +    set LOG_LEVEL ERROR
> +    verbose -log "Using default log level: $LOG_LEVEL" 1
> +}
> +
> +proc bpf_compile {source destfile type options} {
> +
> +    if { $type == "executable" } {
> +        return [bpf_target_compile $source $destfile $type $options]
> +    }
> +    return [default_target_compile $source $destfile $type $options]
> +}
> +
> +proc bpf_target_compile {source destfile type options} {
> +
> +    global srcdir
> +    global KERNEL_VERSION
> +    global LOG_LEVEL
> +    set python3 [find_python3]
> +    if {$python3 == ""} {
> +        error "Cannot find python3 in $PATH"
> +    }
> +    set script_path "$srcdir/../../contrib/bpf-vmtest-tool/main.py"
> +    set opts ""
> +    foreach i $options {
> +        if {[regexp "^compiler=" $i]} {
> +            regsub "^compiler=" $i "" tmp
> +            if { $tmp eq "" } {
> +                return "bpf_target_compile: No compiler to compile with"
> +            }
> +            set compiler [ lindex [split $tmp " "] 0 ]
> +            set compiler_flags [ lindex [split $tmp " "] 1 ]
> +            append opts " $compiler_flags"
> +        }
> +
> +        if {[regexp "^additional_flags=" $i]} {
> +            regsub "^additional_flags=" $i "" tmp
> +            set tmp [string trim $tmp]
> +            append opts " $tmp"
> +        }
> +    }
> +
> +    set opts [string trim $opts]
> +    
> +    setenv BPF_CFLAGS $opts
> +    setenv BPF_CC $compiler
> +    set args [list $script_path --log-level $LOG_LEVEL bpf compile $source 
> -k $KERNEL_VERSION -o $destfile ]
> +    set status [remote_exec host $python3 $args]
> +    set exit_code [lindex $status 0]
> +    set output [lindex $status 1]
> +    unsetenv BPF_CFLAGS
> +    unsetenv BPF_CC
> +
> +    if { $exit_code < 0 } {
> +        verbose -log "Couldn't compile $source: $output"
> +        return $output
> +    }
> +
> +    verbose -log "Executed $source, exit_code $exit_code"
> +    if {$output ne ""} {
> +        verbose -log -- $output 2
> +    }
> +
> +    return $output
> +}
> +
> +proc bpf_load {dest prog args} {
> +    global srcdir
> +    global KERNEL_VERSION
> +    global LOG_LEVEL
> +    # 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 --log-level $LOG_LEVEL vmtest -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..ad5fa58fdc3
> --- /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 "-Wall -Werror"
> +}
> +
> +# 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..96f454bba84
> --- /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 successfully loaded" } */

Reply via email to