Rebase bcc to version 0.36.1

Rebase bcc to the latest upstream version (RHEL-162980) and rebuild
with the LLVM 22 (RHEL-140402). The rebase fixes multiple issues:
- Fix multiple failure introduced by BPF 6.19 update (RHEL-174797)
- Fix klockstat (RHEL-174798)
- Fix bpf-cpufreq (RHEL-93855)
- Fix bpf-syncsnoop (RHEL-93854)
- Fix tcpaccept (RHEL-93424)
- Fix filegone, kvmexit, netqtop and tcpconnect on s390x (RHEL-75515)
- Fix profile on s390x (RHEL-68950)

Resolves: RHEL-162980
Resolves: RHEL-140402
Resolves: RHEL-174797
Resolves: RHEL-174798
Resolves: RHEL-93855
Resolves: RHEL-93854
Resolves: RHEL-75515
Resolves: RHEL-68950

Signed-off-by: Jerome Marchand <jmarchan@redhat.com>
This commit is contained in:
Jerome Marchand 2026-05-19 16:30:25 +02:00
parent 8a18d01e9a
commit 8a21b6323e
11 changed files with 140 additions and 657 deletions

1
.gitignore vendored
View File

@ -26,3 +26,4 @@
/bcc-0.32.0.tar.gz
/bcc-0.34.0.tar.gz
/bcc-0.35.0.tar.gz
/bcc-0.36.1.tar.gz

View File

@ -1,50 +0,0 @@
From 6a0030da509eb0c28d2d8a5ccc2f07c9fd9d4e45 Mon Sep 17 00:00:00 2001
From: yonghong-song <ys114321@gmail.com>
Date: Mon, 14 Jul 2025 20:21:59 -0700
Subject: [PATCH 3/6] Fix a build failure with clang21 (#5369)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The build error message:
src/cc/frontends/clang/loader.cc:400:73: error: no matching function for
call to clang::TextDiagnosticPrinter::TextDiagnosticPrinter(
llvm::raw_fd_ostream&, clang::DiagnosticOptions*)
400 | auto diag_client = new TextDiagnosticPrinter(llvm::errs(), &*diag_opts);
| ^
The llvm commit
https://github.com/llvm/llvm-project/pull/139584
caused the build failure.
Adjust the code properly and the error is fixed.
---
src/cc/frontends/clang/loader.cc | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/src/cc/frontends/clang/loader.cc b/src/cc/frontends/clang/loader.cc
index 07dc9d6a..6f8387aa 100644
--- a/src/cc/frontends/clang/loader.cc
+++ b/src/cc/frontends/clang/loader.cc
@@ -396,11 +396,19 @@ int ClangLoader::do_compile(
flags_cstr_rem.end());
// set up the error reporting class
+#if LLVM_VERSION_MAJOR >= 21
+ DiagnosticOptions diag_opts;
+ auto diag_client = new TextDiagnosticPrinter(llvm::errs(), diag_opts);
+
+ IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
+ DiagnosticsEngine diags(DiagID, diag_opts, diag_client);
+#else
IntrusiveRefCntPtr<DiagnosticOptions> diag_opts(new DiagnosticOptions());
auto diag_client = new TextDiagnosticPrinter(llvm::errs(), &*diag_opts);
IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
DiagnosticsEngine diags(DiagID, &*diag_opts, diag_client);
+#endif
// set up the command line argument wrapper
--
2.51.0

View File

@ -1,31 +0,0 @@
From 43e4e1e12a00366fb29126f8929a7678bbca8323 Mon Sep 17 00:00:00 2001
From: Jerome Marchand <jmarchan@redhat.com>
Date: Tue, 7 Oct 2025 15:32:36 +0200
Subject: [PATCH 5/6] libbpf-tools/javagc: Include usdt.bpf.h header
Include usdt.bpf.h header to javagc.bpf.c.
Fixes the following error:
libbpf: usdt: failed to find USDT support BPF maps, did you forget to include bpf/usdt.bpf.h?
attach usdt mem__pool__gc__begin failed: No such process
Signed-off-by: Jerome Marchand <jmarchan@redhat.com>
---
libbpf-tools/javagc.bpf.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/libbpf-tools/javagc.bpf.c b/libbpf-tools/javagc.bpf.c
index 5bfe635c..35535d92 100644
--- a/libbpf-tools/javagc.bpf.c
+++ b/libbpf-tools/javagc.bpf.c
@@ -3,6 +3,7 @@
#include <vmlinux.h>
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_core_read.h>
+#include <bpf/usdt.bpf.h>
#include "javagc.h"
struct {
--
2.51.0

View File

@ -1,79 +0,0 @@
From 7804b1238f6cb1a874a2c4a06caeac928412d0f5 Mon Sep 17 00:00:00 2001
From: Rong Tao <rongtao@cestc.cn>
Date: Sun, 13 Jul 2025 12:26:14 +0800
Subject: [PATCH 4/6] libbpf-tools: ksnoop: Fix two invalid access to map value
(#5361)
On fedora42, llvm 20.1.7, kernel 6.15.4-200.fc42.x86_64 has two verifier
errors. Test with command:
$ sudo ./ksnoop trace do_sys_openat2
1st:
; last_stack_depth = stack_depth - 1; @ ksnoop.bpf.c:102
108: (bc) w3 = w6 ; frame1: R3_w=scalar(id=5,smin=smin32=0,smax=umax=smax32=umax32=14,var_off=(0x0; 0xf)) R6=scalar(id=5,smin=smin32=0,smax=umax=smax32=umax32=14,var_off=(0x0; 0xf))
109: (04) w3 += -1 ; frame1: R3_w=scalar(smin=0,smax=umax=0xffffffff,smin32=-1,smax32=13,var_off=(0x0; 0xffffffff))
110: (bc) w4 = w3 ; frame1: R3_w=scalar(id=6,smin=0,smax=umax=0xffffffff,smin32=-1,smax32=13,var_off=(0x0; 0xffffffff)) R4_w=scalar(id=6,smin=0,smax=umax=0xffffffff,smin32=-1,smax32=13,var_off=(0x0; 0xffffffff))
111: (54) w4 &= 255 ; frame1: R4_w=scalar(smin=smin32=0,smax=umax=smax32=umax32=255,var_off=(0x0; 0xff))
112: (b7) r7 = 0 ; frame1: R7=0
; if (last_stack_depth >= 0 && @ ksnoop.bpf.c:104
113: (26) if w4 > 0xf goto pc+5 ; frame1: R4=scalar(smin=smin32=0,smax=umax=smax32=umax32=15,var_off=(0x0; 0xf))
; last_ip = func_stack->ips[last_stack_depth]; @ ksnoop.bpf.c:106
114: (57) r3 &= 255 ; frame1: R3_w=scalar(smin=smin32=0,smax=umax=smax32=umax32=255,var_off=(0x0; 0xff))
115: (67) r3 <<= 3 ; frame1: R3_w=scalar(smin=smin32=0,smax=umax=smax32=umax32=2040,var_off=(0x0; 0x7f8))
116: (bf) r4 = r2 ; frame1: R2=map_value(map=ksnoop_func_sta,ks=8,vs=144) R4_w=map_value(map=ksnoop_func_sta,ks=8,vs=144)
117: (0f) r4 += r3 ; frame1: R3_w=scalar(smin=smin32=0,smax=umax=smax32=umax32=2040,var_off=(0x0; 0x7f8)) R4_w=map_value(map=ksnoop_func_sta,ks=8,vs=144,smin=smin32=0,smax=umax=smax32=umax32=2040,var_off=(0x0; 0x7f8))
118: (79) r7 = *(u64 *)(r4 +8)
invalid access to map value, value_size=144 off=2048 size=8
The last_stack_depth use 'w4 > 0xf' check boundary, but 'r3 &= 255'
is beyond 0xf (0~15).
2nd:
; trace_len = sizeof(*trace) + trace->buf_len - MAX_TRACE_BUF; @ ksnoop.bpf.c:222
502: (04) w5 += 4008 ; frame1: R5_w=scalar(smin=umin=smin32=umin32=4009,smax=umax=smax32=umax32=0x10fa7,var_off=(0x0; 0x1ffff))
503: (bc) w2 = w5 ; frame1: R2_w=scalar(id=27,smin=umin=smin32=umin32=4009,smax=umax=smax32=umax32=0x10fa7,var_off=(0x0; 0x1ffff)) R5_w=scalar(id=27,smin=umin=smin32=umin32=4009,smax=umax=smax32=umax32=0x10fa7,var_off=(0x0; 0x1ffff))
504: (54) w2 &= 65535 ; frame1: R2_w=scalar(smin=smin32=0,smax=umax=smax32=umax32=0xffff,var_off=(0x0; 0xffff))
; if (trace_len <= sizeof(*trace)) @ ksnoop.bpf.c:224
505: (26) if w2 > 0x3fa8 goto pc+7 ; frame1: R2_w=scalar(smin=smin32=0,smax=umax=smax32=umax32=16296,var_off=(0x0; 0x3fff))
506: (57) r5 &= 65535 ; frame1: R5_w=scalar(smin=smin32=0,smax=umax=smax32=umax32=0xffff,var_off=(0x0; 0xffff))
507: (18) r2 = 0xffff8ec554700c00 ; frame1: R2_w=map_ptr(map=ksnoop_perf_map,ks=4,vs=4)
509: (18) r3 = 0xffffffff ; frame1: R3_w=0xffffffff
511: (bf) r4 = r9 ; frame1: R4_w=map_value(map=ksnoop_func_map,ks=8,vs=16296) R9=map_value(map=ksnoop_func_map,ks=8,vs=16296)
512: (85) call bpf_perf_event_output#25
invalid access to map value, value_size=16296 off=0 size=65535
Just fix it with size type 'u64' instead of 'u32', see:
long bpf_perf_event_output(void *ctx, struct bpf_map *map, u64 flags, void *data, u64 size)
Signed-off-by: Rong Tao <rongtao@cestc.cn>
---
libbpf-tools/ksnoop.bpf.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/libbpf-tools/ksnoop.bpf.c b/libbpf-tools/ksnoop.bpf.c
index f07ff561..15aa7d75 100644
--- a/libbpf-tools/ksnoop.bpf.c
+++ b/libbpf-tools/ksnoop.bpf.c
@@ -103,7 +103,8 @@ static struct trace *get_trace(struct pt_regs *ctx, bool entry)
/* get address of last function we called */
if (last_stack_depth >= 0 &&
last_stack_depth < FUNC_MAX_STACK_DEPTH)
- last_ip = func_stack->ips[last_stack_depth];
+ bpf_probe_read_kernel(&last_ip, sizeof(last_ip),
+ &func_stack->ips[last_stack_depth]);
/* push ip onto stack. return will pop it. */
func_stack->ips[stack_depth] = ip;
/* mask used in case bounds checks are optimized out */
@@ -202,7 +203,7 @@ static struct trace *get_trace(struct pt_regs *ctx, bool entry)
static void output_trace(struct pt_regs *ctx, struct trace *trace)
{
- __u16 trace_len;
+ __u64 trace_len;
if (trace->buf_len == 0)
goto skip;
--
2.51.0

View File

@ -1,425 +0,0 @@
From cdd2ade85acd05c8c7af17b0802163ad6fcb8ec7 Mon Sep 17 00:00:00 2001
From: Jerome Marchand <jmarchan@redhat.com>
Date: Tue, 15 Jul 2025 02:25:38 +0200
Subject: [PATCH] tools/{biolatency,biosnoop,biotop}: use TRACEPOINT_PROBE()
for tracepoints (#5366)
When support for block_io_* tracepoint was added, it used
attach_tracepoint() since it was closer to the existing code that
attached to kprobes. However, that meant we have to rely on a local
prototype of the args structure and the tool can be broken by a
change of the tracepoints format, which is what happens with kernel
commit aa6ff4eb7c10d ("block: Add ioprio to block_rq tracepoint")
which added a new argument to block tracepoints.
Replace attach_tracepoint() by TRACEPOINT_PROBE() so we don't have to
deal with the tracepoint format changes.
Signed-off-by: Jerome Marchand <jmarchan@redhat.com>
---
tools/biolatency.py | 102 +++++++++++++++++++++++---------------------
tools/biosnoop.py | 86 +++++++++++++++++++------------------
tools/biotop.py | 81 ++++++++++++++++++-----------------
3 files changed, 141 insertions(+), 128 deletions(-)
diff --git a/tools/biolatency.py b/tools/biolatency.py
index 3ba1b237..1d3f2d80 100755
--- a/tools/biolatency.py
+++ b/tools/biolatency.py
@@ -87,17 +87,6 @@ typedef struct ext_val {
u64 count;
} ext_val_t;
-struct tp_args {
- u64 __unused__;
- dev_t dev;
- sector_t sector;
- unsigned int nr_sector;
- unsigned int bytes;
- char rwbs[8];
- char comm[16];
- char cmd[];
-};
-
struct start_key {
dev_t dev;
u32 _pad;
@@ -134,16 +123,6 @@ int trace_req_start(struct pt_regs *ctx, struct request *req)
return __trace_req_start(key);
}
-int trace_req_start_tp(struct tp_args *args)
-{
- struct start_key key = {
- .dev = args->dev,
- .sector = args->sector
- };
-
- return __trace_req_start(key);
-}
-
// output
static int __trace_req_done(struct start_key key)
{
@@ -176,8 +155,22 @@ int trace_req_done(struct pt_regs *ctx, struct request *req)
return __trace_req_done(key);
}
+"""
+
+tp_start_text = """
+TRACEPOINT_PROBE(block, START_TP)
+{
+ struct start_key key = {
+ .dev = args->dev,
+ .sector = args->sector
+ };
+
+ return __trace_req_start(key);
+}
+"""
-int trace_req_done_tp(struct tp_args *args)
+tp_done_text = """
+TRACEPOINT_PROBE(block, DONE_TP)
{
struct start_key key = {
.dev = args->dev,
@@ -266,41 +259,54 @@ bpf_text = bpf_text.replace("STORE", store_str)
if args.ebpf:
exit()
-# load BPF program
-b = BPF(text=bpf_text)
+# Which kprobe/tracepoint to attach to.
+# We can attach to two IO start kprobes but only one of the other types.
+kprobe_start = set()
+tp_start = None
+kprobe_done = None
+tp_done = None
+
if args.queued:
- if BPF.tracepoint_exists("block", "block_io_start"):
- b.attach_tracepoint(tp="block:block_io_start", fn_name="trace_req_start_tp")
- elif BPF.get_kprobe_functions(b'__blk_account_io_start'):
- b.attach_kprobe(event="__blk_account_io_start", fn_name="trace_req_start")
+ if BPF.get_kprobe_functions(b'__blk_account_io_start'):
+ kprobe_start.add("__blk_account_io_start")
elif BPF.get_kprobe_functions(b'blk_account_io_start'):
- b.attach_kprobe(event="blk_account_io_start", fn_name="trace_req_start")
+ kprobe_start.add("blk_account_io_start")
+ elif BPF.tracepoint_exists("block", "block_io_start"):
+ tp_start = "block_io_start"
elif BPF.tracepoint_exists("block", "block_bio_queue"):
- b.attach_tracepoint(tp="block:block_bio_queue", fn_name="trace_req_start_tp")
- else:
- if args.flags:
- # Some flags are accessible in the rwbs field (RAHEAD, SYNC and META)
- # but other aren't. Disable the -F option for tracepoint for now.
- print("ERROR: blk_account_io_start probe not available. Can't use -F.")
- exit()
+ tp_start = "block_bio_queue"
+
else:
if BPF.get_kprobe_functions(b'blk_start_request'):
- b.attach_kprobe(event="blk_start_request", fn_name="trace_req_start")
- b.attach_kprobe(event="blk_mq_start_request", fn_name="trace_req_start")
+ kprobe_start.add("blk_start_request")
+ kprobe_start.add("blk_mq_start_request")
-if BPF.tracepoint_exists("block", "block_io_done"):
- b.attach_tracepoint(tp="block:block_io_done", fn_name="trace_req_done_tp")
-elif BPF.get_kprobe_functions(b'__blk_account_io_done'):
- b.attach_kprobe(event="__blk_account_io_done", fn_name="trace_req_done")
+if BPF.get_kprobe_functions(b'__blk_account_io_done'):
+ kprobe_done = "__blk_account_io_done"
elif BPF.get_kprobe_functions(b'blk_account_io_done'):
- b.attach_kprobe(event="blk_account_io_done", fn_name="trace_req_done")
+ kprobe_done = "blk_account_io_done"
+elif BPF.tracepoint_exists("block", "block_io_done"):
+ tp_done = "block_io_done"
elif BPF.tracepoint_exists("block", "block_rq_complete"):
- b.attach_tracepoint(tp="block:block_rq_complete", fn_name="trace_req_done_tp")
-else:
- if args.flags:
- print("ERROR: blk_account_io_done probe not available. Can't use -F.")
- exit()
+ tp_done = "block_rq_complete"
+
+if args.flags and (tp_start or tp_done):
+ # Some flags are accessible in the rwbs field (RAHEAD, SYNC and META)
+ # but other aren't. Disable the -F option for tracepoint for now.
+ print("ERROR: blk_account_io_start/done probes not available. Can't use -F.")
+ exit()
+
+if tp_start:
+ bpf_text += tp_start_text.replace("START_TP", tp_start)
+if tp_done:
+ bpf_text += tp_done_text.replace("DONE_TP", tp_done)
+# load BPF program
+b = BPF(text=bpf_text)
+for i in kprobe_start:
+ b.attach_kprobe(event=i, fn_name="trace_req_start")
+if kprobe_done:
+ b.attach_kprobe(event=kprobe_done, fn_name="trace_req_done")
if not args.json:
print("Tracing block device I/O... Hit Ctrl-C to end.")
diff --git a/tools/biosnoop.py b/tools/biosnoop.py
index 045e1f9d..65df90c3 100755
--- a/tools/biosnoop.py
+++ b/tools/biosnoop.py
@@ -65,17 +65,6 @@ struct val_t {
char name[TASK_COMM_LEN];
};
-struct tp_args {
- u64 __unused__;
- dev_t dev;
- sector_t sector;
- unsigned int nr_sector;
- unsigned int bytes;
- char rwbs[8];
- char comm[16];
- char cmd[];
-};
-
struct hash_key {
dev_t dev;
u32 rwflag;
@@ -182,17 +171,6 @@ int trace_pid_start(struct pt_regs *ctx, struct request *req)
return __trace_pid_start(key);
}
-int trace_pid_start_tp(struct tp_args *args)
-{
- struct hash_key key = {
- .dev = args->dev,
- .rwflag = get_rwflag_tp(args->rwbs),
- .sector = args->sector
- };
-
- return __trace_pid_start(key);
-}
-
// time block I/O
int trace_req_start(struct pt_regs *ctx, struct request *req)
{
@@ -284,8 +262,23 @@ int trace_req_completion(struct pt_regs *ctx, struct request *req)
return __trace_req_completion(ctx, key);
}
+"""
-int trace_req_completion_tp(struct tp_args *args)
+tp_start_text = """
+TRACEPOINT_PROBE(block, block_io_start)
+{
+ struct hash_key key = {
+ .dev = args->dev,
+ .rwflag = get_rwflag_tp(args->rwbs),
+ .sector = args->sector
+ };
+
+ return __trace_pid_start(key);
+}
+"""
+
+tp_done_text = """
+TRACEPOINT_PROBE(block, block_io_done)
{
struct hash_key key = {
.dev = args->dev,
@@ -296,6 +289,7 @@ int trace_req_completion_tp(struct tp_args *args)
return __trace_req_completion(args, key);
}
"""
+
if args.queue:
bpf_text = bpf_text.replace('##QUEUE##', '1')
else:
@@ -329,31 +323,41 @@ int trace_req_completion_tp(struct tp_args *args)
if args.ebpf:
exit()
-# initialize BPF
-b = BPF(text=bpf_text)
if BPF.tracepoint_exists("block", "block_io_start"):
- b.attach_tracepoint(tp="block:block_io_start", fn_name="trace_pid_start_tp")
-elif BPF.get_kprobe_functions(b'__blk_account_io_start'):
- b.attach_kprobe(event="__blk_account_io_start", fn_name="trace_pid_start")
-elif BPF.get_kprobe_functions(b'blk_account_io_start'):
- b.attach_kprobe(event="blk_account_io_start", fn_name="trace_pid_start")
+ bpf_text += tp_start_text
+ tp_start = True
+else:
+ tp_start = False
+
+if BPF.tracepoint_exists("block", "block_io_done"):
+ bpf_text += tp_done_text
+ tp_done = True
else:
- print("ERROR: No found any block io start probe/tp.")
- exit()
+ tp_done = False
+
+# initialize BPF
+b = BPF(text=bpf_text)
+if not tp_start:
+ if BPF.get_kprobe_functions(b'__blk_account_io_start'):
+ b.attach_kprobe(event="__blk_account_io_start", fn_name="trace_pid_start")
+ elif BPF.get_kprobe_functions(b'blk_account_io_start'):
+ b.attach_kprobe(event="blk_account_io_start", fn_name="trace_pid_start")
+ else:
+ print("ERROR: No found any block io start probe/tp.")
+ exit()
if BPF.get_kprobe_functions(b'blk_start_request'):
b.attach_kprobe(event="blk_start_request", fn_name="trace_req_start")
b.attach_kprobe(event="blk_mq_start_request", fn_name="trace_req_start")
-if BPF.tracepoint_exists("block", "block_io_done"):
- b.attach_tracepoint(tp="block:block_io_done", fn_name="trace_req_completion_tp")
-elif BPF.get_kprobe_functions(b'__blk_account_io_done'):
- b.attach_kprobe(event="__blk_account_io_done", fn_name="trace_req_completion")
-elif BPF.get_kprobe_functions(b'blk_account_io_done'):
- b.attach_kprobe(event="blk_account_io_done", fn_name="trace_req_completion")
-else:
- print("ERROR: No found any block io done probe/tp.")
- exit()
+if not tp_done:
+ if BPF.get_kprobe_functions(b'__blk_account_io_done'):
+ b.attach_kprobe(event="__blk_account_io_done", fn_name="trace_req_completion")
+ elif BPF.get_kprobe_functions(b'blk_account_io_done'):
+ b.attach_kprobe(event="blk_account_io_done", fn_name="trace_req_completion")
+ else:
+ print("ERROR: No found any block io done probe/tp.")
+ exit()
# header
diff --git a/tools/biotop.py b/tools/biotop.py
index 480c37a4..4281b742 100755
--- a/tools/biotop.py
+++ b/tools/biotop.py
@@ -90,17 +90,6 @@ struct val_t {
u32 io;
};
-struct tp_args {
- u64 __unused__;
- dev_t dev;
- sector_t sector;
- unsigned int nr_sector;
- unsigned int bytes;
- char rwbs[8];
- char comm[16];
- char cmd[];
-};
-
struct hash_key {
dev_t dev;
u32 _pad;
@@ -143,16 +132,6 @@ int trace_pid_start(struct pt_regs *ctx, struct request *req)
return __trace_pid_start(key);
}
-int trace_pid_start_tp(struct tp_args *args)
-{
- struct hash_key key = {
- .dev = args->dev,
- .sector = args->sector
- };
-
- return __trace_pid_start(key);
-}
-
// time block I/O
int trace_req_start(struct pt_regs *ctx, struct request *req)
{
@@ -246,8 +225,22 @@ int trace_req_completion(struct pt_regs *ctx, struct request *req)
return __trace_req_completion(key);
}
+"""
+
+tp_start_text = """
+TRACEPOINT_PROBE(block, block_io_start)
+{
+ struct hash_key key = {
+ .dev = args->dev,
+ .sector = args->sector
+ };
+
+ return __trace_pid_start(key);
+}
+"""
-int trace_req_completion_tp(struct tp_args *args)
+tp_done_text = """
+TRACEPOINT_PROBE(block, block_io_done)
{
struct hash_key key = {
.dev = args->dev,
@@ -272,30 +265,40 @@ int trace_req_completion_tp(struct tp_args *args)
else:
bpf_text = bpf_text.replace('FILTER_PID', '0')
-b = BPF(text=bpf_text)
if BPF.tracepoint_exists("block", "block_io_start"):
- b.attach_tracepoint(tp="block:block_io_start", fn_name="trace_pid_start_tp")
-elif BPF.get_kprobe_functions(b'__blk_account_io_start'):
- b.attach_kprobe(event="__blk_account_io_start", fn_name="trace_pid_start")
-elif BPF.get_kprobe_functions(b'blk_account_io_start'):
- b.attach_kprobe(event="blk_account_io_start", fn_name="trace_pid_start")
+ bpf_text += tp_start_text
+ tp_start = True
else:
- print("ERROR: No found any block io start probe/tp.")
- exit()
+ tp_start = False
+
+if BPF.tracepoint_exists("block", "block_io_done"):
+ bpf_text += tp_done_text
+ tp_done = True
+else:
+ tp_done = False
+
+b = BPF(text=bpf_text)
+if not tp_start:
+ if BPF.get_kprobe_functions(b'__blk_account_io_start'):
+ b.attach_kprobe(event="__blk_account_io_start", fn_name="trace_pid_start")
+ elif BPF.get_kprobe_functions(b'blk_account_io_start'):
+ b.attach_kprobe(event="blk_account_io_start", fn_name="trace_pid_start")
+ else:
+ print("ERROR: No found any block io start probe/tp.")
+ exit()
if BPF.get_kprobe_functions(b'blk_start_request'):
b.attach_kprobe(event="blk_start_request", fn_name="trace_req_start")
b.attach_kprobe(event="blk_mq_start_request", fn_name="trace_req_start")
-if BPF.tracepoint_exists("block", "block_io_done"):
- b.attach_tracepoint(tp="block:block_io_done", fn_name="trace_req_completion_tp")
-elif BPF.get_kprobe_functions(b'__blk_account_io_done'):
- b.attach_kprobe(event="__blk_account_io_done", fn_name="trace_req_completion")
-elif BPF.get_kprobe_functions(b'blk_account_io_done'):
- b.attach_kprobe(event="blk_account_io_done", fn_name="trace_req_completion")
-else:
- print("ERROR: No found any block io done probe/tp.")
- exit()
+if not tp_done:
+ if BPF.get_kprobe_functions(b'__blk_account_io_done'):
+ b.attach_kprobe(event="__blk_account_io_done", fn_name="trace_req_completion")
+ elif BPF.get_kprobe_functions(b'blk_account_io_done'):
+ b.attach_kprobe(event="blk_account_io_done", fn_name="trace_req_completion")
+ else:
+ print("ERROR: No found any block io done probe/tp.")
+ exit()
# check whether hash table batch ops is supported
htab_batch_ops = True if BPF.kernel_struct_has_field(b'bpf_map_ops',
--
2.50.1

View File

@ -1,64 +0,0 @@
From 4af39db87ffbc8ae8f4e868da7fa076858f0c734 Mon Sep 17 00:00:00 2001
From: Francois Lesueur <11961066+flesueur@users.noreply.github.com>
Date: Wed, 6 Aug 2025 06:11:02 +0200
Subject: [PATCH 6/6] tools/tcpconnect: fix iov field for DNS with Linux>=6.4
(#5382)
Tcpconnect with DNS (-d flag) does not work with Linux>=6.4. The kernel representation of struct iov_iter changed in 6.4.
This PR adapts the iov field depending on the structure. It also removes inet_sk() which did not work on a recent kernel (6.6).
---
tools/tcpconnect.py | 14 +++++++++-----
1 file changed, 9 insertions(+), 5 deletions(-)
diff --git a/tools/tcpconnect.py b/tools/tcpconnect.py
index a38bad8d..dc35cb28 100755
--- a/tools/tcpconnect.py
+++ b/tools/tcpconnect.py
@@ -276,7 +276,7 @@ int trace_udp_recvmsg(struct pt_regs *ctx)
{
__u64 pid_tgid = bpf_get_current_pid_tgid();
struct sock *sk = (struct sock *)PT_REGS_PARM1(ctx);
- struct inet_sock *is = inet_sk(sk);
+ struct inet_sock *is = (struct inet_sock *)sk;
// only grab port 53 packets, 13568 is ntohs(53)
if (is->inet_dport == 13568) {
@@ -303,7 +303,7 @@ int trace_udp_ret_recvmsg(struct pt_regs *ctx)
goto delete_and_return;
size_t buflen = (size_t)copied;
- if (buflen > msghdr->msg_iter.iov->iov_len)
+ if (buflen > msghdr->msg_iter.IOV_FIELD->iov_len)
goto delete_and_return;
if (buflen > MAX_PKT)
@@ -313,7 +313,7 @@ int trace_udp_ret_recvmsg(struct pt_regs *ctx)
if (!data) // this should never happen, just making the verifier happy
return 0;
- void *iovbase = msghdr->msg_iter.iov->iov_base;
+ void *iovbase = msghdr->msg_iter.IOV_FIELD->iov_base;
bpf_probe_read(data->pkt, buflen, iovbase);
dns_events.perf_submit(ctx, data, buflen);
@@ -386,10 +386,14 @@ bpf_text = bpf_text.replace('FILTER_FAMILY', '')
bpf_text = bpf_text.replace('FILTER_UID', '')
if args.dns:
- if BPF.kernel_struct_has_field(b'iov_iter', b'iter_type') == 1:
+ if BPF.kernel_struct_has_field(b'iov_iter', b'type') == 1:
+ dns_bpf_text = dns_bpf_text.replace('TYPE_FIELD', 'type')
+ else:
dns_bpf_text = dns_bpf_text.replace('TYPE_FIELD', 'iter_type')
+ if BPF.kernel_struct_has_field(b'iov_iter', b'iov') == 1:
+ dns_bpf_text = dns_bpf_text.replace('IOV_FIELD', 'iov')
else:
- dns_bpf_text = dns_bpf_text.replace('TYPE_FIELD', 'type')
+ dns_bpf_text = dns_bpf_text.replace('IOV_FIELD', '__iov')
bpf_text += dns_bpf_text
if debug or args.ebpf:
--
2.51.0

View File

@ -0,0 +1,63 @@
From 6c966fe58767354225cf01a908ec5a9b78c403dc Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Holger=20Hoffst=C3=A4tte?= <holger@applied-asynchrony.com>
Date: Mon, 2 Mar 2026 10:03:15 +0100
Subject: [PATCH] Fix build with LLVM-22
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
LLVM-22 changed the signatures of various createDiagnostics() calls [1].
Introduce a new version macro guard and adapt the code to the changed API.
Fixes #5483
[1] https://github.com/llvm/llvm-project/commit/30633f30894129919050f24fdd1f8f6bc46beae0
Signed-off-by: Holger Hoffstätte <holger@applied-asynchrony.com>
---
src/cc/frontends/clang/loader.cc | 15 ++++++++++++---
1 file changed, 12 insertions(+), 3 deletions(-)
diff --git a/src/cc/frontends/clang/loader.cc b/src/cc/frontends/clang/loader.cc
index 6f8387aa..1f706344 100644
--- a/src/cc/frontends/clang/loader.cc
+++ b/src/cc/frontends/clang/loader.cc
@@ -464,7 +464,10 @@ int ClangLoader::do_compile(
}
invocation0.getFrontendOpts().DisableFree = false;
-#if LLVM_VERSION_MAJOR >= 20
+#if LLVM_VERSION_MAJOR >= 22
+ compiler0.setVirtualFileSystem(llvm::vfs::getRealFileSystem());
+ compiler0.createDiagnostics(new IgnoringDiagConsumer());
+#elif LLVM_VERSION_MAJOR >= 20
compiler0.createDiagnostics(*llvm::vfs::getRealFileSystem(), new IgnoringDiagConsumer());
#else
compiler0.createDiagnostics(new IgnoringDiagConsumer());
@@ -487,7 +490,10 @@ int ClangLoader::do_compile(
add_main_input(invocation1, main_path, &*out_buf);
invocation1.getFrontendOpts().DisableFree = false;
-#if LLVM_VERSION_MAJOR >= 20
+#if LLVM_VERSION_MAJOR >= 22
+ compiler1.setVirtualFileSystem(llvm::vfs::getRealFileSystem());
+ compiler1.createDiagnostics();
+#elif LLVM_VERSION_MAJOR >= 20
compiler1.createDiagnostics(*llvm::vfs::getRealFileSystem());
#else
compiler1.createDiagnostics();
@@ -517,7 +523,10 @@ int ClangLoader::do_compile(
invocation2.getCodeGenOpts().setInlining(CodeGenOptions::NormalInlining);
// suppress warnings in the 2nd pass, but bail out on errors (our fault)
invocation2.getDiagnosticOpts().IgnoreWarnings = true;
-#if LLVM_VERSION_MAJOR >= 20
+#if LLVM_VERSION_MAJOR >= 22
+ compiler2.setVirtualFileSystem(llvm::vfs::getRealFileSystem());
+ compiler2.createDiagnostics();
+#elif LLVM_VERSION_MAJOR >= 20
compiler2.createDiagnostics(*llvm::vfs::getRealFileSystem());
#else
compiler2.createDiagnostics();
--
2.54.0

View File

@ -0,0 +1,59 @@
From 922a47200c19a0b6e436194712886ee082fd9f0a Mon Sep 17 00:00:00 2001
From: Avinesh Kumar <avinesh.kumar@suse.com>
Date: Fri, 6 Mar 2026 16:00:01 +0100
Subject: [PATCH 2/2] clang: Add microsoft extensions build flags
Starting in Linux 6.19, `struct ns_common` fields were moved into an
anonymous nested forward declaration (`struct ns_tree;`) within a
union.[1]
This causes Clang to throw a `[-Wmissing-declarations]` warning and
fail with missing member errors.
This affects tools pulling in `<linux/pid_namespace.h>` directly or
transitively (e.g. filetop, runqlat)
Errors encountered:
include/linux/ns/ns_common_types.h:117:3: warning: declaration does not declare anything [-Wmissing-declarations]
117 | struct ns_tree;
| ^~~~~~~~~~~~~~
In file included from /virtual/main.c:5:
In file included from include/linux/pid_namespace.h:11:
include/linux/ns_common.h:25:23: error: no member named 'ns_id' in 'struct ns_common'
25 | VFS_WARN_ON_ONCE(ns->ns_id == 0);
| ~~ ^
include/linux/ns_common.h:26:13: error: no member named 'ns_id' in 'struct ns_common'
26 | return ns->ns_id <= NS_LAST_INIT_ID;
| ~~ ^
include/linux/ns_common.h:60:26: error: no member named '__ns_ref_active' in 'struct ns_common'
60 | return atomic_read(&ns->__ns_ref_active);
This patch fixes the issue globally by turning on microsoft extensions
flags. These flags have already been in the linux kernel. [2]
[1] https://github.com/torvalds/linux/commit/a657bc8a75cf40c3d0814fe6488ba4af56528f42
[2] https://github.com/torvalds/linux/commit/c4781dc3d1cf0e017e1f290607ddc56cfe187afc
Signed-off-by: Avinesh Kumar <avinesh.kumar@suse.com>
Fixes: #5488
---
src/cc/frontends/clang/kbuild_helper.cc | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/src/cc/frontends/clang/kbuild_helper.cc b/src/cc/frontends/clang/kbuild_helper.cc
index 4f09a398..b5d6a55e 100644
--- a/src/cc/frontends/clang/kbuild_helper.cc
+++ b/src/cc/frontends/clang/kbuild_helper.cc
@@ -137,6 +137,10 @@ int KBuildHelper::get_flags(const char *uname_machine, vector<string> *cflags) {
cflags->push_back("-Wno-pointer-sign");
cflags->push_back("-fno-stack-protector");
+ // Align with Linux kernel's -fms-extensions flags adopted since v6.19
+ cflags->push_back("-fms-extensions");
+ cflags->push_back("-Wno-microsoft-anon-tag");
+
/*
* kernel is usually build with gcc and the kernel devel header
* reflects that fact. However we build with clang and this must be
--
2.54.0

View File

@ -24,18 +24,15 @@
Name: bcc
Version: 0.35.0
Release: 3%{?dist}
Version: 0.36.1
Release: 1%{?dist}
Summary: BPF Compiler Collection (BCC)
License: Apache-2.0
URL: https://github.com/iovisor/bcc
Source0: %{url}/archive/v%{version}/%{name}-%{version}.tar.gz
Patch0: %%{name}-%%{version}-Revert-Fix-bashreadline-4903.patch
Patch1: %%{name}-%%{version}-tools-biolatency-biosnoop-biotop-use-TRACEPOINT_PROB.patch
Patch2: %%{name}-%%{version}-Fix-a-build-failure-with-clang21-5369.patch
Patch3: %%{name}-%%{version}-libbpf-tools-ksnoop-Fix-two-invalid-access-to-map-va.patch
Patch4: %%{name}-%%{version}-libbpf-tools-javagc-Include-usdt.bpf.h-header.patch
Patch5: %%{name}-%%{version}-tools-tcpconnect-fix-iov-field-for-DNS-with-Linux-6..patch
Patch1: %%{name}-%%{version}-Fix-build-with-LLVM-22.patch
Patch2: %%{name}-%%{version}-clang-Add-microsoft-extensions-build-flags.patch
# Arches will be included as upstream support is added and dependencies are
# satisfied in the respective arches
@ -135,6 +132,7 @@ Command line libbpf tools for BPF Compiler Collection (BCC)
%endif
%prep
# mv bcc-0.36.0/ bcc-0.36.1/
%autosetup -p1
@ -268,6 +266,17 @@ cp -a libbpf-tools/tmp-install/bin/* %{buildroot}/%{_sbindir}/
%endif
%changelog
* Mon May 18 2026 Jerome Marchand <jmarchan@redhat.com> - 0.36.1-1
- Rebase to version 0.36.1 (RHEL-162980)
- Rebuild with LLVM 22 (RHEL-140402)
- Fix multiple failure introduced by BPF 6.19 update (RHEL-174797)
- Fix klockstat (RHEL-174798)
- Fix bpf-cpufreq (RHEL-93855)
- Fix bpf-syncsnoop (RHEL-93854)
- Fix tcpaccept (RHEL-93424)
- Fix filegone, kvmexit, netqtop and tcpconnect on s390x (RHEL-75515)
- Fix profile on s390x (RHEL-68950)
* Wed Jan 07 2026 Jerome Marchand <jmarchan@redhat.com> - 0.35.0-3
- Rebuild with LLVM 21 (RHEL-108333)

View File

@ -1 +1 @@
SHA512 (bcc-0.35.0.tar.gz) = 23cc1413fef785165fe9fd29a242fb13e4e56da7d63699dbed3d6d12902a1de392b412cb0e5754eff5aeecf0a023568d593c9f4cb5bca7a88013aadfaef4fa3d
SHA512 (bcc-0.36.1.tar.gz) = bada939f35deb806989a6f8b04943aecde472a4a85cd781861c67051a75fd197988090e67f5f937080b8d47643bc209cf7e83fbd6d811d727484d03f7be92092