aboutsummaryrefslogtreecommitdiff
path: root/include/ccdjit.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/ccdjit.h')
-rw-r--r--include/ccdjit.h330
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