Skip to content

Commit 3786f00

Browse files
committed
Update eBPF C code generation to utilize vmlinux.h for kernel types, simplifying include management and removing unnecessary context-specific headers.
1 parent db3fcec commit 3786f00

4 files changed

Lines changed: 35 additions & 54 deletions

File tree

src/ebpf_c_codegen.ml

Lines changed: 14 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1109,72 +1109,39 @@ let generate_declarations_in_source_order ctx _ir_multi_program type_aliases =
11091109
(** Generate standard eBPF includes *)
11101110

11111111
let generate_includes ctx ?(program_types=[]) () =
1112-
(* Essential kernel types must come first *)
1113-
let base_type_includes = [
1114-
"#include <linux/types.h>";
1112+
(* Use vmlinux.h which contains all kernel types from BTF *)
1113+
let vmlinux_includes = [
1114+
"#include \"vmlinux.h\"";
11151115
] in
11161116

1117+
(* Only include essential eBPF helpers, vmlinux.h provides all kernel types *)
11171118
let standard_includes = [
1118-
"#include <linux/bpf.h>";
11191119
"#include <bpf/bpf_helpers.h>";
1120-
"#include <linux/if_ether.h>";
1121-
"#include <linux/ip.h>";
1122-
"#include <linux/in.h>";
1123-
"#include <linux/if_xdp.h>";
11241120
] in
11251121

1126-
(* Get context-specific includes *)
1127-
let context_includes = List.fold_left (fun acc prog_type ->
1128-
let context_type = match prog_type with
1129-
| Ast.Xdp -> Some "xdp"
1130-
| Ast.Tc -> Some "tc"
1131-
| Ast.Kprobe -> Some "kprobe"
1132-
| Ast.Tracepoint -> Some "tracepoint"
1133-
| _ -> None
1134-
in
1135-
match context_type with
1136-
| Some ctx_type ->
1137-
let includes = Kernelscript_context.Context_codegen.get_context_includes ctx_type in
1138-
acc @ includes
1139-
| None -> acc
1140-
) [] program_types in
1122+
(* When using vmlinux.h, we don't need context-specific kernel headers *)
1123+
(* vmlinux.h contains all kernel types, so we only need eBPF helpers *)
1124+
let context_includes = [] in (* No additional kernel headers needed with vmlinux.h *)
11411125

11421126
(* Remove duplicates between all include sets *)
1143-
let all_base_includes = base_type_includes @ standard_includes in
1127+
let all_base_includes = vmlinux_includes @ standard_includes in
11441128
let unique_context_includes = List.filter (fun inc ->
11451129
not (List.mem inc all_base_includes)) context_includes in
11461130

11471131
(* For kprobe programs, only emit kprobe includes which contain everything needed *)
11481132
let has_kprobe = List.exists (function Ast.Kprobe -> true | _ -> false) program_types in
11491133
if has_kprobe then (
1150-
(* Emit ONLY kprobe includes which contain architecture definition and all needed headers *)
1151-
let kprobe_includes = Kernelscript_context.Context_codegen.get_context_includes "kprobe" in
1152-
List.iter (emit_line ctx) kprobe_includes;
1153-
emit_blank_line ctx;
1154-
1155-
(* Add additional standard includes that aren't in kprobe includes *)
1156-
let all_additional_includes = [
1157-
"#include <linux/types.h>";
1158-
"#include <linux/bpf.h>";
1134+
(* With vmlinux.h, we only need it and eBPF helpers, no additional kernel headers *)
1135+
let vmlinux_and_helpers = [
1136+
"#include \"vmlinux.h\"";
11591137
"#include <bpf/bpf_helpers.h>";
1160-
"#include <linux/if_ether.h>";
1161-
"#include <linux/ip.h>";
1162-
"#include <linux/in.h>";
1163-
"#include <linux/if_xdp.h>";
11641138
] in
1165-
let additional_includes = List.filter (fun inc ->
1166-
not (List.mem inc kprobe_includes)) all_additional_includes in
1167-
1168-
(* Add context-specific includes for non-kprobe programs *)
1169-
let filtered_context_includes = List.filter (fun inc ->
1170-
not (List.mem inc kprobe_includes) && not (List.mem inc additional_includes)) unique_context_includes in
11711139

1172-
List.iter (emit_line ctx) additional_includes;
1173-
List.iter (emit_line ctx) filtered_context_includes;
1140+
List.iter (emit_line ctx) vmlinux_and_helpers;
11741141
emit_blank_line ctx
11751142
) else (
1176-
(* For non-kprobe programs, use standard processing *)
1177-
let all_includes = standard_includes @ unique_context_includes @ base_type_includes in
1143+
(* For non-kprobe programs, use vmlinux.h and standard processing *)
1144+
let all_includes = vmlinux_includes @ standard_includes @ unique_context_includes in
11781145
List.iter (emit_line ctx) all_includes;
11791146
emit_blank_line ctx;
11801147

src/main.ml

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1067,6 +1067,12 @@ uninstall-module:
10671067

10681068
let kernel_module_clean = if has_kernel_module then " $(KERNEL_MODULE_OBJ) modules.order Module.symvers .*.cmd" else "" in
10691069

1070+
(* Determine BTF path for vmlinux.h generation *)
1071+
let btf_path_for_makefile = match btf_vmlinux_path with
1072+
| Some path -> path
1073+
| None -> "/sys/kernel/btf/vmlinux" (* Default fallback *)
1074+
in
1075+
10701076
let makefile_content = Printf.sprintf {|# Multi-Program eBPF Makefile
10711077
# Generated by KernelScript compiler
10721078

@@ -1076,7 +1082,7 @@ CC = gcc
10761082

10771083
# BPF compilation flags
10781084
BPF_CFLAGS = -target bpf -O2 -Wall -Wextra -g
1079-
BPF_INCLUDES = -I/usr/include -I/usr/include/x86_64-linux-gnu
1085+
BPF_INCLUDES = -I.
10801086

10811087
# Userspace compilation flags
10821088
CFLAGS = -Wall -Wextra -O2 -fPIC
@@ -1086,6 +1092,7 @@ LIBS = -lbpf -lelf -lz%s
10861092
BPF_OBJ = %s.ebpf.o
10871093
USERSPACE_BIN = %s
10881094
SKELETON_H = %s.skel.h
1095+
VMLINUX_H = vmlinux.h
10891096

10901097
# Source files
10911098
BPF_SRC = %s.ebpf.c
@@ -1094,8 +1101,15 @@ USERSPACE_SRC = %s.c
10941101
# Default target
10951102
all:%s $(BPF_OBJ) $(SKELETON_H) $(USERSPACE_BIN)%s
10961103

1097-
# Compile eBPF C to object file
1098-
$(BPF_OBJ): $(BPF_SRC)
1104+
# Generate vmlinux.h from BTF (requires bpftool)
1105+
$(VMLINUX_H):
1106+
@echo "Generating vmlinux.h from kernel BTF..."
1107+
@which bpftool > /dev/null || (echo "Error: bpftool not found. Please install bpftool package." && exit 1)
1108+
bpftool btf dump file %s format c > $@
1109+
@echo "Generated vmlinux.h successfully"
1110+
1111+
# Compile eBPF C to object file (depends on vmlinux.h)
1112+
$(BPF_OBJ): $(BPF_SRC) $(VMLINUX_H)
10991113
$(BPF_CC) $(BPF_CFLAGS) $(BPF_INCLUDES) -c $< -o $@
11001114

11011115
# Generate skeleton header
@@ -1110,7 +1124,7 @@ $(USERSPACE_BIN): $(USERSPACE_SRC) $(SKELETON_H)%s
11101124
%s
11111125
# Clean generated files
11121126
clean:
1113-
rm -f $(BPF_OBJ) $(SKELETON_H) $(USERSPACE_BIN)%s%s
1127+
rm -f $(BPF_OBJ) $(SKELETON_H) $(USERSPACE_BIN) $(VMLINUX_H)%s%s
11141128

11151129
# Build just the eBPF object without skeleton (for testing)
11161130
ebpf-only: $(BPF_OBJ)
@@ -1129,7 +1143,7 @@ help:
11291143

11301144
.PHONY: all clean run ebpf-only help%s
11311145
|} kernel_module_vars base_name base_name base_name base_name base_name
1132-
shared_lib_deps kernel_module_target shared_lib_deps
1146+
shared_lib_deps kernel_module_target btf_path_for_makefile shared_lib_deps
11331147
(if shared_lib_targets = "" then "" else (" " ^ String.concat " " (List.map (fun import -> "./" ^ import.Import_resolver.module_name ^ ".so") ks_imports)))
11341148
python_flags
11351149
kernel_module_rules

tests/test_ebpf_c_codegen.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,7 @@ let test_complete_program () =
231231
let c_code = compile_multi_to_c multi_ir in
232232

233233
(* Verify the generated C code contains expected elements *)
234-
check bool "program contains linux/bpf.h include" true (contains_substr c_code "#include <linux/bpf.h>");
234+
check bool "program contains vmlinux.h include" true (contains_substr c_code "#include \"vmlinux.h\"");
235235
check bool "program contains map name" true (contains_substr c_code "packet_count");
236236
check bool "program contains maps section" true (contains_substr c_code "SEC(\".maps\")");
237237
check bool "program contains xdp section" true (contains_substr c_code "SEC(\"xdp\")");

tests/test_ebpf_string_generation.ml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ let test_ebpf_compilation () =
115115
check bool "contains SEC xdp" true
116116
(contains_pattern ebpf_code "SEC(\"xdp\")");
117117
check bool "contains includes" true
118-
(contains_pattern ebpf_code "#include.*linux/bpf.h");
118+
(contains_pattern ebpf_code "#include.*vmlinux.h");
119119
check bool "contains license" true
120120
(contains_pattern ebpf_code "SEC(\"license\")");
121121

0 commit comments

Comments
 (0)