* [PATCH bpf-next] bpftool: Make skeleton C++ compatible with explicit casts
@ 2025-12-31 9:25 WanLi Niu
2025-12-31 9:48 ` bot+bpf-ci
2025-12-31 10:29 ` [PATCH v2 " WanLi Niu
0 siblings, 2 replies; 14+ messages in thread
From: WanLi Niu @ 2025-12-31 9:25 UTC (permalink / raw)
To: Quentin Monnet
Cc: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Martin KaFai Lau, Eduard Zingerman, Song Liu, Yonghong Song,
John Fastabend, KP Singh, Stanislav Fomichev, Hao Luo, Jiri Olsa,
WanLi Niu, Menglong Dong, bpf, linux-kernel, WanLi Niu,
Menglong Dong
From: WanLi Niu <niuwl1@chinatelecom.cn>
Fix C++ compilation errors in generated skeleton by adding explicit
pointer casts and using integer subtraction for offset calculation.
error: invalid conversion from 'void*' to 'trace_bpf*' [-fpermissive]
| skel = skel_alloc(sizeof(*skel));
| ~~~~~~~~~~^~~~~~~~~~~~~~~
| |
| void*
error: invalid use of 'void'
| skel->ctx.sz = (void *)&skel->links - (void *)skel;
Signed-off-by: WanLi Niu <niuwl1@chinatelecom.cn>
Co-developed-by: Menglong Dong <dongml2@chinatelecom.cn>
Signed-off-by: Menglong Dong <dongml2@chinatelecom.cn>
---
tools/bpf/bpftool/gen.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/tools/bpf/bpftool/gen.c b/tools/bpf/bpftool/gen.c
index 993c7d9484a4..71446a776130 100644
--- a/tools/bpf/bpftool/gen.c
+++ b/tools/bpf/bpftool/gen.c
@@ -731,10 +731,10 @@ static int gen_trace(struct bpf_object *obj, const char *obj_name, const char *h
{ \n\
struct %1$s *skel; \n\
\n\
- skel = skel_alloc(sizeof(*skel)); \n\
+ skel = (struct trace_bpf *)skel_alloc(sizeof(*skel));\n\
if (!skel) \n\
goto cleanup; \n\
- skel->ctx.sz = (void *)&skel->links - (void *)skel; \n\
+ skel->ctx.sz = (__u64)&skel->links - (__u64)skel; \n\
",
obj_name, opts.data_sz);
bpf_object__for_each_map(map, obj) {
--
2.39.1
^ permalink raw reply related [flat|nested] 14+ messages in thread* Re: [PATCH bpf-next] bpftool: Make skeleton C++ compatible with explicit casts 2025-12-31 9:25 [PATCH bpf-next] bpftool: Make skeleton C++ compatible with explicit casts WanLi Niu @ 2025-12-31 9:48 ` bot+bpf-ci 2025-12-31 10:29 ` [PATCH v2 " WanLi Niu 1 sibling, 0 replies; 14+ messages in thread From: bot+bpf-ci @ 2025-12-31 9:48 UTC (permalink / raw) To: kiraskyler, qmo Cc: ast, daniel, andrii, martin.lau, eddyz87, song, yonghong.song, john.fastabend, kpsingh, sdf, haoluo, jolsa, kiraskyler, menglong8.dong, bpf, linux-kernel, niuwl1, dongml2, ast, andrii, daniel, martin.lau, eddyz87, yonghong.song, clm, ihor.solodrai [-- Attachment #1: Type: text/plain, Size: 1218 bytes --] > diff --git a/tools/bpf/bpftool/gen.c b/tools/bpf/bpftool/gen.c > index 993c7d9484a4..71446a776130 100644 > --- a/tools/bpf/bpftool/gen.c > +++ b/tools/bpf/bpftool/gen.c > @@ -731,10 +731,10 @@ static int gen_trace(struct bpf_object *obj, const char *obj_name, const char *h > { \n\ > struct %1$s *skel; \n\ > \n\ > - skel = skel_alloc(sizeof(*skel)); \n\ > + skel = (struct trace_bpf *)skel_alloc(sizeof(*skel));\n\ ^^^^^^^^^ Should this cast use (struct %1$s *) instead of (struct trace_bpf *)? The variable skel is declared as "struct %1$s *skel" where %1$s is replaced with obj_name, but the cast hardcodes "trace_bpf" regardless of what skeleton is being generated. This would cause C++ compilation errors for any BPF object with a name other than trace_bpf. For comparison, the non-loader skeleton at do_skeleton() correctly uses "(struct %1$s *)calloc()" to match the skeleton name. --- AI reviewed your patch. Please fix the bug or email reply why it's not a bug. See: https://github.com/kernel-patches/vmtest/blob/master/ci/claude/README.md CI run summary: https://github.com/kernel-patches/bpf/actions/runs/20616299845 ^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH v2 bpf-next] bpftool: Make skeleton C++ compatible with explicit casts 2025-12-31 9:25 [PATCH bpf-next] bpftool: Make skeleton C++ compatible with explicit casts WanLi Niu 2025-12-31 9:48 ` bot+bpf-ci @ 2025-12-31 10:29 ` WanLi Niu 2026-01-02 19:35 ` Yonghong Song 2026-01-04 2:14 ` [PATCH v3 " WanLi Niu 1 sibling, 2 replies; 14+ messages in thread From: WanLi Niu @ 2025-12-31 10:29 UTC (permalink / raw) To: Quentin Monnet Cc: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko, Martin KaFai Lau, Eduard Zingerman, Song Liu, Yonghong Song, John Fastabend, KP Singh, Stanislav Fomichev, Hao Luo, Jiri Olsa, WanLi Niu, Menglong Dong, bpf, linux-kernel, WanLi Niu, Menglong Dong From: WanLi Niu <niuwl1@chinatelecom.cn> Fix C++ compilation errors in generated skeleton by adding explicit pointer casts and using integer subtraction for offset calculation. error: invalid conversion from 'void*' to 'trace_bpf*' [-fpermissive] | skel = skel_alloc(sizeof(*skel)); | ~~~~~~~~~~^~~~~~~~~~~~~~~ | | | void* error: invalid use of 'void' | skel->ctx.sz = (void *)&skel->links - (void *)skel; Signed-off-by: WanLi Niu <niuwl1@chinatelecom.cn> Co-developed-by: Menglong Dong <dongml2@chinatelecom.cn> Signed-off-by: Menglong Dong <dongml2@chinatelecom.cn> --- tools/bpf/bpftool/gen.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/bpf/bpftool/gen.c b/tools/bpf/bpftool/gen.c index 993c7d9484a4..71446a776130 100644 --- a/tools/bpf/bpftool/gen.c +++ b/tools/bpf/bpftool/gen.c @@ -731,10 +731,10 @@ static int gen_trace(struct bpf_object *obj, const char *obj_name, const char *h { \n\ struct %1$s *skel; \n\ \n\ - skel = skel_alloc(sizeof(*skel)); \n\ + skel = (struct %1$s *)skel_alloc(sizeof(*skel)); \n\ if (!skel) \n\ goto cleanup; \n\ - skel->ctx.sz = (void *)&skel->links - (void *)skel; \n\ + skel->ctx.sz = (__u64)&skel->links - (__u64)skel; \n\ ", obj_name, opts.data_sz); bpf_object__for_each_map(map, obj) { -- 2.39.1 ^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH v2 bpf-next] bpftool: Make skeleton C++ compatible with explicit casts 2025-12-31 10:29 ` [PATCH v2 " WanLi Niu @ 2026-01-02 19:35 ` Yonghong Song 2026-01-04 2:14 ` [PATCH v3 " WanLi Niu 1 sibling, 0 replies; 14+ messages in thread From: Yonghong Song @ 2026-01-02 19:35 UTC (permalink / raw) To: WanLi Niu, Quentin Monnet Cc: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko, Martin KaFai Lau, Eduard Zingerman, Song Liu, John Fastabend, KP Singh, Stanislav Fomichev, Hao Luo, Jiri Olsa, Menglong Dong, bpf, linux-kernel, WanLi Niu, Menglong Dong On 12/31/25 2:29 AM, WanLi Niu wrote: > From: WanLi Niu <niuwl1@chinatelecom.cn> > > Fix C++ compilation errors in generated skeleton by adding explicit > pointer casts and using integer subtraction for offset calculation. > > error: invalid conversion from 'void*' to 'trace_bpf*' [-fpermissive] > | skel = skel_alloc(sizeof(*skel)); > | ~~~~~~~~~~^~~~~~~~~~~~~~~ > | | > | void* > > error: invalid use of 'void' > | skel->ctx.sz = (void *)&skel->links - (void *)skel; > > Signed-off-by: WanLi Niu <niuwl1@chinatelecom.cn> > Co-developed-by: Menglong Dong <dongml2@chinatelecom.cn> > Signed-off-by: Menglong Dong <dongml2@chinatelecom.cn> For llvm22, I hacked with core_kern_overflow.lskel.h and has the following warning/errors: In file included from prog_tests/core_kern_overflow.cc:4: /home/yhs/work/bpf-next/tools/testing/selftests/bpf/core_kern_overflow.lskel.h:65:9: error: assigning to 'struct core_kern_overflow_lskel *' from incompatible type 'void *' 65 | skel = skel_alloc(sizeof(*skel)); | ^~~~~~~~~~~~~~~~~~~~~~~~~ /home/yhs/work/bpf-next/tools/testing/selftests/bpf/core_kern_overflow.lskel.h:68:38: error: arithmetic on pointers to void 68 | skel->ctx.sz = (void *)&skel->links - (void *)skel; | ~~~~~~~~~~~~~~~~~~~~ ^ ~~~~~~~~~~~~ Your patch fixed the issue. But for llvm side, I got the following two more errors: /home/yhs/work/bpf-next/tools/testing/selftests/bpf/core_kern_overflow.lskel.h:73:15: error: assigning to 'struct core_kern_overflow_lskel__bss *' from incompatible type 'void *' 73 | skel->bss = skel_prep_map_data((void *)data, 4096, | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 74 | sizeof(data) - 1); | ~~~~~~~~~~~~~~~~~ /home/yhs/work/bpf-next/tools/testing/selftests/bpf/core_kern_overflow.lskel.h:223:14: error: assigning to 'struct core_kern_overflow_lskel__bss *' from incompatible type 'void *' 223 | skel->bss = skel_finalize_map_data(&skel->maps.bss.initial_value, | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 224 | 4096, PROT_READ | PROT_WRITE, skel->maps.bss.map_fd); | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ So these two issues can be fixed similar to above skel_alloc() case. Could you fix both of them? > --- > tools/bpf/bpftool/gen.c | 4 ++-- > 1 file changed, 2 insertions(+), 2 deletions(-) > > diff --git a/tools/bpf/bpftool/gen.c b/tools/bpf/bpftool/gen.c > index 993c7d9484a4..71446a776130 100644 > --- a/tools/bpf/bpftool/gen.c > +++ b/tools/bpf/bpftool/gen.c > @@ -731,10 +731,10 @@ static int gen_trace(struct bpf_object *obj, const char *obj_name, const char *h > { \n\ > struct %1$s *skel; \n\ > \n\ > - skel = skel_alloc(sizeof(*skel)); \n\ > + skel = (struct %1$s *)skel_alloc(sizeof(*skel)); \n\ > if (!skel) \n\ > goto cleanup; \n\ > - skel->ctx.sz = (void *)&skel->links - (void *)skel; \n\ > + skel->ctx.sz = (__u64)&skel->links - (__u64)skel; \n\ > ", > obj_name, opts.data_sz); > bpf_object__for_each_map(map, obj) { ^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH v3 bpf-next] bpftool: Make skeleton C++ compatible with explicit casts 2025-12-31 10:29 ` [PATCH v2 " WanLi Niu 2026-01-02 19:35 ` Yonghong Song @ 2026-01-04 2:14 ` WanLi Niu 2026-01-05 5:27 ` Yonghong Song ` (2 more replies) 1 sibling, 3 replies; 14+ messages in thread From: WanLi Niu @ 2026-01-04 2:14 UTC (permalink / raw) To: Quentin Monnet Cc: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko, Martin KaFai Lau, Eduard Zingerman, Song Liu, Yonghong Song, John Fastabend, KP Singh, Stanislav Fomichev, Hao Luo, Jiri Olsa, WanLi Niu, Menglong Dong, bpf, linux-kernel, WanLi Niu, Menglong Dong From: WanLi Niu <niuwl1@chinatelecom.cn> Fix C++ compilation errors in generated skeleton by adding explicit pointer casts and using integer subtraction for offset calculation. Use struct outer::inner syntax under __cplusplus to access nested skeleton map structs, ensuring C++ compilation compatibility while preserving C support error: invalid conversion from 'void*' to '<obj_name>*' [-fpermissive] | skel = skel_alloc(sizeof(*skel)); | ~~~~~~~~~~^~~~~~~~~~~~~~~ | | | void* error: arithmetic on pointers to void | skel->ctx.sz = (void *)&skel->links - (void *)skel; | ~~~~~~~~~~~~~~~~~~~~ ^ ~~~~~~~~~~~~ error: assigning to 'struct <obj_name>__<ident> *' from incompatible type 'void *' | skel-><ident> = skel_prep_map_data((void *)data, 4096, | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | sizeof(data) - 1); | ~~~~~~~~~~~~~~~~~ error: assigning to 'struct <obj_name>__<ident> *' from incompatible type 'void *' | skel-><ident> = skel_finalize_map_data(&skel->maps.<ident>.initial_value, | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | 4096, PROT_READ | PROT_WRITE, skel->maps.<ident>.map_fd); | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Signed-off-by: WanLi Niu <niuwl1@chinatelecom.cn> Co-developed-by: Menglong Dong <dongml2@chinatelecom.cn> Signed-off-by: Menglong Dong <dongml2@chinatelecom.cn> --- changelog: v3: - Fix two additional <obj_name>__<ident> type mismatches as suggested by Yonghong Song v2: https://lore.kernel.org/all/20251231102929.3843-1-kiraskyler@163.com/ - Use generic (struct %1$s *) instead of project-specific (struct trace_bpf *) v1: https://lore.kernel.org/all/20251231092541.3352-1-kiraskyler@163.com/ --- tools/bpf/bpftool/gen.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/tools/bpf/bpftool/gen.c b/tools/bpf/bpftool/gen.c index 993c7d9484a4..010861b7d0ea 100644 --- a/tools/bpf/bpftool/gen.c +++ b/tools/bpf/bpftool/gen.c @@ -731,10 +731,10 @@ static int gen_trace(struct bpf_object *obj, const char *obj_name, const char *h { \n\ struct %1$s *skel; \n\ \n\ - skel = skel_alloc(sizeof(*skel)); \n\ + skel = (struct %1$s *)skel_alloc(sizeof(*skel)); \n\ if (!skel) \n\ goto cleanup; \n\ - skel->ctx.sz = (void *)&skel->links - (void *)skel; \n\ + skel->ctx.sz = (__u64)&skel->links - (__u64)skel; \n\ ", obj_name, opts.data_sz); bpf_object__for_each_map(map, obj) { @@ -755,13 +755,17 @@ static int gen_trace(struct bpf_object *obj, const char *obj_name, const char *h \n\ \"; \n\ \n\ + #ifdef __cplusplus \n\ + skel->%1$s = (struct %3$s::%3$s__%1$s *)skel_prep_map_data((void *)data, %2$zd,\n\ + #else \n\ skel->%1$s = skel_prep_map_data((void *)data, %2$zd,\n\ + #endif \n\ sizeof(data) - 1);\n\ if (!skel->%1$s) \n\ goto cleanup; \n\ skel->maps.%1$s.initial_value = (__u64) (long) skel->%1$s;\n\ } \n\ - ", ident, bpf_map_mmap_sz(map)); + ", ident, bpf_map_mmap_sz(map), obj_name); } codegen("\ \n\ @@ -857,12 +861,16 @@ static int gen_trace(struct bpf_object *obj, const char *obj_name, const char *h codegen("\ \n\ + #ifdef __cplusplus \n\ + skel->%1$s = (struct %4$s::%4$s__%1$s *)skel_finalize_map_data(&skel->maps.%1$s.initial_value,\n\ + #else \n\ skel->%1$s = skel_finalize_map_data(&skel->maps.%1$s.initial_value, \n\ + #endif \n\ %2$zd, %3$s, skel->maps.%1$s.map_fd);\n\ if (!skel->%1$s) \n\ return -ENOMEM; \n\ ", - ident, bpf_map_mmap_sz(map), mmap_flags); + ident, bpf_map_mmap_sz(map), mmap_flags, obj_name); } codegen("\ \n\ -- 2.39.1 ^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH v3 bpf-next] bpftool: Make skeleton C++ compatible with explicit casts 2026-01-04 2:14 ` [PATCH v3 " WanLi Niu @ 2026-01-05 5:27 ` Yonghong Song 2026-01-05 7:12 ` [PATCH v4 " WanLi Niu 2026-01-06 0:46 ` [PATCH v3 " Andrii Nakryiko 2 siblings, 0 replies; 14+ messages in thread From: Yonghong Song @ 2026-01-05 5:27 UTC (permalink / raw) To: WanLi Niu, Quentin Monnet Cc: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko, Martin KaFai Lau, Eduard Zingerman, Song Liu, John Fastabend, KP Singh, Stanislav Fomichev, Hao Luo, Jiri Olsa, Menglong Dong, bpf, linux-kernel, WanLi Niu, Menglong Dong On 1/3/26 6:14 PM, WanLi Niu wrote: > From: WanLi Niu <niuwl1@chinatelecom.cn> > > Fix C++ compilation errors in generated skeleton by adding explicit > pointer casts and using integer subtraction for offset calculation. > > Use struct outer::inner syntax under __cplusplus to access nested skeleton map > structs, ensuring C++ compilation compatibility while preserving C support > > error: invalid conversion from 'void*' to '<obj_name>*' [-fpermissive] > | skel = skel_alloc(sizeof(*skel)); > | ~~~~~~~~~~^~~~~~~~~~~~~~~ > | | > | void* > > error: arithmetic on pointers to void > | skel->ctx.sz = (void *)&skel->links - (void *)skel; > | ~~~~~~~~~~~~~~~~~~~~ ^ ~~~~~~~~~~~~ > > error: assigning to 'struct <obj_name>__<ident> *' from incompatible type 'void *' > | skel-><ident> = skel_prep_map_data((void *)data, 4096, > | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ > | sizeof(data) - 1); > | ~~~~~~~~~~~~~~~~~ > > error: assigning to 'struct <obj_name>__<ident> *' from incompatible type 'void *' > | skel-><ident> = skel_finalize_map_data(&skel->maps.<ident>.initial_value, > | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ > | 4096, PROT_READ | PROT_WRITE, skel->maps.<ident>.map_fd); > | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ > > Signed-off-by: WanLi Niu <niuwl1@chinatelecom.cn> > Co-developed-by: Menglong Dong <dongml2@chinatelecom.cn> > Signed-off-by: Menglong Dong <dongml2@chinatelecom.cn> LGTM. Could you add a minimum reproducer in the commit message? Acked-by: Yonghong Song <yonghong.song@linux.dev> ^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH v4 bpf-next] bpftool: Make skeleton C++ compatible with explicit casts 2026-01-04 2:14 ` [PATCH v3 " WanLi Niu 2026-01-05 5:27 ` Yonghong Song @ 2026-01-05 7:12 ` WanLi Niu 2026-01-05 10:39 ` Quentin Monnet ` (2 more replies) 2026-01-06 0:46 ` [PATCH v3 " Andrii Nakryiko 2 siblings, 3 replies; 14+ messages in thread From: WanLi Niu @ 2026-01-05 7:12 UTC (permalink / raw) To: Quentin Monnet Cc: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko, Martin KaFai Lau, Eduard Zingerman, Song Liu, Yonghong Song, John Fastabend, KP Singh, Stanislav Fomichev, Hao Luo, Jiri Olsa, WanLi Niu, Menglong Dong, bpf, linux-kernel, WanLi Niu, Menglong Dong From: WanLi Niu <niuwl1@chinatelecom.cn> Fix C++ compilation errors in generated skeleton by adding explicit pointer casts and using integer subtraction for offset calculation. Use struct outer::inner syntax under __cplusplus to access nested skeleton map structs, ensuring C++ compilation compatibility while preserving C support error: invalid conversion from 'void*' to '<obj_name>*' [-fpermissive] | skel = skel_alloc(sizeof(*skel)); | ~~~~~~~~~~^~~~~~~~~~~~~~~ | | | void* error: arithmetic on pointers to void | skel->ctx.sz = (void *)&skel->links - (void *)skel; | ~~~~~~~~~~~~~~~~~~~~ ^ ~~~~~~~~~~~~ error: assigning to 'struct <obj_name>__<ident> *' from incompatible type 'void *' | skel-><ident> = skel_prep_map_data((void *)data, 4096, | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | sizeof(data) - 1); | ~~~~~~~~~~~~~~~~~ error: assigning to 'struct <obj_name>__<ident> *' from incompatible type 'void *' | skel-><ident> = skel_finalize_map_data(&skel->maps.<ident>.initial_value, | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | 4096, PROT_READ | PROT_WRITE, skel->maps.<ident>.map_fd); | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Minimum reproducer: $ cat test.bpf.c int val; // placed in .bss section #include "vmlinux.h" #include <bpf/bpf_helpers.h> SEC("raw_tracepoint/sched_wakeup_new") int handle(void *ctx) { return 0; } $ cat test.cpp #include <cerrno> extern "C" { #include "test.bpf.skel.h" } $ bpftool btf dump file /sys/kernel/btf/vmlinux format c > vmlinux.h $ clang -g -O2 -target bpf -c test.bpf.c -o test.bpf.o $ bpftool gen skeleton test.bpf.o -L > test.bpf.skel.h $ g++ -c test.cpp -I. Signed-off-by: WanLi Niu <niuwl1@chinatelecom.cn> Co-developed-by: Menglong Dong <dongml2@chinatelecom.cn> Signed-off-by: Menglong Dong <dongml2@chinatelecom.cn> --- changelog: v4: - Add a minimum reproducer to demonstrate the issue, as suggested by Yonghong Song v3: https://lore.kernel.org/all/20260104021402.2968-1-kiraskyler@163.com/ - Fix two additional <obj_name>__<ident> type mismatches as suggested by Yonghong Song v2: https://lore.kernel.org/all/20251231102929.3843-1-kiraskyler@163.com/ - Use generic (struct %1$s *) instead of project-specific (struct trace_bpf *) v1: https://lore.kernel.org/all/20251231092541.3352-1-kiraskyler@163.com/ --- tools/bpf/bpftool/gen.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/tools/bpf/bpftool/gen.c b/tools/bpf/bpftool/gen.c index 993c7d9484a4..010861b7d0ea 100644 --- a/tools/bpf/bpftool/gen.c +++ b/tools/bpf/bpftool/gen.c @@ -731,10 +731,10 @@ static int gen_trace(struct bpf_object *obj, const char *obj_name, const char *h { \n\ struct %1$s *skel; \n\ \n\ - skel = skel_alloc(sizeof(*skel)); \n\ + skel = (struct %1$s *)skel_alloc(sizeof(*skel)); \n\ if (!skel) \n\ goto cleanup; \n\ - skel->ctx.sz = (void *)&skel->links - (void *)skel; \n\ + skel->ctx.sz = (__u64)&skel->links - (__u64)skel; \n\ ", obj_name, opts.data_sz); bpf_object__for_each_map(map, obj) { @@ -755,13 +755,17 @@ static int gen_trace(struct bpf_object *obj, const char *obj_name, const char *h \n\ \"; \n\ \n\ + #ifdef __cplusplus \n\ + skel->%1$s = (struct %3$s::%3$s__%1$s *)skel_prep_map_data((void *)data, %2$zd,\n\ + #else \n\ skel->%1$s = skel_prep_map_data((void *)data, %2$zd,\n\ + #endif \n\ sizeof(data) - 1);\n\ if (!skel->%1$s) \n\ goto cleanup; \n\ skel->maps.%1$s.initial_value = (__u64) (long) skel->%1$s;\n\ } \n\ - ", ident, bpf_map_mmap_sz(map)); + ", ident, bpf_map_mmap_sz(map), obj_name); } codegen("\ \n\ @@ -857,12 +861,16 @@ static int gen_trace(struct bpf_object *obj, const char *obj_name, const char *h codegen("\ \n\ + #ifdef __cplusplus \n\ + skel->%1$s = (struct %4$s::%4$s__%1$s *)skel_finalize_map_data(&skel->maps.%1$s.initial_value,\n\ + #else \n\ skel->%1$s = skel_finalize_map_data(&skel->maps.%1$s.initial_value, \n\ + #endif \n\ %2$zd, %3$s, skel->maps.%1$s.map_fd);\n\ if (!skel->%1$s) \n\ return -ENOMEM; \n\ ", - ident, bpf_map_mmap_sz(map), mmap_flags); + ident, bpf_map_mmap_sz(map), mmap_flags, obj_name); } codegen("\ \n\ -- 2.39.1 ^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH v4 bpf-next] bpftool: Make skeleton C++ compatible with explicit casts 2026-01-05 7:12 ` [PATCH v4 " WanLi Niu @ 2026-01-05 10:39 ` Quentin Monnet 2026-01-05 11:50 ` Jose E. Marchesi 2026-01-06 2:31 ` [PATCH v5 " WanLi Niu 2 siblings, 0 replies; 14+ messages in thread From: Quentin Monnet @ 2026-01-05 10:39 UTC (permalink / raw) To: WanLi Niu Cc: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko, Martin KaFai Lau, Eduard Zingerman, Song Liu, Yonghong Song, John Fastabend, KP Singh, Stanislav Fomichev, Hao Luo, Jiri Olsa, Menglong Dong, bpf, linux-kernel, WanLi Niu, Menglong Dong On 05/01/2026 07:12, WanLi Niu wrote: > From: WanLi Niu <niuwl1@chinatelecom.cn> > > Fix C++ compilation errors in generated skeleton by adding explicit > pointer casts and using integer subtraction for offset calculation. > > Use struct outer::inner syntax under __cplusplus to access nested skeleton map > structs, ensuring C++ compilation compatibility while preserving C support > > error: invalid conversion from 'void*' to '<obj_name>*' [-fpermissive] > | skel = skel_alloc(sizeof(*skel)); > | ~~~~~~~~~~^~~~~~~~~~~~~~~ > | | > | void* > > error: arithmetic on pointers to void > | skel->ctx.sz = (void *)&skel->links - (void *)skel; > | ~~~~~~~~~~~~~~~~~~~~ ^ ~~~~~~~~~~~~ > > error: assigning to 'struct <obj_name>__<ident> *' from incompatible type 'void *' > | skel-><ident> = skel_prep_map_data((void *)data, 4096, > | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ > | sizeof(data) - 1); > | ~~~~~~~~~~~~~~~~~ > > error: assigning to 'struct <obj_name>__<ident> *' from incompatible type 'void *' > | skel-><ident> = skel_finalize_map_data(&skel->maps.<ident>.initial_value, > | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ > | 4096, PROT_READ | PROT_WRITE, skel->maps.<ident>.map_fd); > | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ > > Minimum reproducer: > > $ cat test.bpf.c > int val; // placed in .bss section > > #include "vmlinux.h" > #include <bpf/bpf_helpers.h> > > SEC("raw_tracepoint/sched_wakeup_new") int handle(void *ctx) { return 0; } > > $ cat test.cpp > #include <cerrno> > > extern "C" { > #include "test.bpf.skel.h" > } > > $ bpftool btf dump file /sys/kernel/btf/vmlinux format c > vmlinux.h > $ clang -g -O2 -target bpf -c test.bpf.c -o test.bpf.o > $ bpftool gen skeleton test.bpf.o -L > test.bpf.skel.h > $ g++ -c test.cpp -I. I tried it and could confirm that the warnings are gone. > Signed-off-by: WanLi Niu <niuwl1@chinatelecom.cn> > Co-developed-by: Menglong Dong <dongml2@chinatelecom.cn> > Signed-off-by: Menglong Dong <dongml2@chinatelecom.cn> Acked-by: Quentin Monnet <qmo@kernel.org> Thank you! ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v4 bpf-next] bpftool: Make skeleton C++ compatible with explicit casts 2026-01-05 7:12 ` [PATCH v4 " WanLi Niu 2026-01-05 10:39 ` Quentin Monnet @ 2026-01-05 11:50 ` Jose E. Marchesi 2026-01-05 12:53 ` WanLi Niu 2026-01-06 2:31 ` [PATCH v5 " WanLi Niu 2 siblings, 1 reply; 14+ messages in thread From: Jose E. Marchesi @ 2026-01-05 11:50 UTC (permalink / raw) To: WanLi Niu Cc: Quentin Monnet, Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko, Martin KaFai Lau, Eduard Zingerman, Song Liu, Yonghong Song, John Fastabend, KP Singh, Stanislav Fomichev, Hao Luo, Jiri Olsa, Menglong Dong, bpf, linux-kernel, WanLi Niu, Menglong Dong FWIW I tested the reproducer with gcc-bpf and got no pointer conversion warnings (not that I was expecting anything different, but just in case): $ bpf-unknown-none-gcc -std=gnu11 -I./tools/include -g -O2 -c text.bpf.c -o test.bpf.o $ bpftool gen skeleton test.bpf.o -L > test.bpf.skel.h $ g++ -c test.cpp -I. > From: WanLi Niu <niuwl1@chinatelecom.cn> > > Fix C++ compilation errors in generated skeleton by adding explicit > pointer casts and using integer subtraction for offset calculation. > > Use struct outer::inner syntax under __cplusplus to access nested skeleton map > structs, ensuring C++ compilation compatibility while preserving C support > > error: invalid conversion from 'void*' to '<obj_name>*' [-fpermissive] > | skel = skel_alloc(sizeof(*skel)); > | ~~~~~~~~~~^~~~~~~~~~~~~~~ > | | > | void* > > error: arithmetic on pointers to void > | skel->ctx.sz = (void *)&skel->links - (void *)skel; > | ~~~~~~~~~~~~~~~~~~~~ ^ ~~~~~~~~~~~~ > > error: assigning to 'struct <obj_name>__<ident> *' from incompatible type 'void *' > | skel-><ident> = skel_prep_map_data((void *)data, 4096, > | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ > | sizeof(data) - 1); > | ~~~~~~~~~~~~~~~~~ > > error: assigning to 'struct <obj_name>__<ident> *' from incompatible type 'void *' > | skel-><ident> = skel_finalize_map_data(&skel->maps.<ident>.initial_value, > | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ > | 4096, PROT_READ | PROT_WRITE, skel->maps.<ident>.map_fd); > | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ > > Minimum reproducer: > > $ cat test.bpf.c > int val; // placed in .bss section > > #include "vmlinux.h" > #include <bpf/bpf_helpers.h> > > SEC("raw_tracepoint/sched_wakeup_new") int handle(void *ctx) { return 0; } > > $ cat test.cpp > #include <cerrno> > > extern "C" { > #include "test.bpf.skel.h" > } > > $ bpftool btf dump file /sys/kernel/btf/vmlinux format c > vmlinux.h > $ clang -g -O2 -target bpf -c test.bpf.c -o test.bpf.o > $ bpftool gen skeleton test.bpf.o -L > test.bpf.skel.h > $ g++ -c test.cpp -I. > > Signed-off-by: WanLi Niu <niuwl1@chinatelecom.cn> > Co-developed-by: Menglong Dong <dongml2@chinatelecom.cn> > Signed-off-by: Menglong Dong <dongml2@chinatelecom.cn> > --- > changelog: > v4: > - Add a minimum reproducer to demonstrate the issue, as suggested by Yonghong Song > > v3: https://lore.kernel.org/all/20260104021402.2968-1-kiraskyler@163.com/ > - Fix two additional <obj_name>__<ident> type mismatches as suggested by Yonghong Song > > v2: https://lore.kernel.org/all/20251231102929.3843-1-kiraskyler@163.com/ > - Use generic (struct %1$s *) instead of project-specific (struct trace_bpf *) > > v1: https://lore.kernel.org/all/20251231092541.3352-1-kiraskyler@163.com/ > --- > tools/bpf/bpftool/gen.c | 16 ++++++++++++---- > 1 file changed, 12 insertions(+), 4 deletions(-) > > diff --git a/tools/bpf/bpftool/gen.c b/tools/bpf/bpftool/gen.c > index 993c7d9484a4..010861b7d0ea 100644 > --- a/tools/bpf/bpftool/gen.c > +++ b/tools/bpf/bpftool/gen.c > @@ -731,10 +731,10 @@ static int gen_trace(struct bpf_object *obj, const char *obj_name, const char *h > { \n\ > struct %1$s *skel; \n\ > \n\ > - skel = skel_alloc(sizeof(*skel)); \n\ > + skel = (struct %1$s *)skel_alloc(sizeof(*skel)); \n\ > if (!skel) \n\ > goto cleanup; \n\ > - skel->ctx.sz = (void *)&skel->links - (void *)skel; \n\ > + skel->ctx.sz = (__u64)&skel->links - (__u64)skel; \n\ > ", > obj_name, opts.data_sz); > bpf_object__for_each_map(map, obj) { > @@ -755,13 +755,17 @@ static int gen_trace(struct bpf_object *obj, const char *obj_name, const char *h > \n\ > \"; \n\ > \n\ > + #ifdef __cplusplus \n\ > + skel->%1$s = (struct %3$s::%3$s__%1$s *)skel_prep_map_data((void *)data, %2$zd,\n\ > + #else \n\ > skel->%1$s = skel_prep_map_data((void *)data, %2$zd,\n\ > + #endif \n\ > sizeof(data) - 1);\n\ > if (!skel->%1$s) \n\ > goto cleanup; \n\ > skel->maps.%1$s.initial_value = (__u64) (long) skel->%1$s;\n\ > } \n\ > - ", ident, bpf_map_mmap_sz(map)); > + ", ident, bpf_map_mmap_sz(map), obj_name); > } > codegen("\ > \n\ > @@ -857,12 +861,16 @@ static int gen_trace(struct bpf_object *obj, const char *obj_name, const char *h > > codegen("\ > \n\ > + #ifdef __cplusplus \n\ > + skel->%1$s = (struct %4$s::%4$s__%1$s *)skel_finalize_map_data(&skel->maps.%1$s.initial_value,\n\ > + #else \n\ > skel->%1$s = skel_finalize_map_data(&skel->maps.%1$s.initial_value, \n\ > + #endif \n\ > %2$zd, %3$s, skel->maps.%1$s.map_fd);\n\ > if (!skel->%1$s) \n\ > return -ENOMEM; \n\ > ", > - ident, bpf_map_mmap_sz(map), mmap_flags); > + ident, bpf_map_mmap_sz(map), mmap_flags, obj_name); > } > codegen("\ > \n\ ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v4 bpf-next] bpftool: Make skeleton C++ compatible with explicit casts 2026-01-05 11:50 ` Jose E. Marchesi @ 2026-01-05 12:53 ` WanLi Niu 2026-01-05 16:05 ` Jose E. Marchesi 0 siblings, 1 reply; 14+ messages in thread From: WanLi Niu @ 2026-01-05 12:53 UTC (permalink / raw) To: Jose E. Marchesi Cc: Quentin Monnet, Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko, Martin KaFai Lau, Eduard Zingerman, Song Liu, Yonghong Song, John Fastabend, KP Singh, Stanislav Fomichev, Hao Luo, Jiri Olsa, Menglong Dong, bpf, linux-kernel, WanLi Niu, Menglong Dong > FWIW I tested the reproducer with gcc-bpf and got no pointer conversion > warnings (not that I was expecting anything different, but just in > case): > > $ bpf-unknown-none-gcc -std=gnu11 -I./tools/include -g -O2 -c text.bpf.c -o test.bpf.o > $ bpftool gen skeleton test.bpf.o -L > test.bpf.skel.h > $ g++ -c test.cpp -I. Thanks for testing. The issue only occurs when bpftool gen skeleton is used in use_loader mode (bpftool gen skeleton -L|--use-loader). Could you double-check if -L was included? I can reproduce the error reliably with it — here’s the full output: $ rpm -qf `which bpf-unknown-none-gcc` gcc-bpf-unknown-none-15.2.1-1.fc42.x86_64 $ bpf-unknown-none-gcc -std=gnu11 -I/usr/include -g -O2 -c test.bpf.c -o test.bpf.o $ bpftool gen skeleton test.bpf.o -L > test.bpf.skel.h libbpf: elf: skipping section(2) .data (size 0) libbpf: elf: skipping unrecognized data section(7) .comment libbpf: prog 'handle': missing .BTF.ext line info for the main program, skipping all of .BTF.ext line info. $ g++ -c test.cpp -I. In file included from test.cpp:4: test.bpf.skel.h: In function ‘test_bpf* test_bpf__open()’: test.bpf.skel.h:65:26: error: invalid conversion from ‘void*’ to ‘test_bpf*’ [-fpermissive] 65 | skel = skel_alloc(sizeof(*skel)); | ~~~~~~~~~~^~~~~~~~~~~~~~~ | | | void* test.bpf.skel.h:68:55: error: invalid use of ‘void’ 68 | skel->ctx.sz = (void *)&skel->links - (void *)skel; | ^~~~ test.bpf.skel.h:73:47: error: invalid conversion from ‘void*’ to ‘test_bpf::test_bpf__bss*’ [-fpermissive] 73 | skel->bss = skel_prep_map_data((void *)data, 4096, | ~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~ | | | void* 74 | sizeof(data) - 1); | ~~~~~~~~~~~~~~~~~ test.bpf.skel.h: In function ‘int test_bpf__load(test_bpf*)’: test.bpf.skel.h:196:43: error: invalid conversion from ‘void*’ to ‘test_bpf::test_bpf__bss*’ [-fpermissive] 196 | skel->bss = skel_finalize_map_data(&skel->maps.bss.initial_value, | ~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | | | void* 197 | 4096, PROT_READ | PROT_WRITE, skel->maps.bss.map_fd); | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ $ cat test.bpf.skel.h /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ /* THIS FILE IS AUTOGENERATED BY BPFTOOL! */ #ifndef __TEST_BPF_SKEL_H__ #define __TEST_BPF_SKEL_H__ #include <bpf/skel_internal.h> struct test_bpf { struct bpf_loader_ctx ctx; struct { struct bpf_map_desc bss; } maps; struct { struct bpf_prog_desc handle; } progs; struct { int handle_fd; } links; struct test_bpf__bss { int val; } *bss; }; static inline int test_bpf__handle__attach(struct test_bpf *skel) { int prog_fd = skel->progs.handle.prog_fd; int fd = skel_raw_tracepoint_open("sched_wakeup_new", prog_fd); if (fd > 0) skel->links.handle_fd = fd; return fd; } static inline int test_bpf__attach(struct test_bpf *skel) { int ret = 0; ret = ret < 0 ? ret : test_bpf__handle__attach(skel); return ret < 0 ? ret : 0; } static inline void test_bpf__detach(struct test_bpf *skel) { skel_closenz(skel->links.handle_fd); } static void test_bpf__destroy(struct test_bpf *skel) { if (!skel) return; test_bpf__detach(skel); skel_closenz(skel->progs.handle.prog_fd); skel_free_map_data(skel->bss, skel->maps.bss.initial_value, 4096); skel_closenz(skel->maps.bss.map_fd); skel_free(skel); } static inline struct test_bpf * test_bpf__open(void) { struct test_bpf *skel; skel = skel_alloc(sizeof(*skel)); if (!skel) goto cleanup; skel->ctx.sz = (void *)&skel->links - (void *)skel; { static const char data[] __attribute__((__aligned__(8))) = "\ \0\0\0\0"; skel->bss = skel_prep_map_data((void *)data, 4096, sizeof(data) - 1); if (!skel->bss) goto cleanup; skel->maps.bss.initial_value = (__u64) (long) skel->bss; } return skel; cleanup: test_bpf__destroy(skel); return NULL; } static inline int test_bpf__load(struct test_bpf *skel) { struct bpf_load_and_run_opts opts = {}; int err; static const char opts_data[] __attribute__((__aligned__(8))) = "\ \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x9f\xeb\x01\0\ \x18\0\0\0\0\0\0\0\x64\0\0\0\x64\0\0\0\x41\0\0\0\0\0\0\0\x01\0\0\x0d\x02\0\0\0\ \x18\0\0\0\x03\0\0\0\x08\0\0\0\0\0\0\x01\x04\0\0\0\x20\0\0\x01\0\0\0\0\0\0\0\ \x02\0\0\0\0\x13\0\0\0\0\0\0\x0e\x02\0\0\0\x01\0\0\0\x0c\0\0\0\x01\0\0\x0c\x01\ \0\0\0\x3c\0\0\0\x01\0\0\x0f\x04\0\0\0\x04\0\0\0\0\0\0\0\x04\0\0\0\0\x68\x61\ \x6e\x64\x6c\x65\0\x69\x6e\x74\0\x68\x61\x6e\x64\x6c\x65\0\x76\x61\x6c\0\0\x63\ \x74\x78\0\x72\x61\x77\x5f\x74\x72\x61\x63\x65\x70\x6f\x69\x6e\x74\x2f\x73\x63\ \x68\x65\x64\x5f\x77\x61\x6b\x65\x75\x70\x5f\x6e\x65\x77\0\x2e\x62\x73\x73\0\0\ \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\xbd\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x02\0\0\ \0\x04\0\0\0\x04\0\0\0\x01\0\0\0\0\x04\0\0\0\0\0\0\0\0\0\0\x74\x65\x73\x74\x5f\ \x62\x70\x66\x2e\x62\x73\x73\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x06\0\0\0\0\0\0\0\ \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\xb7\0\0\0\0\0\0\0\x95\0\0\0\ \0\0\0\0\0\0\0\0\x05\0\0\0\x11\0\0\0\x02\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x68\x61\x6e\x64\x6c\x65\0\0\0\ \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x08\0\0\0\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\ \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ \0\0\0\x10\0\0\0\0\0\0\0"; static const char opts_insn[] __attribute__((__aligned__(8))) = "\ \xbf\x16\0\0\0\0\0\0\xbf\xa1\0\0\0\0\0\0\x07\x01\0\0\x78\xff\xff\xff\xb7\x02\0\ \0\x88\0\0\0\xb7\x03\0\0\0\0\0\0\x85\0\0\0\x71\0\0\0\x05\0\x11\0\0\0\0\0\x61\ \xa1\x78\xff\0\0\0\0\xd5\x01\x01\0\0\0\0\0\x85\0\0\0\xa8\0\0\0\x61\xa1\x7c\xff\ \0\0\0\0\xd5\x01\x01\0\0\0\0\0\x85\0\0\0\xa8\0\0\0\x61\xa1\x80\xff\0\0\0\0\xd5\ \x01\x01\0\0\0\0\0\x85\0\0\0\xa8\0\0\0\x18\x60\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x61\ \x01\0\0\0\0\0\0\xd5\x01\x02\0\0\0\0\0\xbf\x19\0\0\0\0\0\0\x85\0\0\0\xa8\0\0\0\ \xbf\x70\0\0\0\0\0\0\x95\0\0\0\0\0\0\0\x61\x60\x08\0\0\0\0\0\x18\x61\0\0\0\0\0\ \0\0\0\0\0\xd8\x05\0\0\x63\x01\0\0\0\0\0\0\x61\x60\x0c\0\0\0\0\0\x18\x61\0\0\0\ \0\0\0\0\0\0\0\xd4\x05\0\0\x63\x01\0\0\0\0\0\0\x79\x60\x10\0\0\0\0\0\x18\x61\0\ \0\0\0\0\0\0\0\0\0\xc8\x05\0\0\x7b\x01\0\0\0\0\0\0\x18\x60\0\0\0\0\0\0\0\0\0\0\ \0\x05\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\xc0\x05\0\0\x7b\x01\0\0\0\0\0\0\xb7\x01\ \0\0\x12\0\0\0\x18\x62\0\0\0\0\0\0\0\0\0\0\xc0\x05\0\0\xb7\x03\0\0\x1c\0\0\0\ \x85\0\0\0\xa6\0\0\0\xbf\x07\0\0\0\0\0\0\xc5\x07\xd7\xff\0\0\0\0\x63\x7a\x78\ \xff\0\0\0\0\x61\xa0\x78\xff\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x10\x06\0\0\ \x63\x01\0\0\0\0\0\0\x61\x60\x1c\0\0\0\0\0\x15\0\x03\0\0\0\0\0\x18\x61\0\0\0\0\ \0\0\0\0\0\0\xec\x05\0\0\x63\x01\0\0\0\0\0\0\xb7\x01\0\0\0\0\0\0\x18\x62\0\0\0\ \0\0\0\0\0\0\0\xe0\x05\0\0\xb7\x03\0\0\x48\0\0\0\x85\0\0\0\xa6\0\0\0\xbf\x07\0\ \0\0\0\0\0\xc5\x07\xc6\xff\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x63\x71\ \0\0\0\0\0\0\x79\x63\x20\0\0\0\0\0\x15\x03\x08\0\0\0\0\0\x18\x61\0\0\0\0\0\0\0\ \0\0\0\x28\x06\0\0\xb7\x02\0\0\x04\0\0\0\x61\x60\x04\0\0\0\0\0\x45\0\x02\0\x01\ \0\0\0\x85\0\0\0\x94\0\0\0\x05\0\x01\0\0\0\0\0\x85\0\0\0\x71\0\0\0\x18\x62\0\0\ \0\0\0\0\0\0\0\0\0\0\0\0\x61\x20\0\0\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x38\ \x06\0\0\x63\x01\0\0\0\0\0\0\x18\x60\0\0\0\0\0\0\0\0\0\0\x30\x06\0\0\x18\x61\0\ \0\0\0\0\0\0\0\0\0\x40\x06\0\0\x7b\x01\0\0\0\0\0\0\x18\x60\0\0\0\0\0\0\0\0\0\0\ \x28\x06\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x48\x06\0\0\x7b\x01\0\0\0\0\0\0\xb7\ \x01\0\0\x02\0\0\0\x18\x62\0\0\0\0\0\0\0\0\0\0\x38\x06\0\0\xb7\x03\0\0\x20\0\0\ \0\x85\0\0\0\xa6\0\0\0\xbf\x07\0\0\0\0\0\0\xc5\x07\xa2\xff\0\0\0\0\x18\x60\0\0\ \0\0\0\0\0\0\0\0\x58\x06\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x88\x06\0\0\x7b\x01\0\ \0\0\0\0\0\x18\x60\0\0\0\0\0\0\0\0\0\0\x60\x06\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\ \x80\x06\0\0\x7b\x01\0\0\0\0\0\0\x18\x60\0\0\0\0\0\0\0\0\0\0\x70\x06\0\0\x18\ \x61\0\0\0\0\0\0\0\0\0\0\xc8\x06\0\0\x7b\x01\0\0\0\0\0\0\x18\x60\0\0\0\0\0\0\0\ \0\0\0\x78\x06\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\xd8\x06\0\0\x7b\x01\0\0\0\0\0\0\ \x18\x60\0\0\0\0\0\0\0\0\0\0\x78\x06\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\xf8\x06\0\ \0\x7b\x01\0\0\0\0\0\0\x18\x60\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x18\x61\0\0\0\0\0\0\ \0\0\0\0\xf0\x06\0\0\x7b\x01\0\0\0\0\0\0\x61\x60\x08\0\0\0\0\0\x18\x61\0\0\0\0\ \0\0\0\0\0\0\x90\x06\0\0\x63\x01\0\0\0\0\0\0\x61\x60\x0c\0\0\0\0\0\x18\x61\0\0\ \0\0\0\0\0\0\0\0\x94\x06\0\0\x63\x01\0\0\0\0\0\0\x79\x60\x10\0\0\0\0\0\x18\x61\ \0\0\0\0\0\0\0\0\0\0\x98\x06\0\0\x7b\x01\0\0\0\0\0\0\x61\xa0\x78\xff\0\0\0\0\ \x18\x61\0\0\0\0\0\0\0\0\0\0\xc0\x06\0\0\x63\x01\0\0\0\0\0\0\xb7\x01\0\0\x05\0\ \0\0\x18\x62\0\0\0\0\0\0\0\0\0\0\x78\x06\0\0\xb7\x03\0\0\x8c\0\0\0\x85\0\0\0\ \xa6\0\0\0\xbf\x07\0\0\0\0\0\0\xc5\x07\x6d\xff\0\0\0\0\x63\x7a\x80\xff\0\0\0\0\ \x61\xa1\x78\xff\0\0\0\0\xd5\x01\x02\0\0\0\0\0\xbf\x19\0\0\0\0\0\0\x85\0\0\0\ \xa8\0\0\0\x61\xa0\x80\xff\0\0\0\0\x63\x06\x28\0\0\0\0\0\x18\x61\0\0\0\0\0\0\0\ \0\0\0\0\0\0\0\x61\x10\0\0\0\0\0\0\x63\x06\x18\0\0\0\0\0\xb7\0\0\0\0\0\0\0\x95\ \0\0\0\0\0\0\0"; opts.ctx = (struct bpf_loader_ctx *)skel; opts.data_sz = sizeof(opts_data) - 1; opts.data = (void *)opts_data; opts.insns_sz = sizeof(opts_insn) - 1; opts.insns = (void *)opts_insn; err = bpf_load_and_run(&opts); if (err < 0) return err; skel->bss = skel_finalize_map_data(&skel->maps.bss.initial_value, 4096, PROT_READ | PROT_WRITE, skel->maps.bss.map_fd); if (!skel->bss) return -ENOMEM; return 0; } static inline struct test_bpf * test_bpf__open_and_load(void) { struct test_bpf *skel; skel = test_bpf__open(); if (!skel) return NULL; if (test_bpf__load(skel)) { test_bpf__destroy(skel); return NULL; } return skel; } __attribute__((unused)) static void test_bpf__assert(struct test_bpf *s __attribute__((unused))) { #ifdef __cplusplus #define _Static_assert static_assert #endif _Static_assert(sizeof(s->bss->val) == 4, "unexpected size of 'val'"); #ifdef __cplusplus #undef _Static_assert #endif } #endif /* __TEST_BPF_SKEL_H__ */ At 2026-01-05 19:50:25, "Jose E. Marchesi" <jose.marchesi@oracle.com> wrote: > >FWIW I tested the reproducer with gcc-bpf and got no pointer conversion >warnings (not that I was expecting anything different, but just in >case): > > $ bpf-unknown-none-gcc -std=gnu11 -I./tools/include -g -O2 -c text.bpf.c -o test.bpf.o > $ bpftool gen skeleton test.bpf.o -L > test.bpf.skel.h > $ g++ -c test.cpp -I. > >> From: WanLi Niu <niuwl1@chinatelecom.cn> >> >> Fix C++ compilation errors in generated skeleton by adding explicit >> pointer casts and using integer subtraction for offset calculation. >> >> Use struct outer::inner syntax under __cplusplus to access nested skeleton map >> structs, ensuring C++ compilation compatibility while preserving C support >> >> error: invalid conversion from 'void*' to '<obj_name>*' [-fpermissive] >> | skel = skel_alloc(sizeof(*skel)); >> | ~~~~~~~~~~^~~~~~~~~~~~~~~ >> | | >> | void* >> >> error: arithmetic on pointers to void >> | skel->ctx.sz = (void *)&skel->links - (void *)skel; >> | ~~~~~~~~~~~~~~~~~~~~ ^ ~~~~~~~~~~~~ >> >> error: assigning to 'struct <obj_name>__<ident> *' from incompatible type 'void *' >> | skel-><ident> = skel_prep_map_data((void *)data, 4096, >> | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ >> | sizeof(data) - 1); >> | ~~~~~~~~~~~~~~~~~ >> >> error: assigning to 'struct <obj_name>__<ident> *' from incompatible type 'void *' >> | skel-><ident> = skel_finalize_map_data(&skel->maps.<ident>.initial_value, >> | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ >> | 4096, PROT_READ | PROT_WRITE, skel->maps.<ident>.map_fd); >> | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ >> >> Minimum reproducer: >> >> $ cat test.bpf.c >> int val; // placed in .bss section >> >> #include "vmlinux.h" >> #include <bpf/bpf_helpers.h> >> >> SEC("raw_tracepoint/sched_wakeup_new") int handle(void *ctx) { return 0; } >> >> $ cat test.cpp >> #include <cerrno> >> >> extern "C" { >> #include "test.bpf.skel.h" >> } >> >> $ bpftool btf dump file /sys/kernel/btf/vmlinux format c > vmlinux.h >> $ clang -g -O2 -target bpf -c test.bpf.c -o test.bpf.o >> $ bpftool gen skeleton test.bpf.o -L > test.bpf.skel.h >> $ g++ -c test.cpp -I. >> >> Signed-off-by: WanLi Niu <niuwl1@chinatelecom.cn> >> Co-developed-by: Menglong Dong <dongml2@chinatelecom.cn> >> Signed-off-by: Menglong Dong <dongml2@chinatelecom.cn> >> --- >> changelog: >> v4: >> - Add a minimum reproducer to demonstrate the issue, as suggested by Yonghong Song >> >> v3: https://lore.kernel.org/all/20260104021402.2968-1-kiraskyler@163.com/ >> - Fix two additional <obj_name>__<ident> type mismatches as suggested by Yonghong Song >> >> v2: https://lore.kernel.org/all/20251231102929.3843-1-kiraskyler@163.com/ >> - Use generic (struct %1$s *) instead of project-specific (struct trace_bpf *) >> >> v1: https://lore.kernel.org/all/20251231092541.3352-1-kiraskyler@163.com/ >> --- >> tools/bpf/bpftool/gen.c | 16 ++++++++++++---- >> 1 file changed, 12 insertions(+), 4 deletions(-) >> >> diff --git a/tools/bpf/bpftool/gen.c b/tools/bpf/bpftool/gen.c >> index 993c7d9484a4..010861b7d0ea 100644 >> --- a/tools/bpf/bpftool/gen.c >> +++ b/tools/bpf/bpftool/gen.c >> @@ -731,10 +731,10 @@ static int gen_trace(struct bpf_object *obj, const char *obj_name, const char *h >> { \n\ >> struct %1$s *skel; \n\ >> \n\ >> - skel = skel_alloc(sizeof(*skel)); \n\ >> + skel = (struct %1$s *)skel_alloc(sizeof(*skel)); \n\ >> if (!skel) \n\ >> goto cleanup; \n\ >> - skel->ctx.sz = (void *)&skel->links - (void *)skel; \n\ >> + skel->ctx.sz = (__u64)&skel->links - (__u64)skel; \n\ >> ", >> obj_name, opts.data_sz); >> bpf_object__for_each_map(map, obj) { >> @@ -755,13 +755,17 @@ static int gen_trace(struct bpf_object *obj, const char *obj_name, const char *h >> \n\ >> \"; \n\ >> \n\ >> + #ifdef __cplusplus \n\ >> + skel->%1$s = (struct %3$s::%3$s__%1$s *)skel_prep_map_data((void *)data, %2$zd,\n\ >> + #else \n\ >> skel->%1$s = skel_prep_map_data((void *)data, %2$zd,\n\ >> + #endif \n\ >> sizeof(data) - 1);\n\ >> if (!skel->%1$s) \n\ >> goto cleanup; \n\ >> skel->maps.%1$s.initial_value = (__u64) (long) skel->%1$s;\n\ >> } \n\ >> - ", ident, bpf_map_mmap_sz(map)); >> + ", ident, bpf_map_mmap_sz(map), obj_name); >> } >> codegen("\ >> \n\ >> @@ -857,12 +861,16 @@ static int gen_trace(struct bpf_object *obj, const char *obj_name, const char *h >> >> codegen("\ >> \n\ >> + #ifdef __cplusplus \n\ >> + skel->%1$s = (struct %4$s::%4$s__%1$s *)skel_finalize_map_data(&skel->maps.%1$s.initial_value,\n\ >> + #else \n\ >> skel->%1$s = skel_finalize_map_data(&skel->maps.%1$s.initial_value, \n\ >> + #endif \n\ >> %2$zd, %3$s, skel->maps.%1$s.map_fd);\n\ >> if (!skel->%1$s) \n\ >> return -ENOMEM; \n\ >> ", >> - ident, bpf_map_mmap_sz(map), mmap_flags); >> + ident, bpf_map_mmap_sz(map), mmap_flags, obj_name); >> } >> codegen("\ >> \n\ ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v4 bpf-next] bpftool: Make skeleton C++ compatible with explicit casts 2026-01-05 12:53 ` WanLi Niu @ 2026-01-05 16:05 ` Jose E. Marchesi 0 siblings, 0 replies; 14+ messages in thread From: Jose E. Marchesi @ 2026-01-05 16:05 UTC (permalink / raw) To: WanLi Niu Cc: Quentin Monnet, Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko, Martin KaFai Lau, Eduard Zingerman, Song Liu, Yonghong Song, John Fastabend, KP Singh, Stanislav Fomichev, Hao Luo, Jiri Olsa, Menglong Dong, bpf, linux-kernel, WanLi Niu, Menglong Dong >> FWIW I tested the reproducer with gcc-bpf and got no pointer conversion >> warnings (not that I was expecting anything different, but just in >> case): >> >> $ bpf-unknown-none-gcc -std=gnu11 -I./tools/include -g -O2 -c text.bpf.c -o test.bpf.o >> $ bpftool gen skeleton test.bpf.o -L > test.bpf.skel.h >> $ g++ -c test.cpp -I. > > Thanks for testing. > > The issue only occurs when bpftool gen skeleton is used in use_loader > mode (bpftool gen skeleton -L|--use-loader). > > Could you double-check if -L was included? I can reproduce the error > reliably with it — here’s the full output: I meant to say that I tested the reproducer _with your patch applied_. It indeed cures the issue :) Sorry it wasn't clear. > > $ rpm -qf `which bpf-unknown-none-gcc` > gcc-bpf-unknown-none-15.2.1-1.fc42.x86_64 > $ bpf-unknown-none-gcc -std=gnu11 -I/usr/include -g -O2 -c test.bpf.c -o test.bpf.o > $ bpftool gen skeleton test.bpf.o -L > test.bpf.skel.h > libbpf: elf: skipping section(2) .data (size 0) > libbpf: elf: skipping unrecognized data section(7) .comment > libbpf: prog 'handle': missing .BTF.ext line info for the main program, skipping all of .BTF.ext line info. > $ g++ -c test.cpp -I. > In file included from test.cpp:4: > test.bpf.skel.h: In function ‘test_bpf* test_bpf__open()’: > test.bpf.skel.h:65:26: error: invalid conversion from ‘void*’ to ‘test_bpf*’ [-fpermissive] > 65 | skel = skel_alloc(sizeof(*skel)); > | ~~~~~~~~~~^~~~~~~~~~~~~~~ > | | > | void* > test.bpf.skel.h:68:55: error: invalid use of ‘void’ > 68 | skel->ctx.sz = (void *)&skel->links - (void *)skel; > | ^~~~ > test.bpf.skel.h:73:47: error: invalid conversion from ‘void*’ to ‘test_bpf::test_bpf__bss*’ [-fpermissive] > 73 | skel->bss = skel_prep_map_data((void *)data, 4096, > | ~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~ > | | > | void* > 74 | sizeof(data) - 1); > | ~~~~~~~~~~~~~~~~~ > test.bpf.skel.h: In function ‘int test_bpf__load(test_bpf*)’: > test.bpf.skel.h:196:43: error: invalid conversion from ‘void*’ to ‘test_bpf::test_bpf__bss*’ [-fpermissive] > 196 | skel->bss = skel_finalize_map_data(&skel->maps.bss.initial_value, > | ~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ > | | > | void* > 197 | 4096, PROT_READ | PROT_WRITE, skel->maps.bss.map_fd); > | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ > $ cat test.bpf.skel.h > /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ > /* THIS FILE IS AUTOGENERATED BY BPFTOOL! */ > #ifndef __TEST_BPF_SKEL_H__ > #define __TEST_BPF_SKEL_H__ > > #include <bpf/skel_internal.h> > > struct test_bpf { > struct bpf_loader_ctx ctx; > struct { > struct bpf_map_desc bss; > } maps; > struct { > struct bpf_prog_desc handle; > } progs; > struct { > int handle_fd; > } links; > struct test_bpf__bss { > int val; > } *bss; > }; > > static inline int > test_bpf__handle__attach(struct test_bpf *skel) > { > int prog_fd = skel->progs.handle.prog_fd; > int fd = skel_raw_tracepoint_open("sched_wakeup_new", prog_fd); > > if (fd > 0) > skel->links.handle_fd = fd; > return fd; > } > > static inline int > test_bpf__attach(struct test_bpf *skel) > { > int ret = 0; > > ret = ret < 0 ? ret : test_bpf__handle__attach(skel); > return ret < 0 ? ret : 0; > } > > static inline void > test_bpf__detach(struct test_bpf *skel) > { > skel_closenz(skel->links.handle_fd); > } > static void > test_bpf__destroy(struct test_bpf *skel) > { > if (!skel) > return; > test_bpf__detach(skel); > skel_closenz(skel->progs.handle.prog_fd); > skel_free_map_data(skel->bss, skel->maps.bss.initial_value, 4096); > skel_closenz(skel->maps.bss.map_fd); > skel_free(skel); > } > static inline struct test_bpf * > test_bpf__open(void) > { > struct test_bpf *skel; > > skel = skel_alloc(sizeof(*skel)); > if (!skel) > goto cleanup; > skel->ctx.sz = (void *)&skel->links - (void *)skel; > { > static const char data[] __attribute__((__aligned__(8))) = "\ > \0\0\0\0"; > > skel->bss = skel_prep_map_data((void *)data, 4096, > sizeof(data) - 1); > if (!skel->bss) > goto cleanup; > skel->maps.bss.initial_value = (__u64) (long) skel->bss; > } > return skel; > cleanup: > test_bpf__destroy(skel); > return NULL; > } > > static inline int > test_bpf__load(struct test_bpf *skel) > { > struct bpf_load_and_run_opts opts = {}; > int err; > static const char opts_data[] __attribute__((__aligned__(8))) = "\ > \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ > \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ > \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ > \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ > \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ > \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ > \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ > \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ > \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ > \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ > \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ > \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ > \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ > \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ > \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ > \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ > \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ > \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ > \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ > \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ > \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ > \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ > \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ > \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ > \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ > \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ > \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ > \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ > \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ > \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ > \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ > \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ > \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x9f\xeb\x01\0\ > \x18\0\0\0\0\0\0\0\x64\0\0\0\x64\0\0\0\x41\0\0\0\0\0\0\0\x01\0\0\x0d\x02\0\0\0\ > \x18\0\0\0\x03\0\0\0\x08\0\0\0\0\0\0\x01\x04\0\0\0\x20\0\0\x01\0\0\0\0\0\0\0\ > \x02\0\0\0\0\x13\0\0\0\0\0\0\x0e\x02\0\0\0\x01\0\0\0\x0c\0\0\0\x01\0\0\x0c\x01\ > \0\0\0\x3c\0\0\0\x01\0\0\x0f\x04\0\0\0\x04\0\0\0\0\0\0\0\x04\0\0\0\0\x68\x61\ > \x6e\x64\x6c\x65\0\x69\x6e\x74\0\x68\x61\x6e\x64\x6c\x65\0\x76\x61\x6c\0\0\x63\ > \x74\x78\0\x72\x61\x77\x5f\x74\x72\x61\x63\x65\x70\x6f\x69\x6e\x74\x2f\x73\x63\ > \x68\x65\x64\x5f\x77\x61\x6b\x65\x75\x70\x5f\x6e\x65\x77\0\x2e\x62\x73\x73\0\0\ > \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\xbd\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x02\0\0\ > \0\x04\0\0\0\x04\0\0\0\x01\0\0\0\0\x04\0\0\0\0\0\0\0\0\0\0\x74\x65\x73\x74\x5f\ > \x62\x70\x66\x2e\x62\x73\x73\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x06\0\0\0\0\0\0\0\ > \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ > \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\xb7\0\0\0\0\0\0\0\x95\0\0\0\ > \0\0\0\0\0\0\0\0\x05\0\0\0\x11\0\0\0\x02\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ > \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x68\x61\x6e\x64\x6c\x65\0\0\0\ > \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x08\0\0\0\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\ > \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\ > \0\0\0\x10\0\0\0\0\0\0\0"; > static const char opts_insn[] __attribute__((__aligned__(8))) = "\ > \xbf\x16\0\0\0\0\0\0\xbf\xa1\0\0\0\0\0\0\x07\x01\0\0\x78\xff\xff\xff\xb7\x02\0\ > \0\x88\0\0\0\xb7\x03\0\0\0\0\0\0\x85\0\0\0\x71\0\0\0\x05\0\x11\0\0\0\0\0\x61\ > \xa1\x78\xff\0\0\0\0\xd5\x01\x01\0\0\0\0\0\x85\0\0\0\xa8\0\0\0\x61\xa1\x7c\xff\ > \0\0\0\0\xd5\x01\x01\0\0\0\0\0\x85\0\0\0\xa8\0\0\0\x61\xa1\x80\xff\0\0\0\0\xd5\ > \x01\x01\0\0\0\0\0\x85\0\0\0\xa8\0\0\0\x18\x60\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x61\ > \x01\0\0\0\0\0\0\xd5\x01\x02\0\0\0\0\0\xbf\x19\0\0\0\0\0\0\x85\0\0\0\xa8\0\0\0\ > \xbf\x70\0\0\0\0\0\0\x95\0\0\0\0\0\0\0\x61\x60\x08\0\0\0\0\0\x18\x61\0\0\0\0\0\ > \0\0\0\0\0\xd8\x05\0\0\x63\x01\0\0\0\0\0\0\x61\x60\x0c\0\0\0\0\0\x18\x61\0\0\0\ > \0\0\0\0\0\0\0\xd4\x05\0\0\x63\x01\0\0\0\0\0\0\x79\x60\x10\0\0\0\0\0\x18\x61\0\ > \0\0\0\0\0\0\0\0\0\xc8\x05\0\0\x7b\x01\0\0\0\0\0\0\x18\x60\0\0\0\0\0\0\0\0\0\0\ > \0\x05\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\xc0\x05\0\0\x7b\x01\0\0\0\0\0\0\xb7\x01\ > \0\0\x12\0\0\0\x18\x62\0\0\0\0\0\0\0\0\0\0\xc0\x05\0\0\xb7\x03\0\0\x1c\0\0\0\ > \x85\0\0\0\xa6\0\0\0\xbf\x07\0\0\0\0\0\0\xc5\x07\xd7\xff\0\0\0\0\x63\x7a\x78\ > \xff\0\0\0\0\x61\xa0\x78\xff\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x10\x06\0\0\ > \x63\x01\0\0\0\0\0\0\x61\x60\x1c\0\0\0\0\0\x15\0\x03\0\0\0\0\0\x18\x61\0\0\0\0\ > \0\0\0\0\0\0\xec\x05\0\0\x63\x01\0\0\0\0\0\0\xb7\x01\0\0\0\0\0\0\x18\x62\0\0\0\ > \0\0\0\0\0\0\0\xe0\x05\0\0\xb7\x03\0\0\x48\0\0\0\x85\0\0\0\xa6\0\0\0\xbf\x07\0\ > \0\0\0\0\0\xc5\x07\xc6\xff\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x63\x71\ > \0\0\0\0\0\0\x79\x63\x20\0\0\0\0\0\x15\x03\x08\0\0\0\0\0\x18\x61\0\0\0\0\0\0\0\ > \0\0\0\x28\x06\0\0\xb7\x02\0\0\x04\0\0\0\x61\x60\x04\0\0\0\0\0\x45\0\x02\0\x01\ > \0\0\0\x85\0\0\0\x94\0\0\0\x05\0\x01\0\0\0\0\0\x85\0\0\0\x71\0\0\0\x18\x62\0\0\ > \0\0\0\0\0\0\0\0\0\0\0\0\x61\x20\0\0\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x38\ > \x06\0\0\x63\x01\0\0\0\0\0\0\x18\x60\0\0\0\0\0\0\0\0\0\0\x30\x06\0\0\x18\x61\0\ > \0\0\0\0\0\0\0\0\0\x40\x06\0\0\x7b\x01\0\0\0\0\0\0\x18\x60\0\0\0\0\0\0\0\0\0\0\ > \x28\x06\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x48\x06\0\0\x7b\x01\0\0\0\0\0\0\xb7\ > \x01\0\0\x02\0\0\0\x18\x62\0\0\0\0\0\0\0\0\0\0\x38\x06\0\0\xb7\x03\0\0\x20\0\0\ > \0\x85\0\0\0\xa6\0\0\0\xbf\x07\0\0\0\0\0\0\xc5\x07\xa2\xff\0\0\0\0\x18\x60\0\0\ > \0\0\0\0\0\0\0\0\x58\x06\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x88\x06\0\0\x7b\x01\0\ > \0\0\0\0\0\x18\x60\0\0\0\0\0\0\0\0\0\0\x60\x06\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\ > \x80\x06\0\0\x7b\x01\0\0\0\0\0\0\x18\x60\0\0\0\0\0\0\0\0\0\0\x70\x06\0\0\x18\ > \x61\0\0\0\0\0\0\0\0\0\0\xc8\x06\0\0\x7b\x01\0\0\0\0\0\0\x18\x60\0\0\0\0\0\0\0\ > \0\0\0\x78\x06\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\xd8\x06\0\0\x7b\x01\0\0\0\0\0\0\ > \x18\x60\0\0\0\0\0\0\0\0\0\0\x78\x06\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\xf8\x06\0\ > \0\x7b\x01\0\0\0\0\0\0\x18\x60\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x18\x61\0\0\0\0\0\0\ > \0\0\0\0\xf0\x06\0\0\x7b\x01\0\0\0\0\0\0\x61\x60\x08\0\0\0\0\0\x18\x61\0\0\0\0\ > \0\0\0\0\0\0\x90\x06\0\0\x63\x01\0\0\0\0\0\0\x61\x60\x0c\0\0\0\0\0\x18\x61\0\0\ > \0\0\0\0\0\0\0\0\x94\x06\0\0\x63\x01\0\0\0\0\0\0\x79\x60\x10\0\0\0\0\0\x18\x61\ > \0\0\0\0\0\0\0\0\0\0\x98\x06\0\0\x7b\x01\0\0\0\0\0\0\x61\xa0\x78\xff\0\0\0\0\ > \x18\x61\0\0\0\0\0\0\0\0\0\0\xc0\x06\0\0\x63\x01\0\0\0\0\0\0\xb7\x01\0\0\x05\0\ > \0\0\x18\x62\0\0\0\0\0\0\0\0\0\0\x78\x06\0\0\xb7\x03\0\0\x8c\0\0\0\x85\0\0\0\ > \xa6\0\0\0\xbf\x07\0\0\0\0\0\0\xc5\x07\x6d\xff\0\0\0\0\x63\x7a\x80\xff\0\0\0\0\ > \x61\xa1\x78\xff\0\0\0\0\xd5\x01\x02\0\0\0\0\0\xbf\x19\0\0\0\0\0\0\x85\0\0\0\ > \xa8\0\0\0\x61\xa0\x80\xff\0\0\0\0\x63\x06\x28\0\0\0\0\0\x18\x61\0\0\0\0\0\0\0\ > \0\0\0\0\0\0\0\x61\x10\0\0\0\0\0\0\x63\x06\x18\0\0\0\0\0\xb7\0\0\0\0\0\0\0\x95\ > \0\0\0\0\0\0\0"; > opts.ctx = (struct bpf_loader_ctx *)skel; > opts.data_sz = sizeof(opts_data) - 1; > opts.data = (void *)opts_data; > opts.insns_sz = sizeof(opts_insn) - 1; > opts.insns = (void *)opts_insn; > > err = bpf_load_and_run(&opts); > if (err < 0) > return err; > skel->bss = skel_finalize_map_data(&skel->maps.bss.initial_value, > 4096, PROT_READ | PROT_WRITE, skel->maps.bss.map_fd); > if (!skel->bss) > return -ENOMEM; > return 0; > } > > static inline struct test_bpf * > test_bpf__open_and_load(void) > { > struct test_bpf *skel; > > skel = test_bpf__open(); > if (!skel) > return NULL; > if (test_bpf__load(skel)) { > test_bpf__destroy(skel); > return NULL; > } > return skel; > } > > __attribute__((unused)) static void > test_bpf__assert(struct test_bpf *s __attribute__((unused))) > { > #ifdef __cplusplus > #define _Static_assert static_assert > #endif > _Static_assert(sizeof(s->bss->val) == 4, "unexpected size of 'val'"); > #ifdef __cplusplus > #undef _Static_assert > #endif > } > > #endif /* __TEST_BPF_SKEL_H__ */ > > At 2026-01-05 19:50:25, "Jose E. Marchesi" <jose.marchesi@oracle.com> wrote: >> >>FWIW I tested the reproducer with gcc-bpf and got no pointer conversion >>warnings (not that I was expecting anything different, but just in >>case): >> >> $ bpf-unknown-none-gcc -std=gnu11 -I./tools/include -g -O2 -c text.bpf.c -o test.bpf.o >> $ bpftool gen skeleton test.bpf.o -L > test.bpf.skel.h >> $ g++ -c test.cpp -I. >> >>> From: WanLi Niu <niuwl1@chinatelecom.cn> >>> >>> Fix C++ compilation errors in generated skeleton by adding explicit >>> pointer casts and using integer subtraction for offset calculation. >>> >>> Use struct outer::inner syntax under __cplusplus to access nested skeleton map >>> structs, ensuring C++ compilation compatibility while preserving C support >>> >>> error: invalid conversion from 'void*' to '<obj_name>*' [-fpermissive] >>> | skel = skel_alloc(sizeof(*skel)); >>> | ~~~~~~~~~~^~~~~~~~~~~~~~~ >>> | | >>> | void* >>> >>> error: arithmetic on pointers to void >>> | skel->ctx.sz = (void *)&skel->links - (void *)skel; >>> | ~~~~~~~~~~~~~~~~~~~~ ^ ~~~~~~~~~~~~ >>> >>> error: assigning to 'struct <obj_name>__<ident> *' from incompatible type 'void *' >>> | skel-><ident> = skel_prep_map_data((void *)data, 4096, >>> | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ >>> | sizeof(data) - 1); >>> | ~~~~~~~~~~~~~~~~~ >>> >>> error: assigning to 'struct <obj_name>__<ident> *' from incompatible type 'void *' >>> | skel-><ident> = skel_finalize_map_data(&skel->maps.<ident>.initial_value, >>> | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ >>> | 4096, PROT_READ | PROT_WRITE, skel->maps.<ident>.map_fd); >>> | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ >>> >>> Minimum reproducer: >>> >>> $ cat test.bpf.c >>> int val; // placed in .bss section >>> >>> #include "vmlinux.h" >>> #include <bpf/bpf_helpers.h> >>> >>> SEC("raw_tracepoint/sched_wakeup_new") int handle(void *ctx) { return 0; } >>> >>> $ cat test.cpp >>> #include <cerrno> >>> >>> extern "C" { >>> #include "test.bpf.skel.h" >>> } >>> >>> $ bpftool btf dump file /sys/kernel/btf/vmlinux format c > vmlinux.h >>> $ clang -g -O2 -target bpf -c test.bpf.c -o test.bpf.o >>> $ bpftool gen skeleton test.bpf.o -L > test.bpf.skel.h >>> $ g++ -c test.cpp -I. >>> >>> Signed-off-by: WanLi Niu <niuwl1@chinatelecom.cn> >>> Co-developed-by: Menglong Dong <dongml2@chinatelecom.cn> >>> Signed-off-by: Menglong Dong <dongml2@chinatelecom.cn> >>> --- >>> changelog: >>> v4: >>> - Add a minimum reproducer to demonstrate the issue, as suggested by Yonghong Song >>> >>> v3: https://lore.kernel.org/all/20260104021402.2968-1-kiraskyler@163.com/ >>> - Fix two additional <obj_name>__<ident> type mismatches as suggested by Yonghong Song >>> >>> v2: https://lore.kernel.org/all/20251231102929.3843-1-kiraskyler@163.com/ >>> - Use generic (struct %1$s *) instead of project-specific (struct trace_bpf *) >>> >>> v1: https://lore.kernel.org/all/20251231092541.3352-1-kiraskyler@163.com/ >>> --- >>> tools/bpf/bpftool/gen.c | 16 ++++++++++++---- >>> 1 file changed, 12 insertions(+), 4 deletions(-) >>> >>> diff --git a/tools/bpf/bpftool/gen.c b/tools/bpf/bpftool/gen.c >>> index 993c7d9484a4..010861b7d0ea 100644 >>> --- a/tools/bpf/bpftool/gen.c >>> +++ b/tools/bpf/bpftool/gen.c >>> @@ -731,10 +731,10 @@ static int gen_trace(struct bpf_object *obj, const char *obj_name, const char *h >>> { \n\ >>> struct %1$s *skel; \n\ >>> \n\ >>> - skel = skel_alloc(sizeof(*skel)); \n\ >>> + skel = (struct %1$s *)skel_alloc(sizeof(*skel)); \n\ >>> if (!skel) \n\ >>> goto cleanup; \n\ >>> - skel->ctx.sz = (void *)&skel->links - (void *)skel; \n\ >>> + skel->ctx.sz = (__u64)&skel->links - (__u64)skel; \n\ >>> ", >>> obj_name, opts.data_sz); >>> bpf_object__for_each_map(map, obj) { >>> @@ -755,13 +755,17 @@ static int gen_trace(struct bpf_object *obj, const char *obj_name, const char *h >>> \n\ >>> \"; \n\ >>> \n\ >>> + #ifdef __cplusplus \n\ >>> + skel->%1$s = (struct %3$s::%3$s__%1$s *)skel_prep_map_data((void *)data, %2$zd,\n\ >>> + #else \n\ >>> skel->%1$s = skel_prep_map_data((void *)data, %2$zd,\n\ >>> + #endif \n\ >>> sizeof(data) - 1);\n\ >>> if (!skel->%1$s) \n\ >>> goto cleanup; \n\ >>> skel->maps.%1$s.initial_value = (__u64) (long) skel->%1$s;\n\ >>> } \n\ >>> - ", ident, bpf_map_mmap_sz(map)); >>> + ", ident, bpf_map_mmap_sz(map), obj_name); >>> } >>> codegen("\ >>> \n\ >>> @@ -857,12 +861,16 @@ static int gen_trace(struct bpf_object *obj, const char *obj_name, const char *h >>> >>> codegen("\ >>> \n\ >>> + #ifdef __cplusplus \n\ >>> + skel->%1$s = (struct %4$s::%4$s__%1$s *)skel_finalize_map_data(&skel->maps.%1$s.initial_value,\n\ >>> + #else \n\ >>> skel->%1$s = skel_finalize_map_data(&skel->maps.%1$s.initial_value, \n\ >>> + #endif \n\ >>> %2$zd, %3$s, skel->maps.%1$s.map_fd);\n\ >>> if (!skel->%1$s) \n\ >>> return -ENOMEM; \n\ >>> ", >>> - ident, bpf_map_mmap_sz(map), mmap_flags); >>> + ident, bpf_map_mmap_sz(map), mmap_flags, obj_name); >>> } >>> codegen("\ >>> \n\ ^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH v5 bpf-next] bpftool: Make skeleton C++ compatible with explicit casts 2026-01-05 7:12 ` [PATCH v4 " WanLi Niu 2026-01-05 10:39 ` Quentin Monnet 2026-01-05 11:50 ` Jose E. Marchesi @ 2026-01-06 2:31 ` WanLi Niu 2026-01-09 19:00 ` patchwork-bot+netdevbpf 2 siblings, 1 reply; 14+ messages in thread From: WanLi Niu @ 2026-01-06 2:31 UTC (permalink / raw) To: Quentin Monnet Cc: Andrii Nakryiko, jose.marchesi, Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko, Martin KaFai Lau, Eduard Zingerman, Song Liu, Yonghong Song, John Fastabend, KP Singh, Stanislav Fomichev, Hao Luo, Jiri Olsa, WanLi Niu, Menglong Dong, bpf, linux-kernel, WanLi Niu, Menglong Dong From: WanLi Niu <niuwl1@chinatelecom.cn> Fix C++ compilation errors in generated skeleton by adding explicit pointer casts and use char * subtraction for offset calculation error: invalid conversion from 'void*' to '<obj_name>*' [-fpermissive] | skel = skel_alloc(sizeof(*skel)); | ~~~~~~~~~~^~~~~~~~~~~~~~~ | | | void* error: arithmetic on pointers to void | skel->ctx.sz = (void *)&skel->links - (void *)skel; | ~~~~~~~~~~~~~~~~~~~~ ^ ~~~~~~~~~~~~ error: assigning to 'struct <obj_name>__<ident> *' from incompatible type 'void *' | skel-><ident> = skel_prep_map_data((void *)data, 4096, | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | sizeof(data) - 1); | ~~~~~~~~~~~~~~~~~ error: assigning to 'struct <obj_name>__<ident> *' from incompatible type 'void *' | skel-><ident> = skel_finalize_map_data(&skel->maps.<ident>.initial_value, | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | 4096, PROT_READ | PROT_WRITE, skel->maps.<ident>.map_fd); | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Minimum reproducer: $ cat test.bpf.c int val; // placed in .bss section #include "vmlinux.h" #include <bpf/bpf_helpers.h> SEC("raw_tracepoint/sched_wakeup_new") int handle(void *ctx) { return 0; } $ cat test.cpp #include <cerrno> extern "C" { #include "test.bpf.skel.h" } $ bpftool btf dump file /sys/kernel/btf/vmlinux format c > vmlinux.h $ clang -g -O2 -target bpf -c test.bpf.c -o test.bpf.o $ bpftool gen skeleton test.bpf.o -L > test.bpf.skel.h $ g++ -c test.cpp -I. Signed-off-by: WanLi Niu <niuwl1@chinatelecom.cn> Co-developed-by: Menglong Dong <dongml2@chinatelecom.cn> Signed-off-by: Menglong Dong <dongml2@chinatelecom.cn> --- changelog: v5: - Use char * arithmetic instead of integer subtraction for offsets as suggested by Andrii Nakryiko - Use __typeof__() without __cplusplus special casing as suggested by Andrii Nakryiko v4: https://lore.kernel.org/all/20260105071231.2501-1-kiraskyler@163.com/ - Add a minimum reproducer to demonstrate the issue, as suggested by Yonghong Song v3: https://lore.kernel.org/all/20260104021402.2968-1-kiraskyler@163.com/ - Fix two additional <obj_name>__<ident> type mismatches as suggested by Yonghong Song v2: https://lore.kernel.org/all/20251231102929.3843-1-kiraskyler@163.com/ - Use generic (struct %1$s *) instead of project-specific (struct trace_bpf *) v1: https://lore.kernel.org/all/20251231092541.3352-1-kiraskyler@163.com/ --- tools/bpf/bpftool/gen.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/bpf/bpftool/gen.c b/tools/bpf/bpftool/gen.c index 993c7d9484a4..2f9e10752e28 100644 --- a/tools/bpf/bpftool/gen.c +++ b/tools/bpf/bpftool/gen.c @@ -731,10 +731,10 @@ static int gen_trace(struct bpf_object *obj, const char *obj_name, const char *h { \n\ struct %1$s *skel; \n\ \n\ - skel = skel_alloc(sizeof(*skel)); \n\ + skel = (struct %1$s *)skel_alloc(sizeof(*skel)); \n\ if (!skel) \n\ goto cleanup; \n\ - skel->ctx.sz = (void *)&skel->links - (void *)skel; \n\ + skel->ctx.sz = (char *)&skel->links - (char *)skel; \n\ ", obj_name, opts.data_sz); bpf_object__for_each_map(map, obj) { @@ -755,7 +755,7 @@ static int gen_trace(struct bpf_object *obj, const char *obj_name, const char *h \n\ \"; \n\ \n\ - skel->%1$s = skel_prep_map_data((void *)data, %2$zd,\n\ + skel->%1$s = (__typeof__(skel->%1$s))skel_prep_map_data((void *)data, %2$zd,\n\ sizeof(data) - 1);\n\ if (!skel->%1$s) \n\ goto cleanup; \n\ @@ -857,7 +857,7 @@ static int gen_trace(struct bpf_object *obj, const char *obj_name, const char *h codegen("\ \n\ - skel->%1$s = skel_finalize_map_data(&skel->maps.%1$s.initial_value, \n\ + skel->%1$s = (__typeof__(skel->%1$s))skel_finalize_map_data(&skel->maps.%1$s.initial_value,\n\ %2$zd, %3$s, skel->maps.%1$s.map_fd);\n\ if (!skel->%1$s) \n\ return -ENOMEM; \n\ -- 2.39.1 ^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH v5 bpf-next] bpftool: Make skeleton C++ compatible with explicit casts 2026-01-06 2:31 ` [PATCH v5 " WanLi Niu @ 2026-01-09 19:00 ` patchwork-bot+netdevbpf 0 siblings, 0 replies; 14+ messages in thread From: patchwork-bot+netdevbpf @ 2026-01-09 19:00 UTC (permalink / raw) To: WanLi Niu Cc: qmo, andrii.nakryiko, jose.marchesi, ast, daniel, andrii, martin.lau, eddyz87, song, yonghong.song, john.fastabend, kpsingh, sdf, haoluo, jolsa, menglong8.dong, bpf, linux-kernel, niuwl1, dongml2 Hello: This patch was applied to bpf/bpf-next.git (master) by Andrii Nakryiko <andrii@kernel.org>: On Tue, 6 Jan 2026 10:31:23 +0800 you wrote: > From: WanLi Niu <niuwl1@chinatelecom.cn> > > Fix C++ compilation errors in generated skeleton by adding explicit > pointer casts and use char * subtraction for offset calculation > > error: invalid conversion from 'void*' to '<obj_name>*' [-fpermissive] > | skel = skel_alloc(sizeof(*skel)); > | ~~~~~~~~~~^~~~~~~~~~~~~~~ > | | > | void* > > [...] Here is the summary with links: - [v5,bpf-next] bpftool: Make skeleton C++ compatible with explicit casts https://git.kernel.org/bpf/bpf-next/c/4effccde0a05 You are awesome, thank you! -- Deet-doot-dot, I am a bot. https://korg.docs.kernel.org/patchwork/pwbot.html ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v3 bpf-next] bpftool: Make skeleton C++ compatible with explicit casts 2026-01-04 2:14 ` [PATCH v3 " WanLi Niu 2026-01-05 5:27 ` Yonghong Song 2026-01-05 7:12 ` [PATCH v4 " WanLi Niu @ 2026-01-06 0:46 ` Andrii Nakryiko 2 siblings, 0 replies; 14+ messages in thread From: Andrii Nakryiko @ 2026-01-06 0:46 UTC (permalink / raw) To: WanLi Niu Cc: Quentin Monnet, Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko, Martin KaFai Lau, Eduard Zingerman, Song Liu, Yonghong Song, John Fastabend, KP Singh, Stanislav Fomichev, Hao Luo, Jiri Olsa, Menglong Dong, bpf, linux-kernel, WanLi Niu, Menglong Dong On Sat, Jan 3, 2026 at 6:15 PM WanLi Niu <kiraskyler@163.com> wrote: > > From: WanLi Niu <niuwl1@chinatelecom.cn> > > Fix C++ compilation errors in generated skeleton by adding explicit > pointer casts and using integer subtraction for offset calculation. > > Use struct outer::inner syntax under __cplusplus to access nested skeleton map > structs, ensuring C++ compilation compatibility while preserving C support > > error: invalid conversion from 'void*' to '<obj_name>*' [-fpermissive] > | skel = skel_alloc(sizeof(*skel)); > | ~~~~~~~~~~^~~~~~~~~~~~~~~ > | | > | void* > > error: arithmetic on pointers to void > | skel->ctx.sz = (void *)&skel->links - (void *)skel; > | ~~~~~~~~~~~~~~~~~~~~ ^ ~~~~~~~~~~~~ > > error: assigning to 'struct <obj_name>__<ident> *' from incompatible type 'void *' > | skel-><ident> = skel_prep_map_data((void *)data, 4096, > | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ > | sizeof(data) - 1); > | ~~~~~~~~~~~~~~~~~ > > error: assigning to 'struct <obj_name>__<ident> *' from incompatible type 'void *' > | skel-><ident> = skel_finalize_map_data(&skel->maps.<ident>.initial_value, > | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ > | 4096, PROT_READ | PROT_WRITE, skel->maps.<ident>.map_fd); > | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ > > Signed-off-by: WanLi Niu <niuwl1@chinatelecom.cn> > Co-developed-by: Menglong Dong <dongml2@chinatelecom.cn> > Signed-off-by: Menglong Dong <dongml2@chinatelecom.cn> > --- > changelog: > v3: > - Fix two additional <obj_name>__<ident> type mismatches as suggested by Yonghong Song > > v2: https://lore.kernel.org/all/20251231102929.3843-1-kiraskyler@163.com/ > - Use generic (struct %1$s *) instead of project-specific (struct trace_bpf *) > > v1: https://lore.kernel.org/all/20251231092541.3352-1-kiraskyler@163.com/ > --- > tools/bpf/bpftool/gen.c | 16 ++++++++++++---- > 1 file changed, 12 insertions(+), 4 deletions(-) > > diff --git a/tools/bpf/bpftool/gen.c b/tools/bpf/bpftool/gen.c > index 993c7d9484a4..010861b7d0ea 100644 > --- a/tools/bpf/bpftool/gen.c > +++ b/tools/bpf/bpftool/gen.c > @@ -731,10 +731,10 @@ static int gen_trace(struct bpf_object *obj, const char *obj_name, const char *h > { \n\ > struct %1$s *skel; \n\ > \n\ > - skel = skel_alloc(sizeof(*skel)); \n\ > + skel = (struct %1$s *)skel_alloc(sizeof(*skel)); \n\ > if (!skel) \n\ > goto cleanup; \n\ > - skel->ctx.sz = (void *)&skel->links - (void *)skel; \n\ > + skel->ctx.sz = (__u64)&skel->links - (__u64)skel; \n\ I'm wondering if this can also trigger some warnings under some circumstances? void * is castable to long or unsigned long, but __u64 can be defined as long long (plus it's a question what happens on 32-bit architectures). Why worry about this if we can cast to `char *` to calculate this size? > ", > obj_name, opts.data_sz); > bpf_object__for_each_map(map, obj) { > @@ -755,13 +755,17 @@ static int gen_trace(struct bpf_object *obj, const char *obj_name, const char *h > \n\ > \"; \n\ > \n\ > + #ifdef __cplusplus \n\ > + skel->%1$s = (struct %3$s::%3$s__%1$s *)skel_prep_map_data((void *)data, %2$zd,\n\ we already use __typeof__() (see gen_st_ops_shadow_init), so let's use that unconditionally without __cplusplus special casing pw-bot: cr > + #else \n\ > skel->%1$s = skel_prep_map_data((void *)data, %2$zd,\n\ > + #endif \n\ > sizeof(data) - 1);\n\ > if (!skel->%1$s) \n\ > goto cleanup; \n\ > skel->maps.%1$s.initial_value = (__u64) (long) skel->%1$s;\n\ > } \n\ > - ", ident, bpf_map_mmap_sz(map)); > + ", ident, bpf_map_mmap_sz(map), obj_name); > } > codegen("\ > \n\ > @@ -857,12 +861,16 @@ static int gen_trace(struct bpf_object *obj, const char *obj_name, const char *h > > codegen("\ > \n\ > + #ifdef __cplusplus \n\ > + skel->%1$s = (struct %4$s::%4$s__%1$s *)skel_finalize_map_data(&skel->maps.%1$s.initial_value,\n\ same as above, __typeof__ ? > + #else \n\ > skel->%1$s = skel_finalize_map_data(&skel->maps.%1$s.initial_value, \n\ > + #endif \n\ > %2$zd, %3$s, skel->maps.%1$s.map_fd);\n\ > if (!skel->%1$s) \n\ > return -ENOMEM; \n\ > ", > - ident, bpf_map_mmap_sz(map), mmap_flags); > + ident, bpf_map_mmap_sz(map), mmap_flags, obj_name); > } > codegen("\ > \n\ > -- > 2.39.1 > ^ permalink raw reply [flat|nested] 14+ messages in thread
end of thread, other threads:[~2026-01-09 19:03 UTC | newest] Thread overview: 14+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2025-12-31 9:25 [PATCH bpf-next] bpftool: Make skeleton C++ compatible with explicit casts WanLi Niu 2025-12-31 9:48 ` bot+bpf-ci 2025-12-31 10:29 ` [PATCH v2 " WanLi Niu 2026-01-02 19:35 ` Yonghong Song 2026-01-04 2:14 ` [PATCH v3 " WanLi Niu 2026-01-05 5:27 ` Yonghong Song 2026-01-05 7:12 ` [PATCH v4 " WanLi Niu 2026-01-05 10:39 ` Quentin Monnet 2026-01-05 11:50 ` Jose E. Marchesi 2026-01-05 12:53 ` WanLi Niu 2026-01-05 16:05 ` Jose E. Marchesi 2026-01-06 2:31 ` [PATCH v5 " WanLi Niu 2026-01-09 19:00 ` patchwork-bot+netdevbpf 2026-01-06 0:46 ` [PATCH v3 " Andrii Nakryiko
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox