Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FEATURE] Add CI to test bpftrace #274

Draft
wants to merge 12 commits into
base: master
Choose a base branch
from
29 changes: 29 additions & 0 deletions .github/script/bpftrace/trace_open_syscalls.bt
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
BEGIN
{
printf("Tracing open syscalls... Hit Ctrl-C to end.\n");
printf("%-6s %-16s %4s %3s %s\n", "PID", "COMM", "FD", "ERR", "PATH");
}

tracepoint:syscalls:sys_enter_open,
tracepoint:syscalls:sys_enter_openat
{
@filename[tid] = args.filename;
}

tracepoint:syscalls:sys_exit_open,
tracepoint:syscalls:sys_exit_openat
/@filename[tid]/
{
$ret = args.ret;
$fd = $ret >= 0 ? $ret : -1;
$errno = $ret >= 0 ? 0 : - $ret;

printf("%-6d %-16s %4d %3d %s\n", pid, comm, $fd, $errno,
str(@filename[tid]));
delete(@filename[tid]);
}

END
{
clear(@filename);
}
23 changes: 16 additions & 7 deletions .github/script/run_example.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import re
import sys
import asyncio
import typing
Expand Down Expand Up @@ -25,14 +26,14 @@ async def handle_stdout(
for item in pending:
item.cancel()
if t2 in done:
s = t2.result().decode()
print(f"{title}:", s, end="")
stdout_raw = t2.result().decode()
print(f"{title}:", stdout_raw, end="")
for callback in callback_all:
evt, sig = callback
if sig in s:
if sig in stdout_raw or re.match(sig, stdout_raw.strip()):
evt.set()
print("Callback triggered")
if check_error and "[error]" in s:
if check_error and "[error]" in stdout_raw:
assert False, "Error occurred in agent!"
if t1 in done:
break
Expand All @@ -41,6 +42,17 @@ async def handle_stdout(


async def main():
if len(sys.argv) < 6:
print(
"Usage: python script.py " \
"<executable :str>" \
"<victim :str> "\
"<expected_str :str (regexp also works)> "\
"<bpftime_cli :str> "\
"<is_a_syscall :Union[0, 1]>"
)
return

(
executable,
victim,
Expand Down Expand Up @@ -73,7 +85,6 @@ async def main():
)

await asyncio.wait_for(server_started_signal.wait(), SERVER_TIMEOUT)
await asyncio.sleep(10)
print("Server started!")

# Start the agent
Expand Down Expand Up @@ -101,8 +112,6 @@ async def main():
server.send_signal(signal.SIGINT)
agent.send_signal(signal.SIGINT)
await asyncio.gather(server_out, agent_out)
# for task in asyncio.all_tasks():
# task.cancel()
await asyncio.gather(server.communicate(), agent.communicate())
except Exception as ex:
print(ex)
Expand Down
210 changes: 210 additions & 0 deletions .github/workflows/test-bpftrace.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,210 @@
name: Install and test bpftrace

on:
workflow_dispatch:
push:
branches: ["*"]
pull_request:
branches: ['master']

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}-${{ github.event_name }}
cancel-in-progress: true

jobs:
build-runtime:
strategy:
matrix:
enable_jit:
- true
- false
container:
- image: ubuntu-2204
name: ubuntu
- image: fedora-39
name: fedora
runs-on: ubuntu-22.04
container:
image: "manjusakalza/bpftime-base-image:${{matrix.container.image}}"
options: --privileged
steps:
- uses: actions/checkout@v2
name: "Clone the latest version"
with:
submodules: 'recursive'
path: ./bpftime
# - uses: actions/checkout@v2
# name: "Pull bpftrace"
# with:
# repository: "bpftrace/bpftrace"
# submodules: 'recursive'
# path: './bpftrace_git'
# - name: Install bpftrace dependencies in fedora
# if: ${{ matrix.container.name=='fedora' }}
# run: |
# dnf -y update && dnf install -y \
# make \
# gcc-c++-aarch64-linux-gnu \
# gcc-arm-linux-gnu \
# clang \
# boost-devel \
# zlib-devel \
# libubsan \
# g++ \
# llvm \
# elfutils-libelf-devel \
# qemu-user \
# cmake \
# gcc-c++ \
# gcc-aarch64-linux-gnu \
# llvm15-devel \
# systemtap-sdt-devel \
# gcc \
# asciidoctor \
# bison \
# binutils-devel \
# bcc-devel \
# cereal-devel \
# clang-devel \
# elfutils-devel \
# elfutils-libs \
# flex \
# libpcap-devel \
# libbpf-devel \
# llvm-devel
# - name: Install bpftrace dependencies in ubuntu
# if: ${{ matrix.container.name=='ubuntu' }}
# run: |
# apt-get update && apt-get install -y \
# --no-install-recommends \
# libelf1 \
# libelf-dev \
# zlib1g-dev \
# make \
# cmake \
# git \
# libboost1.74-all-dev \
# binutils-dev \
# libyaml-cpp-dev \
# gcc \
# g++ \
# ca-certificates \
# clang \
# llvm \
# systemtap-sdt-dev \
# libclang-dev \
# liblldb-dev \
# llvm-dev \
# libpcap-dev \
# libiberty-dev \
# libcereal-dev \
# libbpfcc-dev \
# flex \
# build-essential \
# bison \
# asciidoctor \
# libbpf-dev
# - name: Build and install bpftrace
# run: |
# cd ./bpftrace_git
# cmake -B ./bpftrace -DBUILD_TESTING=OFF
# make -C ./bpftrace -j$(nproc)
# cd -
- name: Build and install runtime (with llvm-jit)
if: ${{matrix.enable_jit}}
run: |
cd ./bpftime
make release-with-llvm-jit -j
- name: Build and install runtime (without llvm-jit)
if: ${{!matrix.enable_jit}}
run: |
cd ./bpftime
make release -j
- name: Upload build results (without jit)
uses: actions/upload-artifact@v3
if: ${{!matrix.enable_jit}}
with:
name: runtime-package-no-jit-${{matrix.container.name}}
path: ~/.bpftime
- name: Upload build results (with jit)
uses: actions/upload-artifact@v3
if: ${{matrix.enable_jit}}
with:
name: runtime-package-jit-${{matrix.container.name}}
path: ~/.bpftime
- name: Upload built bpftrace
uses: actions/upload-artifact@v3
with:
name: bpftrace
path: /bpftrace
install-bpftrace-and-test:
runs-on: "ubuntu-latest"
needs: [build-runtime]
strategy:
matrix:
container:
- image: ubuntu-2204
name: ubuntu
- image: fedora-39
name: fedora
enable_jit:
- true
- false
bpftrace_tests:
- command: /__w/bpftime/bpftime/.github/script/bpftrace/trace_open_syscalls.bt
expected_output: ^\d+\s+\w+(\s+#\d+)?\s+-?\d+\s+-?\d+\s+\S+$
victim: 'bash'
is_a_syscall_tracing: true
container:
image: "manjusakalza/bpftime-base-image:${{matrix.container.image}}"
options: --privileged -v /sys/kernel/debug/:/sys/kernel/debug:rw -v /sys/kernel/tracing:/sys/kernel/tracing:rw -v /usr/src:/usr/src:ro -v /lib/modules/:/lib/modules:ro
steps:
- name: Download prebuilt runtime (with jit)
if: ${{matrix.enable_jit}}
uses: actions/download-artifact@v3
with:
name: runtime-package-jit-${{matrix.container.name}}
path: /app/.bpftime
- name: Download prebuilt runtime (without jit)
if: ${{!matrix.enable_jit}}
uses: actions/download-artifact@v3
with:
name: runtime-package-no-jit-${{matrix.container.name}}
path: /app/.bpftime
# - name: Download prebuilt bpftrace
# uses: actions/download-artifact@v3
# with:
# name: bpftrace
# path: /bpftrace
- name: Set permissions
run: |
chmod +x /app/.bpftime/*
- name: Show downloaded artifacts
run: |
ls /app/.bpftime
- uses: actions/checkout@v2
with:
submodules: 'recursive'
- name: Build bpftrace package in fedora
if: ${{ matrix.container.name=='fedora' }}
shell: bash
run: |
dnf update -y
dnf install -y bpftrace
- name: Build bpftrace package in ubuntu
if: ${{ matrix.container.name=='ubuntu' }}
shell: bash
run: apt update && apt install -y bpftrace
- name: Test bpftrace
shell: bash
run: bpftrace -e 'BEGIN { printf("hello world\n"); }'
- name: Test CLI - attach by running (is_a_syscall_tracing)
if: matrix.bpftrace_tests.is_a_syscall_tracing
shell: bash
run: |
python3 $(pwd)/.github/script/run_example.py "bpftrace ${{ matrix.bpftrace_tests.command }}" "${{matrix.bpftrace_tests.victim}}" "${{matrix.bpftrace_tests.expected_output}}" "/app/.bpftime/bpftime -i /app/.bpftime" 1
- name: Test CLI - attach by running (uprobe)
if: '!matrix.bpftrace_tests.is_a_syscall_tracing'
shell: bash
run: |
python3 $(pwd)/.github/script/run_example.py "bpftrace ${{ matrix.bpftrace_tests.command }}" "${{matrix.bpftrace_tests.victim}}" "${{matrix.bpftrace_tests.expected_output}}" "/app/.bpftime/bpftime -i /app/.bpftime" 0
Loading