|
| 1 | +# KernelScript Builtin Functions Reference |
| 2 | + |
| 3 | +This document provides a comprehensive reference for all builtin functions available in KernelScript. These functions are context-aware and translate differently depending on the execution environment (eBPF, userspace, or kernel module). |
| 4 | + |
| 5 | +## Overview |
| 6 | + |
| 7 | +KernelScript builtin functions provide essential functionality across different execution contexts: |
| 8 | +- **eBPF Context**: Functions available within eBPF programs running in kernel space |
| 9 | +- **Userspace Context**: Functions available in userspace programs that manage eBPF programs |
| 10 | +- **Kernel Module Context**: Functions available when compiling to kernel modules |
| 11 | + |
| 12 | +## Builtin Functions by Category |
| 13 | + |
| 14 | +### 1. Input/Output Functions |
| 15 | + |
| 16 | +#### `print(...)` |
| 17 | +**Signature:** `print(...) -> u32` |
| 18 | +**Variadic:** Yes (accepts any number of arguments) |
| 19 | +**Context:** All contexts |
| 20 | + |
| 21 | +**Description:** Print formatted output to the appropriate output stream based on context. |
| 22 | + |
| 23 | +**Context-specific implementations:** |
| 24 | +- **eBPF:** Uses `bpf_printk` to write to kernel trace log (limited to format string + 3 arguments) |
| 25 | +- **Userspace:** Uses `printf` to write to console/stdout |
| 26 | +- **Kernel Module:** Uses `printk` to write to kernel log |
| 27 | + |
| 28 | +**Parameters:** |
| 29 | +- Variable number of arguments of any type |
| 30 | +- First argument typically used as format string in userspace/kernel contexts |
| 31 | + |
| 32 | +**Return Value:** |
| 33 | +- Returns `0` on success (like standard printf family) |
| 34 | +- Returns error code on failure |
| 35 | + |
| 36 | +**Examples:** |
| 37 | +```kernelscript |
| 38 | +print("Hello, world!") |
| 39 | +print("Value:", 42) |
| 40 | +print("Multiple values:", x, y, z) |
| 41 | +``` |
| 42 | + |
| 43 | +**Notes:** |
| 44 | +- In eBPF context, limited to 4 total arguments due to `bpf_printk` restrictions |
| 45 | +- Automatically handles type conversion for different contexts |
| 46 | + |
| 47 | +--- |
| 48 | + |
| 49 | +### 2. Program Lifecycle Management |
| 50 | + |
| 51 | +#### `load(function)` |
| 52 | +**Signature:** `load(function) -> ProgramHandle` |
| 53 | +**Variadic:** No |
| 54 | +**Context:** Userspace only |
| 55 | + |
| 56 | +**Description:** Load an eBPF program function and return a handle for subsequent operations. |
| 57 | + |
| 58 | +**Parameters:** |
| 59 | +- `function`: Any function with eBPF attributes (`@xdp`, `@kprobe`, `@tracepoint`, etc.) |
| 60 | + |
| 61 | +**Return Value:** |
| 62 | +- Returns a `ProgramHandle` that can be used with `attach()` and `detach()` |
| 63 | +- Handle represents the loaded eBPF program file descriptor |
| 64 | + |
| 65 | +**Examples:** |
| 66 | +```kernelscript |
| 67 | +@xdp |
| 68 | +fn my_xdp_program(ctx: *xdp_md) -> xdp_action { |
| 69 | + return XDP_PASS |
| 70 | +} |
| 71 | +
|
| 72 | +fn main() -> i32 { |
| 73 | + var prog = load(my_xdp_program) |
| 74 | + // Use prog with attach() |
| 75 | + return 0 |
| 76 | +} |
| 77 | +``` |
| 78 | + |
| 79 | +**Context-specific implementations:** |
| 80 | +- **eBPF:** Not available |
| 81 | +- **Userspace:** Uses `bpf_prog_load` system call |
| 82 | +- **Kernel Module:** Not available |
| 83 | + |
| 84 | +--- |
| 85 | + |
| 86 | +#### `attach(handle, target, flags)` |
| 87 | +**Signature:** `attach(handle: ProgramHandle, target: str(128), flags: u32) -> u32` |
| 88 | +**Variadic:** No |
| 89 | +**Context:** Userspace only |
| 90 | + |
| 91 | +**Description:** Attach a loaded eBPF program to a target interface or attachment point. |
| 92 | + |
| 93 | +**Parameters:** |
| 94 | +- `handle`: Program handle returned from `load()` |
| 95 | +- `target`: Target interface name (e.g., "eth0", "lo") or attachment point |
| 96 | +- `flags`: Attachment flags (context-dependent) |
| 97 | + |
| 98 | +**Return Value:** |
| 99 | +- Returns `0` on success |
| 100 | +- Returns error code on failure |
| 101 | + |
| 102 | +**Examples:** |
| 103 | +```kernelscript |
| 104 | +var prog = load(my_xdp_program) |
| 105 | +var result = attach(prog, "eth0", 0) |
| 106 | +if (result != 0) { |
| 107 | + print("Failed to attach program") |
| 108 | +} |
| 109 | +``` |
| 110 | + |
| 111 | +**Context-specific implementations:** |
| 112 | +- **eBPF:** Not available |
| 113 | +- **Userspace:** Uses `bpf_prog_attach` system call |
| 114 | +- **Kernel Module:** Not available |
| 115 | + |
| 116 | +--- |
| 117 | + |
| 118 | +#### `detach(handle)` |
| 119 | +**Signature:** `detach(handle: ProgramHandle) -> void` |
| 120 | +**Variadic:** No |
| 121 | +**Context:** Userspace only |
| 122 | + |
| 123 | +**Description:** Detach a loaded eBPF program from its current attachment point. |
| 124 | + |
| 125 | +**Parameters:** |
| 126 | +- `handle`: Program handle returned from `load()` |
| 127 | + |
| 128 | +**Return Value:** |
| 129 | +- No return value (void) |
| 130 | + |
| 131 | +**Examples:** |
| 132 | +```kernelscript |
| 133 | +var prog = load(my_xdp_program) |
| 134 | +attach(prog, "eth0", 0) |
| 135 | +// ... program runs ... |
| 136 | +detach(prog) // Clean up |
| 137 | +``` |
| 138 | + |
| 139 | +**Context-specific implementations:** |
| 140 | +- **eBPF:** Not available |
| 141 | +- **Userspace:** Uses `detach_bpf_program_by_fd` function |
| 142 | +- **Kernel Module:** Not available |
| 143 | + |
| 144 | +--- |
| 145 | + |
| 146 | +### 3. Struct Operations (struct_ops) |
| 147 | + |
| 148 | +#### `register(impl_instance)` |
| 149 | +**Signature:** `register(impl_instance) -> u32` |
| 150 | +**Variadic:** No |
| 151 | +**Context:** Userspace only |
| 152 | + |
| 153 | +**Description:** Register an implementation block instance with the kernel for struct_ops programs. |
| 154 | + |
| 155 | +**Parameters:** |
| 156 | +- `impl_instance`: Instance of a struct with `@struct_ops` attribute |
| 157 | + |
| 158 | +**Return Value:** |
| 159 | +- Returns `0` on success |
| 160 | +- Returns error code on failure |
| 161 | + |
| 162 | +**Validation:** |
| 163 | +- Only accepts impl block instances with `@struct_ops` attribute |
| 164 | +- Validates that the struct_ops type is known to the kernel |
| 165 | +- Must be used with properly attributed implementation blocks |
| 166 | + |
| 167 | +**Examples:** |
| 168 | +```kernelscript |
| 169 | +@struct_ops("tcp_congestion_ops") |
| 170 | +impl TcpCongestion { |
| 171 | + // Implementation methods here |
| 172 | +} |
| 173 | +
|
| 174 | +fn main() -> i32 { |
| 175 | + var tcp_impl = TcpCongestion {} |
| 176 | + var result = register(tcp_impl) |
| 177 | + return result |
| 178 | +} |
| 179 | +``` |
| 180 | + |
| 181 | +**Context-specific implementations:** |
| 182 | +- **eBPF:** Not available |
| 183 | +- **Userspace:** Uses `IRStructOpsRegister` instruction |
| 184 | +- **Kernel Module:** Not available |
| 185 | + |
| 186 | +--- |
| 187 | + |
| 188 | +### 4. Testing and Development |
| 189 | + |
| 190 | +#### `test(program, test_data)` |
| 191 | +**Signature:** `test(program, test_data) -> u32` |
| 192 | +**Variadic:** No |
| 193 | +**Context:** Userspace only (from `@test` functions only) |
| 194 | + |
| 195 | +**Description:** Execute an eBPF program with test data and return the program's return value. |
| 196 | + |
| 197 | +**Parameters:** |
| 198 | +- `program`: eBPF program to test |
| 199 | +- `test_data`: Test input data for the program |
| 200 | + |
| 201 | +**Return Value:** |
| 202 | +- Returns the program's return value |
| 203 | +- Can be used to verify program behavior in tests |
| 204 | + |
| 205 | +**Restrictions:** |
| 206 | +- Can only be called from functions with the `@test` attribute |
| 207 | +- Used for unit testing eBPF programs |
| 208 | + |
| 209 | +**Examples:** |
| 210 | +```kernelscript |
| 211 | +@test |
| 212 | +fn test_my_program() -> i32 { |
| 213 | + var result = test(my_xdp_program, test_packet_data) |
| 214 | + // Assert result == expected_value |
| 215 | + return result |
| 216 | +} |
| 217 | +``` |
| 218 | + |
| 219 | +**Context-specific implementations:** |
| 220 | +- **eBPF:** Not available |
| 221 | +- **Userspace:** Uses `bpf_prog_test_run` system call |
| 222 | +- **Kernel Module:** Not available |
| 223 | + |
| 224 | +--- |
| 225 | + |
| 226 | +### 5. Event Processing |
| 227 | + |
| 228 | +#### `dispatch(...)` |
| 229 | +**Signature:** `dispatch(ringbuf1, ringbuf2, ...) -> i32` |
| 230 | +**Variadic:** Yes (accepts multiple ring buffer arguments) |
| 231 | +**Context:** Userspace only |
| 232 | + |
| 233 | +**Description:** Poll multiple ring buffers for events and dispatch them to their registered callbacks. |
| 234 | + |
| 235 | +**Parameters:** |
| 236 | +- Variable number of ring buffer arguments (RingbufRef or Ringbuf types) |
| 237 | +- Each ring buffer should have associated event callbacks |
| 238 | + |
| 239 | +**Return Value:** |
| 240 | +- Returns `0` on success |
| 241 | +- Returns error code on failure |
| 242 | + |
| 243 | +**Validation:** |
| 244 | +- All arguments must be ring buffer types |
| 245 | +- Requires at least one ring buffer argument |
| 246 | + |
| 247 | +**Examples:** |
| 248 | +```kernelscript |
| 249 | +var rb1: ringbuf<u32>(1024) |
| 250 | +var rb2: ringbuf<u64>(2048) |
| 251 | +
|
| 252 | +fn main() -> i32 { |
| 253 | + // Poll both ring buffers for events |
| 254 | + var result = dispatch(rb1, rb2) |
| 255 | + return result |
| 256 | +} |
| 257 | +``` |
| 258 | + |
| 259 | +**Context-specific implementations:** |
| 260 | +- **eBPF:** Not available |
| 261 | +- **Userspace:** Uses `ring_buffer__poll` from libbpf |
| 262 | +- **Kernel Module:** Not available |
| 263 | + |
| 264 | +--- |
| 265 | + |
| 266 | +### 6. Process Management |
| 267 | + |
| 268 | +#### `daemon()` |
| 269 | +**Signature:** `daemon() -> void` |
| 270 | +**Variadic:** No |
| 271 | +**Context:** Userspace only |
| 272 | + |
| 273 | +**Description:** Become a daemon process by detaching from the terminal and running in the background. |
| 274 | + |
| 275 | +**Parameters:** |
| 276 | +- No parameters |
| 277 | + |
| 278 | +**Return Value:** |
| 279 | +- Never returns in practice (process becomes daemon) |
| 280 | +- Type system requires void return type |
| 281 | + |
| 282 | +**Examples:** |
| 283 | +```kernelscript |
| 284 | +fn main() -> i32 { |
| 285 | + print("Starting daemon...") |
| 286 | + daemon() // Process detaches from terminal |
| 287 | + // Code here runs as daemon |
| 288 | + return 0 |
| 289 | +} |
| 290 | +``` |
| 291 | + |
| 292 | +**Context-specific implementations:** |
| 293 | +- **eBPF:** Not available |
| 294 | +- **Userspace:** Uses `daemon_builtin` custom implementation |
| 295 | +- **Kernel Module:** Not available |
| 296 | + |
| 297 | +--- |
| 298 | + |
| 299 | +#### `exec(python_script)` |
| 300 | +**Signature:** `exec(python_script: str(256)) -> void` |
| 301 | +**Variadic:** No |
| 302 | +**Context:** Userspace only |
| 303 | + |
| 304 | +**Description:** Replace the current process with a Python script, inheriting all eBPF maps and file descriptors. |
| 305 | + |
| 306 | +**Parameters:** |
| 307 | +- `python_script`: Path to Python script file (must have .py extension) |
| 308 | + |
| 309 | +**Return Value:** |
| 310 | +- Never returns (replaces current process) |
| 311 | +- Type system requires void return type |
| 312 | + |
| 313 | +**Validation:** |
| 314 | +- Script path must be a string |
| 315 | +- File suffix validation occurs during code generation |
| 316 | +- Python script inherits eBPF program state |
| 317 | + |
| 318 | +**Examples:** |
| 319 | +```kernelscript |
| 320 | +fn main() -> i32 { |
| 321 | + // Set up eBPF programs and maps |
| 322 | + var prog = load(my_program) |
| 323 | + attach(prog, "eth0", 0) |
| 324 | + |
| 325 | + // Hand off to Python for advanced processing |
| 326 | + exec("advanced_analysis.py") // Never returns |
| 327 | +} |
| 328 | +``` |
| 329 | + |
| 330 | +**Context-specific implementations:** |
| 331 | +- **eBPF:** Not available |
| 332 | +- **Userspace:** Uses `exec_builtin` custom implementation |
| 333 | +- **Kernel Module:** Not available |
| 334 | + |
| 335 | +--- |
| 336 | + |
| 337 | +## Context Availability Summary |
| 338 | + |
| 339 | +| Function | eBPF | Userspace | Kernel Module | Notes | |
| 340 | +|----------|------|-----------|---------------|-------| |
| 341 | +| `print()` | ✅ | ✅ | ✅ | Different output destinations | |
| 342 | +| `load()` | ❌ | ✅ | ❌ | Program management only | |
| 343 | +| `attach()` | ❌ | ✅ | ❌ | Program management only | |
| 344 | +| `detach()` | ❌ | ✅ | ❌ | Program management only | |
| 345 | +| `register()` | ❌ | ✅ | ❌ | struct_ops registration | |
| 346 | +| `test()` | ❌ | ✅ | ❌ | Testing framework only | |
| 347 | +| `dispatch()` | ❌ | ✅ | ❌ | Event processing only | |
| 348 | +| `daemon()` | ❌ | ✅ | ❌ | Process management only | |
| 349 | +| `exec()` | ❌ | ✅ | ❌ | Process replacement only | |
| 350 | + |
| 351 | +## Related Concepts |
| 352 | + |
| 353 | +### Helper Functions vs. Builtin Functions |
| 354 | + |
| 355 | +- **Builtin Functions**: Defined by KernelScript, context-aware, part of the language |
| 356 | +- **Helper Functions**: User-defined functions with `@helper` attribute, compiled as eBPF helpers |
| 357 | +- **Kernel Functions (kfuncs)**: External kernel functions declared with `extern` or `@kfunc` |
| 358 | + |
| 359 | +### External Functions |
| 360 | + |
| 361 | +KernelScript also supports external kernel functions that can be declared and called: |
| 362 | + |
| 363 | +```kernelscript |
| 364 | +// External eBPF helper functions |
| 365 | +extern bpf_ktime_get_ns() -> u64 |
| 366 | +extern bpf_trace_printk(fmt: *u8, fmt_size: u32) -> i32 |
| 367 | +extern bpf_get_current_pid_tgid() -> u64 |
| 368 | +
|
| 369 | +// Usage in eBPF programs |
| 370 | +@xdp |
| 371 | +fn my_program(ctx: *xdp_md) -> xdp_action { |
| 372 | + var timestamp = bpf_ktime_get_ns() |
| 373 | + return XDP_PASS |
| 374 | +} |
| 375 | +``` |
| 376 | + |
| 377 | +### Error Handling |
| 378 | + |
| 379 | +Most builtin functions return error codes where appropriate: |
| 380 | +- `0`: Success |
| 381 | +- Non-zero: Error (specific meaning depends on function) |
| 382 | + |
| 383 | +Always check return values for functions that can fail: |
| 384 | + |
| 385 | +```kernelscript |
| 386 | +var result = attach(prog, "eth0", 0) |
| 387 | +if (result != 0) { |
| 388 | + print("Failed to attach program, error:", result) |
| 389 | + return result |
| 390 | +} |
| 391 | +``` |
| 392 | + |
| 393 | +## See Also |
| 394 | + |
| 395 | +- **SPEC.md**: Language specification and features |
| 396 | +- **examples/**: Example programs demonstrating builtin function usage |
0 commit comments