gcc-12-20250102 is now available
Snapshot gcc-12-20250102 is now available on https://gcc.gnu.org/pub/gcc/snapshots/12-20250102/ and on various mirrors, see https://gcc.gnu.org/mirrors.html for details. This snapshot has been generated from the GCC 12 git branch with the following options: git://gcc.gnu.org/git/gcc.git branch releases/gcc-12 revision df5e5d0ad7764b159848c95acaff848f67f5f574 You'll find: gcc-12-20250102.tar.xz Complete GCC SHA256=dcb3fa61be36019bb94192d358e7cba7170185f799005548e0e3ef0192d3918c SHA1=539b814b07f80c8416212fdb2b52df28a2769aa6 Diffs from 12-20241226 are available in the diffs/ subdirectory. When a particular snapshot is ready for public consumption the LATEST-12 link is updated and a message is sent to the gcc list. Please do not use a snapshot before it has been announced that way.
Re: Errors compiling BPF programs from Linux selftests/bpf with GCC
> 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 __WORDSIZE64 >> #else >> # define __WORDSIZE32 >> #define __WORDSIZE32_SIZE_ULONG0 >> #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: > - /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() > ... > # include_next > ... > #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 #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 "
Re: Errors compiling BPF programs from Linux selftests/bpf with GCC
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: - /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() ... # include_next ... #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
Re: Errors compiling BPF programs from Linux selftests/bpf with GCC
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 > #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.
Re: Errors compiling BPF programs from Linux selftests/bpf with GCC
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 /* for compatibility with glibc */ #include /* for "__kernel_caddr_t" et al */ #include/* for "struct sockaddr" et al */ #include /* for "__user" et al */ #ifndef __KERNEL__ #include /* 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 /* for compatibility with glibc */ #include /* for "__kernel_caddr_t" et al */ #include/* for "struct sockaddr" et al */ /* for "__user" et al */ #include /* 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.
Re: [RFC] Enabling SVE with offloading to nvptx
On 27/12/2024 12:29, Prathamesh Kulkarni wrote: -Original Message- From: Jakub Jelinek Sent: 17 December 2024 19:09 To: Prathamesh Kulkarni Cc: Andrew Stubbs ; Richard Biener ; Richard Biener ; gcc@gcc.gnu.org; Thomas Schwinge Subject: Re: [RFC] Enabling SVE with offloading to nvptx External email: Use caution opening links or attachments On Mon, Dec 02, 2024 at 11:17:08AM +, Prathamesh Kulkarni wrote: --- a/gcc/cfgloop.h +++ b/gcc/cfgloop.h @@ -233,6 +233,12 @@ public: flag_finite_loops or similar pragmas state. */ unsigned finite_p : 1; + /* True if SIMD loop needs delayed lowering of artefacts like + safelen and length of omp simd arrays that depend on target's + max_vf. This is true for offloading, when max_vf is computed after + streaming out to device. */ + unsigned needs_max_vf_lowering: 1; Consistency, finite_p above uses space before :, the above line doesn't. --- a/gcc/omp-expand.cc +++ b/gcc/omp-expand.cc @@ -7170,6 +7170,10 @@ expand_omp_simd (struct omp_region *region, struct omp_for_data *fd) loop->latch = cont_bb; add_loop (loop, l1_bb->loop_father); loop->safelen = safelen_int; + loop->needs_max_vf_lowering = is_in_offload_region (region); + if (loop->needs_max_vf_lowering) + cfun->curr_properties &= ~PROP_gimple_lomp_dev; Do you really need this for non-SVE arches? I mean, could you not set loop->needs_max_vf_lowering if maximum number of poly_int coeffs is 1? Or if omp_max_vf returns constant or something similar? Well, I guess the issue is not really about VLA vectors but when host and device have different max_vf, and selecting optimal max_vf is not really possible during omp-low/omp-expand, since we don't have device's target info available at this point. Andrew's recent patch works around this limitation by searching for "amdgcn" in OFFLOAD_TARGET_NAMES in omp_max_vf, but I guess a more general solution would be to delay lowering max_vf after streaming-out to device irrespective of VLA/VLS vectors ? For AArch64/nvptx offloading with SVE, where host is VLA and device is VLS, the issue is more pronounced (failing to compile), compared to offloading from VLS host to VLS device (selecting sub-optimal max_vf). That patch fixed a couple of cases. The name matching was only used for the case where an oversized VF was harmless. The other case where making the VF too large would reserve excess memory was deferred to the device compiler. In general, deferring decisions is probably a good idea, but it's not always possible, or optimal, and in the above case it certainly wasn't the easy option. There's already precedent for doing the name match in the SIMT VF code (for NVPTX), so it was easier and sufficient to do the same. Andrew
Re: smtgcc end-of-year update
Krister Walfridsson via Gcc writes: > But running smtgcc on the test suite is not the best use case for the > tool -- it only detects bugs where the test triggers an unrelated bug > compared to what the test is checking, which should be uncommon. I > therefore plan to start testing by compiling real-world code and doing > some fuzzing. One problem is that this often finds the open bugs > mentioned in the previous section, making it time-consuming to check > if each new issue is a repeat. For example, running yarpgen gives me a > few failure reports per day of PR106883. I would increase the priority of PR106883 if it blocks so much testing. But does disabling the slsr pass not help? -Andi
Re: Errors compiling BPF programs from Linux selftests/bpf with GCC
> On Thursday, January 2nd, 2025 at 1:47 AM, 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. > > 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 > #include > #include// conflict is between this > #include > > #include > #include// and this > #include > ... > > 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 selft
Re: Errors compiling BPF programs from Linux selftests/bpf with GCC
On Thursday, January 2nd, 2025 at 1:47 AM, 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. 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 #include #include// conflict is between this #include #include #include// and this #include ... Any suggestions? Thanks.
Re: Errors compiling BPF programs from Linux selftests/bpf with GCC
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