* Errors compiling BPF programs from Linux selftests/bpf with GCC
@ 2024-12-30 20:08 Ihor Solodrai
2024-12-30 20:24 ` Andrew Pinski
` (2 more replies)
0 siblings, 3 replies; 21+ messages in thread
From: Ihor Solodrai @ 2024-12-30 20:08 UTC (permalink / raw)
To: gcc@gcc.gnu.org
Cc: Cupertino Miranda, David Faust, Elena Zannoni, Jose E. Marchesi,
Alexei Starovoitov, Manu Bretelle, Eduard Zingerman,
Mykola Lysenko, Yonghong Song, bpf
Hello everyone.
I picked up the work adding GCC BPF backend to BPF CI pipeline [1],
originally done by Cupertino Miranda [2].
I encountered issues compiling BPF objects for selftests/bpf with
recent GCC 15 snapshots. An additional test runner binary is supposed
to be generated by tools/testing/selftests/bpf/Makefile if BPF_GCC is
set to a directory with GCC binaries for BPF backend. The runner
binary depends on BPF binaries, which are produced by GCC.
The first issue is compilation errors on vmlinux.h:
In file included from progs/linked_maps1.c:4:
/ci/workspace/tools/testing/selftests/bpf/tools/include/vmlinux.h:8483:9: error: expected identifier before ‘false’
8483 | false = 0,
| ^~~~~
A snippet from vmlinux.h:
enum {
false = 0,
true = 1,
};
And:
/ci/workspace/tools/testing/selftests/bpf/tools/include/vmlinux.h:23539:15: error: two or more data types in declaration specifiers
23539 | typedef _Bool bool;
| ^~~~
Full log at [3], and also at [4].
You can easily reproduce the errors with a dummy program:
#include "vmlinux.h"
int main() {
return 0;
}
The vmlinux.h is generated from BTF, produced by pahole v1.28 from
DWARF data contained in the vmlinux binary. The vmlinux binary I used
in these experiments is v6.12 (adc218676eef) compiled with gcc 13.3.0
(default Ubuntu installation).
You can download the specific vmlinux.h I tried using a link below [5].
I bisected recent GCC snapshots and determined that the errors related
to the bool declarations started happening on GCC 15-20241117.
Older versions compile the dummy program without errors, however on
attempt to build the selftests there is a different issue: conflicting
int64 definitions (full log at [6]).
In file included from /usr/include/x86_64-linux-gnu/sys/types.h:155,
from /usr/include/x86_64-linux-gnu/bits/socket.h:29,
from /usr/include/x86_64-linux-gnu/sys/socket.h:33,
from /usr/include/linux/if.h:28,
from /usr/include/linux/icmp.h:23,
from progs/test_cls_redirect_dynptr.c:10:
/usr/include/x86_64-linux-gnu/bits/stdint-intn.h:27:19: error: conflicting types for ‘int64_t’; have ‘__int64_t’ {aka ‘long long int’}
27 | typedef __int64_t int64_t;
| ^~~~~~~
In file included from progs/test_cls_redirect_dynptr.c:6:
/ci/workspace/bpfgcc.20240922/lib/gcc/bpf-unknown-none/15.0.0/include/stdint.h:43:24: note: previous declaration of ‘int64_t’ with type ‘int64_t’ {aka ‘long int’}
43 | typedef __INT64_TYPE__ int64_t;
| ^~~~~~~
This is on a typical ubuntu:noble system:
$ dpkg -s libc6 | grep Version
Version: 2.39-0ubuntu8.3
I got this with snapshots 15-20241110 and 15-20240922 (the oldest I
tested). This problem may or may not be present in the most recent
versions, I can't tell for sure.
GCC team, please investigate and let me know if you're aware of
workarounds or if there is a specific GCC version that you know is
capable of building BPF programs in selftests/bpf.
If you suspect something might be wrong with the includes for BPF
programs, or GCC snapshot build etc, please also let me know. I mostly
relied on Cupertino scripts when setting that up, and assumed the
selftests/bpf/Makefile is handling BPF_GCC correctly.
Thank you, and happy holidays!
[1] https://github.com/libbpf/ci/pull/164
[2] https://github.com/libbpf/ci/pull/144
[3] https://gist.github.com/theihor/98883c4266b3489cee69e5d5aa532e79
[4] https://github.com/libbpf/ci/actions/runs/12522053128/job/34929897322
[5] https://gist.github.com/theihor/785bb250dd1cce3612e70b5f6d258401
[6] https://gist.github.com/theihor/a8aa7201b30ac6b48df77bb1ea3ec0b2
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: Errors compiling BPF programs from Linux selftests/bpf with GCC
2024-12-30 20:08 Errors compiling BPF programs from Linux selftests/bpf with GCC Ihor Solodrai
@ 2024-12-30 20:24 ` Andrew Pinski
2024-12-30 20:36 ` Sam James
2025-01-02 9:47 ` Jose E. Marchesi
2025-01-03 23:48 ` Ihor Solodrai
2 siblings, 1 reply; 21+ messages in thread
From: Andrew Pinski @ 2024-12-30 20:24 UTC (permalink / raw)
To: Ihor Solodrai
Cc: gcc@gcc.gnu.org, Cupertino Miranda, David Faust, Elena Zannoni,
Jose E. Marchesi, Alexei Starovoitov, Manu Bretelle,
Eduard Zingerman, Mykola Lysenko, Yonghong Song, bpf
On Mon, Dec 30, 2024 at 12:11 PM Ihor Solodrai via Gcc <gcc@gcc.gnu.org> wrote:
>
> Hello everyone.
>
> I picked up the work adding GCC BPF backend to BPF CI pipeline [1],
> originally done by Cupertino Miranda [2].
>
> I encountered issues compiling BPF objects for selftests/bpf with
> recent GCC 15 snapshots. An additional test runner binary is supposed
> to be generated by tools/testing/selftests/bpf/Makefile if BPF_GCC is
> set to a directory with GCC binaries for BPF backend. The runner
> binary depends on BPF binaries, which are produced by GCC.
>
> The first issue is compilation errors on vmlinux.h:
>
> In file included from progs/linked_maps1.c:4:
> /ci/workspace/tools/testing/selftests/bpf/tools/include/vmlinux.h:8483:9: error: expected identifier before ‘false’
> 8483 | false = 0,
> | ^~~~~
>
> A snippet from vmlinux.h:
>
> enum {
> false = 0,
> true = 1,
> };
>
> And:
>
> /ci/workspace/tools/testing/selftests/bpf/tools/include/vmlinux.h:23539:15: error: two or more data types in declaration specifiers
> 23539 | typedef _Bool bool;
> | ^~~~
>
> Full log at [3], and also at [4].
These are simple, the selftests/bpf programs need to compile with
-std=gnu17 or -std=gnu11 since GCC has changed the default to C23
which defines false and bool as keywords now and can't be redeclared
like before.
Thanks,
Andrew Pinski
>
> You can easily reproduce the errors with a dummy program:
>
> #include "vmlinux.h"
>
> int main() {
> return 0;
> }
>
> The vmlinux.h is generated from BTF, produced by pahole v1.28 from
> DWARF data contained in the vmlinux binary. The vmlinux binary I used
> in these experiments is v6.12 (adc218676eef) compiled with gcc 13.3.0
> (default Ubuntu installation).
>
> You can download the specific vmlinux.h I tried using a link below [5].
>
> I bisected recent GCC snapshots and determined that the errors related
> to the bool declarations started happening on GCC 15-20241117.
>
> Older versions compile the dummy program without errors, however on
> attempt to build the selftests there is a different issue: conflicting
> int64 definitions (full log at [6]).
>
> In file included from /usr/include/x86_64-linux-gnu/sys/types.h:155,
> from /usr/include/x86_64-linux-gnu/bits/socket.h:29,
> from /usr/include/x86_64-linux-gnu/sys/socket.h:33,
> from /usr/include/linux/if.h:28,
> from /usr/include/linux/icmp.h:23,
> from progs/test_cls_redirect_dynptr.c:10:
> /usr/include/x86_64-linux-gnu/bits/stdint-intn.h:27:19: error: conflicting types for ‘int64_t’; have ‘__int64_t’ {aka ‘long long int’}
> 27 | typedef __int64_t int64_t;
> | ^~~~~~~
> In file included from progs/test_cls_redirect_dynptr.c:6:
> /ci/workspace/bpfgcc.20240922/lib/gcc/bpf-unknown-none/15.0.0/include/stdint.h:43:24: note: previous declaration of ‘int64_t’ with type ‘int64_t’ {aka ‘long int’}
> 43 | typedef __INT64_TYPE__ int64_t;
> | ^~~~~~~
>
> This is on a typical ubuntu:noble system:
>
> $ dpkg -s libc6 | grep Version
> Version: 2.39-0ubuntu8.3
>
> I got this with snapshots 15-20241110 and 15-20240922 (the oldest I
> tested). This problem may or may not be present in the most recent
> versions, I can't tell for sure.
>
> GCC team, please investigate and let me know if you're aware of
> workarounds or if there is a specific GCC version that you know is
> capable of building BPF programs in selftests/bpf.
>
> If you suspect something might be wrong with the includes for BPF
> programs, or GCC snapshot build etc, please also let me know. I mostly
> relied on Cupertino scripts when setting that up, and assumed the
> selftests/bpf/Makefile is handling BPF_GCC correctly.
>
> Thank you, and happy holidays!
>
> [1] https://github.com/libbpf/ci/pull/164
> [2] https://github.com/libbpf/ci/pull/144
> [3] https://gist.github.com/theihor/98883c4266b3489cee69e5d5aa532e79
> [4] https://github.com/libbpf/ci/actions/runs/12522053128/job/34929897322
> [5] https://gist.github.com/theihor/785bb250dd1cce3612e70b5f6d258401
> [6] https://gist.github.com/theihor/a8aa7201b30ac6b48df77bb1ea3ec0b2
>
>
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: Errors compiling BPF programs from Linux selftests/bpf with GCC
2024-12-30 20:24 ` Andrew Pinski
@ 2024-12-30 20:36 ` Sam James
2024-12-30 20:59 ` Ihor Solodrai
0 siblings, 1 reply; 21+ messages in thread
From: Sam James @ 2024-12-30 20:36 UTC (permalink / raw)
To: Andrew Pinski via Gcc
Cc: Ihor Solodrai, Andrew Pinski, Cupertino Miranda, David Faust,
Elena Zannoni, Jose E. Marchesi, Alexei Starovoitov,
Manu Bretelle, Eduard Zingerman, Mykola Lysenko, Yonghong Song,
bpf
Andrew Pinski via Gcc <gcc@gcc.gnu.org> writes:
> On Mon, Dec 30, 2024 at 12:11 PM Ihor Solodrai via Gcc <gcc@gcc.gnu.org> wrote:
>>
>> Hello everyone.
>>
>> I picked up the work adding GCC BPF backend to BPF CI pipeline [1],
>> originally done by Cupertino Miranda [2].
>>
>> I encountered issues compiling BPF objects for selftests/bpf with
>> recent GCC 15 snapshots. An additional test runner binary is supposed
>> to be generated by tools/testing/selftests/bpf/Makefile if BPF_GCC is
>> set to a directory with GCC binaries for BPF backend. The runner
>> binary depends on BPF binaries, which are produced by GCC.
>>
>> The first issue is compilation errors on vmlinux.h:
>>
>> In file included from progs/linked_maps1.c:4:
>> /ci/workspace/tools/testing/selftests/bpf/tools/include/vmlinux.h:8483:9: error: expected identifier before ‘false’
>> 8483 | false = 0,
>> | ^~~~~
>>
>> A snippet from vmlinux.h:
>>
>> enum {
>> false = 0,
>> true = 1,
>> };
>>
>> And:
>>
>> /ci/workspace/tools/testing/selftests/bpf/tools/include/vmlinux.h:23539:15: error: two or more data types in declaration specifiers
>> 23539 | typedef _Bool bool;
>> | ^~~~
>>
>> Full log at [3], and also at [4].
>
>
> These are simple, the selftests/bpf programs need to compile with
> -std=gnu17 or -std=gnu11 since GCC has changed the default to C23
> which defines false and bool as keywords now and can't be redeclared
> like before.
Yes, the kernel has various issues like this:
https://lore.kernel.org/linux-kbuild/20241119044724.GA2246422@thelio-3990X/.
Unfortunately, not all the Makefiles correctly declare that they need
gnu11.
Clang will hit issues like this too when they change default to gnu23.
>
> Thanks,
> Andrew Pinski
>
>>
>> You can easily reproduce the errors with a dummy program:
>>
>> #include "vmlinux.h"
>>
>> int main() {
>> return 0;
>> }
>>
>> The vmlinux.h is generated from BTF, produced by pahole v1.28 from
>> DWARF data contained in the vmlinux binary. The vmlinux binary I used
>> in these experiments is v6.12 (adc218676eef) compiled with gcc 13.3.0
>> (default Ubuntu installation).
>>
>> You can download the specific vmlinux.h I tried using a link below [5].
>>
>> I bisected recent GCC snapshots and determined that the errors related
>> to the bool declarations started happening on GCC 15-20241117.
>>
>> Older versions compile the dummy program without errors, however on
>> attempt to build the selftests there is a different issue: conflicting
>> int64 definitions (full log at [6]).
>>
>> In file included from /usr/include/x86_64-linux-gnu/sys/types.h:155,
>> from /usr/include/x86_64-linux-gnu/bits/socket.h:29,
>> from /usr/include/x86_64-linux-gnu/sys/socket.h:33,
>> from /usr/include/linux/if.h:28,
>> from /usr/include/linux/icmp.h:23,
>> from progs/test_cls_redirect_dynptr.c:10:
>> /usr/include/x86_64-linux-gnu/bits/stdint-intn.h:27:19: error: conflicting types for ‘int64_t’; have ‘__int64_t’ {aka ‘long long int’}
>> 27 | typedef __int64_t int64_t;
>> | ^~~~~~~
>> In file included from progs/test_cls_redirect_dynptr.c:6:
>> /ci/workspace/bpfgcc.20240922/lib/gcc/bpf-unknown-none/15.0.0/include/stdint.h:43:24: note: previous declaration of ‘int64_t’ with type ‘int64_t’ {aka ‘long int’}
>> 43 | typedef __INT64_TYPE__ int64_t;
>> | ^~~~~~~
>>
>> This is on a typical ubuntu:noble system:
>>
>> $ dpkg -s libc6 | grep Version
>> Version: 2.39-0ubuntu8.3
>>
>> I got this with snapshots 15-20241110 and 15-20240922 (the oldest I
>> tested). This problem may or may not be present in the most recent
>> versions, I can't tell for sure.
>>
>> GCC team, please investigate and let me know if you're aware of
>> workarounds or if there is a specific GCC version that you know is
>> capable of building BPF programs in selftests/bpf.
>>
>> If you suspect something might be wrong with the includes for BPF
>> programs, or GCC snapshot build etc, please also let me know. I mostly
>> relied on Cupertino scripts when setting that up, and assumed the
>> selftests/bpf/Makefile is handling BPF_GCC correctly.
>>
>> Thank you, and happy holidays!
>>
>> [1] https://github.com/libbpf/ci/pull/164
>> [2] https://github.com/libbpf/ci/pull/144
>> [3] https://gist.github.com/theihor/98883c4266b3489cee69e5d5aa532e79
>> [4] https://github.com/libbpf/ci/actions/runs/12522053128/job/34929897322
>> [5] https://gist.github.com/theihor/785bb250dd1cce3612e70b5f6d258401
>> [6] https://gist.github.com/theihor/a8aa7201b30ac6b48df77bb1ea3ec0b2
>>
>>
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: Errors compiling BPF programs from Linux selftests/bpf with GCC
2024-12-30 20:36 ` Sam James
@ 2024-12-30 20:59 ` Ihor Solodrai
2024-12-30 21:08 ` Sam James
2024-12-31 0:42 ` Alexei Starovoitov
0 siblings, 2 replies; 21+ messages in thread
From: Ihor Solodrai @ 2024-12-30 20:59 UTC (permalink / raw)
To: Andrew Pinski, Sam James
Cc: Andrew Pinski via Gcc, Cupertino Miranda, David Faust,
Elena Zannoni, Jose E. Marchesi, Alexei Starovoitov,
Manu Bretelle, Eduard Zingerman, Mykola Lysenko, Yonghong Song,
bpf
On Monday, December 30th, 2024 at 12:36 PM, Sam James <sam@gentoo.org> wrote:
>
>
> Andrew Pinski via Gcc gcc@gcc.gnu.org writes:
>
> > On Mon, Dec 30, 2024 at 12:11 PM Ihor Solodrai via Gcc gcc@gcc.gnu.org wrote:
> >
> > > Hello everyone.
> > >
> > > I picked up the work adding GCC BPF backend to BPF CI pipeline [1],
> > > originally done by Cupertino Miranda [2].
> > >
> > > I encountered issues compiling BPF objects for selftests/bpf with
> > > recent GCC 15 snapshots. An additional test runner binary is supposed
> > > to be generated by tools/testing/selftests/bpf/Makefile if BPF_GCC is
> > > set to a directory with GCC binaries for BPF backend. The runner
> > > binary depends on BPF binaries, which are produced by GCC.
> > >
> > > The first issue is compilation errors on vmlinux.h:
> > >
> > > In file included from progs/linked_maps1.c:4:
> > > /ci/workspace/tools/testing/selftests/bpf/tools/include/vmlinux.h:8483:9: error: expected identifier before ‘false’
> > > 8483 | false = 0,
> > > | ^~~~~
> > >
> > > A snippet from vmlinux.h:
> > >
> > > enum {
> > > false = 0,
> > > true = 1,
> > > };
> > >
> > > And:
> > >
> > > /ci/workspace/tools/testing/selftests/bpf/tools/include/vmlinux.h:23539:15: error: two or more data types in declaration specifiers
> > > 23539 | typedef _Bool bool;
> > > | ^~~~
> > >
> > > Full log at [3], and also at [4].
> >
> > These are simple, the selftests/bpf programs need to compile with
> > -std=gnu17 or -std=gnu11 since GCC has changed the default to C23
> > which defines false and bool as keywords now and can't be redeclared
> > like before.
>
>
> Yes, the kernel has various issues like this:
> https://lore.kernel.org/linux-kbuild/20241119044724.GA2246422@thelio-3990X/.
>
> Unfortunately, not all the Makefiles correctly declare that they need
> gnu11.
>
> Clang will hit issues like this too when they change default to gnu23.
Andrew, Sam, thank you for a swift response.
vmlinux.h is generated code, so for the booleans perhaps it's more
appropriate to generate a condition, for example:
#if __STDC_VERSION__ < 202311L
enum {
false = 0,
true = 1,
};
#endif
Any drawbacks to this?
Also if vmlinux was built with GCC C23 then I assume DWARF wouldn't
contain the debug info for the enum, hence it wouldn't be present in
vmlinux.h.
I don't think downgrading the standard for a relatively new backend
makes sense, especially in the context of CI testing.
>
> > [...]
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: Errors compiling BPF programs from Linux selftests/bpf with GCC
2024-12-30 20:59 ` Ihor Solodrai
@ 2024-12-30 21:08 ` Sam James
2024-12-31 0:42 ` Alexei Starovoitov
1 sibling, 0 replies; 21+ messages in thread
From: Sam James @ 2024-12-30 21:08 UTC (permalink / raw)
To: Ihor Solodrai
Cc: Andrew Pinski, Andrew Pinski via Gcc, Cupertino Miranda,
David Faust, Elena Zannoni, Jose E. Marchesi, Alexei Starovoitov,
Manu Bretelle, Eduard Zingerman, Mykola Lysenko, Yonghong Song,
bpf
Ihor Solodrai <ihor.solodrai@pm.me> writes:
> On Monday, December 30th, 2024 at 12:36 PM, Sam James <sam@gentoo.org> wrote:
>
>>
>
>>
>
>> Andrew Pinski via Gcc gcc@gcc.gnu.org writes:
>>
>
>> > On Mon, Dec 30, 2024 at 12:11 PM Ihor Solodrai via Gcc gcc@gcc.gnu.org wrote:
>> >
>
>> > > Hello everyone.
>> > >
>
>> > > I picked up the work adding GCC BPF backend to BPF CI pipeline [1],
>> > > originally done by Cupertino Miranda [2].
>> > >
>
>> > > I encountered issues compiling BPF objects for selftests/bpf with
>> > > recent GCC 15 snapshots. An additional test runner binary is supposed
>> > > to be generated by tools/testing/selftests/bpf/Makefile if BPF_GCC is
>> > > set to a directory with GCC binaries for BPF backend. The runner
>> > > binary depends on BPF binaries, which are produced by GCC.
>> > >
>
>> > > The first issue is compilation errors on vmlinux.h:
>> > >
>
>> > > In file included from progs/linked_maps1.c:4:
>> > > /ci/workspace/tools/testing/selftests/bpf/tools/include/vmlinux.h:8483:9: error: expected identifier before ‘false’
>> > > 8483 | false = 0,
>> > > | ^~~~~
>> > >
>
>> > > A snippet from vmlinux.h:
>> > >
>
>> > > enum {
>> > > false = 0,
>> > > true = 1,
>> > > };
>> > >
>
>> > > And:
>> > >
>
>> > > /ci/workspace/tools/testing/selftests/bpf/tools/include/vmlinux.h:23539:15: error: two or more data types in declaration specifiers
>> > > 23539 | typedef _Bool bool;
>> > > | ^~~~
>> > >
>
>> > > Full log at [3], and also at [4].
>> >
>
>> > These are simple, the selftests/bpf programs need to compile with
>> > -std=gnu17 or -std=gnu11 since GCC has changed the default to C23
>> > which defines false and bool as keywords now and can't be redeclared
>> > like before.
>>
>
>>
>
>> Yes, the kernel has various issues like this:
>> https://lore.kernel.org/linux-kbuild/20241119044724.GA2246422@thelio-3990X/.
>>
>
>> Unfortunately, not all the Makefiles correctly declare that they need
>> gnu11.
>>
>
>> Clang will hit issues like this too when they change default to gnu23.
>
> Andrew, Sam, thank you for a swift response.
Thank you for working on CI for this!
>
> vmlinux.h is generated code, so for the booleans perhaps it's more
> appropriate to generate a condition, for example:
>
> #if __STDC_VERSION__ < 202311L
> enum {
> false = 0,
> true = 1,
> };
> #endif
>
> Any drawbacks to this?
>
I think this is fine (enough), given the kernel isn't interested in using _Bool
as far as I know.
> Also if vmlinux was built with GCC C23 then I assume DWARF wouldn't
> contain the debug info for the enum, hence it wouldn't be present in
> vmlinux.h.
>
> I don't think downgrading the standard for a relatively new backend
> makes sense, especially in the context of CI testing.
The issue is that the kernel overall isn't yet worried about being built
as C23.
>
>>
>
>> > [...]
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: Errors compiling BPF programs from Linux selftests/bpf with GCC
2024-12-30 20:59 ` Ihor Solodrai
2024-12-30 21:08 ` Sam James
@ 2024-12-31 0:42 ` Alexei Starovoitov
2024-12-31 1:26 ` Ihor Solodrai
1 sibling, 1 reply; 21+ messages in thread
From: Alexei Starovoitov @ 2024-12-31 0:42 UTC (permalink / raw)
To: Ihor Solodrai
Cc: Andrew Pinski, Sam James, Andrew Pinski via Gcc,
Cupertino Miranda, David Faust, Elena Zannoni, Jose E. Marchesi,
Manu Bretelle, Eduard Zingerman, Mykola Lysenko, Yonghong Song,
bpf
On Mon, Dec 30, 2024 at 12:59 PM Ihor Solodrai <ihor.solodrai@pm.me> wrote:
>
> On Monday, December 30th, 2024 at 12:36 PM, Sam James <sam@gentoo.org> wrote:
>
> >
> >
> > Andrew Pinski via Gcc gcc@gcc.gnu.org writes:
> >
> > > On Mon, Dec 30, 2024 at 12:11 PM Ihor Solodrai via Gcc gcc@gcc.gnu.org wrote:
> > >
> > > > Hello everyone.
> > > >
> > > > I picked up the work adding GCC BPF backend to BPF CI pipeline [1],
> > > > originally done by Cupertino Miranda [2].
> > > >
> > > > I encountered issues compiling BPF objects for selftests/bpf with
> > > > recent GCC 15 snapshots. An additional test runner binary is supposed
> > > > to be generated by tools/testing/selftests/bpf/Makefile if BPF_GCC is
> > > > set to a directory with GCC binaries for BPF backend. The runner
> > > > binary depends on BPF binaries, which are produced by GCC.
> > > >
> > > > The first issue is compilation errors on vmlinux.h:
> > > >
> > > > In file included from progs/linked_maps1.c:4:
> > > > /ci/workspace/tools/testing/selftests/bpf/tools/include/vmlinux.h:8483:9: error: expected identifier before ‘false’
> > > > 8483 | false = 0,
> > > > | ^~~~~
> > > >
> > > > A snippet from vmlinux.h:
> > > >
> > > > enum {
> > > > false = 0,
> > > > true = 1,
> > > > };
> > > >
> > > > And:
> > > >
> > > > /ci/workspace/tools/testing/selftests/bpf/tools/include/vmlinux.h:23539:15: error: two or more data types in declaration specifiers
> > > > 23539 | typedef _Bool bool;
> > > > | ^~~~
> > > >
> > > > Full log at [3], and also at [4].
> > >
> > > These are simple, the selftests/bpf programs need to compile with
> > > -std=gnu17 or -std=gnu11 since GCC has changed the default to C23
> > > which defines false and bool as keywords now and can't be redeclared
> > > like before.
> >
> >
> > Yes, the kernel has various issues like this:
> > https://lore.kernel.org/linux-kbuild/20241119044724.GA2246422@thelio-3990X/.
> >
> > Unfortunately, not all the Makefiles correctly declare that they need
> > gnu11.
> >
> > Clang will hit issues like this too when they change default to gnu23.
>
> Andrew, Sam, thank you for a swift response.
>
> vmlinux.h is generated code, so for the booleans perhaps it's more
> appropriate to generate a condition, for example:
>
> #if __STDC_VERSION__ < 202311L
> enum {
> false = 0,
> true = 1,
> };
> #endif
>
> Any drawbacks to this?
By special hacking this specific enum in bpftool ?
Feels like overkill when just adding -std=gnu17 will do.
>
> Also if vmlinux was built with GCC C23 then I assume DWARF wouldn't
> contain the debug info for the enum, hence it wouldn't be present in
> vmlinux.h.
>
> I don't think downgrading the standard for a relatively new backend
> makes sense, especially in the context of CI testing.
I don't see why not. The flag affects the front-end while CI adds
the test coverage to gcc bpf backend.
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: Errors compiling BPF programs from Linux selftests/bpf with GCC
2024-12-31 0:42 ` Alexei Starovoitov
@ 2024-12-31 1:26 ` Ihor Solodrai
2024-12-31 4:09 ` Alexei Starovoitov
0 siblings, 1 reply; 21+ messages in thread
From: Ihor Solodrai @ 2024-12-31 1:26 UTC (permalink / raw)
To: Alexei Starovoitov
Cc: Andrew Pinski, Sam James, Andrew Pinski via Gcc,
Cupertino Miranda, David Faust, Elena Zannoni, Jose E. Marchesi,
Manu Bretelle, Eduard Zingerman, Mykola Lysenko, Yonghong Song,
bpf, Andrii Nakryiko
On Monday, December 30th, 2024 at 4:42 PM, Alexei Starovoitov <alexei.starovoitov@gmail.com> wrote:
>
>
> On Mon, Dec 30, 2024 at 12:59 PM Ihor Solodrai ihor.solodrai@pm.me wrote:
>
> > On Monday, December 30th, 2024 at 12:36 PM, Sam James sam@gentoo.org wrote:
> >
> > > Andrew Pinski via Gcc gcc@gcc.gnu.org writes:
> > >
> > > > On Mon, Dec 30, 2024 at 12:11 PM Ihor Solodrai via Gcc gcc@gcc.gnu.org wrote:
> > > >
> > > > > Hello everyone.
> > > > >
> > > > > I picked up the work adding GCC BPF backend to BPF CI pipeline [1],
> > > > > originally done by Cupertino Miranda [2].
> > > > >
> > > > > I encountered issues compiling BPF objects for selftests/bpf with
> > > > > recent GCC 15 snapshots. An additional test runner binary is supposed
> > > > > to be generated by tools/testing/selftests/bpf/Makefile if BPF_GCC is
> > > > > set to a directory with GCC binaries for BPF backend. The runner
> > > > > binary depends on BPF binaries, which are produced by GCC.
> > > > >
> > > > > The first issue is compilation errors on vmlinux.h:
> > > > >
> > > > > In file included from progs/linked_maps1.c:4:
> > > > > /ci/workspace/tools/testing/selftests/bpf/tools/include/vmlinux.h:8483:9: error: expected identifier before ‘false’
> > > > > 8483 | false = 0,
> > > > > | ^~~~~
> > > > >
> > > > > A snippet from vmlinux.h:
> > > > >
> > > > > enum {
> > > > > false = 0,
> > > > > true = 1,
> > > > > };
> > > > >
> > > > > And:
> > > > >
> > > > > /ci/workspace/tools/testing/selftests/bpf/tools/include/vmlinux.h:23539:15: error: two or more data types in declaration specifiers
> > > > > 23539 | typedef _Bool bool;
> > > > > | ^~~~
> > > > >
> > > > > Full log at [3], and also at [4].
> > > >
> > > > These are simple, the selftests/bpf programs need to compile with
> > > > -std=gnu17 or -std=gnu11 since GCC has changed the default to C23
> > > > which defines false and bool as keywords now and can't be redeclared
> > > > like before.
> > >
> > > Yes, the kernel has various issues like this:
> > > https://lore.kernel.org/linux-kbuild/20241119044724.GA2246422@thelio-3990X/.
> > >
> > > Unfortunately, not all the Makefiles correctly declare that they need
> > > gnu11.
> > >
> > > Clang will hit issues like this too when they change default to gnu23.
> >
> > Andrew, Sam, thank you for a swift response.
> >
> > vmlinux.h is generated code, so for the booleans perhaps it's more
> > appropriate to generate a condition, for example:
> >
> > #if STDC_VERSION < 202311L
> > enum {
> > false = 0,
> > true = 1,
> > };
> > #endif
> >
> > Any drawbacks to this?
>
>
> By special hacking this specific enum in bpftool ?
> Feels like overkill when just adding -std=gnu17 will do.
Yeah. I've tried both the flag and a btf_dump hack today, and the hack
is indeed an overkill, assuming we don't care about generating
C23-compilant vmlinux.h. To conditionalize the declarations both the
enum and typedef _Bool have to be matched, so it's actually two hacks.
Although we do use hacks like this, noticed an interesting example
today [1].
Regardless of how the bool-related error is fixed (with STDC_VERSION
condition or std flag), I get the same int64 errors with GCC
15-20241229 when building selftests/bpf [2].
[1] https://github.com/libbpf/libbpf/blob/master/src/btf_dump.c#L1198-L1201
[2] https://gist.github.com/theihor/7e3341c5a1e1209a744994143abd9e62
>
> > Also if vmlinux was built with GCC C23 then I assume DWARF wouldn't
> > contain the debug info for the enum, hence it wouldn't be present in
> > vmlinux.h.
> >
> > I don't think downgrading the standard for a relatively new backend
> > makes sense, especially in the context of CI testing.
>
>
> I don't see why not. The flag affects the front-end while CI adds
> the test coverage to gcc bpf backend.
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: Errors compiling BPF programs from Linux selftests/bpf with GCC
2024-12-31 1:26 ` Ihor Solodrai
@ 2024-12-31 4:09 ` Alexei Starovoitov
0 siblings, 0 replies; 21+ messages in thread
From: Alexei Starovoitov @ 2024-12-31 4:09 UTC (permalink / raw)
To: Ihor Solodrai
Cc: Andrew Pinski, Sam James, Andrew Pinski via Gcc,
Cupertino Miranda, David Faust, Elena Zannoni, Jose E. Marchesi,
Manu Bretelle, Eduard Zingerman, Mykola Lysenko, Yonghong Song,
bpf, Andrii Nakryiko
On Mon, Dec 30, 2024 at 5:26 PM Ihor Solodrai <ihor.solodrai@pm.me> wrote:
>
> > >
> > > #if STDC_VERSION < 202311L
> > > enum {
> > > false = 0,
> > > true = 1,
> > > };
> > > #endif
> > >
> > > Any drawbacks to this?
> >
> >
> > By special hacking this specific enum in bpftool ?
> > Feels like overkill when just adding -std=gnu17 will do.
>
> Yeah. I've tried both the flag and a btf_dump hack today, and the hack
> is indeed an overkill, assuming we don't care about generating
> C23-compilant vmlinux.h. To conditionalize the declarations both the
> enum and typedef _Bool have to be matched, so it's actually two hacks.
> Although we do use hacks like this, noticed an interesting example
> today [1].
>
> Regardless of how the bool-related error is fixed (with STDC_VERSION
> condition or std flag), I get the same int64 errors with GCC
> 15-20241229 when building selftests/bpf [2].
>
> [1] https://github.com/libbpf/libbpf/blob/master/src/btf_dump.c#L1198-L1201
This is more of a workaround for differences in gcc behavior.
There is no way to cure it with a flag.
While in this case -std will work. So use it.
No need for extra hacks.
There is no objective to produce c23 compliant vmlinux.h at the moment.
> [2] https://gist.github.com/theihor/7e3341c5a1e1209a744994143abd9e62
/usr/include/x86_64-linux-gnu/bits/stdint-intn.h
vs
/ci/workspace/bpfgcc.20241229/lib/gcc/bpf-unknown-none/15.0.0/include/stdint.h
looks like a configuration issue.
We can skip test_cls_redirect*.c for now.
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: Errors compiling BPF programs from Linux selftests/bpf with GCC
2024-12-30 20:08 Errors compiling BPF programs from Linux selftests/bpf with GCC Ihor Solodrai
2024-12-30 20:24 ` Andrew Pinski
@ 2025-01-02 9:47 ` Jose E. Marchesi
2025-01-02 17:35 ` Ihor Solodrai
2025-01-02 23:04 ` Eduard Zingerman
2025-01-03 23:48 ` Ihor Solodrai
2 siblings, 2 replies; 21+ messages in thread
From: Jose E. Marchesi @ 2025-01-02 9:47 UTC (permalink / raw)
To: Ihor Solodrai
Cc: gcc@gcc.gnu.org, Cupertino Miranda, David Faust, Elena Zannoni,
Alexei Starovoitov, Manu Bretelle, Eduard Zingerman,
Mykola Lysenko, Yonghong Song, bpf
Hi Ihor.
Thanks for working on this! :)
> [...]
> Older versions compile the dummy program without errors, however on
> attempt to build the selftests there is a different issue: conflicting
> int64 definitions (full log at [6]).
>
> In file included from /usr/include/x86_64-linux-gnu/sys/types.h:155,
> from /usr/include/x86_64-linux-gnu/bits/socket.h:29,
> from /usr/include/x86_64-linux-gnu/sys/socket.h:33,
> from /usr/include/linux/if.h:28,
> from /usr/include/linux/icmp.h:23,
> from progs/test_cls_redirect_dynptr.c:10:
> /usr/include/x86_64-linux-gnu/bits/stdint-intn.h:27:19: error: conflicting types for ‘int64_t’; have ‘__int64_t’ {aka ‘long long int’}
> 27 | typedef __int64_t int64_t;
> | ^~~~~~~
> In file included from progs/test_cls_redirect_dynptr.c:6:
> /ci/workspace/bpfgcc.20240922/lib/gcc/bpf-unknown-none/15.0.0/include/stdint.h:43:24:
> note: previous declaration of ‘int64_t’ with type ‘int64_t’ {aka ‘long
> int’}
> 43 | typedef __INT64_TYPE__ int64_t;
> | ^~~~~~~
I think this is what is going on:
The BPF selftest is indirectly including glibc headers from the host
where it is being compiled. In this case your x86_64 ubuntu system.
Many glibc headers include bits/wordsize.h, which in the case of x86_64
is:
#if defined __x86_64__ && !defined __ILP32__
# define __WORDSIZE 64
#else
# define __WORDSIZE 32
#define __WORDSIZE32_SIZE_ULONG 0
#define __WORDSIZE32_PTRDIFF_LONG 0
#endif
and then in bits/types.h:
#if __WORDSIZE == 64
typedef signed long int __int64_t;
typedef unsigned long int __uint64_t;
#else
__extension__ typedef signed long long int __int64_t;
__extension__ typedef unsigned long long int __uint64_t;
#endif
i.e. your BPF program ends using __WORDSIZE 32. This eventually leads
to int64_t being defined as `signed long long int' in stdint-intn.h, as
it would correspond to a x86_64 program running in 32-bit mode.
GCC BPF, on the other hand, is a "baremetal" compiler and it provides a
small set of headers (including stdint.h) that implement standard C99
types like int64_t, adjusted to the BPF architecture.
In this case there is a conflict between the 32-bit x86_64 definition of
int64_t and the one of BPF.
PS: the other headers installed by GCC BPF are:
float.h iso646.h limits.h stdalign.h stdarg.h stdatomic.h stdbool.h
stdckdint.h stddef.h stdfix.h stdint.h stdnoreturn.h syslimits.h
tgmath.h unwind.h varargs.h
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: Errors compiling BPF programs from Linux selftests/bpf with GCC
2025-01-02 9:47 ` Jose E. Marchesi
@ 2025-01-02 17:35 ` Ihor Solodrai
2025-01-02 18:24 ` Jose E. Marchesi
2025-01-02 23:04 ` Eduard Zingerman
1 sibling, 1 reply; 21+ messages in thread
From: Ihor Solodrai @ 2025-01-02 17:35 UTC (permalink / raw)
To: Jose E. Marchesi
Cc: gcc@gcc.gnu.org, Cupertino Miranda, David Faust, Elena Zannoni,
Alexei Starovoitov, Manu Bretelle, Eduard Zingerman,
Mykola Lysenko, Yonghong Song, bpf
On Thursday, January 2nd, 2025 at 1:47 AM, Jose E. Marchesi <jose.marchesi@oracle.com> wrote:
> Hi Ihor.
> Thanks for working on this! :)
>
> > [...]
> > Older versions compile the dummy program without errors, however on
> > attempt to build the selftests there is a different issue: conflicting
> > int64 definitions (full log at [6]).
> >
> > In file included from /usr/include/x86_64-linux-gnu/sys/types.h:155,
> > from /usr/include/x86_64-linux-gnu/bits/socket.h:29,
> > from /usr/include/x86_64-linux-gnu/sys/socket.h:33,
> > from /usr/include/linux/if.h:28,
> > from /usr/include/linux/icmp.h:23,
> > from progs/test_cls_redirect_dynptr.c:10:
> > /usr/include/x86_64-linux-gnu/bits/stdint-intn.h:27:19: error: conflicting types for ‘int64_t’; have ‘__int64_t’ {aka ‘long long int’}
> > 27 | typedef __int64_t int64_t;
> > | ^~~~~~~
> > In file included from progs/test_cls_redirect_dynptr.c:6:
> > /ci/workspace/bpfgcc.20240922/lib/gcc/bpf-unknown-none/15.0.0/include/stdint.h:43:24:
> > note: previous declaration of ‘int64_t’ with type ‘int64_t’ {aka ‘long
> > int’}
> > 43 | typedef INT64_TYPE int64_t;
> > | ^~~~~~~
>
>
> I think this is what is going on:
>
> The BPF selftest is indirectly including glibc headers from the host
> where it is being compiled. In this case your x86_64 ubuntu system.
>
> Many glibc headers include bits/wordsize.h, which in the case of x86_64
> is:
>
> #if defined x86_64 && !defined ILP32
> # define __WORDSIZE 64
> #else
> # define __WORDSIZE 32
> #define __WORDSIZE32_SIZE_ULONG 0
> #define __WORDSIZE32_PTRDIFF_LONG 0
> #endif
>
> and then in bits/types.h:
>
> #if __WORDSIZE == 64
> typedef signed long int __int64_t;
> typedef unsigned long int __uint64_t;
> #else
> extension typedef signed long long int __int64_t;
> extension typedef unsigned long long int __uint64_t;
> #endif
>
> i.e. your BPF program ends using __WORDSIZE 32. This eventually leads
> to int64_t being defined as `signed long long int' in stdint-intn.h, as
> it would correspond to a x86_64 program running in 32-bit mode.
>
> GCC BPF, on the other hand, is a "baremetal" compiler and it provides a
> small set of headers (including stdint.h) that implement standard C99
> types like int64_t, adjusted to the BPF architecture.
>
> In this case there is a conflict between the 32-bit x86_64 definition of
> int64_t and the one of BPF.
Hi Jose, thanks for breaking this down.
I was able to mitigate int64_t declaration conflict by passing
-nostdinc to gcc.
Currently system-installed headers are being passed via -idirafter in
a compilation command:
/ci/workspace/bpfgcc.20241229/bin/bpf-unknown-none-gcc \
-g -Wall -Werror -D__TARGET_ARCH_x86 -mlittle-endian \
-I/ci/workspace/tools/testing/selftests/bpf/tools/include
-I/ci/workspace/tools/testing/selftests/bpf \
-I/ci/workspace/tools/include/uapi \
-I/ci/workspace/tools/testing/selftests/usr/include \
-Wno-compare-distinct-pointer-types \
-idirafter /usr/lib/gcc/x86_64-linux-gnu/13/include \
-idirafter /usr/local/include \
-idirafter /usr/include/x86_64-linux-gnu \
-idirafter /usr/include \
-DBPF_NO_PRESERVE_ACCESS_INDEX \
-Wno-attributes \
-O2 -std=gnu17 \ # -nostdinc here helps
-c progs/test_cls_redirect.c \
-o /ci/workspace/tools/testing/selftests/bpf/bpf_gcc/test_cls_redirect.bpf.o
Passing -nostdinc makes gcc to pick compiler-installed header, if I
understand correctly.
>
> PS: the other headers installed by GCC BPF are:
> float.h iso646.h limits.h stdalign.h stdarg.h stdatomic.h stdbool.h
> stdckdint.h stddef.h stdfix.h stdint.h stdnoreturn.h syslimits.h
> tgmath.h unwind.h varargs.h
From your comments, it seems that BPF programs *must not* include
system glibc headers when compiled with GCC. Or is this only true for
the headers you listed above?
I wonder what is the proper way to build BPF programs with gcc then.
In the source code the includes are what you'd expect:
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h> // conflict is between this
#include <string.h>
#include <linux/bpf.h>
#include <linux/icmp.h> // and this
#include <linux/icmpv6.h>
...
Any suggestions?
Thanks.
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: Errors compiling BPF programs from Linux selftests/bpf with GCC
2025-01-02 17:35 ` Ihor Solodrai
@ 2025-01-02 18:24 ` Jose E. Marchesi
2025-01-03 0:42 ` Eduard Zingerman
0 siblings, 1 reply; 21+ messages in thread
From: Jose E. Marchesi @ 2025-01-02 18:24 UTC (permalink / raw)
To: Ihor Solodrai
Cc: gcc@gcc.gnu.org, Cupertino Miranda, David Faust, Elena Zannoni,
Alexei Starovoitov, Manu Bretelle, Eduard Zingerman,
Mykola Lysenko, Yonghong Song, bpf
> On Thursday, January 2nd, 2025 at 1:47 AM, Jose E. Marchesi <jose.marchesi@oracle.com> wrote:
>
>> Hi Ihor.
>> Thanks for working on this! :)
>>
>> > [...]
>> > Older versions compile the dummy program without errors, however on
>> > attempt to build the selftests there is a different issue: conflicting
>> > int64 definitions (full log at [6]).
>> >
>> > In file included from /usr/include/x86_64-linux-gnu/sys/types.h:155,
>> > from /usr/include/x86_64-linux-gnu/bits/socket.h:29,
>> > from /usr/include/x86_64-linux-gnu/sys/socket.h:33,
>> > from /usr/include/linux/if.h:28,
>> > from /usr/include/linux/icmp.h:23,
>> > from progs/test_cls_redirect_dynptr.c:10:
>> > /usr/include/x86_64-linux-gnu/bits/stdint-intn.h:27:19: error:
>> > conflicting types for ‘int64_t’; have ‘__int64_t’ {aka ‘long long
>> > int’}
>> > 27 | typedef __int64_t int64_t;
>> > | ^~~~~~~
>> > In file included from progs/test_cls_redirect_dynptr.c:6:
>> > /ci/workspace/bpfgcc.20240922/lib/gcc/bpf-unknown-none/15.0.0/include/stdint.h:43:24:
>> > note: previous declaration of ‘int64_t’ with type ‘int64_t’ {aka ‘long
>> > int’}
>> > 43 | typedef INT64_TYPE int64_t;
>> > | ^~~~~~~
>>
>>
>> I think this is what is going on:
>>
>> The BPF selftest is indirectly including glibc headers from the host
>> where it is being compiled. In this case your x86_64 ubuntu system.
>>
>> Many glibc headers include bits/wordsize.h, which in the case of x86_64
>> is:
>>
>> #if defined x86_64 && !defined ILP32
>> # define __WORDSIZE 64
>> #else
>> # define __WORDSIZE 32
>> #define __WORDSIZE32_SIZE_ULONG 0
>> #define __WORDSIZE32_PTRDIFF_LONG 0
>> #endif
>>
>> and then in bits/types.h:
>>
>> #if __WORDSIZE == 64
>> typedef signed long int __int64_t;
>> typedef unsigned long int __uint64_t;
>> #else
>> extension typedef signed long long int __int64_t;
>> extension typedef unsigned long long int __uint64_t;
>> #endif
>>
>> i.e. your BPF program ends using __WORDSIZE 32. This eventually leads
>> to int64_t being defined as `signed long long int' in stdint-intn.h, as
>> it would correspond to a x86_64 program running in 32-bit mode.
>>
>> GCC BPF, on the other hand, is a "baremetal" compiler and it provides a
>> small set of headers (including stdint.h) that implement standard C99
>> types like int64_t, adjusted to the BPF architecture.
>>
>> In this case there is a conflict between the 32-bit x86_64 definition of
>> int64_t and the one of BPF.
>
> Hi Jose, thanks for breaking this down.
>
> I was able to mitigate int64_t declaration conflict by passing
> -nostdinc to gcc.
>
> Currently system-installed headers are being passed via -idirafter in
> a compilation command:
>
> /ci/workspace/bpfgcc.20241229/bin/bpf-unknown-none-gcc \
> -g -Wall -Werror -D__TARGET_ARCH_x86 -mlittle-endian \
> -I/ci/workspace/tools/testing/selftests/bpf/tools/include
> -I/ci/workspace/tools/testing/selftests/bpf \
> -I/ci/workspace/tools/include/uapi \
> -I/ci/workspace/tools/testing/selftests/usr/include \
> -Wno-compare-distinct-pointer-types \
> -idirafter /usr/lib/gcc/x86_64-linux-gnu/13/include \
> -idirafter /usr/local/include \
> -idirafter /usr/include/x86_64-linux-gnu \
> -idirafter /usr/include \
> -DBPF_NO_PRESERVE_ACCESS_INDEX \
> -Wno-attributes \
> -O2 -std=gnu17 \ # -nostdinc here helps
> -c progs/test_cls_redirect.c \
> -o /ci/workspace/tools/testing/selftests/bpf/bpf_gcc/test_cls_redirect.bpf.o
>
> Passing -nostdinc makes gcc to pick compiler-installed header, if I
> understand correctly.
I think that passing -nostdinc is having the opposite effect: it makes
GCC to not use its own distributed stdint.h, so it finds the host's
stdint.h via idirafter.
With that option GCC BPF behaves like clang BPF, include-wise.
>>
>> PS: the other headers installed by GCC BPF are:
>> float.h iso646.h limits.h stdalign.h stdarg.h stdatomic.h stdbool.h
>> stdckdint.h stddef.h stdfix.h stdint.h stdnoreturn.h syslimits.h
>> tgmath.h unwind.h varargs.h
>
> From your comments, it seems that BPF programs *must not* include
> system glibc headers when compiled with GCC. Or is this only true for
> the headers you listed above?
>
> I wonder what is the proper way to build BPF programs with gcc then.
> In the source code the includes are what you'd expect:
>
> #include <stdbool.h>
> #include <stddef.h>
> #include <stdint.h> // conflict is between this
> #include <string.h>
>
> #include <linux/bpf.h>
> #include <linux/icmp.h> // and this
> #include <linux/icmpv6.h>
> ...
>
> Any suggestions?
IMO the BPP selftest (and BPF programs in general) must not include host
glibc headers at all, regardless of what BPF compiler is used. The
glibc headers installed in the host are tailored to some particular
architecture, be it x86_64 or whatever, not necessarily compatible with
what the compilers assume for the BPF target.
This particular case shows the problem well: all the glibc headers
included by that BPF selftest assume that `long' is 32 bits, not 64
bits, because x86_64 is not defined. This conflicts with both clang's
and GCC's assumption that in BPF a `long' is 64 bits. This may or may
not be a problem, depending on whether the BPF program uses the stuff
defined in the headers and how it uses it. Had you be using an arm or
sparc host instead of x86_64, you may be including macros and stuff that
assume chars are unsigned. But chars are signed in bpf.
>
> Thanks.
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: Errors compiling BPF programs from Linux selftests/bpf with GCC
2025-01-02 9:47 ` Jose E. Marchesi
2025-01-02 17:35 ` Ihor Solodrai
@ 2025-01-02 23:04 ` Eduard Zingerman
2025-01-03 0:16 ` Jose E. Marchesi
1 sibling, 1 reply; 21+ messages in thread
From: Eduard Zingerman @ 2025-01-02 23:04 UTC (permalink / raw)
To: Jose E. Marchesi, Ihor Solodrai
Cc: gcc@gcc.gnu.org, Cupertino Miranda, David Faust, Elena Zannoni,
Alexei Starovoitov, Manu Bretelle, Mykola Lysenko, Yonghong Song,
bpf
On Thu, 2025-01-02 at 10:47 +0100, Jose E. Marchesi wrote:
> Hi Ihor.
> Thanks for working on this! :)
>
> > [...]
> > Older versions compile the dummy program without errors, however on
> > attempt to build the selftests there is a different issue: conflicting
> > int64 definitions (full log at [6]).
> >
> > In file included from /usr/include/x86_64-linux-gnu/sys/types.h:155,
> > from /usr/include/x86_64-linux-gnu/bits/socket.h:29,
> > from /usr/include/x86_64-linux-gnu/sys/socket.h:33,
> > from /usr/include/linux/if.h:28,
> > from /usr/include/linux/icmp.h:23,
> > from progs/test_cls_redirect_dynptr.c:10:
> > /usr/include/x86_64-linux-gnu/bits/stdint-intn.h:27:19: error: conflicting types for ‘int64_t’; have ‘__int64_t’ {aka ‘long long int’}
> > 27 | typedef __int64_t int64_t;
> > | ^~~~~~~
> > In file included from progs/test_cls_redirect_dynptr.c:6:
> > /ci/workspace/bpfgcc.20240922/lib/gcc/bpf-unknown-none/15.0.0/include/stdint.h:43:24:
> > note: previous declaration of ‘int64_t’ with type ‘int64_t’ {aka ‘long
> > int’}
> > 43 | typedef __INT64_TYPE__ int64_t;
> > | ^~~~~~~
>
> I think this is what is going on:
>
> The BPF selftest is indirectly including glibc headers from the host
> where it is being compiled. In this case your x86_64 ubuntu system.
>
> Many glibc headers include bits/wordsize.h, which in the case of x86_64
> is:
>
> #if defined __x86_64__ && !defined __ILP32__
> # define __WORDSIZE 64
> #else
> # define __WORDSIZE 32
> #define __WORDSIZE32_SIZE_ULONG 0
> #define __WORDSIZE32_PTRDIFF_LONG 0
> #endif
>
> and then in bits/types.h:
>
> #if __WORDSIZE == 64
> typedef signed long int __int64_t;
> typedef unsigned long int __uint64_t;
> #else
> __extension__ typedef signed long long int __int64_t;
> __extension__ typedef unsigned long long int __uint64_t;
> #endif
>
> i.e. your BPF program ends using __WORDSIZE 32. This eventually leads
> to int64_t being defined as `signed long long int' in stdint-intn.h, as
> it would correspond to a x86_64 program running in 32-bit mode.
>
> GCC BPF, on the other hand, is a "baremetal" compiler and it provides a
> small set of headers (including stdint.h) that implement standard C99
> types like int64_t, adjusted to the BPF architecture.
>
> In this case there is a conflict between the 32-bit x86_64 definition of
> int64_t and the one of BPF.
>
> PS: the other headers installed by GCC BPF are:
> float.h iso646.h limits.h stdalign.h stdarg.h stdatomic.h stdbool.h
> stdckdint.h stddef.h stdfix.h stdint.h stdnoreturn.h syslimits.h
> tgmath.h unwind.h varargs.h
I wondered how this works with clang, because it does not define
__x86_64__ for bpf target. After staring and the output of -E:
- for clang int64_t is defined once and definition originate from
/usr/include/bits/stdint-intn.h included from /usr/include/stdint.h;
- for gcc int64_t is defined two times, definitions originate from:
- <gcc-install-path>/bpf-unknown-none/15.0.0/include/stdint.h
- /usr/include/bits/stdint-intn.h included from /usr/include/sys/types.h.
So, both refer to stdint-intn.h, but only gcc refers to
compiler-specific stdint.h. This is so because of the structure of the
clang's /usr/lib/clang/19/include/stdint.h:
...
#if __STDC_HOSTED__ && __has_include_next(<stdint.h>)
...
# include_next <stdint.h>
...
#else
...
typedef __INT64_TYPE__ int64_t;
...
#endif
...
The __STDC_HOSTED__ is defined as 1, thus when clang compiles the test case,
compiler-specific stdint.h is included, but it's content is ifdef'ed out and
it refers to system stdint.h instead. On the other hand, gcc-specific stdint.h
unconditionally typedefs int64_t.
Links:
- test case pre-processed by clang and gcc:
https://gist.github.com/eddyz87/d381094d67979291bd8338655b15dd5e
- LLVM source code for stdint.h:
https://github.com/llvm/llvm-project/blob/c703b4645c79e889fd6a0f3f64f01f957d981aa4/clang/lib/Headers/stdint.h#L24
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: Errors compiling BPF programs from Linux selftests/bpf with GCC
2025-01-02 23:04 ` Eduard Zingerman
@ 2025-01-03 0:16 ` Jose E. Marchesi
2025-01-03 0:46 ` Eduard Zingerman
0 siblings, 1 reply; 21+ messages in thread
From: Jose E. Marchesi @ 2025-01-03 0:16 UTC (permalink / raw)
To: Eduard Zingerman
Cc: Ihor Solodrai, gcc@gcc.gnu.org, Cupertino Miranda, David Faust,
Elena Zannoni, Alexei Starovoitov, Manu Bretelle, Mykola Lysenko,
Yonghong Song, bpf
> On Thu, 2025-01-02 at 10:47 +0100, Jose E. Marchesi wrote:
>> Hi Ihor.
>> Thanks for working on this! :)
>>
>> > [...]
>> > Older versions compile the dummy program without errors, however on
>> > attempt to build the selftests there is a different issue: conflicting
>> > int64 definitions (full log at [6]).
>> >
>> > In file included from /usr/include/x86_64-linux-gnu/sys/types.h:155,
>> > from /usr/include/x86_64-linux-gnu/bits/socket.h:29,
>> > from /usr/include/x86_64-linux-gnu/sys/socket.h:33,
>> > from /usr/include/linux/if.h:28,
>> > from /usr/include/linux/icmp.h:23,
>> > from progs/test_cls_redirect_dynptr.c:10:
>> > /usr/include/x86_64-linux-gnu/bits/stdint-intn.h:27:19: error: conflicting types for ‘int64_t’; have ‘__int64_t’ {aka ‘long long int’}
>> > 27 | typedef __int64_t int64_t;
>> > | ^~~~~~~
>> > In file included from progs/test_cls_redirect_dynptr.c:6:
>> > /ci/workspace/bpfgcc.20240922/lib/gcc/bpf-unknown-none/15.0.0/include/stdint.h:43:24:
>> > note: previous declaration of ‘int64_t’ with type ‘int64_t’ {aka ‘long
>> > int’}
>> > 43 | typedef __INT64_TYPE__ int64_t;
>> > | ^~~~~~~
>>
>> I think this is what is going on:
>>
>> The BPF selftest is indirectly including glibc headers from the host
>> where it is being compiled. In this case your x86_64 ubuntu system.
>>
>> Many glibc headers include bits/wordsize.h, which in the case of x86_64
>> is:
>>
>> #if defined __x86_64__ && !defined __ILP32__
>> # define __WORDSIZE 64
>> #else
>> # define __WORDSIZE 32
>> #define __WORDSIZE32_SIZE_ULONG 0
>> #define __WORDSIZE32_PTRDIFF_LONG 0
>> #endif
>>
>> and then in bits/types.h:
>>
>> #if __WORDSIZE == 64
>> typedef signed long int __int64_t;
>> typedef unsigned long int __uint64_t;
>> #else
>> __extension__ typedef signed long long int __int64_t;
>> __extension__ typedef unsigned long long int __uint64_t;
>> #endif
>>
>> i.e. your BPF program ends using __WORDSIZE 32. This eventually leads
>> to int64_t being defined as `signed long long int' in stdint-intn.h, as
>> it would correspond to a x86_64 program running in 32-bit mode.
>>
>> GCC BPF, on the other hand, is a "baremetal" compiler and it provides a
>> small set of headers (including stdint.h) that implement standard C99
>> types like int64_t, adjusted to the BPF architecture.
>>
>> In this case there is a conflict between the 32-bit x86_64 definition of
>> int64_t and the one of BPF.
>>
>> PS: the other headers installed by GCC BPF are:
>> float.h iso646.h limits.h stdalign.h stdarg.h stdatomic.h stdbool.h
>> stdckdint.h stddef.h stdfix.h stdint.h stdnoreturn.h syslimits.h
>> tgmath.h unwind.h varargs.h
>
> I wondered how this works with clang, because it does not define
> __x86_64__ for bpf target. After staring and the output of -E:
> - for clang int64_t is defined once and definition originate from
> /usr/include/bits/stdint-intn.h included from /usr/include/stdint.h;
> - for gcc int64_t is defined two times, definitions originate from:
> - <gcc-install-path>/bpf-unknown-none/15.0.0/include/stdint.h
> - /usr/include/bits/stdint-intn.h included from /usr/include/sys/types.h.
>
> So, both refer to stdint-intn.h, but only gcc refers to
> compiler-specific stdint.h. This is so because of the structure of the
> clang's /usr/lib/clang/19/include/stdint.h:
>
> ...
> #if __STDC_HOSTED__ && __has_include_next(<stdint.h>)
> ...
> # include_next <stdint.h>
> ...
> #else
> ...
> typedef __INT64_TYPE__ int64_t;
> ...
> #endif
> ...
>
> The __STDC_HOSTED__ is defined as 1, thus when clang compiles the test case,
> compiler-specific stdint.h is included, but it's content is ifdef'ed out and
> it refers to system stdint.h instead. On the other hand, gcc-specific stdint.h
> unconditionally typedefs int64_t.
Yes, in the GCC BPF backend we are using
use_gcc_stdint=provide
which makes GCC to provide the version of stdint.h that assumes
freestanding ("baremetal") mode. If we changed it to use
use_gcc_stdint=wrap
then it would install a stdint.h that does somethins similar to what
clang does, at least in hosts providing C99 headers (note the lack of
__has_include_next):
#ifndef _GCC_WRAP_STDINT_H
#if __STDC_HOSTED__
# if defined __cplusplus && __cplusplus >= 201103L
# undef __STDC_LIMIT_MACROS
# define __STDC_LIMIT_MACROS
# undef __STDC_CONSTANT_MACROS
# define __STDC_CONSTANT_MACROS
# endif
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpedantic" // include_next
# include_next <stdint.h>
#pragma GCC diagnostic pop
#else
# include "stdint-gcc.h"
#endif
#define _GCC_WRAP_STDINT_H
#endif
We could switch to "wrap" to align with clang, but in that case it would
be up to the user to provide a "host" stdint.h that contains sensible
definitions for BPF. The kernel selftests, for example, would need to
do so to avoid including /usr/include/stdint.h that more likely than not
will provide incorrect definitions for int64_t and friends...
>
> Links:
> - test case pre-processed by clang and gcc:
> https://gist.github.com/eddyz87/d381094d67979291bd8338655b15dd5e
> - LLVM source code for stdint.h:
> https://github.com/llvm/llvm-project/blob/c703b4645c79e889fd6a0f3f64f01f957d981aa4/clang/lib/Headers/stdint.h#L24
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: Errors compiling BPF programs from Linux selftests/bpf with GCC
2025-01-02 18:24 ` Jose E. Marchesi
@ 2025-01-03 0:42 ` Eduard Zingerman
2025-01-03 13:23 ` Jose E. Marchesi
0 siblings, 1 reply; 21+ messages in thread
From: Eduard Zingerman @ 2025-01-03 0:42 UTC (permalink / raw)
To: Jose E. Marchesi, Ihor Solodrai
Cc: gcc@gcc.gnu.org, Cupertino Miranda, David Faust, Elena Zannoni,
Alexei Starovoitov, Manu Bretelle, Mykola Lysenko, Yonghong Song,
bpf
On Thu, 2025-01-02 at 19:24 +0100, Jose E. Marchesi wrote:
[...]
> IMO the BPP selftest (and BPF programs in general) must not include host
> glibc headers at all, regardless of what BPF compiler is used. The
> glibc headers installed in the host are tailored to some particular
> architecture, be it x86_64 or whatever, not necessarily compatible with
> what the compilers assume for the BPF target.
>
> This particular case shows the problem well: all the glibc headers
> included by that BPF selftest assume that `long' is 32 bits, not 64
> bits, because x86_64 is not defined. This conflicts with both clang's
> and GCC's assumption that in BPF a `long' is 64 bits. This may or may
> not be a problem, depending on whether the BPF program uses the stuff
> defined in the headers and how it uses it. Had you be using an arm or
> sparc host instead of x86_64, you may be including macros and stuff that
> assume chars are unsigned. But chars are signed in bpf.
This makes sense, but might cause some friction.
The following glibc headers are included directly from selftests:
- errno.h
- features.h
- inttypes.h
- limits.h
- netinet/in.h
- netinet/udp.h
- sched.h
- stdint.h
- stdlib.h
- string.h
- sys/socket.h
- sys/types.h
- time.h
- unistd.h
However, removing includes for these headers does not help the test in
question, because some linux UAPI headers include libc headers when exported:
In file included from /usr/include/netinet/udp.h:51,
from progs/test_cls_redirect_dynptr.c:20:
/home/eddy/work/tmp/gccbpf/lib/gcc/bpf-unknown-none/15.0.0/include/stdint.h:43:24: error: conflicting types for ‘int64_t’; have ‘long int’
43 | typedef __INT64_TYPE__ int64_t;
| ^~~~~~~
In file included from /usr/include/sys/types.h:155,
from /usr/include/bits/socket.h:29,
from /usr/include/sys/socket.h:33,
from /usr/include/linux/if.h:28,
from /usr/include/linux/icmp.h:23,
from progs/test_cls_redirect_dynptr.c:12:
/usr/include/bits/stdint-intn.h:27:19: note: previous declaration of ‘int64_t’ with type ‘int64_t’ {aka ‘long long int’}
27 | typedef __int64_t int64_t;
| ^~~~~~~
On my system (Fedora 41) the linux/{icmp,if}.h UAPI headers are
provided by kernel-headers package, sys/socket.h is provided by
glibc-devel package.
The UAPI headers have two modes depending whether __KERNEL__ is
defined. When used during kernel build the __KERNEL__ is defined and
there are no outside references. When exported for packages like
kernel-headers (via 'make headers' target) the __KERNEL__ is not
defined and there are some references to libc includes
(in fact, references to '#ifdef __KERNEL__' blocks are cut out during
headers export).
E.g. here is a fragment of linux/if.h, when viewed from kernel source:
#ifndef _LINUX_IF_H
#define _LINUX_IF_H
#include <linux/libc-compat.h> /* for compatibility with glibc */
#include <linux/types.h> /* for "__kernel_caddr_t" et al */
#include <linux/socket.h> /* for "struct sockaddr" et al */
#include <linux/compiler.h> /* for "__user" et al */
#ifndef __KERNEL__
#include <sys/socket.h> /* for struct sockaddr. */
#endif
And here is the same fragment as part of the kernel-headers package
(/usr/include/linux/if.h):
#ifndef _LINUX_IF_H
#define _LINUX_IF_H
#include <linux/libc-compat.h> /* for compatibility with glibc */
#include <linux/types.h> /* for "__kernel_caddr_t" et al */
#include <linux/socket.h> /* for "struct sockaddr" et al */
/* for "__user" et al */
#include <sys/socket.h> /* for struct sockaddr. */
As far as I understand, the idea right now is that BPF users can
install the kernel-headers package (or its equivalent) and start
hacking. If we declare that this is no longer a blessed way, people
would need to switch to packages like kernel-devel that provide full
set of kernel headers for use with dkms etc, e.g. for my system the
if.h would be located here:
/usr/src/kernels/6.12.6-200.fc41.x86_64/include/uapi/linux/if.h .
To me this seems logical, however potentially such change might have
implications for existing BPF code-base.
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: Errors compiling BPF programs from Linux selftests/bpf with GCC
2025-01-03 0:16 ` Jose E. Marchesi
@ 2025-01-03 0:46 ` Eduard Zingerman
2025-01-03 10:17 ` Jose E. Marchesi
0 siblings, 1 reply; 21+ messages in thread
From: Eduard Zingerman @ 2025-01-03 0:46 UTC (permalink / raw)
To: Jose E. Marchesi
Cc: Ihor Solodrai, gcc@gcc.gnu.org, Cupertino Miranda, David Faust,
Elena Zannoni, Alexei Starovoitov, Manu Bretelle, Mykola Lysenko,
Yonghong Song, bpf
On Fri, 2025-01-03 at 01:16 +0100, Jose E. Marchesi wrote:
[...]
> Yes, in the GCC BPF backend we are using
>
> use_gcc_stdint=provide
>
> which makes GCC to provide the version of stdint.h that assumes
> freestanding ("baremetal") mode. If we changed it to use
>
> use_gcc_stdint=wrap
>
> then it would install a stdint.h that does somethins similar to what
> clang does, at least in hosts providing C99 headers (note the lack of
> __has_include_next):
>
> #ifndef _GCC_WRAP_STDINT_H
> #if __STDC_HOSTED__
> # if defined __cplusplus && __cplusplus >= 201103L
> # undef __STDC_LIMIT_MACROS
> # define __STDC_LIMIT_MACROS
> # undef __STDC_CONSTANT_MACROS
> # define __STDC_CONSTANT_MACROS
> # endif
> #pragma GCC diagnostic push
> #pragma GCC diagnostic ignored "-Wpedantic" // include_next
> # include_next <stdint.h>
> #pragma GCC diagnostic pop
> #else
> # include "stdint-gcc.h"
> #endif
> #define _GCC_WRAP_STDINT_H
> #endif
>
> We could switch to "wrap" to align with clang, but in that case it would
> be up to the user to provide a "host" stdint.h that contains sensible
> definitions for BPF. The kernel selftests, for example, would need to
> do so to avoid including /usr/include/stdint.h that more likely than not
> will provide incorrect definitions for int64_t and friends...
Would it be possible to push a branch that uses '=wrap' thing somewhere?
So that it could be further tested to see if there are more issues with selftests.
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: Errors compiling BPF programs from Linux selftests/bpf with GCC
2025-01-03 0:46 ` Eduard Zingerman
@ 2025-01-03 10:17 ` Jose E. Marchesi
2025-01-03 12:52 ` Jose E. Marchesi
0 siblings, 1 reply; 21+ messages in thread
From: Jose E. Marchesi @ 2025-01-03 10:17 UTC (permalink / raw)
To: Eduard Zingerman
Cc: Ihor Solodrai, gcc@gcc.gnu.org, Cupertino Miranda, David Faust,
Elena Zannoni, Alexei Starovoitov, Manu Bretelle, Mykola Lysenko,
Yonghong Song, bpf
> On Fri, 2025-01-03 at 01:16 +0100, Jose E. Marchesi wrote:
>
> [...]
>
>> Yes, in the GCC BPF backend we are using
>>
>> use_gcc_stdint=provide
>>
>> which makes GCC to provide the version of stdint.h that assumes
>> freestanding ("baremetal") mode. If we changed it to use
>>
>> use_gcc_stdint=wrap
>>
>> then it would install a stdint.h that does somethins similar to what
>> clang does, at least in hosts providing C99 headers (note the lack of
>> __has_include_next):
>>
>> #ifndef _GCC_WRAP_STDINT_H
>> #if __STDC_HOSTED__
>> # if defined __cplusplus && __cplusplus >= 201103L
>> # undef __STDC_LIMIT_MACROS
>> # define __STDC_LIMIT_MACROS
>> # undef __STDC_CONSTANT_MACROS
>> # define __STDC_CONSTANT_MACROS
>> # endif
>> #pragma GCC diagnostic push
>> #pragma GCC diagnostic ignored "-Wpedantic" // include_next
>> # include_next <stdint.h>
>> #pragma GCC diagnostic pop
>> #else
>> # include "stdint-gcc.h"
>> #endif
>> #define _GCC_WRAP_STDINT_H
>> #endif
>>
>> We could switch to "wrap" to align with clang, but in that case it would
>> be up to the user to provide a "host" stdint.h that contains sensible
>> definitions for BPF. The kernel selftests, for example, would need to
>> do so to avoid including /usr/include/stdint.h that more likely than not
>> will provide incorrect definitions for int64_t and friends...
>
> Would it be possible to push a branch that uses '=wrap' thing
> somewhere? So that it could be further tested to see if there are
> more issues with selftests.
No need. After reflecting a bit I can't see why the requirements on the
"host" stdint.h must be different for BPF than for any other target: its
contents must match the expectations of the compiler for the arch. If
it doesn't... well, it is not the responsibility of the compiler to
assure that. I will install a patch to switch to the wrapper stdint.h.
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: Errors compiling BPF programs from Linux selftests/bpf with GCC
2025-01-03 10:17 ` Jose E. Marchesi
@ 2025-01-03 12:52 ` Jose E. Marchesi
0 siblings, 0 replies; 21+ messages in thread
From: Jose E. Marchesi @ 2025-01-03 12:52 UTC (permalink / raw)
To: Eduard Zingerman
Cc: Ihor Solodrai, gcc@gcc.gnu.org, Cupertino Miranda, David Faust,
Elena Zannoni, Alexei Starovoitov, Manu Bretelle, Mykola Lysenko,
Yonghong Song, bpf
> [...]
>>> We could switch to "wrap" to align with clang, but in that case it would
>>> be up to the user to provide a "host" stdint.h that contains sensible
>>> definitions for BPF. The kernel selftests, for example, would need to
>>> do so to avoid including /usr/include/stdint.h that more likely than not
>>> will provide incorrect definitions for int64_t and friends...
>>
>> Would it be possible to push a branch that uses '=wrap' thing
>> somewhere? So that it could be further tested to see if there are
>> more issues with selftests.
>
> No need. After reflecting a bit I can't see why the requirements on the
> "host" stdint.h must be different for BPF than for any other target: its
> contents must match the expectations of the compiler for the arch. If
> it doesn't... well, it is not the responsibility of the compiler to
> assure that. I will install a patch to switch to the wrapper stdint.h.
https://gcc.gnu.org/pipermail/gcc-patches/2025-January/672508.html
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: Errors compiling BPF programs from Linux selftests/bpf with GCC
2025-01-03 0:42 ` Eduard Zingerman
@ 2025-01-03 13:23 ` Jose E. Marchesi
0 siblings, 0 replies; 21+ messages in thread
From: Jose E. Marchesi @ 2025-01-03 13:23 UTC (permalink / raw)
To: Eduard Zingerman
Cc: Ihor Solodrai, gcc@gcc.gnu.org, Cupertino Miranda, David Faust,
Elena Zannoni, Alexei Starovoitov, Manu Bretelle, Mykola Lysenko,
Yonghong Song, bpf
> On Thu, 2025-01-02 at 19:24 +0100, Jose E. Marchesi wrote:
>
> [...]
>
>> IMO the BPP selftest (and BPF programs in general) must not include host
>> glibc headers at all, regardless of what BPF compiler is used. The
>> glibc headers installed in the host are tailored to some particular
>> architecture, be it x86_64 or whatever, not necessarily compatible with
>> what the compilers assume for the BPF target.
>>
>> This particular case shows the problem well: all the glibc headers
>> included by that BPF selftest assume that `long' is 32 bits, not 64
>> bits, because x86_64 is not defined. This conflicts with both clang's
>> and GCC's assumption that in BPF a `long' is 64 bits. This may or may
>> not be a problem, depending on whether the BPF program uses the stuff
>> defined in the headers and how it uses it. Had you be using an arm or
>> sparc host instead of x86_64, you may be including macros and stuff that
>> assume chars are unsigned. But chars are signed in bpf.
>
> This makes sense, but might cause some friction.
> The following glibc headers are included directly from selftests:
> - errno.h
> - features.h
> - inttypes.h
> - limits.h
> - netinet/in.h
> - netinet/udp.h
> - sched.h
> - stdint.h
> - stdlib.h
> - string.h
> - sys/socket.h
> - sys/types.h
> - time.h
> - unistd.h
>
> However, removing includes for these headers does not help the test in
> question, because some linux UAPI headers include libc headers when exported:
>
> In file included from /usr/include/netinet/udp.h:51,
> from progs/test_cls_redirect_dynptr.c:20:
> /home/eddy/work/tmp/gccbpf/lib/gcc/bpf-unknown-none/15.0.0/include/stdint.h:43:24: error: conflicting types for ‘int64_t’; have ‘long int’
> 43 | typedef __INT64_TYPE__ int64_t;
> | ^~~~~~~
> In file included from /usr/include/sys/types.h:155,
> from /usr/include/bits/socket.h:29,
> from /usr/include/sys/socket.h:33,
> from /usr/include/linux/if.h:28,
> from /usr/include/linux/icmp.h:23,
> from progs/test_cls_redirect_dynptr.c:12:
> /usr/include/bits/stdint-intn.h:27:19: note: previous declaration of ‘int64_t’ with type ‘int64_t’ {aka ‘long long int’}
> 27 | typedef __int64_t int64_t;
> | ^~~~~~~
>
> On my system (Fedora 41) the linux/{icmp,if}.h UAPI headers are
> provided by kernel-headers package, sys/socket.h is provided by
> glibc-devel package.
>
> The UAPI headers have two modes depending whether __KERNEL__ is
> defined. When used during kernel build the __KERNEL__ is defined and
> there are no outside references. When exported for packages like
> kernel-headers (via 'make headers' target) the __KERNEL__ is not
> defined and there are some references to libc includes
> (in fact, references to '#ifdef __KERNEL__' blocks are cut out during
> headers export).
>
> E.g. here is a fragment of linux/if.h, when viewed from kernel source:
>
> #ifndef _LINUX_IF_H
> #define _LINUX_IF_H
>
> #include <linux/libc-compat.h> /* for compatibility with glibc */
> #include <linux/types.h> /* for "__kernel_caddr_t" et al */
> #include <linux/socket.h> /* for "struct sockaddr" et al */
> #include <linux/compiler.h> /* for "__user" et al */
>
> #ifndef __KERNEL__
> #include <sys/socket.h> /* for struct sockaddr. */
> #endif
>
> And here is the same fragment as part of the kernel-headers package
> (/usr/include/linux/if.h):
>
> #ifndef _LINUX_IF_H
> #define _LINUX_IF_H
>
> #include <linux/libc-compat.h> /* for compatibility with glibc */
> #include <linux/types.h> /* for "__kernel_caddr_t" et al */
> #include <linux/socket.h> /* for "struct sockaddr" et al */
> /* for "__user" et al */
>
> #include <sys/socket.h> /* for struct sockaddr. */
>
> As far as I understand, the idea right now is that BPF users can
> install the kernel-headers package (or its equivalent) and start
> hacking. If we declare that this is no longer a blessed way, people
> would need to switch to packages like kernel-devel that provide full
> set of kernel headers for use with dkms etc, e.g. for my system the
> if.h would be located here:
> /usr/src/kernels/6.12.6-200.fc41.x86_64/include/uapi/linux/if.h .
>
> To me this seems logical, however potentially such change might have
> implications for existing BPF code-base.
Aren't the kernel UAPI headers themselves architecture-specific, even if
__KERNEL__ is defined? I see arch/**/include/uapi/asm/socket.h files in
the kernel tree for example.
I suppose a way to handle this would be to add BPF as an arch in glibc,
but at this point BPF objects are not really linked externally (despite
the linker supporting it) only "internally" at load time by bpftool, so
it would be a "headers only" port, and these headers could probably be
more easily provided by BPF "hosts" like the kernel. Now I am wondering
whether NaCL, the precursor of WebAssembly, which was used to be
supported in glibc, faced a similar situation and if so how it handled
it. Will take a look.
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: Errors compiling BPF programs from Linux selftests/bpf with GCC
2024-12-30 20:08 Errors compiling BPF programs from Linux selftests/bpf with GCC Ihor Solodrai
2024-12-30 20:24 ` Andrew Pinski
2025-01-02 9:47 ` Jose E. Marchesi
@ 2025-01-03 23:48 ` Ihor Solodrai
2025-01-03 23:56 ` Andrew Pinski
2025-01-04 8:05 ` Jose E. Marchesi
2 siblings, 2 replies; 21+ messages in thread
From: Ihor Solodrai @ 2025-01-03 23:48 UTC (permalink / raw)
To: bpf, gcc@gcc.gnu.org
Cc: Cupertino Miranda, David Faust, Elena Zannoni, Jose E. Marchesi,
Alexei Starovoitov, Manu Bretelle, Eduard Zingerman,
Mykola Lysenko, Yonghong Song, Andrew Pinski, Sam James,
Andrii Nakryiko
Hi everyone.
I built and ran selftests/bpf with GCC 15-20241229, and would like to
share my findings.
Building required small adjustments in the Makefile, besides -std=gnu17
With the following change we can mitigate int64_t issue:
+progs/test_cls_redirect.c-CFLAGS := -nostdinc
+progs/test_cls_redirect_dynptr.c-CFLAGS := -nostdinc
+progs/test_cls_redirect_subprogs.c-CFLAGS := -nostdinc
Then, the compiler complains about an uninitialized variable in
progs/verifier_bpf_fastcall.c and progs/verifier_search_pruning.c
(full log at [1]):
In file included from progs/verifier_bpf_fastcall.c:7:
progs/verifier_bpf_fastcall.c: In function ‘may_goto_interaction’:
progs/bpf_misc.h:153:42: error: ‘<Uc098>’ is used uninitialized [-Werror=uninitialized]
153 | #define __imm_insn(name, expr) [name]"i"(*(long *)&(expr))
| ^~~~~~~~~~~~~~~~
progs/verifier_bpf_fastcall.c:652:11: note: in expansion of macro ‘__imm_insn’
652 | __imm_insn(may_goto, BPF_RAW_INSN(BPF_JMP | BPF_JCOND, 0, 0, +1 /* offset */, 0))
| ^~~~~~~~~~
/ci/workspace/tools/testing/selftests/bpf/../../../include/linux/filter.h:299:28: note: ‘({anonymous})’ declared here
299 | ((struct bpf_insn) { \
| ^
progs/bpf_misc.h:153:53: note: in definition of macro ‘__imm_insn’
153 | #define __imm_insn(name, expr) [name]"i"(*(long *)&(expr))
| ^~~~
progs/verifier_bpf_fastcall.c:652:32: note: in expansion of macro ‘BPF_RAW_INSN’
652 | __imm_insn(may_goto, BPF_RAW_INSN(BPF_JMP | BPF_JCOND, 0, 0, +1 /* offset */, 0))
BPF_RAW_INSN expands into struct init expr (include/linux/filter.h):
#define BPF_RAW_INSN(CODE, DST, SRC, OFF, IMM) \
((struct bpf_insn) { \
.code = CODE, \
.dst_reg = DST, \
.src_reg = SRC, \
.off = OFF, \
.imm = IMM })
This can be silenced with:
+progs/verifier_bpf_fastcall.c-CFLAGS := -Wno-error
+progs/verifier_search_pruning.c-CFLAGS := -Wno-error
Then the selftests/bpf build completes successfully, although libbpf
prints a lot of warnings like these on GEN-SKEL:
[...]
libbpf: elf: skipping section(3) .data (size 0)
libbpf: elf: skipping section(4) .data (size 0)
libbpf: elf: skipping unrecognized data section(13) .comment
libbpf: elf: skipping unrecognized data section(9) .comment
libbpf: elf: skipping unrecognized data section(12) .comment
libbpf: elf: skipping unrecognized data section(7) .comment
[...]
Test .bpf.o files are compiled regardless. Full log at [2].
Running all tests at once, as is usually done on CI, produces a too
cluttered log. I wrote a script to run each test individually in a
separate qemu instance and collect the logs.
187/581 of toplevel tests fail on current bpf-next [3]. Many tests
have subtests: toplevel test passes if all of its subtests pass.
You can find the archive with per-test logs at [4].
[1] https://gist.github.com/theihor/10b2425e6780fcfebb80aeceafba7678
[2] https://gist.github.com/theihor/9e96643ca730365cf79cea8445e40aeb
[3] https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next.git/commit/?id=96ea081ed52bf077cad6d00153b6fba68e510767
[4] https://github.com/kernel-patches/bpf/blob/8f2e62702ee17675464ab00d97d89d599922de20/tools/testing/selftests/bpf/gcc-bpf-selftests-logs.tgz
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: Errors compiling BPF programs from Linux selftests/bpf with GCC
2025-01-03 23:48 ` Ihor Solodrai
@ 2025-01-03 23:56 ` Andrew Pinski
2025-01-04 8:05 ` Jose E. Marchesi
1 sibling, 0 replies; 21+ messages in thread
From: Andrew Pinski @ 2025-01-03 23:56 UTC (permalink / raw)
To: Ihor Solodrai
Cc: bpf, gcc@gcc.gnu.org, Cupertino Miranda, David Faust,
Elena Zannoni, Jose E. Marchesi, Alexei Starovoitov,
Manu Bretelle, Eduard Zingerman, Mykola Lysenko, Yonghong Song,
Sam James, Andrii Nakryiko
On Fri, Jan 3, 2025 at 3:48 PM Ihor Solodrai <ihor.solodrai@pm.me> wrote:
>
> Hi everyone.
>
> I built and ran selftests/bpf with GCC 15-20241229, and would like to
> share my findings.
>
> Building required small adjustments in the Makefile, besides -std=gnu17
>
> With the following change we can mitigate int64_t issue:
>
> +progs/test_cls_redirect.c-CFLAGS := -nostdinc
> +progs/test_cls_redirect_dynptr.c-CFLAGS := -nostdinc
> +progs/test_cls_redirect_subprogs.c-CFLAGS := -nostdinc
>
> Then, the compiler complains about an uninitialized variable in
> progs/verifier_bpf_fastcall.c and progs/verifier_search_pruning.c
> (full log at [1]):
>
> In file included from progs/verifier_bpf_fastcall.c:7:
> progs/verifier_bpf_fastcall.c: In function ‘may_goto_interaction’:
> progs/bpf_misc.h:153:42: error: ‘<Uc098>’ is used uninitialized [-Werror=uninitialized]
> 153 | #define __imm_insn(name, expr) [name]"i"(*(long *)&(expr))
> | ^~~~~~~~~~~~~~~~
> progs/verifier_bpf_fastcall.c:652:11: note: in expansion of macro ‘__imm_insn’
> 652 | __imm_insn(may_goto, BPF_RAW_INSN(BPF_JMP | BPF_JCOND, 0, 0, +1 /* offset */, 0))
> | ^~~~~~~~~~
> /ci/workspace/tools/testing/selftests/bpf/../../../include/linux/filter.h:299:28: note: ‘({anonymous})’ declared here
> 299 | ((struct bpf_insn) { \
> | ^
> progs/bpf_misc.h:153:53: note: in definition of macro ‘__imm_insn’
> 153 | #define __imm_insn(name, expr) [name]"i"(*(long *)&(expr))
> | ^~~~
> progs/verifier_bpf_fastcall.c:652:32: note: in expansion of macro ‘BPF_RAW_INSN’
> 652 | __imm_insn(may_goto, BPF_RAW_INSN(BPF_JMP | BPF_JCOND, 0, 0, +1 /* offset */, 0))
>
> BPF_RAW_INSN expands into struct init expr (include/linux/filter.h):
>
> #define BPF_RAW_INSN(CODE, DST, SRC, OFF, IMM) \
> ((struct bpf_insn) { \
> .code = CODE, \
> .dst_reg = DST, \
> .src_reg = SRC, \
> .off = OFF, \
> .imm = IMM })
That: `*(long *)&(expr)` is 100% undefined behavior there since it is
an alias violation.
I suspect you should use an union instead,
something like:
#define __imm_insn(name, expr) [name]"i"(((union { struct bpf_insn
insn_s; long insn; }){.insn_s = (expr)}).insn)
Should fix the issue.
Thanks,
Andrew
>
> This can be silenced with:
>
> +progs/verifier_bpf_fastcall.c-CFLAGS := -Wno-error
> +progs/verifier_search_pruning.c-CFLAGS := -Wno-error
>
> Then the selftests/bpf build completes successfully, although libbpf
> prints a lot of warnings like these on GEN-SKEL:
>
> [...]
> libbpf: elf: skipping section(3) .data (size 0)
> libbpf: elf: skipping section(4) .data (size 0)
> libbpf: elf: skipping unrecognized data section(13) .comment
> libbpf: elf: skipping unrecognized data section(9) .comment
> libbpf: elf: skipping unrecognized data section(12) .comment
> libbpf: elf: skipping unrecognized data section(7) .comment
> [...]
>
> Test .bpf.o files are compiled regardless. Full log at [2].
>
> Running all tests at once, as is usually done on CI, produces a too
> cluttered log. I wrote a script to run each test individually in a
> separate qemu instance and collect the logs.
>
> 187/581 of toplevel tests fail on current bpf-next [3]. Many tests
> have subtests: toplevel test passes if all of its subtests pass.
>
> You can find the archive with per-test logs at [4].
>
> [1] https://gist.github.com/theihor/10b2425e6780fcfebb80aeceafba7678
> [2] https://gist.github.com/theihor/9e96643ca730365cf79cea8445e40aeb
> [3] https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next.git/commit/?id=96ea081ed52bf077cad6d00153b6fba68e510767
> [4] https://github.com/kernel-patches/bpf/blob/8f2e62702ee17675464ab00d97d89d599922de20/tools/testing/selftests/bpf/gcc-bpf-selftests-logs.tgz
>
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: Errors compiling BPF programs from Linux selftests/bpf with GCC
2025-01-03 23:48 ` Ihor Solodrai
2025-01-03 23:56 ` Andrew Pinski
@ 2025-01-04 8:05 ` Jose E. Marchesi
1 sibling, 0 replies; 21+ messages in thread
From: Jose E. Marchesi @ 2025-01-04 8:05 UTC (permalink / raw)
To: Ihor Solodrai
Cc: bpf, gcc@gcc.gnu.org, Cupertino Miranda, David Faust,
Elena Zannoni, Alexei Starovoitov, Manu Bretelle,
Eduard Zingerman, Mykola Lysenko, Yonghong Song, Andrew Pinski,
Sam James, Andrii Nakryiko
> Hi everyone.
>
> I built and ran selftests/bpf with GCC 15-20241229, and would like to
> share my findings.
>
> Building required small adjustments in the Makefile, besides -std=gnu17
>
> With the following change we can mitigate int64_t issue:
>
> +progs/test_cls_redirect.c-CFLAGS := -nostdinc
> +progs/test_cls_redirect_dynptr.c-CFLAGS := -nostdinc
> +progs/test_cls_redirect_subprogs.c-CFLAGS := -nostdinc
These shouldn' be necessary anymore after the change in
https://gcc.gnu.org/pipermail/gcc-patches/2025-January/672508.html
> Then, the compiler complains about an uninitialized variable in
> progs/verifier_bpf_fastcall.c and progs/verifier_search_pruning.c
> (full log at [1]):
>
> In file included from progs/verifier_bpf_fastcall.c:7:
> progs/verifier_bpf_fastcall.c: In function ‘may_goto_interaction’:
> progs/bpf_misc.h:153:42: error: ‘<Uc098>’ is used uninitialized [-Werror=uninitialized]
> 153 | #define __imm_insn(name, expr) [name]"i"(*(long *)&(expr))
> | ^~~~~~~~~~~~~~~~
> progs/verifier_bpf_fastcall.c:652:11: note: in expansion of macro ‘__imm_insn’
> 652 | __imm_insn(may_goto, BPF_RAW_INSN(BPF_JMP | BPF_JCOND, 0, 0, +1 /* offset */, 0))
> | ^~~~~~~~~~
> /ci/workspace/tools/testing/selftests/bpf/../../../include/linux/filter.h:299:28:
> note: ‘({anonymous})’ declared here
> 299 | ((struct bpf_insn) { \
> | ^
> progs/bpf_misc.h:153:53: note: in definition of macro ‘__imm_insn’
> 153 | #define __imm_insn(name, expr) [name]"i"(*(long *)&(expr))
> | ^~~~
> progs/verifier_bpf_fastcall.c:652:32: note: in expansion of macro ‘BPF_RAW_INSN’
> 652 | __imm_insn(may_goto, BPF_RAW_INSN(BPF_JMP | BPF_JCOND, 0, 0, +1 /* offset */, 0))
>
> BPF_RAW_INSN expands into struct init expr (include/linux/filter.h):
>
> #define BPF_RAW_INSN(CODE, DST, SRC, OFF, IMM) \
> ((struct bpf_insn) { \
> .code = CODE, \
> .dst_reg = DST, \
> .src_reg = SRC, \
> .off = OFF, \
> .imm = IMM })
>
> This can be silenced with:
>
> +progs/verifier_bpf_fastcall.c-CFLAGS := -Wno-error
> +progs/verifier_search_pruning.c-CFLAGS := -Wno-error
Ignoring the warning doesn't cure the resulting undefined behavior.
These selftests seems to be violating strict aliasing rules, so it is
better to either change the testcase to work well with anti-aliasing
rules or to disable strict aliasing, like it is done for many other
tests already:
progs/verifier_bpf_fastcall.c-CFLAGS := -fno-strict-aliasing
progs/verifier_search_pruning.c-CFLAGS := -fno-strict-aliasing
> Then the selftests/bpf build completes successfully, although libbpf
> prints a lot of warnings like these on GEN-SKEL:
>
> [...]
> libbpf: elf: skipping section(3) .data (size 0)
> libbpf: elf: skipping section(4) .data (size 0)
> libbpf: elf: skipping unrecognized data section(13) .comment
> libbpf: elf: skipping unrecognized data section(9) .comment
> libbpf: elf: skipping unrecognized data section(12) .comment
> libbpf: elf: skipping unrecognized data section(7) .comment
> [...]
>
> Test .bpf.o files are compiled regardless. Full log at [2].
>
> Running all tests at once, as is usually done on CI, produces a too
> cluttered log. I wrote a script to run each test individually in a
> separate qemu instance and collect the logs.
>
> 187/581 of toplevel tests fail on current bpf-next [3]. Many tests
> have subtests: toplevel test passes if all of its subtests pass.
Thanks for the report.
>
> You can find the archive with per-test logs at [4].
>
> [1] https://gist.github.com/theihor/10b2425e6780fcfebb80aeceafba7678
> [2] https://gist.github.com/theihor/9e96643ca730365cf79cea8445e40aeb
> [3] https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next.git/commit/?id=96ea081ed52bf077cad6d00153b6fba68e510767
> [4] https://github.com/kernel-patches/bpf/blob/8f2e62702ee17675464ab00d97d89d599922de20/tools/testing/selftests/bpf/gcc-bpf-selftests-logs.tgz
^ permalink raw reply [flat|nested] 21+ messages in thread
end of thread, other threads:[~2025-01-04 8:06 UTC | newest]
Thread overview: 21+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-12-30 20:08 Errors compiling BPF programs from Linux selftests/bpf with GCC Ihor Solodrai
2024-12-30 20:24 ` Andrew Pinski
2024-12-30 20:36 ` Sam James
2024-12-30 20:59 ` Ihor Solodrai
2024-12-30 21:08 ` Sam James
2024-12-31 0:42 ` Alexei Starovoitov
2024-12-31 1:26 ` Ihor Solodrai
2024-12-31 4:09 ` Alexei Starovoitov
2025-01-02 9:47 ` Jose E. Marchesi
2025-01-02 17:35 ` Ihor Solodrai
2025-01-02 18:24 ` Jose E. Marchesi
2025-01-03 0:42 ` Eduard Zingerman
2025-01-03 13:23 ` Jose E. Marchesi
2025-01-02 23:04 ` Eduard Zingerman
2025-01-03 0:16 ` Jose E. Marchesi
2025-01-03 0:46 ` Eduard Zingerman
2025-01-03 10:17 ` Jose E. Marchesi
2025-01-03 12:52 ` Jose E. Marchesi
2025-01-03 23:48 ` Ihor Solodrai
2025-01-03 23:56 ` Andrew Pinski
2025-01-04 8:05 ` Jose E. Marchesi
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox