diff mbox series

[meta-oe,3/8] bpftrace: link test data source binary without host runtime

Message ID 20260713004502.716970-3-khem.raj@oss.qualcomm.com
State New
Headers show
Series [meta-python,1/8] python3-dbus-deviation: Drop all setup_requires to fix build failure | expand

Commit Message

Khem Raj July 13, 2026, 12:44 a.m. UTC
The build host HOME directory check recently added to OE-Core's
buildpaths QA test flags the ptest gtest binary:

WARNING: bpftrace-0.25.1-r0 do_package_qa: QA Issue: File
/usr/lib/bpftrace/ptest/tests/bpftrace_test in package bpftrace-ptest
contains a reference to the build host HOME directory. [buildpaths]

WARNING: bpftrace-0.25.1-r0 do_package_qa: QA Issue: File
/usr/lib/bpftrace/ptest/tests/.debug/bpftrace_test in package
bpftrace-dbg contains a reference to the build host HOME directory.
[buildpaths]

cmake/BuildBPF.cmake links the intermediate DWARF carrier binary
data_source_exe with the plain build host gcc, which bakes the host
dynamic loader's absolute path into the PT_INTERP segment. With a
distro gcc that is an innocuous /lib64/ld-linux-x86-64.so.2, but when
the host toolchain is a buildtools-extended/SDK gcc installed under
the build user's home directory (as on the autobuilder workers), it
is a $HOME-prefixed path like

  /srv/pokybuild/.../buildtools/sysroots/x86_64-pokysdk-linux/lib/ld-linux-x86-64.so.2

The executable is then embedded byte-for-byte into bpftrace_test via
embed()/xxd (tests/data/CMakeLists.txt), so the path ends up in the
test binary's .rodata, triggering the bpftrace-ptest warning. And
because cmake/Embed.tmpl declares the embedded blob as a constexpr
array, gcc additionally copies its contents into .debug_info as
DW_AT_const_value, which is how the same string survives
objcopy --only-keep-debug into the split debug file, triggering the
bpftrace-dbg warning. This is the same embedding mechanism that
previously leaked TMPDIR paths, fixed for the compile step by the
DEBUG_PREFIX_MAP patch; the link step was still leaking.

The tests only write this binary to a temp file and use it as a
uprobe target (tests/dwarf_common.h), parsing its DWARF and symbols;
it is never executed. So link it with -nostdlib -no-pie -Wl,--entry=0:
no interpreter, no host crt objects, no dynamic segment, and thus
nothing host-specific in the embedded blob. Function symbols, DWARF
type information and the pahole -J BTF encoding step are unaffected,
and the field_analyser_dwarf ptests still pass.

Because the object is now linked -nostdlib it must not reference the
libc stack-protector runtime. Host gcc toolchains that default to
-fstack-protector-strong (e.g. Debian/Ubuntu and the Yocto
autobuilder workers) otherwise leave an undefined reference and the
link fails:

  ld: data_source.o: in function `main':
  data_source.c:212: undefined reference to `__stack_chk_fail'
  collect2: error: ld returned 1 exit status

Compile the object and link the binary with -fno-stack-protector; the
canary is irrelevant to a DWARF/BTF carrier that is never run.

Signed-off-by: Khem Raj <khem.raj@oss.qualcomm.com>
---
 ...make-link-data-source-binary-without.patch | 78 +++++++++++++++++++
 .../bpftrace/bpftrace_0.25.1.bb               |  1 +
 2 files changed, 79 insertions(+)
 create mode 100644 meta-oe/dynamic-layers/meta-python/recipes-devtools/bpftrace/bpftrace/0003-cmake-BuildBPF.cmake-link-data-source-binary-without.patch
diff mbox series

Patch

diff --git a/meta-oe/dynamic-layers/meta-python/recipes-devtools/bpftrace/bpftrace/0003-cmake-BuildBPF.cmake-link-data-source-binary-without.patch b/meta-oe/dynamic-layers/meta-python/recipes-devtools/bpftrace/bpftrace/0003-cmake-BuildBPF.cmake-link-data-source-binary-without.patch
new file mode 100644
index 0000000000..7a69d0f8c1
--- /dev/null
+++ b/meta-oe/dynamic-layers/meta-python/recipes-devtools/bpftrace/bpftrace/0003-cmake-BuildBPF.cmake-link-data-source-binary-without.patch
@@ -0,0 +1,78 @@ 
+From: Khem Raj <khem.raj@oss.qualcomm.com>
+Date: Thu, 2 Jul 2026 15:30:00 -0700
+Subject: [PATCH] cmake/BuildBPF.cmake: link data source binary without host
+ runtime
+
+The `bpf()` helper links the intermediate DWARF carrier binary
+(data_source_exe) with the plain host gcc:
+
+  ${GCC} -g -o data_source_exe data_source.o
+
+and the resulting executable is then embedded byte-for-byte into
+bpftrace_test via embed()/xxd (tests/data/CMakeLists.txt). Linking it as
+a regular dynamic executable bakes host-toolchain artifacts into it:
+
+  * PT_INTERP: the absolute path of the host toolchain's dynamic
+    loader. With a vendored/SDK toolchain (e.g. Yocto
+    buildtools-extended installed under the build user's home) this is
+    an absolute build-host path such as
+    /srv/pokybuild/.../buildtools/sysroots/x86_64-pokysdk-linux/lib/ld-linux-x86-64.so.2
+  * crt startup objects (crt1.o, crti.o, crtbegin.o) including whatever
+    debug info the host libc was built with.
+
+Since the embedded blob carries these strings into the packaged test
+binary, the build is not reproducible across hosts and leaks build host
+paths, flagged by OE's buildpaths QA check:
+
+  WARNING: bpftrace-0.25.1-r0 do_package_qa: QA Issue: File
+  /usr/lib/bpftrace/ptest/tests/bpftrace_test in package bpftrace-ptest
+  contains a reference to the build host HOME directory. [buildpaths]
+
+The binary only serves as a DWARF/BTF container: the tests write it to
+a temp file and use it as a uprobe target (tests/dwarf_common.h), which
+parses debug info and symbols but never executes it. So link it with
+-nostdlib -no-pie: no interpreter, no dynamic segment, no host crt
+code. -Wl,--entry=0 silences the "cannot find entry symbol _start"
+warning. All function symbols, DWARF type information and the
+pahole -J BTF encoding step are unaffected.
+
+Because the object is now linked -nostdlib, it must not emit references
+to the libc stack-protector runtime. Host gcc toolchains that default to
+-fstack-protector-strong (e.g. Debian/Ubuntu, the Yocto autobuilders)
+otherwise leave an undefined reference and the link fails:
+
+  ld: data_source.o: in function `main':
+  data_source.c:212: undefined reference to `__stack_chk_fail'
+  collect2: error: ld returned 1 exit status
+
+Compile the object (and link the binary) with -fno-stack-protector; the
+canary is irrelevant to a DWARF/BTF carrier that is never run.
+
+Upstream-Status: Pending
+Signed-off-by: Khem Raj <khem.raj@oss.qualcomm.com>
+---
+ cmake/BuildBPF.cmake | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/cmake/BuildBPF.cmake b/cmake/BuildBPF.cmake
+index cb8cd68..8aa059f 100644
+--- a/cmake/BuildBPF.cmake
++++ b/cmake/BuildBPF.cmake
+@@ -90,7 +90,7 @@ function(bpf NAME)
+     OUTPUT ${ARG_OBJECT}
+     DEPENDS ${ARG_SOURCE} ${ARG_DEPENDS}
+     # See above: fresh compilation and the use of `gcc`.
+-    COMMAND ${GCC} -Wno-attributes -g -I ${CMAKE_CURRENT_BINARY_DIR} -c ${CMAKE_CURRENT_SOURCE_DIR}/${ARG_SOURCE} -o ${CMAKE_CURRENT_BINARY_DIR}/${ARG_OBJECT}
++    COMMAND ${GCC} -Wno-attributes -fno-stack-protector -g -I ${CMAKE_CURRENT_BINARY_DIR} -c ${CMAKE_CURRENT_SOURCE_DIR}/${ARG_SOURCE} -o ${CMAKE_CURRENT_BINARY_DIR}/${ARG_OBJECT}
+     COMMAND cmake -E env LLVM_OBJCOPY=${LLVM_OBJCOPY} ${PAHOLE} -J ${CMAKE_CURRENT_BINARY_DIR}/${ARG_OBJECT}
+     VERBATIM
+   )
+@@ -107,7 +107,7 @@ function(bpf NAME)
+     add_custom_command(
+       OUTPUT ${ARG_BINARY}
+       DEPENDS ${ARG_SOURCE} ${NAME}_gen_object
+-      COMMAND ${GCC} -g -o ${CMAKE_CURRENT_BINARY_DIR}/${ARG_BINARY} ${CMAKE_CURRENT_BINARY_DIR}/${ARG_OBJECT}
++      COMMAND ${GCC} -g -fno-stack-protector -nostdlib -no-pie -Wl,--entry=0 -o ${CMAKE_CURRENT_BINARY_DIR}/${ARG_BINARY} ${CMAKE_CURRENT_BINARY_DIR}/${ARG_OBJECT}
+       COMMAND cmake -E env LLVM_OBJCOPY=${LLVM_OBJCOPY} ${PAHOLE} -J ${CMAKE_CURRENT_BINARY_DIR}/${ARG_BINARY}
+       VERBATIM
+     )
diff --git a/meta-oe/dynamic-layers/meta-python/recipes-devtools/bpftrace/bpftrace_0.25.1.bb b/meta-oe/dynamic-layers/meta-python/recipes-devtools/bpftrace/bpftrace_0.25.1.bb
index 62e0c17f9d..7daf02ba1c 100644
--- a/meta-oe/dynamic-layers/meta-python/recipes-devtools/bpftrace/bpftrace_0.25.1.bb
+++ b/meta-oe/dynamic-layers/meta-python/recipes-devtools/bpftrace/bpftrace_0.25.1.bb
@@ -19,6 +19,7 @@  SRC_URI = "git://github.com/iovisor/bpftrace;branch=release/0.25.x;protocol=http
            file://run-ptest \
            file://0002-CMakeLists.txt-allow-to-set-BISON_FLAGS-like-l.patch \
            file://0001-cmake-BuildBPF.cmake-introduce-DEBUG_PREFIX_MAP.patch \
+           file://0003-cmake-BuildBPF.cmake-link-data-source-binary-without.patch \
 "
 SRCREV = "e491811e5d648288c01f42ce087967b271f504a0"