]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
bpf: refactor skeleton generation
authorJames Hilliard <james.hilliard1@gmail.com>
Thu, 12 Aug 2021 03:59:19 +0000 (21:59 -0600)
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Tue, 7 Dec 2021 17:37:17 +0000 (18:37 +0100)
This should hopefully fix cross compilation for the bpf programs.

12 files changed:
meson.build
src/core/bpf-socket-bind.c
src/core/bpf/meson.build [new file with mode: 0644]
src/core/bpf/restrict_fs/meson.build
src/core/bpf/restrict_fs/restrict-fs-skel.h [new file with mode: 0644]
src/core/bpf/restrict_ifaces/meson.build
src/core/bpf/restrict_ifaces/restrict-ifaces-skel.h [new file with mode: 0644]
src/core/bpf/socket_bind/meson.build
src/core/bpf/socket_bind/socket-bind-skel.h [new file with mode: 0644]
src/core/meson.build
src/core/restrict-ifaces.c
tools/build-bpf-skel.py [deleted file]

index 519de53345976f83d7ab58057727dcf60147db9d..2115e7f991839b4e5abd2d5f83cf3ab07d5aa45b 100644 (file)
@@ -1008,11 +1008,9 @@ else
         # We check for 'bpftool' first, honouring $PATH, and in /usr/sbin/ for Debian.
         bpftool = find_program('bpftool', '/usr/sbin/bpftool', required : bpf_framework_required)
 
-        bpf_arches = ['x86_64']
         deps_found = libbpf.found() and clang.found() and llvm_strip.found() and bpftool.found()
         # Can build BPF program from source code in restricted C
-        conf.set10('BPF_FRAMEWORK',
-                bpf_arches.contains(host_machine.cpu_family()) and deps_found)
+        conf.set10('BPF_FRAMEWORK', deps_found)
 endif
 
 libmount = dependency('mount',
@@ -1685,7 +1683,6 @@ subdir('src/boot/efi')
 
 ############################################################
 
-build_bpf_skel_py = find_program('tools/build-bpf-skel.py')
 generate_gperfs = find_program('tools/generate-gperfs.py')
 make_autosuspend_rules_py = find_program('tools/make-autosuspend-rules.py')
 make_directive_index_py = find_program('tools/make-directive-index.py')
index e9c0a2f9bd284bef892dc33b1cdd8367129d1607..c5176aa481a45289ff2d4f9e082b2eeb9c3a5660 100644 (file)
@@ -11,7 +11,7 @@
 /* libbpf, clang, llvm and bpftool compile time dependencies are satisfied */
 #include "bpf-dlopen.h"
 #include "bpf-link.h"
-#include "bpf/socket_bind/socket-bind.skel.h"
+#include "bpf/socket_bind/socket-bind-skel.h"
 #include "bpf/socket_bind/socket-bind-api.bpf.h"
 
 static struct socket_bind_bpf *socket_bind_bpf_free(struct socket_bind_bpf *obj) {
diff --git a/src/core/bpf/meson.build b/src/core/bpf/meson.build
new file mode 100644 (file)
index 0000000..ab1a716
--- /dev/null
@@ -0,0 +1,61 @@
+# SPDX-License-Identifier: LGPL-2.1+
+
+if conf.get('BPF_FRAMEWORK') == 1
+        clang_flags = [
+                '-Wno-compare-distinct-pointer-types',
+                '-O2',
+                '-target',
+                'bpf',
+                '-g',
+                '-c',
+        ]
+
+        clang_arch_flag = '-D__@0@__'.format(host_machine.cpu_family())
+
+        if meson.version().version_compare('>= 0.58')
+                libbpf_include_dir = libbpf.get_variable('includedir')
+        else
+                libbpf_include_dir = libbpf.get_variable(pkgconfig : 'includedir')
+        endif
+
+        bpf_o_unstripped_cmd = [
+                clang,
+                clang_flags,
+                clang_arch_flag,
+                '-I.'
+        ]
+
+        if not meson.is_cross_build()
+                target_triplet_cmd = run_command('gcc', '-dumpmachine', check: false)
+                if target_triplet_cmd.returncode() == 0
+                        target_triplet = target_triplet_cmd.stdout().strip()
+                        bpf_o_unstripped_cmd += [
+                                '-isystem',
+                                '/usr/include/@0@'.format(target_triplet)
+                        ]
+                endif
+        endif
+
+        bpf_o_unstripped_cmd += [
+                '-idirafter',
+                libbpf_include_dir,
+                '@INPUT@',
+                '-o',
+                '@OUTPUT@'
+        ]
+
+        bpf_o_cmd = [
+                llvm_strip,
+                '-g',
+                '@INPUT@',
+                '-o',
+                '@OUTPUT@'
+        ]
+
+        skel_h_cmd = [
+                bpftool,
+                'g',
+                's',
+                '@INPUT@'
+        ]
+endif
index c92cccae260e337d449bb62e12e7395f29512758..dfe3f120337916d7fb936b6d75566d02a4ca26e9 100644 (file)
@@ -1,14 +1,22 @@
 # SPDX-License-Identifier: LGPL-2.1-or-later
 
 if conf.get('BPF_FRAMEWORK') == 1
-        restrict_fs_skel_h = custom_target(
-                'restrict-fs-skel.h',
+        restrict_fs_bpf_o_unstripped = custom_target(
+                'restrict-fs.bpf.unstripped.o',
                 input : 'restrict-fs.bpf.c',
-                output : 'restrict-fs-skel.h',
-                command : [build_bpf_skel_py,
-                           '--clang_exec', clang.path(),
-                           '--llvm_strip_exec', llvm_strip.path(),
-                           '--bpftool_exec', bpftool.path(),
-                           '--arch', host_machine.cpu_family(),
-                           '@INPUT@', '@OUTPUT@'])
+                output : 'restrict-fs.bpf.unstripped.o',
+                command : bpf_o_unstripped_cmd)
+
+        restrict_fs_bpf_o = custom_target(
+                'restrict-fs.bpf.o',
+                input : restrict_fs_bpf_o_unstripped,
+                output : 'restrict-fs.bpf.o',
+                command : bpf_o_cmd)
+
+        restrict_fs_skel_h = custom_target(
+                'restrict-fs.skel.h',
+                input : restrict_fs_bpf_o,
+                output : 'restrict-fs.skel.h',
+                command : skel_h_cmd,
+                capture : true)
 endif
diff --git a/src/core/bpf/restrict_fs/restrict-fs-skel.h b/src/core/bpf/restrict_fs/restrict-fs-skel.h
new file mode 100644 (file)
index 0000000..412cf62
--- /dev/null
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+/* The SPDX header above is actually correct in claiming this was
+ * LGPL-2.1-or-later, because it is. Since the kernel doesn't consider that
+ * compatible with GPL we will claim this to be GPL however, which should be
+ * fine given that LGPL-2.1-or-later downgrades to GPL if needed.
+ */
+
+/* libbpf is used via dlopen(), so rename symbols */
+#define bpf_object__open_skeleton sym_bpf_object__open_skeleton
+#define bpf_object__load_skeleton sym_bpf_object__load_skeleton
+#define bpf_object__destroy_skeleton sym_bpf_object__destroy_skeleton
+
+#include "bpf/restrict_fs/restrict-fs.skel.h"
index 38f7dbbd5119a68b3c9e6f9691b5979a60407135..b7e2bc15197a58c7daedc37d3555322c8d2d949e 100644 (file)
@@ -1,14 +1,22 @@
 # SPDX-License-Identifier: LGPL-2.1-or-later
 
 if conf.get('BPF_FRAMEWORK') == 1
+        restrict_ifaces_bpf_o_unstripped = custom_target(
+                'restrict-ifaces.bpf.unstripped.o',
+                input : 'restrict-ifaces.bpf.c',
+                output : 'restrict-ifaces.bpf.unstripped.o',
+                command : bpf_o_unstripped_cmd)
+
+        restrict_ifaces_bpf_o = custom_target(
+                'restrict-ifaces.bpf.o',
+                input : restrict_ifaces_bpf_o_unstripped,
+                output : 'restrict-ifaces.bpf.o',
+                command : bpf_o_cmd)
+
         restrict_ifaces_skel_h = custom_target(
                 'restrict-ifaces.skel.h',
-                input : 'restrict-ifaces.bpf.c',
+                input : restrict_ifaces_bpf_o,
                 output : 'restrict-ifaces.skel.h',
-                command : [build_bpf_skel_py,
-                           '--clang_exec', clang.path(),
-                           '--llvm_strip_exec', llvm_strip.path(),
-                           '--bpftool_exec', bpftool.path(),
-                           '--arch', host_machine.cpu_family(),
-                           '@INPUT@', '@OUTPUT@'])
+                command : skel_h_cmd,
+                capture : true)
 endif
diff --git a/src/core/bpf/restrict_ifaces/restrict-ifaces-skel.h b/src/core/bpf/restrict_ifaces/restrict-ifaces-skel.h
new file mode 100644 (file)
index 0000000..f937490
--- /dev/null
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+/* The SPDX header above is actually correct in claiming this was
+ * LGPL-2.1-or-later, because it is. Since the kernel doesn't consider that
+ * compatible with GPL we will claim this to be GPL however, which should be
+ * fine given that LGPL-2.1-or-later downgrades to GPL if needed.
+ */
+
+/* libbpf is used via dlopen(), so rename symbols */
+#define bpf_object__open_skeleton sym_bpf_object__open_skeleton
+#define bpf_object__load_skeleton sym_bpf_object__load_skeleton
+#define bpf_object__destroy_skeleton sym_bpf_object__destroy_skeleton
+
+#include "bpf/restrict_ifaces/restrict-ifaces.skel.h"
index f5cfc04b0067ee6c2870482406487f6af24a9945..8211a7a5c91498f0f766ecdec1cebbe489a243da 100644 (file)
@@ -1,14 +1,22 @@
 # SPDX-License-Identifier: LGPL-2.1-or-later
 
 if conf.get('BPF_FRAMEWORK') == 1
+        socket_bind_bpf_o_unstripped = custom_target(
+                'socket-bind.bpf.unstripped.o',
+                input : 'socket-bind.bpf.c',
+                output : 'socket-bind.bpf.unstripped.o',
+                command : bpf_o_unstripped_cmd)
+
+        socket_bind_bpf_o = custom_target(
+                'socket-bind.bpf.o',
+                input : socket_bind_bpf_o_unstripped,
+                output : 'socket-bind.bpf.o',
+                command : bpf_o_cmd)
+
         socket_bind_skel_h = custom_target(
                 'socket-bind.skel.h',
-                input : 'socket-bind.bpf.c',
+                input : socket_bind_bpf_o,
                 output : 'socket-bind.skel.h',
-                command : [build_bpf_skel_py,
-                           '--clang_exec', clang.path(),
-                           '--llvm_strip_exec', llvm_strip.path(),
-                           '--bpftool_exec', bpftool.path(),
-                           '--arch', host_machine.cpu_family(),
-                           '@INPUT@', '@OUTPUT@'])
+                command : skel_h_cmd,
+                capture : true)
 endif
diff --git a/src/core/bpf/socket_bind/socket-bind-skel.h b/src/core/bpf/socket_bind/socket-bind-skel.h
new file mode 100644 (file)
index 0000000..e0d1626
--- /dev/null
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: LGPL-2.1-or-later */
+
+/* The SPDX header above is actually correct in claiming this was
+ * LGPL-2.1-or-later, because it is. Since the kernel doesn't consider that
+ * compatible with GPL we will claim this to be GPL however, which should be
+ * fine given that LGPL-2.1-or-later downgrades to GPL if needed.
+ */
+
+/* libbpf is used via dlopen(), so rename symbols */
+#define bpf_object__open_skeleton sym_bpf_object__open_skeleton
+#define bpf_object__load_skeleton sym_bpf_object__load_skeleton
+#define bpf_object__destroy_skeleton sym_bpf_object__destroy_skeleton
+
+#include "bpf/socket_bind/socket-bind.skel.h"
index c02543bd062f7f079efb9e98296c889b04b3df92..92a811f2f060e076d33a874e6322ea943fc899f2 100644 (file)
@@ -133,6 +133,8 @@ libcore_sources = '''
         unit.h
 '''.split()
 
+subdir('bpf')
+
 subdir('bpf/socket_bind')
 if conf.get('BPF_FRAMEWORK') == 1
         libcore_sources += [socket_bind_skel_h]
index a17c5d2bf7b80268282b4b3c1d7525cdd3b5560a..7650031434eec4bc2c0c1639f7782333e96efdc1 100644 (file)
@@ -10,7 +10,7 @@
 #include "bpf-dlopen.h"
 #include "bpf-link.h"
 
-#include "bpf/restrict_ifaces/restrict-ifaces.skel.h"
+#include "bpf/restrict_ifaces/restrict-ifaces-skel.h"
 
 static struct restrict_ifaces_bpf *restrict_ifaces_bpf_free(struct restrict_ifaces_bpf *obj) {
         restrict_ifaces_bpf__destroy(obj);
diff --git a/tools/build-bpf-skel.py b/tools/build-bpf-skel.py
deleted file mode 100755 (executable)
index 0752174..0000000
+++ /dev/null
@@ -1,128 +0,0 @@
-#!/usr/bin/env python3
-# SPDX-License-Identifier: LGPL-2.1-or-later
-
-import argparse
-import logging
-import pathlib
-import re
-import subprocess
-import sys
-
-def clang_arch_flag(arch):
-    return '-D__{}__'.format(arch)
-
-
-def target_triplet():
-    gcc_exec = 'gcc'
-
-    try:
-        return subprocess.check_output([gcc_exec, '-dumpmachine'],
-                universal_newlines=True).strip()
-    except subprocess.CalledProcessError as e:
-        logging.error('Failed to get target triplet: {}'.format(e))
-    except FileNotFoundError:
-        logging.error('gcc not installed')
-    return None
-
-
-def clang_compile(clang_exec, clang_flags, src_c, out_file, target_arch,
-        target_triplet):
-    clang_args = [clang_exec, *clang_flags, target_arch, '-I.']
-
-    if target_triplet:
-        clang_args += [
-            '-isystem',
-            '/usr/include/{}'.format(target_triplet)]
-
-    clang_args += [
-        '-idirafter',
-        '/usr/local/include',
-        '-idirafter',
-        '/usr/include']
-
-    clang_args += [src_c, '-o', out_file]
-
-    logging.debug('{}'.format(' '.join(clang_args)))
-    subprocess.check_call(clang_args)
-
-
-def llvm_strip(llvm_strip_exec, in_file):
-    llvm_strip_args = [llvm_strip_exec, '-g', in_file]
-
-    logging.debug('Stripping useless DWARF info:')
-    logging.debug('{}'.format(' '.join(llvm_strip_args)))
-
-    subprocess.check_call(llvm_strip_args)
-
-
-def gen_bpf_skeleton(bpftool_exec, in_file, out_fd):
-    bpftool_args = [bpftool_exec, 'g', 's', in_file]
-
-    logging.debug('Generating BPF skeleton:')
-    logging.debug('{}'.format(' '.join(bpftool_args)))
-    skel = subprocess.check_output(bpftool_args, universal_newlines=True)
-    # libbpf is used via dlopen(), so rename symbols as defined
-    # in src/shared/bpf-dlopen.h
-    skel = re.sub(r'(bpf_object__\w+_skeleton)', r'sym_\1', skel)
-    out_fd.write(skel)
-
-
-def bpf_build(args):
-    clang_flags = [
-            '-Wno-compare-distinct-pointer-types',
-            '-O2',
-            '-target',
-            'bpf',
-            '-g',
-            '-c',
-    ]
-
-    clang_out_path = pathlib.Path(args.bpf_src_c).with_suffix('.o')
-    with clang_out_path.open(mode='w') as clang_out, \
-            open(args.bpf_skel_h, mode='w') as bpf_skel_h:
-        clang_compile(clang_exec=args.clang_exec,
-                clang_flags=clang_flags,
-                src_c=args.bpf_src_c,
-                out_file=clang_out.name,
-                target_arch=clang_arch_flag(args.arch),
-                target_triplet=target_triplet())
-
-        llvm_strip(llvm_strip_exec=args.llvm_strip_exec, in_file=clang_out.name)
-
-        gen_bpf_skeleton(bpftool_exec=args.bpftool_exec,
-                in_file=clang_out.name,
-                out_fd=bpf_skel_h)
-
-if __name__ == '__main__':
-    parser = argparse.ArgumentParser()
-
-    parser.add_argument(
-            'bpf_src_c',
-            help='Path to *.c source of BPF program in systemd source tree \
-                    relative to the work directory')
-
-    parser.add_argument(
-            'bpf_skel_h',
-            help='Path to C header file')
-
-    parser.add_argument(
-            '--clang_exec',
-            help='Path to clang exec')
-
-    parser.add_argument(
-            '--llvm_strip_exec',
-            help='Path to llvm-strip exec')
-
-    parser.add_argument(
-            '--bpftool_exec',
-            help='Path to bpftool exec')
-
-    parser.add_argument(
-            '--arch',
-            help='Target CPU architecture',
-            default='x86_64')
-
-    args = parser.parse_args();
-
-    logging.basicConfig(stream=sys.stderr, level=logging.WARNING)
-    bpf_build(args)