mirror of
https://github.com/systemd/systemd.git
synced 2024-12-22 17:35:35 +03:00
bpf: refactor skeleton generation
This should hopefully fix cross compilation for the bpf programs.
This commit is contained in:
parent
d4f8cd4d83
commit
d40ce01814
@ -1008,11 +1008,9 @@ else
|
|||||||
# We check for 'bpftool' first, honouring $PATH, and in /usr/sbin/ for Debian.
|
# We check for 'bpftool' first, honouring $PATH, and in /usr/sbin/ for Debian.
|
||||||
bpftool = find_program('bpftool', '/usr/sbin/bpftool', required : bpf_framework_required)
|
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()
|
deps_found = libbpf.found() and clang.found() and llvm_strip.found() and bpftool.found()
|
||||||
# Can build BPF program from source code in restricted C
|
# Can build BPF program from source code in restricted C
|
||||||
conf.set10('BPF_FRAMEWORK',
|
conf.set10('BPF_FRAMEWORK', deps_found)
|
||||||
bpf_arches.contains(host_machine.cpu_family()) and deps_found)
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
libmount = dependency('mount',
|
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')
|
generate_gperfs = find_program('tools/generate-gperfs.py')
|
||||||
make_autosuspend_rules_py = find_program('tools/make-autosuspend-rules.py')
|
make_autosuspend_rules_py = find_program('tools/make-autosuspend-rules.py')
|
||||||
make_directive_index_py = find_program('tools/make-directive-index.py')
|
make_directive_index_py = find_program('tools/make-directive-index.py')
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
/* libbpf, clang, llvm and bpftool compile time dependencies are satisfied */
|
/* libbpf, clang, llvm and bpftool compile time dependencies are satisfied */
|
||||||
#include "bpf-dlopen.h"
|
#include "bpf-dlopen.h"
|
||||||
#include "bpf-link.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"
|
#include "bpf/socket_bind/socket-bind-api.bpf.h"
|
||||||
|
|
||||||
static struct socket_bind_bpf *socket_bind_bpf_free(struct socket_bind_bpf *obj) {
|
static struct socket_bind_bpf *socket_bind_bpf_free(struct socket_bind_bpf *obj) {
|
||||||
|
61
src/core/bpf/meson.build
Normal file
61
src/core/bpf/meson.build
Normal file
@ -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
|
@ -1,14 +1,22 @@
|
|||||||
# SPDX-License-Identifier: LGPL-2.1-or-later
|
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||||
|
|
||||||
if conf.get('BPF_FRAMEWORK') == 1
|
if conf.get('BPF_FRAMEWORK') == 1
|
||||||
restrict_fs_skel_h = custom_target(
|
restrict_fs_bpf_o_unstripped = custom_target(
|
||||||
'restrict-fs-skel.h',
|
'restrict-fs.bpf.unstripped.o',
|
||||||
input : 'restrict-fs.bpf.c',
|
input : 'restrict-fs.bpf.c',
|
||||||
output : 'restrict-fs-skel.h',
|
output : 'restrict-fs.bpf.unstripped.o',
|
||||||
command : [build_bpf_skel_py,
|
command : bpf_o_unstripped_cmd)
|
||||||
'--clang_exec', clang.path(),
|
|
||||||
'--llvm_strip_exec', llvm_strip.path(),
|
restrict_fs_bpf_o = custom_target(
|
||||||
'--bpftool_exec', bpftool.path(),
|
'restrict-fs.bpf.o',
|
||||||
'--arch', host_machine.cpu_family(),
|
input : restrict_fs_bpf_o_unstripped,
|
||||||
'@INPUT@', '@OUTPUT@'])
|
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
|
endif
|
||||||
|
14
src/core/bpf/restrict_fs/restrict-fs-skel.h
Normal file
14
src/core/bpf/restrict_fs/restrict-fs-skel.h
Normal file
@ -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"
|
@ -1,14 +1,22 @@
|
|||||||
# SPDX-License-Identifier: LGPL-2.1-or-later
|
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||||
|
|
||||||
if conf.get('BPF_FRAMEWORK') == 1
|
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 = custom_target(
|
||||||
'restrict-ifaces.skel.h',
|
'restrict-ifaces.skel.h',
|
||||||
input : 'restrict-ifaces.bpf.c',
|
input : restrict_ifaces_bpf_o,
|
||||||
output : 'restrict-ifaces.skel.h',
|
output : 'restrict-ifaces.skel.h',
|
||||||
command : [build_bpf_skel_py,
|
command : skel_h_cmd,
|
||||||
'--clang_exec', clang.path(),
|
capture : true)
|
||||||
'--llvm_strip_exec', llvm_strip.path(),
|
|
||||||
'--bpftool_exec', bpftool.path(),
|
|
||||||
'--arch', host_machine.cpu_family(),
|
|
||||||
'@INPUT@', '@OUTPUT@'])
|
|
||||||
endif
|
endif
|
||||||
|
14
src/core/bpf/restrict_ifaces/restrict-ifaces-skel.h
Normal file
14
src/core/bpf/restrict_ifaces/restrict-ifaces-skel.h
Normal file
@ -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"
|
@ -1,14 +1,22 @@
|
|||||||
# SPDX-License-Identifier: LGPL-2.1-or-later
|
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||||
|
|
||||||
if conf.get('BPF_FRAMEWORK') == 1
|
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 = custom_target(
|
||||||
'socket-bind.skel.h',
|
'socket-bind.skel.h',
|
||||||
input : 'socket-bind.bpf.c',
|
input : socket_bind_bpf_o,
|
||||||
output : 'socket-bind.skel.h',
|
output : 'socket-bind.skel.h',
|
||||||
command : [build_bpf_skel_py,
|
command : skel_h_cmd,
|
||||||
'--clang_exec', clang.path(),
|
capture : true)
|
||||||
'--llvm_strip_exec', llvm_strip.path(),
|
|
||||||
'--bpftool_exec', bpftool.path(),
|
|
||||||
'--arch', host_machine.cpu_family(),
|
|
||||||
'@INPUT@', '@OUTPUT@'])
|
|
||||||
endif
|
endif
|
||||||
|
14
src/core/bpf/socket_bind/socket-bind-skel.h
Normal file
14
src/core/bpf/socket_bind/socket-bind-skel.h
Normal file
@ -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"
|
@ -133,6 +133,8 @@ libcore_sources = '''
|
|||||||
unit.h
|
unit.h
|
||||||
'''.split()
|
'''.split()
|
||||||
|
|
||||||
|
subdir('bpf')
|
||||||
|
|
||||||
subdir('bpf/socket_bind')
|
subdir('bpf/socket_bind')
|
||||||
if conf.get('BPF_FRAMEWORK') == 1
|
if conf.get('BPF_FRAMEWORK') == 1
|
||||||
libcore_sources += [socket_bind_skel_h]
|
libcore_sources += [socket_bind_skel_h]
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
#include "bpf-dlopen.h"
|
#include "bpf-dlopen.h"
|
||||||
#include "bpf-link.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) {
|
static struct restrict_ifaces_bpf *restrict_ifaces_bpf_free(struct restrict_ifaces_bpf *obj) {
|
||||||
restrict_ifaces_bpf__destroy(obj);
|
restrict_ifaces_bpf__destroy(obj);
|
||||||
|
@ -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)
|
|
Loading…
Reference in New Issue
Block a user