new file mode 100755
@@ -0,0 +1,92 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# Copyright (c) 2025, Oracle and/or its affiliates.
+#
+
+PHASES=(${@:-SETUP RUN CLEANUP})
+DEBIAN_RELEASE="${DEBIAN_RELEASE:-testing}"
+CONT_NAME="${CONT_NAME:-dwarves-debian-$DEBIAN_RELEASE}"
+ENV_VARS="${ENV_VARS:-}"
+DOCKER_RUN="${DOCKER_RUN:-docker run}"
+REPO_ROOT="${REPO_ROOT:-$PWD}"
+ADDITIONAL_DEPS=(pkgconf)
+EXTRA_CFLAGS=""
+EXTRA_LDFLAGS=""
+
+function info() {
+ echo -e "\033[33;1m$1\033[0m"
+}
+
+function error() {
+ echo -e "\033[31;1m$1\033[0m"
+}
+
+function docker_exec() {
+ docker exec $ENV_VARS $CONT_NAME "$@"
+}
+
+set -eu
+
+source "$(dirname $0)/travis_wait.bash"
+
+for phase in "${PHASES[@]}"; do
+ case $phase in
+ SETUP)
+ info "Setup phase"
+ info "Using Debian $DEBIAN_RELEASE"
+
+ docker --version
+
+ docker pull debian:$DEBIAN_RELEASE
+ info "Starting container $CONT_NAME"
+ $DOCKER_RUN -v $REPO_ROOT:/build:rw \
+ -w /build --privileged=true --name $CONT_NAME \
+ -dit --net=host debian:$DEBIAN_RELEASE /bin/bash
+ echo -e "::group::Build Env Setup"
+
+ docker_exec apt-get -y update
+ docker_exec apt-get -y install aptitude
+ docker_exec aptitude -y install make cmake libz-dev libelf-dev libdw-dev git
+ docker_exec aptitude -y install "${ADDITIONAL_DEPS[@]}"
+ echo -e "::endgroup::"
+ ;;
+ RUN|RUN_CLANG|RUN_CLANG16|RUN_GCC12)
+ CC="cc"
+ if [[ "$phase" =~ "RUN_CLANG(\d+)(_ASAN)?" ]]; then
+ ENV_VARS="-e CC=clang-${BASH_REMATCH[1]} -e CXX=clang++-${BASH_REMATCH[1]}"
+ CC="clang-${BASH_REMATCH[1]}"
+ elif [[ "$phase" = *"CLANG"* ]]; then
+ ENV_VARS="-e CC=clang -e CXX=clang++"
+ CC="clang"
+ elif [[ "$phase" =~ "RUN_GCC(\d+)(_ASAN)?" ]]; then
+ ENV_VARS="-e CC=gcc-${BASH_REMATCH[1]} -e CXX=g++-${BASH_REMATCH[1]}"
+ CC="gcc-${BASH_REMATCH[1]}"
+ fi
+ if [[ "$CC" != "cc" ]]; then
+ docker_exec aptitude -y install "$CC"
+ else
+ docker_exec aptitude -y install gcc
+ fi
+ git config --global --add safe.directory $REPO_ROOT
+ pushd $REPO_ROOT
+ git submodule update --init
+ popd
+ docker_exec mkdir build install
+ docker_exec ${CC} --version
+ info "build"
+ docker_exec cmake -DGIT_SUBMODULE=OFF .
+ docker_exec make -j$((4*$(nproc)))
+ info "install"
+ docker_exec make DESTDIR=../install install
+ ;;
+ CLEANUP)
+ info "Cleanup phase"
+ docker stop $CONT_NAME
+ docker rm -f $CONT_NAME
+ ;;
+ *)
+ echo >&2 "Unknown phase '$phase'"
+ exit 1
+ esac
+done
new file mode 100755
@@ -0,0 +1,35 @@
+#!/usr/bin/bash
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# Copyright (c) 2025, Oracle and/or its affiliates.
+#
+
+GITHUB_WORKSPACE=${GITHUB_WORKSPACE:-$(dirname $0)/../..}
+INPUTS_ARCH=${INPUTS_ARCH:-$(uname -m)}
+REPO=${REPO:-https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next.git}
+REPO_BRANCH=${REPO_BRANCH:-master}
+REPO_TARGET=${GITHUB_WORKSPACE}/.kernel
+
+export PATH=${GITHUB_WORKSPACE}/install/usr/local/bin:${PATH}
+export PAHOLE=${GITHUB_WORKSPACE}/install/usr/local/bin/pahole
+
+which pahole
+$PAHOLE --version
+
+if [[ ! -d $REPO_TARGET ]]; then
+ git clone $REPO $REPO_TARGET
+fi
+cd $REPO_TARGET
+git checkout $REPO_BRANCH
+
+cat tools/testing/selftests/bpf/config \
+ tools/testing/selftests/bpf/config.${INPUTS_ARCH} > .config
+# this file might or might not exist depending on kernel version
+if [[ -f tools/testing/selftests/bpf/config.vm ]]; then
+ cat tools/testing/selftests/bpf/config.vm >> .config
+fi
+make olddefconfig && make prepare
+grep PAHOLE .config
+grep _BTF .config
+make -j $((4*$(nproc))) all
+
new file mode 100755
@@ -0,0 +1,17 @@
+#!/usr/bin/bash
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# Copyright (c) 2025, Oracle and/or its affiliates.
+#
+
+GITHUB_WORKSPACE=${GITHUB_WORKSPACE:-$(dirname $0)/../..}
+cd $GITHUB_WORKSPACE
+git config --global --add safe.directory $GITHUB_WORKSPACE
+git submodule update --init
+mkdir -p build
+cd build
+pwd
+cmake -DGIT_SUBMODULE=OFF -DBUILD_SHARED_LIBS=OFF ..
+make -j$((4*$(nproc))) all
+make DESTDIR=../install install
+
new file mode 100755
@@ -0,0 +1,15 @@
+#!/usr/bin/bash
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# Copyright (c) 2025, Oracle and/or its affiliates.
+#
+
+GITHUB_WORKSPACE=${GITHUB_WORKSPACE:-$(pwd)}
+VMLINUX=${GITHUB_WORKSPACE}/.kernel/vmlinux
+SELFTESTS=${GITHUB_WORKSPACE}/tests
+cd $SELFTESTS
+export PATH=${GITHUB_WORKSPACE}/install/usr/local/bin:${PATH}
+which pahole
+pahole --version
+vmlinux=$VMLINUX ./tests
+
new file mode 100755
@@ -0,0 +1,61 @@
+# This was borrowed from https://github.com/travis-ci/travis-build/tree/master/lib/travis/build/bash
+# to get around https://github.com/travis-ci/travis-ci/issues/9979. It should probably be removed
+# as soon as Travis CI has started to provide an easy way to export the functions to bash scripts.
+
+travis_jigger() {
+ local cmd_pid="${1}"
+ shift
+ local timeout="${1}"
+ shift
+ local count=0
+
+ echo -e "\\n"
+
+ while [[ "${count}" -lt "${timeout}" ]]; do
+ count="$((count + 1))"
+ echo -ne "Still running (${count} of ${timeout}): ${*}\\r"
+ sleep 60
+ done
+
+ echo -e "\\n${ANSI_RED}Timeout (${timeout} minutes) reached. Terminating \"${*}\"${ANSI_RESET}\\n"
+ kill -9 "${cmd_pid}"
+}
+
+travis_wait() {
+ local timeout="${1}"
+
+ if [[ "${timeout}" =~ ^[0-9]+$ ]]; then
+ shift
+ else
+ timeout=20
+ fi
+
+ local cmd=("${@}")
+ local log_file="travis_wait_${$}.log"
+
+ "${cmd[@]}" &>"${log_file}" &
+ local cmd_pid="${!}"
+
+ travis_jigger "${!}" "${timeout}" "${cmd[@]}" &
+ local jigger_pid="${!}"
+ local result
+
+ {
+ set +e
+ wait "${cmd_pid}" 2>/dev/null
+ result="${?}"
+ ps -p"${jigger_pid}" &>/dev/null && kill "${jigger_pid}"
+ set -e
+ }
+
+ if [[ "${result}" -eq 0 ]]; then
+ echo -e "\\n${ANSI_GREEN}The command ${cmd[*]} exited with ${result}.${ANSI_RESET}"
+ else
+ echo -e "\\n${ANSI_RED}The command ${cmd[*]} exited with ${result}.${ANSI_RESET}"
+ fi
+
+ echo -e "\\n${ANSI_GREEN}Log:${ANSI_RESET}\\n"
+ cat "${log_file}"
+
+ return "${result}"
+}
new file mode 100644
@@ -0,0 +1,34 @@
+name: dwarves-build
+
+on:
+ pull_request:
+ push:
+ schedule:
+ - cron: '0 18 * * *'
+
+concurrency:
+ group: ci-build-${{ github.head_ref }}
+ cancel-in-progress: true
+
+jobs:
+
+ debian:
+ runs-on: ubuntu-latest
+ name: Debian Build (${{ matrix.name }})
+ strategy:
+ fail-fast: false
+ matrix:
+ include:
+ - name: default
+ target: RUN
+ - name: gcc-12
+ target: RUN_GCC12
+ - name: clang
+ target: RUN_CLANG
+ steps:
+ - uses: actions/checkout@v4
+ name: Checkout
+ - name: setup
+ shell: bash
+ run: ./.github/scripts/build-debian.sh SETUP ${{ matrix.target }}
+
new file mode 100644
@@ -0,0 +1,53 @@
+---
+# vi: ts=2 sw=2 et:
+
+name: "CodeQL"
+
+on:
+ push:
+ branches:
+ - master
+ pull_request:
+ branches:
+ - master
+ - next
+
+permissions:
+ contents: read
+
+jobs:
+ analyze:
+ name: Analyze
+ runs-on: ubuntu-latest
+ concurrency:
+ group: ${{ github.workflow }}-${{ matrix.language }}-${{ github.ref }}
+ cancel-in-progress: true
+ permissions:
+ actions: read
+ security-events: write
+
+ strategy:
+ fail-fast: false
+ matrix:
+ language: ['cpp', 'python']
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v4
+
+ - name: Initialize CodeQL
+ uses: github/codeql-action/init@v2
+ with:
+ languages: ${{ matrix.language }}
+ queries: +security-extended,security-and-quality
+
+ - name: Setup
+ uses: ./.github/actions/setup
+
+ - name: Build
+ run: |
+ source /tmp/ci_setup
+ make -C ./src
+
+ - name: Perform CodeQL Analysis
+ uses: github/codeql-action/analyze@v2
new file mode 100644
@@ -0,0 +1,33 @@
+name: dwarves-ci-coverity
+
+on:
+ push:
+ branches:
+ - master
+ - next
+ schedule:
+ - cron: '0 18 * * *'
+
+jobs:
+ coverity:
+ runs-on: ubuntu-latest
+ name: Coverity
+ env:
+ COVERITY_SCAN_TOKEN: ${{ secrets.COVERITY_SCAN_TOKEN }}
+ steps:
+ - uses: actions/checkout@v4
+ - uses: ./.github/actions/setup
+ - name: Run coverity
+ if: ${{ env.COVERITY_SCAN_TOKEN }}
+ run: |
+ source /tmp/ci_setup
+ export COVERITY_SCAN_NOTIFICATION_EMAIL="${AUTHOR_EMAIL}"
+ export COVERITY_SCAN_BRANCH_PATTERN=${GITHUB_REF##refs/*/}
+ export TRAVIS_BRANCH=${COVERITY_SCAN_BRANCH_PATTERN}
+ scripts/coverity.sh
+ env:
+ COVERITY_SCAN_PROJECT_NAME: dwarves
+ COVERITY_SCAN_BUILD_COMMAND_PREPEND: 'cmake .'
+ COVERITY_SCAN_BUILD_COMMAND: 'make'
+ - name: SCM log
+ run: cat /home/runner/work/dwarves/cov-int/scm_log.txt
new file mode 100644
@@ -0,0 +1,20 @@
+name: "lint"
+
+on:
+ pull_request:
+ push:
+ branches:
+ - master
+ - next
+
+jobs:
+ shellcheck:
+ name: ShellCheck
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v4
+ - name: Run ShellCheck
+ uses: ludeeus/action-shellcheck@master
+ env:
+ SHELLCHECK_OPTS: --severity=error
new file mode 100644
@@ -0,0 +1,31 @@
+name: ondemand
+
+on:
+ workflow_dispatch:
+ inputs:
+ arch:
+ default: 'x86_64'
+ required: true
+ llvm-version:
+ default: '18'
+ required: true
+ kernel:
+ default: 'LATEST'
+ required: true
+ pahole:
+ default: "master"
+ required: true
+ runs-on:
+ default: 'ubuntu-24.04'
+ required: true
+
+jobs:
+ vmtest:
+ name: ${{ inputs.kernel }} kernel llvm-${{ inputs.llvm-version }} pahole@${{ inputs.pahole }}
+ uses: ./.github/workflows/vmtest.yml
+ with:
+ runs_on: ${{ inputs.runs-on }}
+ kernel: ${{ inputs.kernel }}
+ arch: ${{ inputs.arch }}
+ llvm-version: ${{ inputs.llvm-version }}
+ pahole: ${{ inputs.pahole }}
new file mode 100644
@@ -0,0 +1,36 @@
+name: dwarves-ci
+
+on:
+ pull_request:
+ push:
+ schedule:
+ - cron: '0 18 * * *'
+
+concurrency:
+ group: ci-test-${{ github.head_ref }}
+ cancel-in-progress: true
+
+jobs:
+ vmtest:
+ strategy:
+ fail-fast: false
+ matrix:
+ include:
+ - kernel: 'LATEST'
+ runs_on: 'ubuntu-24.04'
+ arch: 'x86_64'
+ llvm-version: '18'
+ pahole: 'master'
+ - kernel: 'LATEST'
+ runs_on: 'ubuntu-24.04-arm'
+ arch: 'aarch64'
+ llvm-version: '18'
+ pahole: 'tmp.master'
+ name: Linux ${{ matrix.kernel }}
+ uses: ./.github/workflows/vmtest.yml
+ with:
+ runs_on: ${{ matrix.runs_on }}
+ kernel: ${{ matrix.kernel }}
+ arch: ${{ matrix.arch }}
+ llvm-version: ${{ matrix.llvm-version }}
+ pahole: ${{ matrix.pahole }}
new file mode 100644
@@ -0,0 +1,62 @@
+name: 'Build kernel run selftests via vmtest'
+
+on:
+ workflow_call:
+ inputs:
+ runs_on:
+ required: true
+ default: 'ubuntu-24.04'
+ type: string
+ arch:
+ description: 'what arch to test'
+ required: true
+ default: 'x86_64'
+ type: string
+ kernel:
+ description: 'kernel version or LATEST'
+ required: true
+ default: 'LATEST'
+ type: string
+ pahole:
+ description: 'pahole rev or branch'
+ required: false
+ default: 'master'
+ type: string
+ llvm-version:
+ description: 'llvm version'
+ required: false
+ default: '18'
+ type: string
+jobs:
+ vmtest:
+ name: pahole@${{ inputs.arch }}
+ runs-on: ${{ inputs.runs_on }}
+ steps:
+
+ - uses: actions/checkout@v4
+
+ - name: Setup environment
+ uses: libbpf/ci/setup-build-env@v3
+ with:
+ pahole: ${{ inputs.pahole }}
+ arch: ${{ inputs.arch }}
+ llvm-version: ${{ inputs.llvm-version }}
+
+ - name: Build,install current pahole
+ shell: bash
+ run: .github/scripts/build-pahole.sh
+
+ - name: Get kernel source
+ uses: libbpf/ci/get-linux-source@v3
+ with:
+ repo: 'https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next.git'
+ dest: '${{ github.workspace }}/.kernel'
+
+ - name: Configure, build kernel with current pahole
+ shell: bash
+ run: .github/scripts/build-kernel.sh
+
+ - name: Run selftests
+ shell: bash
+ run: .github/scripts/run-selftests.sh
+
@@ -21,3 +21,21 @@ cmake Options:
You may need to update the libbpf git submodule:
git submodule update --init --recursive
+
+Testing:
+
+Tests are available in the tests subdirectory and should be run prior to
+submitting patches. Patches that add functionality should add to tests
+here also. Tests can be run by
+
+- running the scripts directly using a pre-existing vmlinux binary; i.e.
+ cd tests ; vmlinux=/path/2/vmlinux ./tests
+ (the vmlinux binary must contain DWARF to be converted to BTF)
+
+- running the tests via local scripts in .github/scripts; i.e.
+ bash .github/scripts/build-pahole.sh; \
+ bash .github/scripts/build-kernel.sh; \
+ bash .github/scripts/run-selftests.sh
+- via GitHub actions: push a branch to a GitHub repo; actions will be
+ triggered for build and test matching the above steps. See the "Actions"
+ tab in the github repo for info on job pass/fail and logs.
Borrowing heavily from libbpf github actions, add workflows to - build dwarves for gcc, LLVM - build dwarves for x86_64/aarch64 and use it to build a Linux kernel including BTF generation; then run dwarves selftests using generated vmlinux These workflows trigger on all pushes. This will allow both developers working on dwarves to push a branch to their github repo and test, and also for maintainer pushes from git.kernel.org pahole repo to trigger tests. The build/test workflows can also be run as bash scripts locally, as is described in the toplevel README. Similar to libbpf, additional workflows for coverity etc are triggered for pushes to master/next. Signed-off-by: Alan Maguire <alan.maguire@oracle.com> --- .github/scripts/build-debian.sh | 92 ++++++++++++++++++++++++++++++++ .github/scripts/build-kernel.sh | 35 ++++++++++++ .github/scripts/build-pahole.sh | 17 ++++++ .github/scripts/run-selftests.sh | 15 ++++++ .github/scripts/travis_wait.bash | 61 +++++++++++++++++++++ .github/workflows/build.yml | 34 ++++++++++++ .github/workflows/codeql.yml | 53 ++++++++++++++++++ .github/workflows/coverity.yml | 33 ++++++++++++ .github/workflows/lint.yml | 20 +++++++ .github/workflows/ondemand.yml | 31 +++++++++++ .github/workflows/test.yml | 36 +++++++++++++ .github/workflows/vmtest.yml | 62 +++++++++++++++++++++ README | 18 +++++++ 13 files changed, 507 insertions(+) create mode 100755 .github/scripts/build-debian.sh create mode 100755 .github/scripts/build-kernel.sh create mode 100755 .github/scripts/build-pahole.sh create mode 100755 .github/scripts/run-selftests.sh create mode 100755 .github/scripts/travis_wait.bash create mode 100644 .github/workflows/build.yml create mode 100644 .github/workflows/codeql.yml create mode 100644 .github/workflows/coverity.yml create mode 100644 .github/workflows/lint.yml create mode 100644 .github/workflows/ondemand.yml create mode 100644 .github/workflows/test.yml create mode 100644 .github/workflows/vmtest.yml