diff --git a/.github/scripts/install-bpftrace.sh b/.github/scripts/install-bpftrace.sh index a225f25..e81474c 100755 --- a/.github/scripts/install-bpftrace.sh +++ b/.github/scripts/install-bpftrace.sh @@ -3,27 +3,19 @@ set -x -euo pipefail BPFTRACE_VERSION=${BPFTRACE_VERSION:-0.22.1} -BUILD_BPFTRACE=${BUILD_BPFTRACE:-} - BIN_DIR=/usr/local/bin sudo mkdir -p $BIN_DIR -if [[ -n "$BUILD_BPFTRACE" ]]; then - # see https://github.com/bpftrace/bpftrace/blob/master/docker/Dockerfile.ubuntu - sudo apt-get install -y \ - asciidoctor binutils-dev bison build-essential clang cmake flex git libbpf-dev \ - libbpfcc-dev libcereal-dev libelf-dev libiberty-dev libpcap-dev llvm-dev liblldb-dev \ - libclang-dev systemtap-sdt-dev zlib1g-dev - git clone --depth 1 -b v${BPFTRACE_VERSION} https://github.com/bpftrace/bpftrace - cd bpftrace/src - cmake -B build -DBUILD_TESTING=OFF -DCMAKE_BUILD_TYPE=Release -DLLVM_DIR=$(llvm-config --prefix)/lib/cmake/llvm - make -C build -j$(nproc) - cd - - sudo mv bpftrace/src/build/bpftrace $BIN_DIR/bpftrace -else # download AppImage - sudo curl -L -o $BIN_DIR/bpftrace https://github.com/bpftrace/bpftrace/releases/download/v${BPFTRACE_VERSION}/bpftrace +if [ $(uname -m) == "x86_64" ]; then + URL=https://github.com/bpftrace/bpftrace/releases/download/v${BPFTRACE_VERSION}/bpftrace +elif [ $(uname -m) == "aarch64" ]; then + URL=https://github.com/theihor/bpftrace/releases/download/v${BPFTRACE_VERSION}-arm64/bpftrace-arm64 +else + echo "Unexpected arch: $(uname -m)" + exit 1 fi +sudo curl -L -o $BIN_DIR/bpftrace $URL sudo chmod +x $BIN_DIR/bpftrace # mount tracefs to avoid warnings from bpftrace diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 0aed5ee..fd5f59e 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -12,7 +12,7 @@ jobs: strategy: fail-fast: false matrix: - runs-on: [ 'ubuntu-latest' ] + runs-on: [ 'ubuntu-latest', 'ubuntu-24.04-arm' ] shared: [ 0, 1 ] compiler: - { name: 'gcc', version: 11 } @@ -25,10 +25,9 @@ jobs: runs-on: ${{ matrix.runs-on }} - name: ${{ endsWith(matrix.runs-on, '-arm') && 'arm64' || 'x86_64' }} SHARED=${{ matrix.shared }} ${{ matrix.compiler.name }}-${{ matrix.compiler.version }} + name: ${{ endsWith(matrix.runs-on, '-arm') && 'arm64' || 'x86_64' }} ${{ matrix.shared == 1 && 'shared' || 'static' }} ${{ matrix.compiler.name }}-${{ matrix.compiler.version }} env: - ARCH: ${{ endsWith(matrix.runs-on, '-arm') && 'arm64' || 'x86_64' }} COMPILER: ${{ matrix.compiler.name }} COMPILER_VERSION: ${{ matrix.compiler.version }} SHARED: ${{ matrix.shared }} @@ -44,3 +43,11 @@ jobs: - name: Test SHARED=${{ matrix.shared }} run: make -C tests test + + - uses: actions/upload-artifact@v4 + if: always() + with: + name: tests-output-${{ endsWith(matrix.runs-on, '-arm') && 'arm64' || 'x86_64' }}-${{ matrix.shared == 1 && 'shared' || 'static' }}-${{ matrix.compiler.name }}-${{ matrix.compiler.version }} + if-no-files-found: warn + path: tests/.output + include-hidden-files: true diff --git a/tests/arg_consts.c b/tests/arg_consts.c index 99b9f85..bd50e71 100644 --- a/tests/arg_consts.c +++ b/tests/arg_consts.c @@ -21,6 +21,17 @@ int main(int argc, char **argv) return 0; } +#ifdef __aarch64__ +const char *USDT_SPECS = +"test:chars base=BASE1 sema=0 argn=2 args=1@1 -1@-1.\n" +"test:shorts base=BASE1 sema=0 argn=2 args=2@2 -2@-2.\n" +"test:ints base=BASE1 sema=0 argn=2 args=4@3 -4@-3.\n" +"test:longs base=BASE1 sema=0 argn=2 args=*@4 -*@-4.\n" +"test:longlongs base=BASE1 sema=0 argn=2 args=8@5 -8@-5.\n" +"test:size_ts base=BASE1 sema=0 argn=2 args=*@6 -*@-6.\n" +"test:ptrs base=BASE1 sema=0 argn=2 args=*@0 *@7.\n" +; +#else const char *USDT_SPECS = "test:chars base=BASE1 sema=0 argn=2 args=1@$1 -1@$-1.\n" "test:shorts base=BASE1 sema=0 argn=2 args=2@$2 -2@$-2.\n" @@ -30,7 +41,7 @@ const char *USDT_SPECS = "test:size_ts base=BASE1 sema=0 argn=2 args=*@$6 -*@$-6.\n" "test:ptrs base=BASE1 sema=0 argn=2 args=*@$0 *@$7.\n" ; - +#endif const char *BPFTRACE_SCRIPT = "test:chars { arg0=%hhu arg1=%hhd -> arg0, arg1 }\n" "test:shorts { arg0=%hu arg1=%hd -> arg0, arg1 }\n" diff --git a/tests/arg_nums.c b/tests/arg_nums.c index b1e87a4..20b0840 100644 --- a/tests/arg_nums.c +++ b/tests/arg_nums.c @@ -25,6 +25,23 @@ int main(int argc, char **argv) return 0; } +#ifdef __aarch64__ +const char *USDT_SPECS = +"test:name0 base=BASE1 sema=0 argn=0 args=.\n" +"test:name1 base=BASE1 sema=0 argn=1 args=-4@1.\n" +"test:name2 base=BASE1 sema=0 argn=2 args=-4@1 -4@2.\n" +"test:name3 base=BASE1 sema=0 argn=3 args=-4@1 -4@2 -4@3.\n" +"test:name4 base=BASE1 sema=0 argn=4 args=-4@1 -4@2 -4@3 -4@4.\n" +"test:name5 base=BASE1 sema=0 argn=5 args=-4@1 -4@2 -4@3 -4@4 -4@5.\n" +"test:name6 base=BASE1 sema=0 argn=6 args=-4@1 -4@2 -4@3 -4@4 -4@5 -4@6.\n" +"test:name7 base=BASE1 sema=0 argn=7 args=-4@1 -4@2 -4@3 -4@4 -4@5 -4@6 -4@7.\n" +"test:name8 base=BASE1 sema=0 argn=8 args=-4@1 -4@2 -4@3 -4@4 -4@5 -4@6 -4@7 -4@8.\n" +"test:name9 base=BASE1 sema=0 argn=9 args=-4@1 -4@2 -4@3 -4@4 -4@5 -4@6 -4@7 -4@8 -4@9.\n" +"test:name10 base=BASE1 sema=0 argn=10 args=-4@1 -4@2 -4@3 -4@4 -4@5 -4@6 -4@7 -4@8 -4@9 -4@10.\n" +"test:name11 base=BASE1 sema=0 argn=11 args=-4@1 -4@2 -4@3 -4@4 -4@5 -4@6 -4@7 -4@8 -4@9 -4@10 -4@11.\n" +"test:name12 base=BASE1 sema=0 argn=12 args=-4@1 -4@2 -4@3 -4@4 -4@5 -4@6 -4@7 -4@8 -4@9 -4@10 -4@11 -4@12.\n" +; +#else const char *USDT_SPECS = "test:name0 base=BASE1 sema=0 argn=0 args=.\n" "test:name1 base=BASE1 sema=0 argn=1 args=-4@$1.\n" @@ -40,6 +57,7 @@ const char *USDT_SPECS = "test:name11 base=BASE1 sema=0 argn=11 args=-4@$1 -4@$2 -4@$3 -4@$4 -4@$5 -4@$6 -4@$7 -4@$8 -4@$9 -4@$10 -4@$11.\n" "test:name12 base=BASE1 sema=0 argn=12 args=-4@$1 -4@$2 -4@$3 -4@$4 -4@$5 -4@$6 -4@$7 -4@$8 -4@$9 -4@$10 -4@$11 -4@$12.\n" ; +#endif const char *BPFTRACE_SCRIPT = "test:name0 { triggered }\n" diff --git a/tests/arg_types.c b/tests/arg_types.c index dfc5de7..375da20 100644 --- a/tests/arg_types.c +++ b/tests/arg_types.c @@ -122,7 +122,7 @@ const char *BPFTRACE_SCRIPT = str(arg0), \ *(int32 *)(arg1 + 0), *(int32 *)(arg1 + 4), *(int32 *)(arg1 + 8) }\n" "test:struct_by_val_reg { arg0=%hhu arg1=%u -> arg0, arg1 }\n" -#ifndef __clang__ /* bpftrace generates a bad BPF program in this case */ +#if ALLOW_STRUCT_BY_VALUE_TEST "test:struct_by_val_reg_pair { s.x=%llx -> arg0 }\n" /* captures first half of a struct */ #endif /* bpftrace can't handle 24-byte struct-by-value case in struct_by_val_stack */ @@ -140,7 +140,7 @@ const char *BPFTRACE_OUTPUT = "test:ptrs: arg0=0x* arg1='some literal' arg2=&42\n" "test:arrs: arg0='STRING' arg1=(-100,-200,-300)\n" "test:struct_by_val_reg: arg0=1 arg1=2\n" -#ifndef __clang__ +#if ALLOW_STRUCT_BY_VALUE_TEST "test:struct_by_val_reg_pair: s.x=3\n" #endif "test:structs_by_ref: a=(1) b=(2) c=(3,4) d=(4,5,6)\n" diff --git a/tests/common.h b/tests/common.h index 094dd10..11339f3 100644 --- a/tests/common.h +++ b/tests/common.h @@ -8,6 +8,15 @@ #define __always_inline inline __attribute__((always_inline)) #endif +/* Struct-by-value USDT argument currently only works on x86_64 with gcc + * See: https://github.com/bpftrace/bpftrace/issues/3798 + */ +#if defined(__clang__) || defined(__aarch64__) + #define ALLOW_STRUCT_BY_VALUE_TEST 0 +#else + #define ALLOW_STRUCT_BY_VALUE_TEST 1 +#endif + #ifdef __cplusplus extern "C" { #endif diff --git a/tests/cxx_arg_consts.cpp b/tests/cxx_arg_consts.cpp index 62eca84..90ca910 100644 --- a/tests/cxx_arg_consts.cpp +++ b/tests/cxx_arg_consts.cpp @@ -30,6 +30,17 @@ int main(int argc, char **argv) return 0; } +#ifdef __aarch64__ +const char *USDT_SPECS = +"test:chars base=BASE1 sema=0 argn=2 args=1@1 -1@-1.\n" +"test:shorts base=BASE1 sema=0 argn=2 args=2@2 -2@-2.\n" +"test:ints base=BASE1 sema=0 argn=2 args=4@3 -4@-3.\n" +"test:longs base=BASE1 sema=0 argn=2 args=*@4 -*@-4.\n" +"test:longlongs base=BASE1 sema=0 argn=2 args=8@5 -8@-5.\n" +"test:size_ts base=BASE1 sema=0 argn=2 args=*@6 -*@-6.\n" +"test:ptrs base=BASE1 sema=0 argn=2 args=*@0 *@7.\n" +; +#else const char *USDT_SPECS = "test:chars base=BASE1 sema=0 argn=2 args=1@$1 -1@$-1.\n" "test:shorts base=BASE1 sema=0 argn=2 args=2@$2 -2@$-2.\n" @@ -39,6 +50,7 @@ const char *USDT_SPECS = "test:size_ts base=BASE1 sema=0 argn=2 args=*@$6 -*@$-6.\n" "test:ptrs base=BASE1 sema=0 argn=2 args=*@$0 *@$7.\n" ; +#endif const char *BPFTRACE_SCRIPT = "test:chars { arg0=%hhu arg1=%hhd -> arg0, arg1 }\n" diff --git a/tests/cxx_arg_nums.cpp b/tests/cxx_arg_nums.cpp index 940b1fa..ae68117 100644 --- a/tests/cxx_arg_nums.cpp +++ b/tests/cxx_arg_nums.cpp @@ -35,6 +35,23 @@ int main(int argc, char **argv) return 0; } +#ifdef __aarch64__ +const char *USDT_SPECS = +"test:name0 base=BASE1 sema=0 argn=0 args=.\n" +"test:name1 base=BASE1 sema=0 argn=1 args=-4@1.\n" +"test:name2 base=BASE1 sema=0 argn=2 args=-4@1 -4@2.\n" +"test:name3 base=BASE1 sema=0 argn=3 args=-4@1 -4@2 -4@3.\n" +"test:name4 base=BASE1 sema=0 argn=4 args=-4@1 -4@2 -4@3 -4@4.\n" +"test:name5 base=BASE1 sema=0 argn=5 args=-4@1 -4@2 -4@3 -4@4 -4@5.\n" +"test:name6 base=BASE1 sema=0 argn=6 args=-4@1 -4@2 -4@3 -4@4 -4@5 -4@6.\n" +"test:name7 base=BASE1 sema=0 argn=7 args=-4@1 -4@2 -4@3 -4@4 -4@5 -4@6 -4@7.\n" +"test:name8 base=BASE1 sema=0 argn=8 args=-4@1 -4@2 -4@3 -4@4 -4@5 -4@6 -4@7 -4@8.\n" +"test:name9 base=BASE1 sema=0 argn=9 args=-4@1 -4@2 -4@3 -4@4 -4@5 -4@6 -4@7 -4@8 -4@9.\n" +"test:name10 base=BASE1 sema=0 argn=10 args=-4@1 -4@2 -4@3 -4@4 -4@5 -4@6 -4@7 -4@8 -4@9 -4@10.\n" +"test:name11 base=BASE1 sema=0 argn=11 args=-4@1 -4@2 -4@3 -4@4 -4@5 -4@6 -4@7 -4@8 -4@9 -4@10 -4@11.\n" +"test:name12 base=BASE1 sema=0 argn=12 args=-4@1 -4@2 -4@3 -4@4 -4@5 -4@6 -4@7 -4@8 -4@9 -4@10 -4@11 -4@12.\n" +; +#else const char *USDT_SPECS = "test:name0 base=BASE1 sema=0 argn=0 args=.\n" "test:name1 base=BASE1 sema=0 argn=1 args=-4@$1.\n" @@ -50,6 +67,7 @@ const char *USDT_SPECS = "test:name11 base=BASE1 sema=0 argn=11 args=-4@$1 -4@$2 -4@$3 -4@$4 -4@$5 -4@$6 -4@$7 -4@$8 -4@$9 -4@$10 -4@$11.\n" "test:name12 base=BASE1 sema=0 argn=12 args=-4@$1 -4@$2 -4@$3 -4@$4 -4@$5 -4@$6 -4@$7 -4@$8 -4@$9 -4@$10 -4@$11 -4@$12.\n" ; +#endif const char *BPFTRACE_SCRIPT = "test:name0 { triggered }\n" diff --git a/tests/cxx_arg_types.cpp b/tests/cxx_arg_types.cpp index 90e3619..7135fda 100644 --- a/tests/cxx_arg_types.cpp +++ b/tests/cxx_arg_types.cpp @@ -122,7 +122,7 @@ const char *BPFTRACE_SCRIPT = str(arg0), \ *(int32 *)(arg1 + 0), *(int32 *)(arg1 + 4), *(int32 *)(arg1 + 8) }\n" "test:struct_by_val_reg { arg0=%hhu arg1=%u -> arg0, arg1 }\n" -#ifndef __clang__ /* bpftrace generates a bad BPF program in this case */ +#if ALLOW_STRUCT_BY_VALUE_TEST "test:struct_by_val_reg_pair { s.x=%llx -> arg0 }\n" /* captures first half of a struct */ #endif /* bpftrace can't handle 24-byte struct-by-value case in struct_by_val_stack */ @@ -140,7 +140,7 @@ const char *BPFTRACE_OUTPUT = "test:ptrs: arg0=0x* arg1='some literal' arg2=&42\n" "test:arrs: arg0='STRING' arg1=(-100,-200,-300)\n" "test:struct_by_val_reg: arg0=1 arg1=2\n" -#ifndef __clang__ +#if ALLOW_STRUCT_BY_VALUE_TEST "test:struct_by_val_reg_pair: s.x=3\n" #endif "test:structs_by_ref: a=(1) b=(2) c=(3,4) d=(4,5,6)\n" diff --git a/tests/fetch-usdts.awk b/tests/fetch-usdts.awk index 0cfadd9..6f690dd 100644 --- a/tests/fetch-usdts.awk +++ b/tests/fetch-usdts.awk @@ -13,20 +13,26 @@ function reset_entry() function print_entry() { - if (base != 0 && !(base in basemap)) { - basemap[base] = ++base_cnt; + base_key = filename ":" base; + if (base != 0 && !(base_key in basemap)) { + basemap[base_key] = ++base_cnt; } - if (sema != 0 && !(sema in semamap)) { - semamap[sema] = ++sema_cnt; + + sema_key = filename ":" sema; + if (sema != 0 && !(sema_key in semamap)) { + semamap[sema_key] = ++sema_cnt; } - base_stub = (base == 0) ? "0" : sprintf("BASE%d", basemap[base]); - sema_stub = (sema == 0) ? "0" : sprintf("SEMA%d", semamap[sema]); + + base_stub = (base == 0) ? "0" : sprintf("BASE%d", basemap[base_key]); + sema_stub = (sema == 0) ? "0" : sprintf("SEMA%d", semamap[sema_key]); + printf "%s:%s base=%s sema=%s argn=%d args=%s.\n", grp, name, base_stub, sema_stub, argn, args; } BEGIN { reset_entry(); + filename = ""; } # stapsdt 0x0000003b NT_STAPSDT (SystemTap probe descriptors) @@ -35,6 +41,14 @@ BEGIN { # Location: 0x0000000000401198, Base: 0x0000000000402043, Semaphore: 0x0000000000000000 # Arguments: -4@$1 -4@$2 -4@$3 -4@$4 +/File:/ { + if (entry != "") { + print_entry(); + reset_entry(); + } + filename = $2; +} + /\sstapsdt\s/ { if (entry != "") { print_entry(); @@ -47,7 +61,12 @@ BEGIN { /Provider:/ { grp = $2; } /Name:/ { name = $2; } /Location:/ { base = strtonum($4); sema = strtonum($6); } -/Arguments:/ { argn = NF - 1; args = (argn > 0) ? substr($0, index($0,$2)) : ""; } +/Arguments:/ { + arg_str = substr($0, index($0, "Arguments: ") + 11); + # Count arguments by looking for patterns like "-4@" that start each argument + argn = gsub(/-?[0-9]+@/, "&", arg_str); + args = (argn > 0) ? arg_str : ""; +} END { if (entry != "") diff --git a/tests/run_test.sh b/tests/run_test.sh index 7caaafc..540c54b 100755 --- a/tests/run_test.sh +++ b/tests/run_test.sh @@ -65,7 +65,7 @@ $TEST_BIN -B > $TEST_BTOUT_SPEC if [ -s "$TEST_BTSCRIPT" ]; then # start attaching bpftrace - setsid sudo $bpftrace ${V:+-v} -v -B none "$TEST_BTSCRIPT" >"$TEST_BTOUT_RAW" 2>&1 & + setsid sudo $bpftrace ${V:+-v} -B none "$TEST_BTSCRIPT" >"$TEST_BTOUT_RAW" 2>&1 & bt_pid=$! bt_pgid="$(ps -opgid= "$bt_pid" | tr -d ' ')"