Skip to content

Commit b0dfa99

Browse files
committed
Implement kprobe support by extracting kernel function signatures and updating context handling. Remove KprobeContext references and replace with pt_regs.
1 parent 32bd5e3 commit b0dfa99

15 files changed

Lines changed: 436 additions & 50 deletions

src/ast.ml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ and bpf_type =
7474
| Function of bpf_type list * bpf_type
7575
| Map of bpf_type * bpf_type * map_type
7676
(* Built-in context types *)
77-
| Xdp_md | KprobeContext | UprobeContext
77+
| Xdp_md | UprobeContext
7878
| TracepointContext | LsmContext | CgroupSkbContext
7979
| Xdp_action
8080
(* Program reference types *)
@@ -527,7 +527,6 @@ let rec string_of_bpf_type = function
527527
(string_of_bpf_type value_type)
528528
(string_of_map_type map_type)
529529
| Xdp_md -> "xdp_md"
530-
| KprobeContext -> "KprobeContext"
531530
| UprobeContext -> "UprobeContext"
532531
| TracepointContext -> "TracepointContext"
533532
| LsmContext -> "LsmContext"

src/btf_binary_parser.ml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ external btf_type_by_id : btf_handle -> int -> (int * string * int * int * int)
3737

3838
external btf_type_get_members : btf_handle -> int -> (string * int) array = "btf_type_get_members_stub"
3939
external btf_resolve_type : btf_handle -> int -> string = "btf_resolve_type_stub"
40+
external btf_extract_function_signatures : btf_handle -> string list -> (string * string) list = "btf_extract_function_signatures_stub"
4041
external btf_free : btf_handle -> unit = "btf_free_stub"
4142

4243
(** Parse BTF file and extract requested types using libbpf *)
@@ -152,4 +153,31 @@ let parse_btf_file btf_path target_types =
152153
with
153154
| exn ->
154155
printf "Error parsing BTF file %s: %s\n" btf_path (Printexc.to_string exn);
156+
[]
157+
158+
(** Extract kernel function signatures for kprobe targets *)
159+
let extract_kernel_function_signatures btf_path function_names =
160+
try
161+
printf "Extracting function signatures from BTF file: %s\n" btf_path;
162+
printf "Target functions: %s\n" (String.concat ", " function_names);
163+
164+
match btf_new_from_file btf_path with
165+
| None -> (
166+
printf "Error: Failed to open BTF file %s\n" btf_path;
167+
[]
168+
)
169+
| Some btf_handle -> (
170+
let signatures = btf_extract_function_signatures btf_handle function_names in
171+
btf_free btf_handle;
172+
173+
printf "Successfully extracted %d function signatures\n" (List.length signatures);
174+
List.iter (fun (name, sig_str) ->
175+
printf " Function: %s -> %s\n" name sig_str
176+
) signatures;
177+
178+
signatures
179+
)
180+
with
181+
| exn ->
182+
printf "Error extracting function signatures from BTF file %s: %s\n" btf_path (Printexc.to_string exn);
155183
[]

src/btf_binary_parser.mli

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,10 @@ type btf_type_info = {
2828
@param btf_path Path to the binary BTF file
2929
@param target_types List of type names to extract
3030
@return List of extracted type definitions in KernelScript format *)
31-
val parse_btf_file : string -> string list -> btf_type_info list
31+
val parse_btf_file : string -> string list -> btf_type_info list
32+
33+
(** Extract kernel function signatures for kprobe targets.
34+
@param btf_path Path to the binary BTF file
35+
@param function_names List of kernel function names to extract signatures for
36+
@return List of (function_name, signature) pairs *)
37+
val extract_kernel_function_signatures : string -> string list -> (string * string) list

src/btf_parser.ml

Lines changed: 69 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ type program_template = {
3232
return_type: string;
3333
includes: string list;
3434
types: btf_type_info list;
35+
function_signatures: (string * string) list; (* Function name and signature for kprobe targets *)
3536
}
3637

3738

@@ -106,12 +107,16 @@ let rec get_program_template prog_type btf_path =
106107

107108
let all_types = filtered_types @ hardcoded_types in
108109

110+
(* No function signatures for generic program templates - kprobe uses specific template *)
111+
let function_signatures = [] in
112+
109113
{
110114
program_type = prog_type;
111115
context_type = context_type;
112116
return_type = return_type;
113117
includes = ["linux/bpf.h"; "linux/pkt_cls.h"; "linux/if_ether.h"; "linux/ip.h"; "linux/tcp.h"; "linux/udp.h"];
114118
types = all_types;
119+
function_signatures = function_signatures;
115120
}
116121

117122
(** Extract specific types from BTF file using binary parser *)
@@ -141,7 +146,40 @@ and extract_types_from_btf btf_path type_names =
141146
| exn ->
142147
failwith (sprintf "BTF extraction failed: %s" (Printexc.to_string exn))
143148

144-
149+
(** Get kprobe program template for a specific target function *)
150+
let get_kprobe_program_template target_function btf_path =
151+
let context_type = "*pt_regs" in
152+
let return_type = "i32" in
153+
let common_types = ["pt_regs"] in
154+
155+
(* Extract types from BTF - BTF file is required *)
156+
let extracted_types = match btf_path with
157+
| Some path when Sys.file_exists path -> extract_types_from_btf path common_types
158+
| Some path -> failwith (sprintf "BTF file not found: %s" path)
159+
| None -> failwith "BTF file path is required. Use --btf-vmlinux-path option."
160+
in
161+
162+
(* Extract specific function signature for the target *)
163+
let function_signatures = match btf_path with
164+
| Some path when Sys.file_exists path ->
165+
printf "🔧 Extracting function signature for %s...\n" target_function;
166+
let signatures = Btf_binary_parser.extract_kernel_function_signatures path [target_function] in
167+
if signatures = [] then
168+
printf "⚠️ Function '%s' not found in BTF - proceeding without signature\n" target_function
169+
else
170+
printf "✅ Extracted signature for %s\n" target_function;
171+
signatures
172+
| _ -> []
173+
in
174+
175+
{
176+
program_type = "kprobe";
177+
context_type = context_type;
178+
return_type = return_type;
179+
includes = ["linux/bpf.h"; "linux/pkt_cls.h"; "linux/if_ether.h"; "linux/ip.h"; "linux/tcp.h"; "linux/udp.h"];
180+
types = extracted_types;
181+
function_signatures = function_signatures;
182+
}
145183

146184
(** Extract struct_ops definitions from BTF and generate KernelScript code *)
147185
let extract_struct_ops_definitions btf_path struct_ops_names =
@@ -230,13 +268,38 @@ let generate_kernelscript_source template project_name =
230268
| [] -> "0"
231269
in
232270

271+
(* Generate function signature comments for kprobe programs *)
272+
let (function_signatures_comment, target_function_name) =
273+
if template.program_type = "kprobe" && template.function_signatures <> [] then
274+
let signature_lines = List.map (fun (func_name, signature) ->
275+
sprintf "// Target function: %s -> %s" func_name signature
276+
) template.function_signatures in
277+
let comment = sprintf "\n// Target kernel function signature:\n%s\n"
278+
(String.concat "\n" signature_lines) in
279+
let first_func = match template.function_signatures with
280+
| (name, _) :: _ -> name
281+
| [] -> "target_function"
282+
in
283+
(comment, first_func)
284+
else
285+
("", "target_function")
286+
in
287+
288+
(* Customize attach call for kprobe *)
289+
let attach_target = if template.program_type = "kprobe" then target_function_name else "eth0" in
290+
let attach_comment = if template.program_type = "kprobe" then
291+
" // Attach kprobe to target kernel function"
292+
else
293+
" // TODO: Update interface name and attachment parameters"
294+
in
295+
233296
sprintf {|%s
234297
// Generated by KernelScript compiler with direct BTF parsing
235-
298+
%s
236299
%s
237300

238301
@%s
239-
fn %s_handler(ctx: *%s) -> %s {
302+
fn %s_handler(ctx: %s) -> %s {
240303
// TODO: Implement your %s logic here
241304

242305
return %s
@@ -245,8 +308,8 @@ fn %s_handler(ctx: *%s) -> %s {
245308
fn main() -> i32 {
246309
var prog = load(%s_handler)
247310

248-
// TODO: Update interface name and attachment parameters
249-
var result = attach(prog, "eth0", 0)
311+
%s
312+
var result = attach(prog, "%s", 0)
250313

251314
if (result == 0) {
252315
print("%s program loaded successfully")
@@ -257,4 +320,4 @@ fn main() -> i32 {
257320

258321
return 0
259322
}
260-
|} context_comment type_definitions template.program_type project_name template.context_type template.return_type template.program_type sample_return project_name template.program_type template.program_type
323+
|} context_comment function_signatures_comment type_definitions template.program_type project_name template.context_type template.return_type template.program_type sample_return project_name attach_comment attach_target template.program_type template.program_type

src/btf_parser.mli

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,15 @@ type program_template = {
3030
return_type: string;
3131
includes: string list;
3232
types: btf_type_info list;
33+
function_signatures: (string * string) list; (* Function name and signature for kprobe targets *)
3334
}
3435

3536
(** Get program template based on eBPF program type with optional BTF extraction *)
3637
val get_program_template : string -> string option -> program_template
3738

39+
(** Get kprobe program template for a specific target function *)
40+
val get_kprobe_program_template : string -> string option -> program_template
41+
3842
(** Check if a type name is a well-known eBPF kernel type *)
3943
val is_well_known_kernel_type : string -> bool
4044

src/btf_stubs.c

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -500,6 +500,83 @@ value btf_resolve_type_stub(value btf_handle, value type_id) {
500500
CAMLreturn(caml_copy_string("unknown"));
501501
}
502502

503+
/* Extract kernel function signatures for kprobe targets */
504+
value btf_extract_function_signatures_stub(value btf_handle, value function_names) {
505+
CAMLparam2(btf_handle, function_names);
506+
CAMLlocal3(result_list, current, tuple);
507+
508+
struct btf *btf = btf_of_value(btf_handle);
509+
if (!btf) {
510+
CAMLreturn(Val_emptylist);
511+
}
512+
513+
result_list = Val_emptylist;
514+
515+
/* Convert OCaml list to C array */
516+
int func_count = 0;
517+
value temp = function_names;
518+
while (temp != Val_emptylist) {
519+
func_count++;
520+
temp = Field(temp, 1);
521+
}
522+
523+
char **target_functions = malloc(func_count * sizeof(char*));
524+
temp = function_names;
525+
for (int i = 0; i < func_count; i++) {
526+
target_functions[i] = String_val(Field(temp, 0));
527+
temp = Field(temp, 1);
528+
}
529+
530+
int nr_types = btf__type_cnt(btf);
531+
532+
/* Search for function prototypes */
533+
for (int i = 1; i < nr_types; i++) {
534+
const struct btf_type *t = btf__type_by_id(btf, i);
535+
if (!t) continue;
536+
537+
int kind = btf_kind(t);
538+
539+
if (kind == BTF_KIND_FUNC) {
540+
const char *func_name = btf__name_by_offset(btf, t->name_off);
541+
if (!func_name) continue;
542+
543+
/* Check if this is one of our target functions */
544+
int is_target = 0;
545+
for (int j = 0; j < func_count; j++) {
546+
if (strcmp(func_name, target_functions[j]) == 0) {
547+
is_target = 1;
548+
break;
549+
}
550+
}
551+
552+
if (is_target) {
553+
/* Get the function prototype */
554+
const struct btf_type *func_proto = btf__type_by_id(btf, t->type);
555+
if (func_proto && btf_kind(func_proto) == BTF_KIND_FUNC_PROTO) {
556+
/* Extract function signature */
557+
char *signature = format_function_prototype(btf, func_proto);
558+
559+
/* Create tuple (function_name, signature) */
560+
tuple = caml_alloc_tuple(2);
561+
Store_field(tuple, 0, caml_copy_string(func_name));
562+
Store_field(tuple, 1, caml_copy_string(signature));
563+
564+
/* Add to result list */
565+
current = caml_alloc(2, 0);
566+
Store_field(current, 0, tuple);
567+
Store_field(current, 1, result_list);
568+
result_list = current;
569+
570+
free(signature);
571+
}
572+
}
573+
}
574+
}
575+
576+
free(target_functions);
577+
CAMLreturn(result_list);
578+
}
579+
503580
/* Free BTF handle */
504581
value btf_free_stub(value btf_handle) {
505582
CAMLparam1(btf_handle);

src/context/dune

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
(library
22
(public_name kernelscript.context)
33
(name kernelscript_context)
4-
(modules context_codegen xdp_codegen tc_codegen)
4+
(modules context_codegen xdp_codegen tc_codegen kprobe_codegen)
55
(libraries unix str))

0 commit comments

Comments
 (0)