Parking lot for items we've identified during real implementation work but deferred to avoid going down rabbit holes. One line per item — if it grows past a line, it deserves its own doc or a real ticket. Append, don't refactor.
- Allocator vtable: per-call alignment parameter on
AllocatorAlloc/AllocatorRealloc(currently fixed at allocator init). GuardPageAllocator: per-allocationmmap+mprotect(PROT_NONE)flanking guard pages for overflow-traps-instantly testing.
Sys/Socket: moveSocketPollfrompoll()toepoll/kqueuefor >1000-fd scale.Sys/Backtrace: consider symbolize-once cache so repeatedFormatStackTracecalls don't redoSymbolResolverlookups for already-seen IPs.Sys/Backtrace(Linux/macOS x86-64): sigsetjmp-guardedread_u64_atso a wild RIP during CFI / FP walking aborts the walk instead of crashing the whole process.Sys/Backtrace: aarch64 CFI walker — same shape as the x86-64 path but reads x29 / x30 / sp registers; deferred until we have an arm64 host to test on.Sys/Dns: DNS-over-TLS / DNS-over-HTTPS — currently plain UDP/TCP only.Sys/Dns: response caching (TTL-aware), currently every resolve hits the wire.
- Multi-connection concurrency — currently one connection serviced at a time.
- TLS termination — needs an external library (mbedTLS / LibreSSL) or a serious in-tree commitment.
- HTTP/2 and WebSockets — parser today is HTTP/1.1-only.
- Host-header rewrite and routing rules — currently passes everything through to one upstream.
- Config file (KvConfig-based) instead of
--listen/--upstreamflags.
Scope:ScopeReturn/ScopeGotoviasetjmp/longjmpfor clean early-return from inside aScopeblock.
- Extend
Parsers/Elfto ELF32 + big-endian (v1 is ELF64-LSB only). - Add DWARF 5 support to
Parsers/Dwarf(.debug_lineheader changed to entry-format records; current parser silently skips v5 CUs). - Add DWARF 64-bit length form to
Parsers/Dwarf(0xffffffff-prefixed initial length; rare on Linux but used on macOS / large binaries). - Validate
.gnu_debuglinkCRC32 against the sidecar's contents before using it (currently only Build-ID lookup is verified end-to-end). - Add an integration test that strips a binary and reattaches a separate-debug-file via
objcopy --add-gnu-debuglink, then asserts that SymbolResolver still resolves symbols + source lines through the sidecar. Parsers/Dwarf: walkDW_AT_rangesfor discontiguous subprograms (currently they're skipped — only contiguouslow_pc/high_pcfunctions land inDwarfFunctions).Parsers/Dwarf: followDW_AT_specification/DW_AT_abstract_originto attach a name to defining subprogram DIEs that themselves carry noDW_AT_name(e.g. some C++ out-of-line method definitions).Parsers/Pdb: support PDBs whose directory block-map spills past a single MSF page (currently v1 caps at one block-map page, ~4 MB of directory bytes).Parsers/Pdb: line-number resolution via the per-module symbol stream (current v1 only resolves names;file:linefor stack frames is a v2 task).Parsers/Pdb: also walkS_LPROC32/S_GPROC32records in module symbol streams so private (non-public) function names appear in stack traces.Parsers/MachO: fat / universal binary support — pick the slice matching the host CPU instead of rejecting outright.Sys/MachoCache: also check~/Library/Developer/Xcode/DerivedData/.../dSYMfor the dSYM when no sibling<binary>.dSYMbundle exists alongside the loaded image.
FileGetSize/ProcGetCurrentIdcarry namespace prefixes only to avoid WINAPI macro collisions (GetFileSize,GetCurrentProcessId). Consider#undef'ing the WINAPI macros inside theSys/*translation units and reverting to the cleaner bare names.
Items below have landed; kept here as a history of what each branch closed out.
- Allocator vtable gains a
resize(self, ptr, new_size) -> i8slot alongside the renamedremap(self, ptr, new_size) -> void *(wasreallocate). Old size is recovered from the allocator's own bookkeeping, so the caller never passes it -- the API boundary forecloses the "wrong size hint" class of bug.AllocatorReallocstays as the realloc-shaped public API but is now a thin cascade: triesAllocatorResizefirst (no copy, pointer stays valid), falls back toAllocatorRemap(may move). All existing callers (Vec,BitVec,Str,File, JSON, etc.) keep usingAllocatorReallocand auto-benefit from the in-place fast path with zero source changes. - Per-allocator semantics:
HeapAllocator: resize succeeds when old + new sizes round to the same bin (no slot change needed).PageAllocator: resize succeeds when old + new round to the same page count (no kernel work).ArenaAllocator: resize succeeds whenptris the last bump (bump the high-water mark forward / backward); refused otherwise (earlier allocations have stuff after them).SlabAllocator: resize succeeds whennew <= slot_size(slot is already big enough); refused otherwise (slabs are fixed-size).BudgetAllocator: same shape as SlabAllocator.DebugAllocator: resize always refused (forces every realloc through alloc-fresh + copy + free so canary + live-map invariants stay simple).
- New public APIs
AllocatorResize(...) -> i8andAllocatorRemap(...) -> void *for callers that need to know whether the pointer moved (any data structure that holds external pointers into its buffer can askResizeand bail on failure instead of silently corrupting). None of those callers exist in-tree yet -- the immediate win is the no-copy fast path for the existingRealloc-using callers. ValidateAllocatornow checks all four vtable slots (allocate,resize,remap,deallocate). Container validators (Vec,List,Map,Graph) updated the same way.
Sys/Mutexon macOS migrated from libSystemos_unfair_lockto direct XNU__ulock_wait(#515) /__ulock_wake(#516) syscalls with op =UL_COMPARE_AND_WAIT+ULF_NO_ERRNO. Collapses the Mac path into the same Drepper 3-state futex algorithm the Linux path already uses; only the wait/wake primitive differs (futex on Linux, __ulock on Mac). Wrapped in sharedmutex_wait/mutex_wake_onestatic-inline helpers so the lock/unlock paths are OS-agnostic. Verified:Mutex.c.oon Mac has zero_os_unfair_lock_*references; all test binaries'nm -ustill lists only the four allowed__dyld_*entries. This was the last libSystem dep that survived once anything in a build pulled Sys/Mutex into the link line.
Source/Misra/_Syscall.h: extended the Linux x86_64/aarch64 plumbing with Darwin x86_64/aarch64.MISRA_DARWIN_SC(n)macro stamps BSD-class prefix on syscall numbers. asm wrappers translate XNU's carry-flag-on-error contract to Linux-style-errnoso every TU sees the same shape.misra_darwin_pipe()helper handles Darwin's pipe-returns-fds-in-registers ABI quirk.- macOS direct XNU syscalls landed across
Sys/Socket.c(poll),Sys/Proc.c(pipe / fork / dup2 / readlink),Sys/Dir.c(getdirentries64with the Darwinstruct direntlayout — d_seekoff / d_namlen — vs Linux'slinux_dirent64),Sys/Dns.c(SYS_gettimeofdaysinceclock_gettimeis libSystem-only on Mac), andStd/File.c(Darwin O_CLOEXEC=0x1000000 vs Linux 0x80000). Bin/Beam.cDarwin sigaction: hand-rolledsa_trampper arch (aarch64 + x86_64). Darwin won't call user signal handlers directly — kernel invokessa_tramp(handler, sigstyle, sig, sinfo, uctx)which must call handler then issueSYS_sigreturn(#184). Verified end-to-end: beam takes SIGINT and SIGTERM cleanly on Apple Silicon, exits 0.Bin/Beam.cWindows: replaced libcsignal()withSetConsoleCtrlHandler(kernel32). Same Ctrl-C/Ctrl-Break/close/logoff/shutdown coverage; no UCRT dep.Source/Misra/_Freestanding.c: cross-platform compiler-emitted intrinsic forwarders.memcpy/memmove/memset/memcmpuse__SIZE_TYPE__so the signatures matchsize_ton LP64 (Linux/Mac) and LLVM (Windows) alike.bzeroon Linux+Mac (Darwin clang emits direct calls).__chkstk_darwinstubbed on Mac.setjmp/longjmpnaked-asm Linux-only (test harness still uses libSystem/UCRT on Mac/Windows).Source/Misra/_StartLinux.c: in-tree_startasm trampoline. Reads argc/argv/envp from stack as the Linux ELF kernel hands them, callsmain, thenSYS_exit_group. Wired in via-nostartfilesso crt1.o never ships.Source/Misra/_StartWin.c: custommisra_startWindows entry point. Callskernel32!GetCommandLineA, tokenises into argv (basic whitespace + double-quote support), callsmain, thenExitProcess. Wired in via/ENTRY:misra_start.Source/Misra/_WinStubs.c: Windows UCRT/compiler-runtime stubs that get linked per-Bin-target (not into libmisra_std.a, to avoidduplicate symbolclash with msvcrtd in test binaries). Stubs:__security_cookie,__security_check_cookie,__chkstk,_fltused,__imp___stdio_common_vsprintf.- meson: project-wide
-fno-stack-protector+-U_FORTIFY_SOURCEon GCC/clang to drop libc-resident canary helpers. On clang-cl freestanding:/GS-+-mno-stack-arg-probeto stop emission of__security_cookie/__chkstkrefs in the first place. - meson
freestandingflag (renamed fromenable_libc_dietfor clarity): the library's default identity. _Freestanding.c / _StartLinux.c / the in-tree stack-protector helpers / the-nostdlib-shaped Bin/ link args are all keyed off this. Auto-derived fromb_sanitize: sanitizer runtimes live in libsanitizer which is libc-side, so any sanitizer build automatically falls back to a hosted configuration (libc kept, freestanding-specific TUs skipped). Not a user-facing meson option -- the shipping build is always freestanding, sanitizers are a CI / dev tool that opts out for libsanitizer compatibility. Sys/Dir.c+Sys/Proc.cper-OS gate cleanups: paths previously gated on__aarch64__(assumed Linux) now gate on__APPLE__ || __x86_64__so Darwin aarch64 takes the BSD-style branches (where Darwin has SYS_open / SYS_unlink / SYS_rmdir on both arches, unlike Linux aarch64 which went openat/unlinkat-only).Sys/Proc.cGetCurrentExecutablePathon Mac: replaced libSystem_NSGetExecutablePathwith_dyld_get_image_name(0). Stays inside the four allowed__dyld_*symbols (already pulled by Sys/Backtrace).Std/Str.cround_f64: returns x unchanged for |x| >= 2^53 to dodge UB on the i64 cast. Pre-existing latent bug from the libm drop; UBSan caught it once Mac CI got sanitizers running.- CI matrix: each of
test-linux.yml,test-macos.yml,test-windows-llvm.ymlnow runs bothsanitized(full libc + ASan + UBSan) andfreestanding(libc-diet on, asserts onnm -u/dumpbin-equivalent allowlist) flavours. Linux freestanding asserts every Bin/ tool has emptynm -u+lddreportsstatically linked. Mac freestanding asserts only the four__dyld_*entries remain. Windows LLVM freestanding asserts the IAT lists only platform DLLs (kernel32 / ws2_32 / dbghelp / advapi32 / user32 / gdi32 / etc.) —ucrtbase*,vcruntime*,msvcp*,api-ms-win-crt-*explicitly forbidden. - Per-Bin Bin/ tool surface: trimmed to two complete tools (
beam,resolve). RemovedDocGen(incomplete),EnumGen(no longer needed),ElfInfo(incomplete),SubProcComm(demo scaffolding),Demangler(skeleton with no actual demangler). Std/ArgParse: new module — clap-style argument parser withArgRequired/ArgOptional/ArgFlagandArgParseRunreturning a typed result. Used by beam + resolve. Replaces the per-binary hand-rolled argv-walking that existed in DocGen / EnumGen / ElfInfo.Sys/Dir: addedFileRemove(path)+DirRemove(path). Direct syscall on Linux (SYS_unlink / SYS_rmdir on Linux x86_64 + Darwin both arches; SYS_unlinkat on Linux aarch64). Win32DeleteFileA/RemoveDirectoryAon Windows. Returnsi8(notbool) because Darwin's<pthread.h>transitively definesboolas_Booland our project typedef isi8, so the cross-TU clash would be a compile error otherwise.
Parsers/Elf:.note.gnu.build-id+.gnu_debuglinkparsing so the resolver can find a stripped binary's sidecar.debugfile.Parsers/Dwarf:.eh_frameCIE/FDE parser + CFA bytecode interpreter + walker driver (CaptureStackTraceCfi) so unwinding works on-fomit-frame-pointerbuilds.Parsers/Dwarf:.debug_infofunction-name index (DwarfFunctions) for stripped binaries whose debug info kept the names.SymbolResolvercascade extended: main.symtab→ sidecar.symtab→ main.debug_info→ sidecar.debug_info, with build-ID and (best-effort) debuglink pairing.Parsers/Pe: PE/COFF parser with DOS / NT / optional-header walk and CodeView (RSDS) record extraction.Parsers/Pdb: MSF container reader + PDB Info stream + DBI / SymRecord / SectionHdr walker for public function names.Sys/PdbCache: portable PE → PDB resolver with GUID/age validation; wired as the primary symbolizer in the WindowsSys/Backtracepath (dbghelp kept as fallback).Parsers/MachO: 64-bit Mach-O parser (LC_SEGMENT_64 + LC_SYMTAB + LC_UUID).Sys/MachoCache: dSYM-aware resolver (main symtab → dSYM symtab → dSYM DWARF) with UUID-match enforcement.Sys/Backtrace: macOS / Darwin backend (FP walk + dyld image lookup + MachoCache); brings the in-tree symbolizer to all three desktop platforms.Sys/Backtrace: raw + Vec shapes forCaptureStackTrace/CaptureStackTraceCfi/FormatStackTrace/FormatStackTraceWithviaOVERLOAD; preserves the alloc-free path the DebugAllocator depends on.Std/Container/BitVec: raw + Vec shapes forBitVecFindAllPattern(Vec of indices) andBitVecRunLengths(Vec of{length, value}records); sameOVERLOADdispatch.Std/Allocator/Debug: backtrace + symbol resolution now goes through the in-tree chain end-to-end; no libcbacktrace()ordladdrdependency. Static functions resolve through.symtabor.debug_info.Parsers/MachO:N_STABfilter fix -- per the Mach-O spec any high bit ofn_type(mask0xE0) flags an entry as a debug stab; the original check required all three bits set so common stab types (N_SO,N_FUN,N_OSO,N_BNSYM) were polluting symbol lookups. Caught when explicit Backtrace tests ran on the macOS host.Tests/Std/MachO: Darwin-only round-trip against the running test binary via_NSGetExecutablePath+MachoOpen+MachoResolveAddress; structural parallel of the LinuxTests/Std/Elf/proc/self/exesmoke tests.
- Project-wide: dropped 65 of 67 imported libc symbols from
libmisra_std.a. The remaining 2 are compiler-emitted (__errno_location,__stack_chk_fail) and would need different build flags to drop. Sys/Socket:SocketAddrParsenow uses in-treeparse_ipv4/parse_ipv6/parse_portinstead of libcgetaddrinfo. RFC 5952 "::" compression on the v6 side. Hostname resolution returns a clear error pointing at the future-plans DNS resolver entry.freeaddrinfoalso gone;<netdb.h>no longer included.Source/Misra/_Syscall.h: private internal header withmisra_sys0..misra_sys6inline-asm wrappers and aMISRA_SYS_*syscall-number table for Linux x86_64 and aarch64. Single shared plumbing for every direct-syscall site; macOS / Windows fall through to libSystem / kernel32.Sys.c:abort()-> per-arch inline-asm trap (ud2/brk #0/udf #0/__debugbreak);getpid-> direct syscall;getenv-> walkextern char **environ;strerror_r-> in-tree errno description table covering ~45 POSIX values.Sys/Mutex.c: pthread -> futex (Linux) /os_unfair_lock(macOS) /SRWLOCK(Windows). Sizeof(Mutex) shrinks from ~40 bytes to 4-pointer-sized. Drepper-style 3-state futex; lock fast-path is one CAS.Sys/Proc.c: 10 process / I/O wrappers (close,read,write,pipe/pipe2,dup2/dup3,fork/clone,execve,kill,readlink/readlinkat,waitpid/wait4) re-routed throughmisra_sys*via local#defineshims so the existing call sites stay textually unchanged.Sys/Socket.c: full BSD-sockets call set (socket,bind,connect,listen,accept,recv/recvfrom,send/sendto,setsockopt,close,fcntl,poll/ppoll) re-routed throughmisra_sys*.gai_strerror-> in-tree EAI table.inet_ntop-> in-tree IPv4 dotted-quad + RFC 5952 IPv6 compression formatter.ntohs->FROM_BIG_ENDIAN2from Types.h.Sys/Dir.c:opendir/readdir/closedir-> directgetdents64syscall + manualstruct linux_dirent64walk.statforFileGetSize->open+lseek(END)+close(avoids the kernel/libcstruct statABI mismatch).Std/Allocator/Page.c:mmap/munmap/mprotectvia direct syscalls;sysconf(_SC_PAGESIZE)-> hardcoded per-arch constant (4 KiB everywhere except Apple Silicon at 16 KiB).Std/File.h/Std/File.c: new cross-platformFilevalue type wrapping an fd on POSIX /HANDLEon Windows.FileOpen/FileClose/FileRead/FileWrite/FileSeek/FileTell/FileFlush/FileIsEof/FileFromFd/FileStdin/FileStdout/FileStderr. Replaces allFILE *use acrossFile.c,Log.c,Io.c,ProcMaps.c,MachoCache.c,PdbCache.c,SymbolResolver.c.Std/Io.c:f_write_fmt/f_read_fmtnow takeFile *instead ofFILE *.FWriteFmt/FWriteFmtLn/FReadFmtkeep their macro shape;WriteFmt/WriteFmtLn/ReadFmtexpand to a stack-localFile f = FileStdout()-style binding so the OS's well-known channels are wrapped per-call without process state.Std/Log.c: completely stateless rewrite. No globals, no init, no deinit, no mutex. Per-call stackHeapAllocatorformats the line viaStrWriteFmt, singleFileWriteto fd 1 (INFO) or fd 2 (ERROR/FATAL) — POSIX atomic-small-write carries the thread-safety load.LOG_FATALauto-appends a captured stack trace beforeAbort().LogInit/LogDeinitdeleted from the public API; 6Bin/callers updated.Std/Container/Str.c+ JSON.h: dropped the printf-styleStrPrintf/StrAppendf(vsnprintf-backed). JSON.h'sJW_*writer macros now route throughStrWriteFmtso the typed-dispatch path handles{}placeholders forStr/Int/Float/ etc. natively.Std/Container/Float.c:snprintf("%g"/"%.17g")round-trip replaced by direct IEEE-754 bit-fishing into(sig * 5^|binexp|, dexp = binexp)form. Round-trip is now bit-exact (the libc%.17gpath was shortest-form and could lose information).Std/Memory.h/Std/Memory.c: addedMemSort(quicksort + insertion-sort fallback + tail-iter on larger partition, replaces libcqsort),ZstrToI64/ZstrToF64(decimal parsers replacingstrtoll/strtod). All Vec / List / JSON / KvConfig / Float consumers migrated.Std/Allocator/Page.c: ctype +strtol(base=16)inIo.creplaced with a 20-linehex_nibble/hex_bytehelper for\xNNescape parsing.Std/Container/Map.c: probe-budget exhaustion now forces capacity growth (passesn = capacity + 1tonext_capacity) instead of looping at the same size when a hash cluster exceedsmax_probe_count. Drove the DebugAllocator runaway-rehash bug earlier; regression test added.
Std/Allocator/Debug: init-by-value refactor -- struct literal you assign to a stack variable, no Create/Destroy, no globals. Each instance owns inlineheap/meta/pageallocators; the live-map's allocator pointer is lazily rebound on first use against the now-stableself. Thread affinity enforced via TLS-marker-address creator-TID check (no mutex, no globals).Std/Allocator/Debug:force_page_backingconfig (UAF detection mode) -- routes every alloc through the internalPageAllocator,PageProtect(PROT_NONE)'s the region on free so any dangling-pointer dereference traps with SIGSEGV at the bug site. Reserved for tests / fuzz harnesses (freed pages are never reclaimed).Std/Allocator/Default:default_alloc_debugmeson option aliasesDefaultAllocatortoDebugAllocator(per-instance, no globals); drop-in ASan/MSan-style leak + double-free + canary-overflow tracking with no call-site changes. Pairs withdefault_alloc_debug_page_backedto also flip on the UAF mode.Sys/Backtrace: forward-declaresSymbolResolverso transitively pullingParsers/Elf.hinto every TU stops happening; needed onceDefault.hstarted pullingDebug.hthroughdefault_alloc_debug=true.Std/Container/Map: probe-budget exhaustion now forces capacity growth instead of rehashing at the same size. Linear / quadratic probing limited tomax_probe_count=128could otherwise loop forever when a hash cluster exceeded the budget (rehash at same size -> same first_index -> same cluster). Surfaced under DebugAllocator churn; regression test added.