On 10/12/25 21:26, Piyush Raj wrote:
> 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

I noticed that depending on the local vmlinux.h, we may get some extraneous
"excess error" FAILs originating from warnings like with -Wattributes
in vmlinux.h.  I think we could also potentially end up with things like
#pragmas that are specific to clang in vmlinux.h or elsewhere, depending
on where those files are coming from.

I'm not sure what is the best way to deal with that for this testsuite.
Disabling -Wattributes doesn't seem ideal, but neither does annotating
each individual test #including vmlinux.h to suppress the warning...

Opinions/thoughts anyone?

(I don't think this should be a blocker, but it would be nice to deal
 with it somehow.)

> 
> 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" } */

Reply via email to