Skip to content

Commit e76cb86

Browse files
committed
Add dynptr functionality checks and macros in eBPF code generation.
1 parent f0570cb commit e76cb86

File tree

1 file changed

+138
-46
lines changed

1 file changed

+138
-46
lines changed

src/ebpf_c_codegen.ml

Lines changed: 138 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1152,6 +1152,137 @@ let check_object_allocation_usage ir_multi_prog =
11521152
let check_object_allocation_usage_in_program ir_prog =
11531153
check_object_allocation_usage_in_function ir_prog.entry_function
11541154

1155+
(** Check if dynptr functionality is used in IR instructions *)
1156+
let rec check_dynptr_usage_in_instrs instrs =
1157+
List.exists (fun instr ->
1158+
match instr.instr_desc with
1159+
| IRRingbufOp (_, _) -> true (* Ring buffer operations always use dynptr *)
1160+
| IRStructFieldAssignment (obj_val, _, _) ->
1161+
(* Struct field assignments on packet data or map values use dynptr *)
1162+
(match detect_memory_region_enhanced obj_val with
1163+
| PacketData | MapValue -> true
1164+
| _ -> false)
1165+
| IRAssign (_, expr) ->
1166+
(* Check if assignment expressions use enhanced memory access patterns *)
1167+
check_dynptr_usage_in_expr expr
1168+
| IRCall (_, args, _) ->
1169+
(* Check function call arguments for enhanced memory patterns *)
1170+
List.exists check_dynptr_usage_in_value args
1171+
| IRIf (condition, then_body, else_body) ->
1172+
(check_dynptr_usage_in_value condition) ||
1173+
(check_dynptr_usage_in_instrs then_body) ||
1174+
(match else_body with
1175+
| Some else_instrs -> check_dynptr_usage_in_instrs else_instrs
1176+
| None -> false)
1177+
| IRIfElseChain (conditions_and_bodies, final_else) ->
1178+
(List.exists (fun (condition, then_body) ->
1179+
(check_dynptr_usage_in_value condition) ||
1180+
(check_dynptr_usage_in_instrs then_body)
1181+
) conditions_and_bodies) ||
1182+
(match final_else with
1183+
| Some else_instrs -> check_dynptr_usage_in_instrs else_instrs
1184+
| None -> false)
1185+
| IRBpfLoop (_, _, _, _, body_instrs) ->
1186+
check_dynptr_usage_in_instrs body_instrs
1187+
| _ -> false
1188+
) instrs
1189+
1190+
and check_dynptr_usage_in_expr expr =
1191+
match expr.expr_desc with
1192+
| IRValue value -> check_dynptr_usage_in_value value
1193+
| IRBinOp (left, _, right) ->
1194+
(check_dynptr_usage_in_value left) || (check_dynptr_usage_in_value right)
1195+
| IRUnOp (IRDeref, value) ->
1196+
(* Dereference operations on packet data or map values use dynptr *)
1197+
(match detect_memory_region_enhanced value with
1198+
| PacketData | MapValue -> true
1199+
| _ -> false)
1200+
| IRUnOp (_, value) -> check_dynptr_usage_in_value value
1201+
| IRFieldAccess (obj_value, _) ->
1202+
(* Field access on packet data or map values uses dynptr *)
1203+
(match detect_memory_region_enhanced obj_value with
1204+
| PacketData | MapValue -> true
1205+
| _ -> false)
1206+
| IRCast (value, _) -> check_dynptr_usage_in_value value
1207+
| _ -> false
1208+
1209+
and check_dynptr_usage_in_value value =
1210+
match value.value_desc with
1211+
| IRMapAccess (_, _, _) -> true (* Map access may use enhanced patterns *)
1212+
| IRContextField (_, _) -> true (* Context field access may use enhanced patterns *)
1213+
| _ -> false
1214+
1215+
(** Check if dynptr functionality is used in a function *)
1216+
let check_dynptr_usage_in_function ir_func =
1217+
List.exists (fun basic_block ->
1218+
check_dynptr_usage_in_instrs basic_block.instructions
1219+
) ir_func.basic_blocks
1220+
1221+
(** Check if dynptr functionality is used in a multi-program *)
1222+
let check_dynptr_usage ir_multi_prog =
1223+
(* Conservative approach: include dynptr for XDP/TC programs or any enhanced memory access *)
1224+
(List.exists (fun ir_prog ->
1225+
match ir_prog.program_type with
1226+
| Xdp | Tc -> true (* XDP/TC commonly use packet data access *)
1227+
| _ -> check_dynptr_usage_in_function ir_prog.entry_function
1228+
) ir_multi_prog.programs) ||
1229+
(* Check kernel functions *)
1230+
(List.exists check_dynptr_usage_in_function ir_multi_prog.kernel_functions)
1231+
1232+
(** Check if a single IR program uses dynptr functionality *)
1233+
let check_dynptr_usage_in_program ir_prog =
1234+
match ir_prog.program_type with
1235+
| Xdp | Tc -> true (* XDP/TC commonly use packet data access *)
1236+
| _ -> check_dynptr_usage_in_function ir_prog.entry_function
1237+
1238+
(** Generate dynptr safety macros and helper functions *)
1239+
let generate_dynptr_macros ctx =
1240+
emit_line ctx "/* eBPF Dynptr API integration for enhanced pointer safety */";
1241+
emit_line ctx "/* Using system-provided bpf_dynptr_* helper functions from bpf_helpers.h */";
1242+
emit_blank_line ctx;
1243+
1244+
(* Generate enhanced dynptr safety macros *)
1245+
emit_line ctx "/* Enhanced dynptr safety macros */";
1246+
emit_line ctx "#define DYNPTR_SAFE_ACCESS(dynptr, offset, size, type) \\";
1247+
emit_line ctx " ({ \\";
1248+
emit_line ctx " type *__ptr = (type*)bpf_dynptr_data(dynptr, offset, sizeof(type)); \\";
1249+
emit_line ctx " __ptr ? *__ptr : (type){0}; \\";
1250+
emit_line ctx " })";
1251+
emit_blank_line ctx;
1252+
1253+
emit_line ctx "#define DYNPTR_SAFE_WRITE(dynptr, offset, value, type) \\";
1254+
emit_line ctx " ({ \\";
1255+
emit_line ctx " type __tmp = (value); \\";
1256+
emit_line ctx " bpf_dynptr_write(dynptr, offset, &__tmp, sizeof(type), 0); \\";
1257+
emit_line ctx " })";
1258+
emit_blank_line ctx;
1259+
1260+
emit_line ctx "#define DYNPTR_SAFE_READ(dst, dynptr, offset, type) \\";
1261+
emit_line ctx " bpf_dynptr_read(dst, sizeof(type), dynptr, offset, 0)";
1262+
emit_blank_line ctx;
1263+
1264+
(* Fallback macros for regular pointers *)
1265+
emit_line ctx "/* Fallback macros for regular pointer operations */";
1266+
emit_line ctx "#define SAFE_DEREF(ptr) \\";
1267+
emit_line ctx " ({ \\";
1268+
emit_line ctx " typeof(*ptr) __val = {0}; \\";
1269+
emit_line ctx " if (ptr) { \\";
1270+
emit_line ctx " __builtin_memcpy(&__val, ptr, sizeof(__val)); \\";
1271+
emit_line ctx " } \\";
1272+
emit_line ctx " __val; \\";
1273+
emit_line ctx " })";
1274+
emit_blank_line ctx;
1275+
1276+
emit_line ctx "#define SAFE_PTR_ACCESS(ptr, field) \\";
1277+
emit_line ctx " ({ \\";
1278+
emit_line ctx " typeof((ptr)->field) __val = {0}; \\";
1279+
emit_line ctx " if (ptr) { \\";
1280+
emit_line ctx " __val = (ptr)->field; \\";
1281+
emit_line ctx " } \\";
1282+
emit_line ctx " __val; \\";
1283+
emit_line ctx " })";
1284+
emit_blank_line ctx
1285+
11551286
(** Generate standard eBPF includes *)
11561287

11571288
let generate_includes ctx ?(program_types=[]) ?(ir_multi_prog=None) ?(ir_program=None) () =
@@ -3523,6 +3654,10 @@ let generate_c_program ?_config_declarations ir_prog =
35233654
let program_types = [ir_prog.program_type] in
35243655
generate_includes ctx ~program_types ~ir_program:(Some ir_prog) ();
35253656

3657+
(* Generate dynptr safety macros only if needed for single program *)
3658+
let uses_dynptr = check_dynptr_usage_in_program ir_prog in
3659+
if uses_dynptr then generate_dynptr_macros ctx;
3660+
35263661
(* Generate string type definitions *)
35273662
let temp_multi_prog = {
35283663
source_name = ir_prog.name;
@@ -3715,52 +3850,9 @@ let compile_multi_to_c_with_tail_calls
37153850
let program_types = List.map (fun ir_prog -> ir_prog.program_type) ir_multi_prog.programs in
37163851
generate_includes ctx ~program_types ~ir_multi_prog:(Some ir_multi_prog) ();
37173852

3718-
(* Generate dynptr safety macros and helper functions *)
3719-
emit_line ctx "/* eBPF Dynptr API integration for enhanced pointer safety */";
3720-
emit_line ctx "/* Using system-provided bpf_dynptr_* helper functions from bpf_helpers.h */";
3721-
emit_blank_line ctx;
3722-
3723-
(* Generate enhanced dynptr safety macros *)
3724-
emit_line ctx "/* Enhanced dynptr safety macros */";
3725-
emit_line ctx "#define DYNPTR_SAFE_ACCESS(dynptr, offset, size, type) \\";
3726-
emit_line ctx " ({ \\";
3727-
emit_line ctx " type *__ptr = (type*)bpf_dynptr_data(dynptr, offset, sizeof(type)); \\";
3728-
emit_line ctx " __ptr ? *__ptr : (type){0}; \\";
3729-
emit_line ctx " })";
3730-
emit_blank_line ctx;
3731-
3732-
emit_line ctx "#define DYNPTR_SAFE_WRITE(dynptr, offset, value, type) \\";
3733-
emit_line ctx " ({ \\";
3734-
emit_line ctx " type __tmp = (value); \\";
3735-
emit_line ctx " bpf_dynptr_write(dynptr, offset, &__tmp, sizeof(type), 0); \\";
3736-
emit_line ctx " })";
3737-
emit_blank_line ctx;
3738-
3739-
emit_line ctx "#define DYNPTR_SAFE_READ(dst, dynptr, offset, type) \\";
3740-
emit_line ctx " bpf_dynptr_read(dst, sizeof(type), dynptr, offset, 0)";
3741-
emit_blank_line ctx;
3742-
3743-
(* Fallback macros for regular pointers *)
3744-
emit_line ctx "/* Fallback macros for regular pointer operations */";
3745-
emit_line ctx "#define SAFE_DEREF(ptr) \\";
3746-
emit_line ctx " ({ \\";
3747-
emit_line ctx " typeof(*ptr) __val = {0}; \\";
3748-
emit_line ctx " if (ptr) { \\";
3749-
emit_line ctx " __builtin_memcpy(&__val, ptr, sizeof(__val)); \\";
3750-
emit_line ctx " } \\";
3751-
emit_line ctx " __val; \\";
3752-
emit_line ctx " })";
3753-
emit_blank_line ctx;
3754-
3755-
emit_line ctx "#define SAFE_PTR_ACCESS(ptr, field) \\";
3756-
emit_line ctx " ({ \\";
3757-
emit_line ctx " typeof((ptr)->field) __val = {0}; \\";
3758-
emit_line ctx " if (ptr) { \\";
3759-
emit_line ctx " __val = (ptr)->field; \\";
3760-
emit_line ctx " } \\";
3761-
emit_line ctx " __val; \\";
3762-
emit_line ctx " })";
3763-
emit_blank_line ctx;
3853+
(* Generate dynptr safety macros and helper functions only if needed *)
3854+
let uses_dynptr = check_dynptr_usage ir_multi_prog in
3855+
if uses_dynptr then generate_dynptr_macros ctx;
37643856

37653857
(* Store variable type aliases for later lookup *)
37663858
ctx.variable_type_aliases <- variable_type_aliases;

0 commit comments

Comments
 (0)