* [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
* 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
* [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
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