diff options
Diffstat (limited to 'include/ccdjit.h')
| -rw-r--r-- | include/ccdjit.h | 330 |
1 files changed, 330 insertions, 0 deletions
diff --git a/include/ccdjit.h b/include/ccdjit.h new file mode 100644 index 0000000..f8a212b --- /dev/null +++ b/include/ccdjit.h @@ -0,0 +1,330 @@ +#ifndef CCDJIT_PUBLIC_H +#define CCDJIT_PUBLIC_H + +/* + * CCDJIT public embedding API + * + * This header is the stable boundary for hosts that want to compile and run C + * code at runtime. The implementation lives in ccdjit.c, but the intended use + * should be clear from this file alone. + * + * Basic use: + * + * ccdjit_context *ctx = ccdjit_context_new(NULL); + * ccdjit_module *module = NULL; + * + * if (ccdjit_compile_string(ctx, source, "plugin.c", &module) == 0) { + * int result = 0; + * ccdjit_module_call_main(module, 0, NULL, &result); + * ccdjit_module_free(module); + * } + * ccdjit_context_free(ctx); + * + * Return convention: + * Functions returning int use 0 for success and -1 for failure unless + * documented otherwise. On failure, call ccdjit_context_last_error(). + * + * Lifetime: + * A context owns options, include paths, registered symbols, and the last + * diagnostic. A module owns generated code or a loaded CCDJIT binary. + * Modules keep their context state alive, so ccdjit_context_free() may be + * called before ccdjit_module_free(); the context is released when the + * last module using it is freed. + * Function pointers returned by ccdjit_module_symbol() are invalid after + * ccdjit_module_free(). + * + * Threads: + * Independent contexts may compile and run from different threads. Do + * not mutate or use the same context or module concurrently from multiple + * threads unless the host provides its own synchronization. + * + * Safety: + * Normal calls run in the host process. Set sandbox_execution to + * CCDJIT_SANDBOX_PROCESS to run ccdjit_module_call_main() in a child + * process with optional resource, syscall, and filesystem limits. + */ + +#include <stddef.h> +#include <stdio.h> + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct ccdjit_context ccdjit_context; +typedef struct ccdjit_module ccdjit_module; + +typedef struct { + /* Host compiler or linker driver. NULL uses $CC, then cc. */ + const char *driver; + + /* Extra linker arguments such as -L, -l, or -Wl options. */ + const char *const *link_args; + size_t link_arg_count; + + /* Print the host linker command to stderr when nonzero. */ + int verbose; +} ccdjit_link_options; + +/* + * Host symbol callback. Return NULL when the name is unknown. + * + * The returned pointer is used as an external function or object address by + * generated code. Keep any pointed-to object alive while modules using it may + * run. + */ +typedef void *(*ccdjit_symbol_resolver)(const char *name, void *userdata); + +typedef enum { + /* Run generated code directly in the host process. */ + CCDJIT_SANDBOX_OFF = 0, + + /* Run ccdjit_module_call_main() in a forked child process. */ + CCDJIT_SANDBOX_PROCESS = 1, +} ccdjit_sandbox_mode; + +typedef enum { + /* + * Minimal child profile: enough to write the result pipe, write + * captured output, and exit. Unexpected syscalls are trapped. + */ + CCDJIT_SANDBOX_SYSCALL_STRICT = 0, + + /* STRICT plus read/close for simple stdio-style code. */ + CCDJIT_SANDBOX_SYSCALL_STDIO = 1, + + /* STDIO plus mmap/munmap/mprotect/brk/clock_gettime. */ + CCDJIT_SANDBOX_SYSCALL_RUNTIME = 2, + + /* Disable the seccomp filter. Resource limits still apply. */ + CCDJIT_SANDBOX_SYSCALL_PERMISSIVE = 3, +} ccdjit_sandbox_syscall_policy; + +typedef enum { + /* Runtime file syscalls are denied by the syscall policy. */ + CCDJIT_SANDBOX_FS_NONE = 0, + + /* Permit read-only access under explicitly added roots. */ + CCDJIT_SANDBOX_FS_READ_ONLY_ROOTS = 1, + + /* Permit writes only for roots added with writable != 0. */ + CCDJIT_SANDBOX_FS_WRITABLE_ROOTS = 2, +} ccdjit_sandbox_filesystem_policy; + +typedef struct { + /* Allow #include to read files from include paths. */ + int allow_filesystem_includes; + + /* Allow the preprocessor to discover and read host system includes. */ + int allow_system_includes; + + /* Allow executable mappings for JIT code and loaded CCDJIT binaries. */ + int allow_executable_memory; + + /* ccdjit_sandbox_mode. Default is CCDJIT_SANDBOX_OFF. */ + int sandbox_execution; + + /* ccdjit_sandbox_syscall_policy. Default is STRICT. */ + int sandbox_syscalls; + + /* ccdjit_sandbox_filesystem_policy. Default is FS_NONE. */ + int sandbox_filesystem; + + /* + * In sandbox mode, default dlsym lookup is disabled unless this is set. + * Prefer explicit ccdjit_context_register_symbol() capabilities. + */ + int sandbox_allow_implicit_symbols; + + /* Wall-clock timeout for one sandboxed main call. Zero means no limit. + */ + unsigned int sandbox_timeout_ms; + + /* RLIMIT_CPU for sandboxed calls, rounded up to seconds by the OS. */ + unsigned int sandbox_cpu_time_ms; + + /* RLIMIT_AS for sandboxed calls. Zero means keep the host default. */ + size_t sandbox_address_space_bytes; + + /* RLIMIT_STACK for sandboxed calls. Zero means keep the host default. + */ + size_t sandbox_stack_bytes; + + /* RLIMIT_FSIZE for sandboxed calls. Zero means keep the host default. + */ + size_t sandbox_file_size_bytes; + + /* Captured stdout/stderr cap for sandboxed calls. Zero means 64 KiB. + */ + size_t sandbox_output_limit_bytes; + + /* + * Preprocessor output byte cap. Zero uses the default currently 128 + * MiB. + */ + size_t preprocessor_output_limit_bytes; + + /* Macro expansion recursion cap. Zero uses the default. */ + unsigned int preprocessor_macro_depth_limit; + + /* Nested include cap. Zero uses the default. */ + unsigned int preprocessor_include_depth_limit; +} ccdjit_options; + +typedef struct { + /* Compiler phase such as LEXER, PARSER, JIT, API, or SANDBOX. */ + const char *phase; + + /* Source file, binary path, symbol name, or "<input>". */ + const char *filename; + + /* Human-readable error text owned by the context. */ + const char *message; + + /* Optional source excerpt for lexer/parser/type diagnostics. */ + const char *source_line; + const char *caret_line; + + /* One-based line and column when available, otherwise zero. */ + int line; + int column; + + /* Raw child wait status or errno-style value for sandbox/API failures. + */ + int status; + + /* Signal that terminated the sandbox child, or zero. */ + int signal_number; +} ccdjit_diagnostic; + +/* Create a compiler context. Passing NULL uses permissive CLI-like defaults. + */ +ccdjit_context *ccdjit_context_new(const ccdjit_options *options); + +/* Free the context and all context-owned diagnostics/options/lists. */ +void ccdjit_context_free(ccdjit_context *ctx); + +/* Add a preprocessor include search path, like -I. */ +int ccdjit_context_add_include_path(ccdjit_context *ctx, const char *path); + +/* Restrict filesystem includes to this root when include roots are used. */ +int ccdjit_context_add_include_root(ccdjit_context *ctx, const char *path); + +/* Add a preprocessor definition, like -DNAME or -DNAME=value. */ +int ccdjit_context_add_define(ccdjit_context *ctx, const char *define); + +/* Grant generated code an explicit external symbol capability. */ +int ccdjit_context_register_symbol(ccdjit_context *ctx, const char *name, + void *addr); + +/* Add an explicit shared library path for external symbol lookup. */ +int ccdjit_context_add_library(ccdjit_context *ctx, const char *path); + +/* Install a fallback external symbol resolver. */ +void ccdjit_context_set_symbol_resolver(ccdjit_context *ctx, + ccdjit_symbol_resolver resolver, void *userdata); + +/* Update sandbox mode, syscall policy, filesystem policy, and symbol policy. */ +int ccdjit_context_set_sandbox_options(ccdjit_context *ctx, int mode, + int syscall_policy, int filesystem_policy, int allow_implicit_symbols); + +/* Update all sandbox resource limits in one call. */ +int ccdjit_context_set_sandbox_limits(ccdjit_context *ctx, + unsigned int timeout_ms, unsigned int cpu_time_ms, + size_t address_space_bytes, size_t stack_bytes, size_t file_size_bytes, + size_t output_limit_bytes); + +/* Update preprocessor resource limits. Passing zero keeps the default. */ +int ccdjit_context_set_preprocessor_limits(ccdjit_context *ctx, + size_t output_limit_bytes, unsigned int macro_depth, + unsigned int include_depth); + +/* + * Add a Landlock filesystem root for sandboxed execution. + * + * writable is only honored when sandbox_filesystem is + * CCDJIT_SANDBOX_FS_WRITABLE_ROOTS. On systems without Landlock, requesting a + * root-based filesystem policy fails while entering the sandbox. + */ +int ccdjit_context_add_sandbox_filesystem_root(ccdjit_context *ctx, + const char *path, int writable); + +/* Return the last error for this context. The pointer is context-owned. */ +const ccdjit_diagnostic *ccdjit_context_last_error(ccdjit_context *ctx); + +/* Return captured sandbox stdout/stderr from the last sandboxed main call. */ +const char *ccdjit_context_last_stdout(ccdjit_context *ctx); +const char *ccdjit_context_last_stderr(ccdjit_context *ctx); + +/* Compile a source file into a live JIT module. */ +int ccdjit_compile_file(ccdjit_context *ctx, const char *path, + ccdjit_module **out); + +/* Compile a source string into a live JIT module. */ +int ccdjit_compile_string(ccdjit_context *ctx, const char *source, + const char *filename, ccdjit_module **out); + +/* + * Compile a source file into a live JIT module without requiring main(). + * Use ccdjit_module_symbol() to find and call exported config/plugin symbols. + */ +int ccdjit_compile_file_module(ccdjit_context *ctx, const char *path, + ccdjit_module **out); + +/* + * Compile a source string into a live JIT module without requiring main(). + * Use ccdjit_module_symbol() to find and call exported config/plugin symbols. + */ +int ccdjit_compile_string_module(ccdjit_context *ctx, const char *source, + const char *filename, ccdjit_module **out); + +/* Convenience wrapper: compile a source string, call main, free the module. */ +int ccdjit_eval_string(ccdjit_context *ctx, const char *source, + const char *filename, int argc, char **argv, int *result_out); + +/* + * Find a function or object symbol in a module. + * + * Calling the returned function pointer runs in the host process even when the + * context has sandbox_execution enabled. Use ccdjit_module_call_main() for + * sandboxed execution. + */ +void *ccdjit_module_symbol(ccdjit_module *module, const char *name); + +/* Call module main(argc, argv). Honors CCDJIT_SANDBOX_PROCESS. */ +int ccdjit_module_call_main(ccdjit_module *module, int argc, char **argv, + int *result_out); + +/* Emit textual assembly-like bytes for inspection. */ +int ccdjit_module_emit_assembly(ccdjit_module *module, FILE *out); + +/* Emit a CCDJITB2 binary image. */ +int ccdjit_module_emit_binary(ccdjit_module *module, FILE *out); + +/* Emit an ELF64 relocatable object. */ +int ccdjit_module_emit_object(ccdjit_module *module, FILE *out); + +/* + * Emit a linked host executable. + * + * This depends on the host compiler driver. It is intended for trusted build + * paths, not sandboxed execution. + */ +int ccdjit_module_emit_executable_file(ccdjit_module *module, const char *path, + const ccdjit_link_options *options); + +/* Emit a CCDJITB2 binary image directly to a path. */ +int ccdjit_module_emit_binary_file(ccdjit_module *module, const char *path); + +/* Load a CCDJITB2 binary image into executable memory. */ +int ccdjit_module_load_binary(ccdjit_context *ctx, const char *path, + ccdjit_module **out); + +/* Free generated code, loaded binary storage, AST, and module-owned source. */ +void ccdjit_module_free(ccdjit_module *module); + +#ifdef __cplusplus +} +#endif + +#endif |
