bpftrace: fix tcp*.bt/runqlat.bt scripts

tcp*.bt scripts tried to include glibc headers, which didn't work on
nixos because bpftrace tried to call clang-major with some options to
get the paths, but we never told it where to find it.
Give bpftrace the path directly instead of giving it a path to clang.

runqlat.bt doesn't work with glibc headers and requires kernel headers
which are no longer extracted, just provide its value.

Note the default clang output also had some clang-internal headers, but
these seem to be included anyway through libclang API without having to
give them here, so we only pass the glibc ones.

While here:
- also backport another bpftrace patch that made the tcp*.bt tools to
actually not require these includes
- and add tests that we can include these.

Co-authored-by: Arian van Putten <arian.vanputten@gmail.com>
This commit is contained in:
Dominique Martinet 2024-06-14 23:16:20 +09:00
parent 051f920625
commit 0bf9c7660f
5 changed files with 268 additions and 4 deletions

View File

@ -16,14 +16,14 @@ import ./make-test-python.nix ({ pkgs, ... }: {
# list probes
machine.succeed("bpftrace -l")
# simple BEGIN probe (user probe on bpftrace itself)
print(machine.succeed("bpftrace -e 'BEGIN { print(\"ok\"); exit(); }'"))
print(machine.succeed("bpftrace -e 'BEGIN { print(\"ok\\n\"); exit(); }'"))
# tracepoint
print(machine.succeed("bpftrace -e 'tracepoint:syscalls:sys_enter_* { print(probe); exit() }'"))
# kprobe
print(machine.succeed("bpftrace -e 'kprobe:schedule { print(probe); exit() }'"))
# BTF
print(machine.succeed("bpftrace -e 'kprobe:schedule { "
" printf(\"tgid: %d\", ((struct task_struct*) curtask)->tgid); exit() "
" printf(\"tgid: %d\\n\", ((struct task_struct*) curtask)->tgid); exit() "
"}'"))
# module BTF (bpftrace >= 0.17)
# test is currently disabled on aarch64 as kfunc does not work there yet
@ -32,5 +32,8 @@ import ./make-test-python.nix ({ pkgs, ... }: {
"bpftrace -e 'kfunc:nft_trans_alloc_gfp { "
" printf(\"portid: %d\\n\", args->ctx->portid); "
"} BEGIN { exit() }'"))
# glibc includes
print(machine.succeed("bpftrace -e '#include <errno.h>\n"
"BEGIN { printf(\"ok %d\\n\", EINVAL); exit(); }'"))
'';
})

View File

@ -0,0 +1,94 @@
From c1737d4ab6ab263932caa9e3ac170ebe3e28d404 Mon Sep 17 00:00:00 2001
From: Dominique Martinet <asmadeus@codewreck.org>
Date: Fri, 14 Jun 2024 21:56:46 +0900
Subject: [PATCH] clang_parser system_include_paths: allow overriding at
compile time
While bpftrace depends on libclang it can be installed without a clang
frontend, so some distributions might want to make these paths fixed as
they are unlikely to change.
In particular, this is necessary to include system libraries as used by
older versions of tcpaccept.bt (they now no longer require these since
#3152, but that illustrate this was a recurring problem)
(cherry picked from commit 5bf5f86313600b16c8c23e03b31337941cbefdd0)
---
CMakeLists.txt | 2 ++
src/CMakeLists.txt | 4 +++-
src/clang_parser.cpp | 19 +++++++++++++++----
3 files changed, 20 insertions(+), 5 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index cd620d0e56e5..ade33c503efb 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -21,6 +21,8 @@ set(VENDOR_GTEST OFF CACHE BOOL "Clone gtest from github")
set(BUILD_FUZZ OFF CACHE BOOL "Build bpftrace for fuzzing")
set(USE_LIBFUZZER OFF CACHE BOOL "Use libfuzzer for fuzzing")
set(FUZZ_TARGET "codegen" CACHE STRING "Fuzzing target")
+set(KERNEL_HEADERS_DIR "" CACHE PATH "Hard-code kernel headers directory")
+set(SYSTEM_INCLUDE_PATHS "auto" CACHE STRING "Hard-code system include paths (colon separated, the default value \"auto\" queries clang at runtime)")
set(ENABLE_SKB_OUTPUT ON CACHE BOOL "Enable skb_output, will include libpcap")
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 88f5928c8a75..eadb11207052 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -88,11 +88,13 @@ endif()
# compile definitions
-set(KERNEL_HEADERS_DIR "" CACHE PATH "Hard-code kernel headers directory")
if (KERNEL_HEADERS_DIR)
MESSAGE(STATUS "Using KERNEL_HEADERS_DIR=${KERNEL_HEADERS_DIR}")
target_compile_definitions(runtime PUBLIC KERNEL_HEADERS_DIR="${KERNEL_HEADERS_DIR}")
endif()
+if (NOT SYSTEM_INCLUDE_PATHS EQUAL "auto")
+ MESSAGE(STATUS "Using SYSTEM_INCLUDE_PATHS=${SYSTEM_INCLUDE_PATHS}")
+endif()
execute_process(
COMMAND git describe --abbrev=4 --dirty --tags
diff --git a/src/clang_parser.cpp b/src/clang_parser.cpp
index 8b6689454267..9367e6692eb0 100644
--- a/src/clang_parser.cpp
+++ b/src/clang_parser.cpp
@@ -882,11 +882,9 @@ std::string ClangParser::get_arch_include_path()
return "/usr/include/" + std::string(utsname.machine) + "-linux-gnu";
}
-std::vector<std::string> ClangParser::system_include_paths()
+static void query_clang_include_dirs(std::vector<std::string> &result)
{
- std::vector<std::string> result;
- try
- {
+ try {
auto clang = "clang-" + std::to_string(LLVM_VERSION_MAJOR);
auto cmd = clang + " -Wp,-v -x c -fsyntax-only /dev/null 2>&1";
auto check = exec_system(cmd.c_str());
@@ -902,6 +900,19 @@ std::vector<std::string> ClangParser::system_include_paths()
catch (std::runtime_error &)
{ // If exec_system fails, just ignore it
}
+}
+
+std::vector<std::string> ClangParser::system_include_paths()
+{
+ std::vector<std::string> result;
+ std::istringstream lines(SYSTEM_INCLUDE_PATHS);
+ std::string line;
+ while (std::getline(lines, line, ':')) {
+ if (line == "auto")
+ query_clang_include_dirs(result);
+ else
+ result.push_back(trim(line));
+ }
if (result.empty())
result = { "/usr/local/include", "/usr/include" };
--
2.45.2

View File

@ -1,6 +1,6 @@
{ lib, stdenv, fetchFromGitHub
, llvmPackages, elfutils, bcc
, libbpf, libbfd, libopcodes
, libbpf, libbfd, libopcodes, glibc
, cereal, asciidoctor
, cmake, pkg-config, flex, bison
, util-linux
@ -41,9 +41,17 @@ stdenv.mkDerivation rec {
"-DBUILD_TESTING=FALSE"
"-DLIBBCC_INCLUDE_DIRS=${bcc}/include"
"-DINSTALL_TOOL_DOCS=OFF"
"-DUSE_SYSTEM_BPF_BCC=ON"
"-DSYSTEM_INCLUDE_PATHS=${glibc.dev}/include"
];
patches = [
# https://github.com/bpftrace/bpftrace/pull/3243 (merged)
./override-system-headers.patch
# https://github.com/bpftrace/bpftrace/pull/3152 (merged)
./tcp-bt-no-includes.patch
# https://github.com/bpftrace/bpftrace/pull/3262 (merged)
./runqlat-bt-no-includes.patch
];
# Pull BPF scripts into $PATH (next to their bcc program equivalents), but do
# not move them to keep `${pkgs.bpftrace}/share/bpftrace/tools/...` working.

View File

@ -0,0 +1,45 @@
From 9b5f22854297aabb924969c25af66461d8d2fcb9 Mon Sep 17 00:00:00 2001
From: Dominique Martinet <asmadeus@codewreck.org>
Date: Fri, 21 Jun 2024 21:02:09 +0900
Subject: [PATCH] tools/runqlat: provide TASK_RUNNING as a define
runqlat requires kernel headers to run even with BTF, just because of a
define.
TASK_RUNNING isn't part of the stable API but it's never changed in all
of the linux git history so let's pretend it's stable and just define
it.
If we find a way to handle kheaders again in the future we might want to
consider reverting this.
Fixes: #3255
(cherry picked from commit aa041d9d85f9ec11235c39fdcb5833412ec27083)
---
tools/runqlat.bt | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/tools/runqlat.bt b/tools/runqlat.bt
index 3d71b76062eb..1298f399aee7 100755
--- a/tools/runqlat.bt
+++ b/tools/runqlat.bt
@@ -11,7 +11,17 @@
* 17-Sep-2018 Brendan Gregg Created this.
*/
+#ifndef BPFTRACE_HAVE_BTF
#include <linux/sched.h>
+#else
+/*
+ * With BTF providing types, full headers are not needed.
+ * We only need to supply the preprocessor defines used in this script.
+ * TASK_RUNNING is not arch-dependant and has not changed in the linux
+ * git history (it is not part of the stable API though)
+ */
+#define TASK_RUNNING 0
+#endif
BEGIN
{
--
2.45.2

View File

@ -0,0 +1,114 @@
From ebb12512f6ea0a1113ad8ddf30db26128f7a3426 Mon Sep 17 00:00:00 2001
From: Dominique Martinet <asmadeus@codewreck.org>
Date: Sun, 23 Jun 2024 20:41:01 +0900
Subject: [PATCH] With BTF, users do not need libc headers installed for
AF_INET/AF_INET6
Signed-off-by: Bernhard Kaindl <bernhardkaindl7@gmail.com>
(cherry picked from commit c0b9d252a43f99b9091245dedb178a6874803306)
---
tools/tcpaccept.bt | 8 +++++++-
tools/tcpconnect.bt | 8 +++++++-
tools/tcpdrop.bt | 8 +++++++-
tools/tcplife.bt | 8 +++++++-
tools/tcpretrans.bt | 8 +++++++-
5 files changed, 35 insertions(+), 5 deletions(-)
diff --git a/tools/tcpaccept.bt b/tools/tcpaccept.bt
index 08e6af0158fc..cbffe36889ee 100755
--- a/tools/tcpaccept.bt
+++ b/tools/tcpaccept.bt
@@ -20,7 +20,13 @@
#include <linux/socket.h>
#include <net/sock.h>
#else
-#include <sys/socket.h>
+/*
+ * With BTF providing types, socket headers are not needed.
+ * We only need to supply the preprocessor defines in this script.
+ * AF_INET/AF_INET6 are part of the stable arch-independent Linux ABI
+ */
+#define AF_INET 2
+#define AF_INET6 10
#endif
BEGIN
diff --git a/tools/tcpconnect.bt b/tools/tcpconnect.bt
index 1ac1eb99e9ad..636337275cd8 100755
--- a/tools/tcpconnect.bt
+++ b/tools/tcpconnect.bt
@@ -22,7 +22,13 @@
#include <linux/socket.h>
#include <net/sock.h>
#else
-#include <sys/socket.h>
+/*
+ * BTF provides the types, we just need to define AF_INET and AF_INET6.
+ * These are Linux ABI defines, and are not architecture-specific.
+ * With BTF, this allows tcpconnect.bt to work without glibc headers:
+ */
+#define AF_INET 2 /* IPv4 */
+#define AF_INET6 10 /* IPv6 */
#endif
BEGIN
diff --git a/tools/tcpdrop.bt b/tools/tcpdrop.bt
index fd3e55f490bf..a56bf69fcc6c 100755
--- a/tools/tcpdrop.bt
+++ b/tools/tcpdrop.bt
@@ -24,7 +24,13 @@
#include <linux/socket.h>
#include <net/sock.h>
#else
-#include <sys/socket.h>
+/*
+ * With BTF providing types, socket headers are not needed.
+ * We only need to supply the preprocessor defines in this script.
+ * AF_INET/AF_INET6 are part of the stable arch-independent Linux ABI
+ */
+#define AF_INET 2
+#define AF_INET6 10
#endif
BEGIN
diff --git a/tools/tcplife.bt b/tools/tcplife.bt
index dd4c1d68284e..d5a09c4e5da9 100755
--- a/tools/tcplife.bt
+++ b/tools/tcplife.bt
@@ -19,7 +19,13 @@
#include <linux/socket.h>
#include <linux/tcp.h>
#else
-#include <sys/socket.h>
+/*
+ * With BTF providing types, socket headers are not needed.
+ * We only need to supply the preprocessor defines in this script.
+ * AF_INET/AF_INET6 are part of the stable arch-independent Linux ABI
+ */
+#define AF_INET 2
+#define AF_INET6 10
#endif
BEGIN
diff --git a/tools/tcpretrans.bt b/tools/tcpretrans.bt
index ee2975d6e545..32a11bfa81b2 100755
--- a/tools/tcpretrans.bt
+++ b/tools/tcpretrans.bt
@@ -21,7 +21,13 @@
#include <linux/socket.h>
#include <net/sock.h>
#else
-#include <sys/socket.h>
+/*
+ * With BTF providing types, socket headers are not needed.
+ * We only need to supply the preprocessor defines in this script.
+ * AF_INET/AF_INET6 are part of the stable arch-independent Linux ABI
+ */
+#define AF_INET 2
+#define AF_INET6 10
#endif
BEGIN
--
2.45.2