commit 5f921ccf5d33c3f9022764988bd06e70d864a4f0 parent 5716bb7b4a506bdee79e1670ba42fe9f6b8fd763 Author: Ryan Sepassi <rsepassi@gmail.com> Date: Mon, 1 Jun 2026 09:47:40 -0700 driver/ reorganize into cmd/ lib/ subdirs Diffstat:
48 files changed, 74 insertions(+), 66 deletions(-)
diff --git a/Makefile b/Makefile @@ -85,8 +85,8 @@ LIB_CFLAGS = $(FREESTANDING_CFLAGS) $(LIB_VISIBILITY_CFLAGS) -Iinclude -Isrc # driver/env/ holds all hosted OS/libc adapter code and is compiled with # DRIVER_ENV_CFLAGS. The per-OS feature-test macros and the exact source # list (DRIVER_ENV_OS_CFLAGS / DRIVER_ENV_SRCS) come from mk/env.mk. -DRIVER_CFLAGS = $(FREESTANDING_CFLAGS) -Iinclude -Ilang -DRIVER_ENV_CFLAGS = $(HOST_CFLAGS) -Iinclude -Ilang +DRIVER_CFLAGS = $(FREESTANDING_CFLAGS) -Iinclude -Ilang -Idriver -Idriver/lib +DRIVER_ENV_CFLAGS = $(HOST_CFLAGS) -Iinclude -Ilang -Idriver -Idriver/lib TEST_HOST_CFLAGS = $(HOST_CFLAGS) -Iinclude -Ilang include mk/config.mk @@ -305,68 +305,68 @@ LIB_OBJS = $(patsubst src/%.c,$(BUILD_DIR)/lib/%.o,$(LIB_SRCS)) \ LIB_DEPS = $(LIB_OBJS:.o=.d) LIB_RELOC_OBJ = $(BUILD_DIR)/libcfree.o -DRIVER_SRCS = driver/main.c driver/target.c $(DRIVER_ENV_SRCS) +DRIVER_SRCS = driver/main.c driver/lib/target.c $(DRIVER_ENV_SRCS) DRIVER_TOOL_SRCS = ifeq ($(CFREE_TOOL_CC_ENABLED),1) -DRIVER_TOOL_SRCS += driver/cc.c +DRIVER_TOOL_SRCS += driver/cmd/cc.c endif ifeq ($(CFREE_TOOL_CHECK_ENABLED),1) -DRIVER_TOOL_SRCS += driver/cc.c +DRIVER_TOOL_SRCS += driver/cmd/cc.c endif ifeq ($(CFREE_TOOL_CPP_ENABLED),1) -DRIVER_TOOL_SRCS += driver/cpp.c +DRIVER_TOOL_SRCS += driver/cmd/cpp.c endif ifeq ($(CFREE_TOOL_AS_ENABLED),1) -DRIVER_TOOL_SRCS += driver/as.c +DRIVER_TOOL_SRCS += driver/cmd/as.c endif ifeq ($(CFREE_TOOL_LD_ENABLED),1) -DRIVER_TOOL_SRCS += driver/ld.c +DRIVER_TOOL_SRCS += driver/cmd/ld.c endif ifeq ($(CFREE_TOOL_AR_ENABLED),1) -DRIVER_TOOL_SRCS += driver/ar.c +DRIVER_TOOL_SRCS += driver/cmd/ar.c endif ifeq ($(CFREE_TOOL_RANLIB_ENABLED),1) -DRIVER_TOOL_SRCS += driver/ranlib.c +DRIVER_TOOL_SRCS += driver/cmd/ranlib.c endif ifeq ($(CFREE_TOOL_STRIP_ENABLED),1) -DRIVER_TOOL_SRCS += driver/strip.c +DRIVER_TOOL_SRCS += driver/cmd/strip.c endif ifeq ($(CFREE_TOOL_OBJCOPY_ENABLED),1) -DRIVER_TOOL_SRCS += driver/objcopy.c +DRIVER_TOOL_SRCS += driver/cmd/objcopy.c endif ifeq ($(CFREE_TOOL_OBJDUMP_ENABLED),1) -DRIVER_TOOL_SRCS += driver/objdump.c +DRIVER_TOOL_SRCS += driver/cmd/objdump.c endif ifeq ($(CFREE_TOOL_DBG_ENABLED),1) -DRIVER_TOOL_SRCS += driver/dbg.c +DRIVER_TOOL_SRCS += driver/cmd/dbg.c endif ifeq ($(CFREE_TOOL_RUN_ENABLED),1) -DRIVER_TOOL_SRCS += driver/run.c +DRIVER_TOOL_SRCS += driver/cmd/run.c endif ifeq ($(CFREE_TOOL_EMU_ENABLED),1) -DRIVER_TOOL_SRCS += driver/emu.c +DRIVER_TOOL_SRCS += driver/cmd/emu.c endif ifeq ($(CFREE_TOOL_NM_ENABLED),1) -DRIVER_TOOL_SRCS += driver/nm.c +DRIVER_TOOL_SRCS += driver/cmd/nm.c endif ifeq ($(CFREE_TOOL_SIZE_ENABLED),1) -DRIVER_TOOL_SRCS += driver/size.c +DRIVER_TOOL_SRCS += driver/cmd/size.c endif ifeq ($(CFREE_TOOL_ADDR2LINE_ENABLED),1) -DRIVER_TOOL_SRCS += driver/addr2line.c +DRIVER_TOOL_SRCS += driver/cmd/addr2line.c endif ifeq ($(CFREE_TOOL_STRINGS_ENABLED),1) -DRIVER_TOOL_SRCS += driver/strings.c +DRIVER_TOOL_SRCS += driver/cmd/strings.c endif ifneq ($(filter 1,$(CFREE_TOOL_CAS_ENABLED) $(CFREE_TOOL_PKG_ENABLED)),) DRIVER_TOOL_SRCS += driver/dist/dist.c driver/dist/blake2b.c \ driver/dist/blob.c driver/dist/tree.c driver/dist/cas.c endif ifeq ($(CFREE_TOOL_CAS_ENABLED),1) -DRIVER_TOOL_SRCS += driver/cas.c +DRIVER_TOOL_SRCS += driver/cmd/cas.c endif ifeq ($(CFREE_TOOL_PKG_ENABLED),1) -DRIVER_TOOL_SRCS += driver/pkg.c +DRIVER_TOOL_SRCS += driver/cmd/pkg.c DRIVER_TOOL_SRCS += driver/dist/dist.c driver/dist/b64.c \ driver/dist/blake2b.c driver/dist/ed25519.c \ driver/dist/vendor/monocypher/monocypher.c \ @@ -378,19 +378,19 @@ DRIVER_TOOL_SRCS += driver/dist/dist.c driver/dist/b64.c \ endif DRIVER_SRCS += $(sort $(DRIVER_TOOL_SRCS)) ifneq ($(filter 1,$(CFREE_TOOL_CC_ENABLED) $(CFREE_TOOL_CHECK_ENABLED) $(CFREE_TOOL_CPP_ENABLED) $(CFREE_TOOL_AS_ENABLED) $(CFREE_TOOL_DBG_ENABLED) $(CFREE_TOOL_RUN_ENABLED)),) -DRIVER_SRCS += driver/cflags.c +DRIVER_SRCS += driver/lib/cflags.c endif ifneq ($(filter 1,$(CFREE_TOOL_CC_ENABLED) $(CFREE_TOOL_CHECK_ENABLED) $(CFREE_TOOL_LD_ENABLED) $(CFREE_TOOL_RUN_ENABLED)),) -DRIVER_SRCS += driver/lib_resolve.c +DRIVER_SRCS += driver/lib/lib_resolve.c endif ifneq ($(filter 1,$(CFREE_TOOL_CC_ENABLED) $(CFREE_TOOL_CHECK_ENABLED) $(CFREE_TOOL_RUN_ENABLED)),) -DRIVER_SRCS += driver/hosted.c +DRIVER_SRCS += driver/lib/hosted.c endif ifneq ($(filter 1,$(CFREE_TOOL_CC_ENABLED) $(CFREE_TOOL_CHECK_ENABLED) $(CFREE_TOOL_LD_ENABLED)),) -DRIVER_SRCS += driver/runtime.c +DRIVER_SRCS += driver/lib/runtime.c endif ifneq ($(filter 1,$(CFREE_TOOL_AR_ENABLED) $(CFREE_TOOL_RANLIB_ENABLED) $(CFREE_TOOL_STRIP_ENABLED) $(CFREE_TOOL_DBG_ENABLED) $(CFREE_TOOL_RUN_ENABLED)),) -DRIVER_SRCS += driver/inputs.c +DRIVER_SRCS += driver/lib/inputs.c endif DRIVER_SRCS := $(sort $(DRIVER_SRCS)) DRIVER_OBJS = $(patsubst driver/%.c,$(BUILD_DIR)/driver/%.o,$(DRIVER_SRCS)) diff --git a/doc/ASM.md b/doc/ASM.md @@ -98,7 +98,7 @@ src/api/disasm.c cfree_disasm_iter_* / cfree_obj_disasm + reloc/ symbol annotation overlay. src/api/arch_regs.c stateless cfree_arch_register_name / _index dispatcher. -driver/as.c cfree as subcommand wired to +driver/cmd/as.c cfree as subcommand wired to cfree_compile_obj_emit(CFREE_LANG_ASM). ``` diff --git a/doc/ASM_ROUNDTRIP_TESTING.md b/doc/ASM_ROUNDTRIP_TESTING.md @@ -281,14 +281,14 @@ without clang/podman. ## Background — what cfree can do today (verified) - **`cc -S` exists** and is *disassembly-to-text plus module scaffolding*: - `driver/cc.c` (`emit_asm_source`, ~line 1116) → `cfree_obj_builder_emit_asm` + `driver/cmd/cc.c` (`emit_asm_source`, ~line 1116) → `cfree_obj_builder_emit_asm` (`src/api/asm_emit.c:256`). It walks each section, emits labels for **symbols** (`collect_labels`, `asm_emit.c:68`), and disassembles `.text` via `emit_disasm_range` (`asm_emit.c:215`) using `arch_disasm_decode`. So `-S` and `objdump -d` share the **same disassembler** — they are one decode surface. - **Cross-arch execution needs no qemu/podman**: `cfree run` (in-process JIT, - `driver/run.c`) and `cfree emu` (user-mode ELF emulator, `driver/emu.c`) both + `driver/cmd/run.c`) and `cfree emu` (user-mode ELF emulator, `driver/cmd/emu.c`) both run guest code on the host. The asm harness already has JIT/exec paths (`test/asm/run.sh`, the `D`/`J`/`E` lanes; `link-exe-runner`, `jit-runner`). - **The assembler accepts the reloc-operator syntax** (this is the key enabler): @@ -454,8 +454,8 @@ forms where they agree.) (`arch_disasm_decode`, `CfreeInsn`). - Reloc kinds: `src/obj/obj.h` (`RelocKind`); per-arch ELF maps under `src/obj/elf/reloc_*.c`. -- Tools: `cfree as` (`driver/as.c`), `objdump` (`driver/objdump.c`), - `run` (`driver/run.c`), `emu` (`driver/emu.c`), `ld` (`driver/ld.c`). +- Tools: `cfree as` (`driver/cmd/as.c`), `objdump` (`driver/cmd/objdump.c`), + `run` (`driver/cmd/run.c`), `emu` (`driver/cmd/emu.c`), `ld` (`driver/cmd/ld.c`). - Test harness: `test/asm/run.sh` (H/T/L/D/J/E), `test/toy/run.sh`, `test/lib/exec_target.sh`; golden regen `test/asm/regen.sh` / `test/asm/regen-rv64.sh`. Cross toolchain present on dev host: `clang`, diff --git a/doc/DBG.md b/doc/DBG.md @@ -74,7 +74,7 @@ stdin → dbg REPL → CfreeJitSession ──► worker thread runs JIT entry DWARF (line/CFI/var) → user-visible output ``` -The REPL is already wired (`driver/dbg.c`). It owns the breakpoint id +The REPL is already wired (`driver/cmd/dbg.c`). It owns the breakpoint id namespace presented to the user, the DWARF consumer, and SIGINT forwarding at the prompt. Everything *behind* `cfree_jit_session_*` — threading, signals, memory protection — is what this doc covers. @@ -341,7 +341,7 @@ DWARF concerns the consumer must handle: ## 11. Driver-side changes Three TUs in the driver carry dbg-specific code: `driver/env.c`, -`driver/dbg.c`, and the shared `driver/inputs.{c,h}` module that backs +`driver/cmd/dbg.c`, and the shared `driver/lib/inputs.{c,h}` module that backs both `cfree run` and `cfree dbg`. - `driver/env.c` carries the `g_dbg_os_posix` singleton populated by @@ -358,12 +358,12 @@ both `cfree run` and `cfree dbg`. `__builtin___clear_cache` elsewhere), guarded copy (TLS `sigjmp_buf` + armed flag; the SEGV/BUS handler checks this slot before delegating to `on_fault`). -- `driver/dbg.c` calls `cfree_jit_session_attach_dwarf(session, +- `driver/cmd/dbg.c` calls `cfree_jit_session_attach_dwarf(session, debug_info)` right after `cfree_dwarf_open` succeeds, so source-level resume modes light up the moment `cfree_jit_view` returns non-NULL. The degraded-mode warning at `dbg.c:1862-1868` is left in place; it now only fires on non-aarch64 hosts. -- `driver/inputs.{c,h}` owns the `DriverInputs` struct + classify / +- `driver/lib/inputs.{c,h}` owns the `DriverInputs` struct + classify / load / compile-and-jit pipeline, shared with `cfree run`. Recognized positionals: `.c` / `.cc` / `.cpp` sources, `.o` / `.obj` objects, `.a` archives, and `-` for stdin (single source). The dbg-specific @@ -434,13 +434,13 @@ the box. - [ ] Windows host: vectored exception handlers + `SetThreadContext` instead of POSIX signals -### Driver — `driver/dbg.c` and `driver/inputs.{c,h}` +### Driver — `driver/cmd/dbg.c` and `driver/lib/inputs.{c,h}` - [x] `cfree_jit_session_attach_dwarf` call right after `cfree_dwarf_open` - [x] Degraded-mode warning still present but only fires on non-aarch64 - [x] Accept the full `cfree run` input shape (`.c` / `.cc` / `.cpp`, `.o` / `.obj`, `.a`, stdin via `-`) through the shared - `DriverInputs` module in `driver/inputs.{c,h}` + `DriverInputs` module in `driver/lib/inputs.{c,h}` - [ ] Remove the warning entirely once x64 / rv64 sessions are real ### DWARF / multi-input (lands once `cfree_jit_view` is real) @@ -459,7 +459,7 @@ against real debug info; see §10 for the failure modes each addresses. `bt` as `[no debug info for this frame]`, `p NAME` as `"no debug info for this frame; '%s' not in global symbols"`, and `b file:line` as `"file not covered by debug info: %s"`. -- [ ] `driver/dbg.c` source listing (`list file:line`) reads from disk +- [ ] `driver/cmd/dbg.c` source listing (`list file:line`) reads from disk via `env.file_io`; when the input is from a `.o` / `.a` debug section whose source file isn't accessible, show the DWARF line number alone and omit the source snippet. diff --git a/doc/DBG_TODO.md b/doc/DBG_TODO.md @@ -8,7 +8,7 @@ experience is solid. ## Current Shape -- `cfree dbg` has a real REPL in `driver/dbg.c`: `run`, `cont`, stepping, +- `cfree dbg` has a real REPL in `driver/cmd/dbg.c`: `run`, `cont`, stepping, breakpoints, `jit`, `expr`, `bt`, `p`, `set`, `x`, `disasm`, `list`, and `info` commands. - `src/dbg/` owns the JIT session, worker thread, signal stop/resume loop, diff --git a/doc/DESIGN.md b/doc/DESIGN.md @@ -187,7 +187,7 @@ The JIT path shares the same compile, object, symbol, and relocation machinery as file output. Mapping executable memory is delegated to the host through `CfreeEnv`; libcfree enforces the image layout and relocation model. -`driver/run.c` invokes an entry point in-process. `driver/dbg.c` builds on JIT +`driver/cmd/run.c` invokes an entry point in-process. `driver/cmd/dbg.c` builds on JIT sessions and `src/dbg/` for breakpoints, stepping, register display, and memory inspection. diff --git a/doc/IMAGE_INSPECT.md b/doc/IMAGE_INSPECT.md @@ -28,7 +28,7 @@ oriented. It has no notion of a **segment** (PT_LOAD), the **dynamic table** or **data directories** — which is exactly what image inspection is about. Consequence today: `objdump` carries a hand-rolled `pe_parse_image` raw-byte -walker (`driver/objdump.c:1597`) that bypasses the library to serve `-f`/`-h`/ +walker (`driver/cmd/objdump.c:1597`) that bypasses the library to serve `-f`/`-h`/ `-p` for PE, and emits a soft error for `-t`/`-d`/`-r`/`-s`. nm, size, strip, objcopy, addr2line all share `cfree_obj_open` and inherit the relocatable-only limit. diff --git a/doc/INCREMENTAL_LINK.md b/doc/INCREMENTAL_LINK.md @@ -25,7 +25,7 @@ workstream. This document intentionally keeps the motivating path in selectively reapply them. - Keep the public surface small until the implementation has one real consumer. The first API can be private to `src/link/`, `src/dbg/`, and - `driver/dbg.c`. + `driver/cmd/dbg.c`. ## 2. Non-goals diff --git a/doc/INTERPRETER.md b/doc/INTERPRETER.md @@ -338,7 +338,7 @@ Implemented and validated differentially against the JIT: consistent and persist across calls. Anything it can't resolve safely — a non-Mach-O image or a foreign descriptor (e.g. an extern thread-local) — returns NULL and is **diagnosed**, never treated as storage. -- **`cfree run --no-jit`** (`driver/run.c`): forces `-O1` minimum, attaches an `InterpProgram` +- **`cfree run --no-jit`** (`driver/cmd/run.c`): forces `-O1` minimum, attaches an `InterpProgram` so each function is captured while the normal object/JIT-link still runs (it lays out data globals and resolves externs / function pointers). The entry executes **only** through the interpreter — there is **no JIT execution fallback**; a non-interpretable entry is an error. diff --git a/doc/JIT.md b/doc/JIT.md @@ -1,8 +1,8 @@ # JIT — known limitations and TODOs Status of the in-process JIT path: `cfree_link_jit` (`src/link/link_jit.c`), -its driver front-end `cfree run` (`driver/run.c`), and the debugger session -that rides on top (`cfree dbg`, `driver/dbg.c`). Adjacent docs that cover +its driver front-end `cfree run` (`driver/cmd/run.c`), and the debugger session +that rides on top (`cfree dbg`, `driver/cmd/dbg.c`). Adjacent docs that cover specific slices stay authoritative; entries here cross-reference instead of duplicating. @@ -21,7 +21,7 @@ Companion docs: - [x] Pipeline outlives the JIT — `cfree_jit_lookup` dereferences `jit->c`, so freeing the pipeline (and its Compiler) before lookup segfaults. Ownership lifted to `driver_run` to mirror - `driver/dbg.c`. + `driver/cmd/dbg.c`. - [x] Zero-source input case (`.o`/`.a` only) no longer spuriously reports "out of memory" from a 0-byte `driver_alloc_zeroed`. - [x] `driver_dlsym_resolver` retries with the leading `_` stripped so diff --git a/doc/LINK_DEBUG.md b/doc/LINK_DEBUG.md @@ -22,7 +22,7 @@ PT_LOAD), so they carry link-time vaddrs and need **no dynamic relocations** — which is exactly what `addr2line -e` reads statically. For PIE/DSO `img_base` is 0, so the same `img_base + vaddr` formula yields link-time vaddrs that match the symbol table. Default keeps debug when present; existing `-S`/`--strip-debug` -(already plumbed to `l->strip_debug`, `driver/ld.c:112,839`; +(already plumbed to `l->strip_debug`, `driver/cmd/ld.c:112,839`; `src/link/link.c:365`) drops it. ## Design diff --git a/doc/TOY_TRANSACTIONAL.md b/doc/TOY_TRANSACTIONAL.md @@ -35,7 +35,7 @@ Implementation notes: ## 1. Problem `cfree dbg` runs one long-lived `CfreeCompileSession` per language -(`driver/dbg.c:1821-1845`, cached in `s->compile_sessions[lang]`). For Toy, +(`driver/cmd/dbg.c:1821-1845`, cached in `s->compile_sessions[lang]`). For Toy, that session owns a single heap-resident `ToyParser` that accumulates all REPL declarations across snippets (`lang/toy/compile.c:6-11`). Two things are wrong: @@ -85,7 +85,7 @@ four append-only arrays: `vars`/`scopes`/`labels`/`goto_targets` are per-compile scratch and need no transaction. A top-level REPL `let` is **not** a `ToyVar`: `jit { … }` and bare `{ … }` strip braces and feed the body as `REPL_TOPLEVEL` -(`driver/dbg.c:1981-2034,3034`), parsed by `toy_parse_program` → +(`driver/cmd/dbg.c:1981-2034,3034`), parsed by `toy_parse_program` → `toy_parse_global_var` → a **durable global** (`parser.c:1830`, `data.c:78`). That is why `value` persists in `toy-empty-repl`. @@ -120,7 +120,7 @@ image (`dbg_objs_owned=0`, `link_jit.c:1386-1387`) and intentionally leaks until `cfree_jit_free`; it must not be freed on the success path. Driver `$N`: `id = ++s->expr_counter` runs **before** the compile -(`driver/dbg.c:2195`) and is not rolled back on the `goto out` failure path, +(`driver/cmd/dbg.c:2195`) and is not rolled back on the `goto out` failure path, so a failed expression still burns a `$N`. The golden requires the failed `1 +` to leave numbering at `$1` for the next valid input. diff --git a/doc/WASM.md b/doc/WASM.md @@ -24,7 +24,7 @@ The public API already names the target and format: - `CFREE_ARCH_WASM`, `CFREE_OBJ_WASM`, and `CFREE_OS_WASI` exist in `include/cfree.h`. -- `driver/target.c` parses `wasm32` and `wasm64` triples and selects +- `driver/lib/target.c` parses `wasm32` and `wasm64` triples and selects `CFREE_OBJ_WASM` for freestanding/WASI. - `CFREE_CG_CC_WASM` exists in `include/cfree/cg.h`, and `src/api/cg.c` reports it supported only for `CFREE_ARCH_WASM`. @@ -799,7 +799,7 @@ The wiring path on the runtime side is straightforward: module's `WasmFuncType` table** (also emitted as static data), and writes the function pointer into `*(void**)((char*)instance + slot_offset)`. -- `driver/run.c`, `test/link/harness/jit_runner.c`, and +- `driver/cmd/run.c`, `test/link/harness/jit_runner.c`, and `test/wasm/harness/start_wasm.c` call the binder **before** `__cfree_wasm_init`. With no imports configured the binder is a no-op, so existing modules with empty import lists continue to work diff --git a/doc/WINDOWS.md b/doc/WINDOWS.md @@ -160,7 +160,7 @@ podman run --rm --arch arm64 -v "$PWD:/work:ro" \ ### Target And Driver -`driver/target.c` recognizes `x86_64-windows` and +`driver/lib/target.c` recognizes `x86_64-windows` and `aarch64-windows`, sets `CFREE_OS_WINDOWS`, and selects `CFREE_OBJ_COFF`. Windows targets use `.obj` for relocatable output and `.exe` for linked programs. diff --git a/driver/addr2line.c b/driver/cmd/addr2line.c diff --git a/driver/ar.c b/driver/cmd/ar.c diff --git a/driver/as.c b/driver/cmd/as.c diff --git a/driver/cas.c b/driver/cmd/cas.c diff --git a/driver/cc.c b/driver/cmd/cc.c diff --git a/driver/cpp.c b/driver/cmd/cpp.c diff --git a/driver/dbg.c b/driver/cmd/dbg.c diff --git a/driver/emu.c b/driver/cmd/emu.c diff --git a/driver/ld.c b/driver/cmd/ld.c diff --git a/driver/nm.c b/driver/cmd/nm.c diff --git a/driver/objcopy.c b/driver/cmd/objcopy.c diff --git a/driver/objdump.c b/driver/cmd/objdump.c diff --git a/driver/pkg.c b/driver/cmd/pkg.c diff --git a/driver/ranlib.c b/driver/cmd/ranlib.c diff --git a/driver/run.c b/driver/cmd/run.c diff --git a/driver/size.c b/driver/cmd/size.c diff --git a/driver/strings.c b/driver/cmd/strings.c diff --git a/driver/strip.c b/driver/cmd/strip.c diff --git a/driver/env/common.c b/driver/env/common.c @@ -196,6 +196,10 @@ void cfree_debug_printf(const char* fmt, ...) { va_end(ap); } +const char* cfree_debug_getenv(const char* name) { + return getenv(name); +} + void driver_printf(const char* fmt, ...) { va_list ap; va_start(ap, fmt); diff --git a/driver/cflags.c b/driver/lib/cflags.c diff --git a/driver/cflags.h b/driver/lib/cflags.h diff --git a/driver/hosted.c b/driver/lib/hosted.c diff --git a/driver/hosted.h b/driver/lib/hosted.h diff --git a/driver/inputs.c b/driver/lib/inputs.c diff --git a/driver/inputs.h b/driver/lib/inputs.h diff --git a/driver/lib_resolve.c b/driver/lib/lib_resolve.c diff --git a/driver/lib_resolve.h b/driver/lib/lib_resolve.h diff --git a/driver/runtime.c b/driver/lib/runtime.c diff --git a/driver/runtime.h b/driver/lib/runtime.h diff --git a/driver/target.c b/driver/lib/target.c diff --git a/scripts/gen_compile_commands.py b/scripts/gen_compile_commands.py @@ -79,7 +79,7 @@ def flags_for(rel): if rel.startswith("driver/env/"): return list(HOSTED) if rel.startswith("driver/"): - return FREESTANDING + ["-Iinclude", "-Ilang"] + return FREESTANDING + ["-Iinclude", "-Ilang", "-Idriver", "-Idriver/lib"] if rel.startswith("rt/lib/"): return list(RT) return None diff --git a/src/opt/opt.c b/src/opt/opt.c @@ -71,8 +71,7 @@ static void opt_registry_add(OptImpl* o, CgIrFunc* f) { } static void opt_dbg_dump(OptImpl* o, Func* f, const char* tag) { - extern char* getenv(const char*); - const char* s = getenv("CFREE_DUMP"); + const char* s = cfree_debug_getenv("CFREE_DUMP"); CfreeWriter* w = NULL; size_t len = 0; const uint8_t* bytes; @@ -255,8 +254,7 @@ Func* opt_run_o1_interp(Compiler* c, const CgIrFunc* cg) { opt_dead_def_elim_with_live(f, &live); metrics_scope_end(c, "opt.interp.total"); { - extern char* getenv(const char*); - if (getenv("CFREE_DUMP_INTERP")) { + if (cfree_debug_getenv("CFREE_DUMP_INTERP")) { CfreeWriter* w = NULL; size_t len = 0; const uint8_t* bytes; @@ -297,11 +295,10 @@ static void opt_maybe_capture_interp(OptImpl* o, const CgIrFunc* cg) { #endif static void opt_dbg_dump_cg(OptImpl* o, const CgIrFunc* f) { - extern char* getenv(const char*); CfreeWriter* w = NULL; size_t len = 0; const uint8_t* bytes; - if (!getenv("CFREE_DUMPCG")) return; + if (!cfree_debug_getenv("CFREE_DUMPCG")) return; cfree_writer_mem(o->c->ctx->heap, &w); cg_ir_func_dump(f, w); bytes = cfree_writer_mem_bytes(w, &len); diff --git a/test/lib_deps.allowlist b/test/lib_deps.allowlist @@ -1,6 +1,7 @@ ___stack_chk_fail ___stack_chk_guard _longjmp +_memchr _memcmp _memcpy _memmove diff --git a/test/test.mk b/test/test.mk @@ -898,17 +898,23 @@ test-libc-glibc-rv64: # if a relocatable link exposes non-public global definitions. # External dependency drift in either direction (new dep, or stale entry) is a # failure. -LIB_DEPS_ACTUAL = build/libcfree.deps.txt -LIB_RELOC = build/libcfree.reloc.o -LIB_RELOC_BAD = build/libcfree.reloc.bad-symbols.txt +# +# Inspect the RELEASE artifacts only: the debug build is ASan/UBSan-instrumented +# and pulls in __asan_*/__ubsan_* externals that are not part of the shipped +# library's dependency surface. +LIB_DEPS_RELEASE_DIR = build/release +LIB_DEPS_AR = $(LIB_DEPS_RELEASE_DIR)/libcfree.a +LIB_DEPS_ACTUAL = $(LIB_DEPS_RELEASE_DIR)/libcfree.deps.txt +LIB_RELOC = $(LIB_DEPS_RELEASE_DIR)/libcfree.reloc.o +LIB_RELOC_BAD = $(LIB_DEPS_RELEASE_DIR)/libcfree.reloc.bad-symbols.txt test-lib-deps: @$(MAKE) lib RELEASE=1 @mkdir -p $(dir $(LIB_DEPS_ACTUAL)) - @python3 scripts/lib_external_deps.py $(LIB_AR) > $(LIB_DEPS_ACTUAL) + @python3 scripts/lib_external_deps.py $(LIB_DEPS_AR) > $(LIB_DEPS_ACTUAL) @diff -u test/lib_deps.allowlist $(LIB_DEPS_ACTUAL) \ || { echo "libcfree.a external symbol set drifted from test/lib_deps.allowlist"; exit 1; } - @python3 scripts/lib_reloc_defined_prefixes.py $(LIB_AR) \ + @python3 scripts/lib_reloc_defined_prefixes.py $(LIB_DEPS_AR) \ --output $(LIB_RELOC) --ar $(AR) --cc $(CC) > $(LIB_RELOC_BAD) @test ! -s $(LIB_RELOC_BAD) \ || { echo "libcfree relocatable link exposes non-public symbols"; cat $(LIB_RELOC_BAD); exit 1; }