The current bpf_helper_defs.h helpers are llvm specific and don't work correctly with gcc. GCC requires kernel helper funcs to have the following attribute set: __attribute__((kernel_helper(NUM))) Generate gcc compatible headers based on the format in bpf-helpers.h. This leaves the bpf_helper_defs.h entirely unchanged and generates a fully separate GCC compatible bpf_helper_defs_attr.h header file which is conditionally included if the GCC kernel_helper attribute is supported. This adds GCC attribute style kernel helpers in bpf_helper_defs_attr.h: void *bpf_map_lookup_elem(void *map, const void *key) __attribute__((kernel_helper(1))); long bpf_map_update_elem(void *map, const void *key, const void *value, __u64 flags) __attribute__((kernel_helper(2))); See: https://github.com/gcc-mirror/gcc/blob/releases/gcc-12.1.0/gcc/config/bpf/bpf-helpers.h#L24-L27 This fixes the following build error: error: indirect call in function, which are not supported by eBPF Signed-off-by: James Hilliard <james.hilliard1@xxxxxxxxx> --- Changes v3 -> v4: - don't modify bpf_helper_defs.h - generate bpf_helper_defs_attr.h for GCC - check __has_attribute(kernel_helper) for selecting GCC defs Changes v2 -> v3: - use a conditional helper macro Changes v1 -> v2: - more details in commit log --- scripts/bpf_doc.py | 58 ++++++++++++++++++++++--------------- tools/lib/bpf/Makefile | 7 ++++- tools/lib/bpf/bpf_helpers.h | 4 +++ 3 files changed, 45 insertions(+), 24 deletions(-) diff --git a/scripts/bpf_doc.py b/scripts/bpf_doc.py index dfb260de17a8..c4e8fa3619d8 100755 --- a/scripts/bpf_doc.py +++ b/scripts/bpf_doc.py @@ -570,9 +570,10 @@ class PrinterHelpers(Printer): be included from BPF program. @parser: A HeaderParser with Helper objects to print to standard output """ - def __init__(self, parser): + def __init__(self, parser, attr_header): self.elements = parser.helpers self.elem_number_check(parser.desc_unique_helpers, parser.define_unique_helpers, 'helper', '__BPF_FUNC_MAPPER') + self.attr_header = attr_header type_fwds = [ 'struct bpf_fib_lookup', @@ -719,6 +720,24 @@ class PrinterHelpers(Printer): seen_helpers = set() + def print_args(self, proto): + comma = '' + for i, a in enumerate(proto['args']): + t = a['type'] + n = a['name'] + if proto['name'] in self.overloaded_helpers and i == 0: + t = 'void' + n = 'ctx' + one_arg = '{}{}'.format(comma, self.map_type(t)) + if n: + if a['star']: + one_arg += ' {}'.format(a['star']) + else: + one_arg += ' ' + one_arg += '{}'.format(n) + comma = ', ' + print(one_arg, end='') + def print_one(self, helper): proto = helper.proto_break_down() @@ -742,26 +761,16 @@ class PrinterHelpers(Printer): print(' *{}{}'.format(' \t' if line else '', line)) print(' */') - print('static %s %s(*%s)(' % (self.map_type(proto['ret_type']), - proto['ret_star'], proto['name']), end='') - comma = '' - for i, a in enumerate(proto['args']): - t = a['type'] - n = a['name'] - if proto['name'] in self.overloaded_helpers and i == 0: - t = 'void' - n = 'ctx' - one_arg = '{}{}'.format(comma, self.map_type(t)) - if n: - if a['star']: - one_arg += ' {}'.format(a['star']) - else: - one_arg += ' ' - one_arg += '{}'.format(n) - comma = ', ' - print(one_arg, end='') - - print(') = (void *) %d;' % len(self.seen_helpers)) + if self.attr_header: + print('%s %s%s(' % (self.map_type(proto['ret_type']), + proto['ret_star'], proto['name']), end='') + self.print_args(proto) + print(') __attribute__((kernel_helper(%d)));' % len(self.seen_helpers)) + else: + print('static %s %s(*%s)(' % (self.map_type(proto['ret_type']), + proto['ret_star'], proto['name']), end='') + self.print_args(proto) + print(') = (void *) %d;' % len(self.seen_helpers)) print('') ############################################################################### @@ -785,6 +794,8 @@ rst2man utility. """) argParser.add_argument('--header', action='store_true', help='generate C header file') +argParser.add_argument('--attr-header', action='store_true', + help='generate GCC attr style C header file') if (os.path.isfile(bpfh)): argParser.add_argument('--filename', help='path to include/uapi/linux/bpf.h', default=bpfh) @@ -799,10 +810,11 @@ headerParser = HeaderParser(args.filename) headerParser.run() # Print formatted output to standard output. -if args.header: +if args.header or args.attr_header: if args.target != 'helpers': raise NotImplementedError('Only helpers header generation is supported') - printer = PrinterHelpers(headerParser) + attr_header = True if args.attr_header else False + printer = PrinterHelpers(headerParser, attr_header) else: printer = printers[args.target](headerParser) printer.print_all() diff --git a/tools/lib/bpf/Makefile b/tools/lib/bpf/Makefile index 4c904ef0b47e..cf9efe764030 100644 --- a/tools/lib/bpf/Makefile +++ b/tools/lib/bpf/Makefile @@ -116,7 +116,8 @@ STATIC_OBJDIR := $(OUTPUT)staticobjs/ BPF_IN_SHARED := $(SHARED_OBJDIR)libbpf-in.o BPF_IN_STATIC := $(STATIC_OBJDIR)libbpf-in.o BPF_HELPER_DEFS := $(OUTPUT)bpf_helper_defs.h -BPF_GENERATED := $(BPF_HELPER_DEFS) +BPF_HELPER_DEFS_ATTR := $(OUTPUT)bpf_helper_defs_attr.h +BPF_GENERATED := $(BPF_HELPER_DEFS) $(BPF_HELPER_DEFS_ATTR) LIB_TARGET := $(addprefix $(OUTPUT),$(LIB_TARGET)) LIB_FILE := $(addprefix $(OUTPUT),$(LIB_FILE)) @@ -160,6 +161,10 @@ $(BPF_HELPER_DEFS): $(srctree)/tools/include/uapi/linux/bpf.h $(QUIET_GEN)$(srctree)/scripts/bpf_doc.py --header \ --file $(srctree)/tools/include/uapi/linux/bpf.h > $(BPF_HELPER_DEFS) +$(BPF_HELPER_DEFS_ATTR): $(srctree)/tools/include/uapi/linux/bpf.h + $(QUIET_GEN)$(srctree)/scripts/bpf_doc.py --attr-header \ + --file $(srctree)/tools/include/uapi/linux/bpf.h > $(BPF_HELPER_DEFS_ATTR) + $(OUTPUT)libbpf.so: $(OUTPUT)libbpf.so.$(LIBBPF_VERSION) $(OUTPUT)libbpf.so.$(LIBBPF_VERSION): $(BPF_IN_SHARED) $(VERSION_SCRIPT) diff --git a/tools/lib/bpf/bpf_helpers.h b/tools/lib/bpf/bpf_helpers.h index 7349b16b8e2f..b7573e7d3feb 100644 --- a/tools/lib/bpf/bpf_helpers.h +++ b/tools/lib/bpf/bpf_helpers.h @@ -8,7 +8,11 @@ * in advance since bpf_helper_defs.h uses such types * as __u64. */ +#if __has_attribute(kernel_helper) +#include "bpf_helper_defs_attr.h" +#else #include "bpf_helper_defs.h" +#endif #define __uint(name, val) int (*name)[val] #define __type(name, val) typeof(val) *name -- 2.34.1