From: "Jose E. Marchesi" <jose.marchesi@oracle.com>
To: Eduard Zingerman <eddyz87@gmail.com>
Cc: Ihor Solodrai <ihor.solodrai@pm.me>,
"gcc@gcc.gnu.org" <gcc@gcc.gnu.org>,
Cupertino Miranda <cupertino.miranda@oracle.com>,
David Faust <david.faust@oracle.com>,
Elena Zannoni <elena.zannoni@oracle.com>,
Alexei Starovoitov <alexei.starovoitov@gmail.com>,
Manu Bretelle <chantra@meta.com>,
Mykola Lysenko <mykolal@meta.com>,
Yonghong Song <yonghong.song@linux.dev>,
bpf <bpf@vger.kernel.org>
Subject: Re: Errors compiling BPF programs from Linux selftests/bpf with GCC
Date: Fri, 03 Jan 2025 14:23:33 +0100 [thread overview]
Message-ID: <87ldvsuj3e.fsf@oracle.com> (raw)
In-Reply-To: <5fc0ff106733d93488e4dba03f23a9ab71444fb1.camel@gmail.com> (Eduard Zingerman's message of "Thu, 02 Jan 2025 16:42:50 -0800")
> 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.
next prev parent reply other threads:[~2025-01-03 13:24 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
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 [this message]
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
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=87ldvsuj3e.fsf@oracle.com \
--to=jose.marchesi@oracle.com \
--cc=alexei.starovoitov@gmail.com \
--cc=bpf@vger.kernel.org \
--cc=chantra@meta.com \
--cc=cupertino.miranda@oracle.com \
--cc=david.faust@oracle.com \
--cc=eddyz87@gmail.com \
--cc=elena.zannoni@oracle.com \
--cc=gcc@gcc.gnu.org \
--cc=ihor.solodrai@pm.me \
--cc=mykolal@meta.com \
--cc=yonghong.song@linux.dev \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox