kit

kit
git clone https://git.ryansepassi.com/git/kit.git
Log | Files | Refs | README

commit c289ef65e1f1eaa78ef7a2370c97a9d7653a6eb6
parent 0cca95ea4a0d690b13f196cfadd82f6a34de859b
Author: Ryan Sepassi <rsepassi@gmail.com>
Date:   Fri, 12 Jun 2026 09:11:52 -0700

feat(dbg): complete the x86_64-macOS debugger host adapter

The POSIX dbg signal path marshals register state through per-(arch,OS)
ucontext TUs, but darwin only had the aarch64 one — an x86_64-macOS host
build errored in env.mk ("no ucontext marshalling"), so the debugger
(and `kit run`'s crash guard) had no x86_64 Darwin backing.

- Add driver/env/uctx_x86_64_macos.c: marshal Darwin's
  __darwin_x86_thread_state64 (mc->__ss) <-> KitUnwindFrame using System
  V x86-64 DWARF numbering, mirroring the aarch64-macOS sibling.
- Wire the darwin/x86_64 branch in mk/env.mk.
- Fix a latent kit_cross.sh bug: the clang/macOS cc wrapper omitted
  -arch, so a `macos-x64` cross-build silently produced the native arm64
  slice while env.mk selected HOST_ARCH=x86_64 sources. Pass -arch
  (mapping kit's `aarch64` tag to Apple's `arm64`).

Verified via the clang lane: the x86_64 kit builds, links, and runs
under Rosetta; `kit dbg` stops at a breakpoint with correct register
state (rdi=20, rsi=22 for add(20,22)) and resumes to exit 42. Native
test-dbg unaffected (29/0).

Diffstat:
Adriver/env/uctx_x86_64_macos.c | 64++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mmk/env.mk | 2++
Mscripts/kit_cross.sh | 10+++++++++-
3 files changed, 75 insertions(+), 1 deletion(-)

diff --git a/driver/env/uctx_x86_64_macos.c b/driver/env/uctx_x86_64_macos.c @@ -0,0 +1,64 @@ +/* ucontext_t <-> KitUnwindFrame marshalling for x86_64 on macOS. + * The frame array uses DWARF numbering, which is the System V x86-64 order + * (rax=0 rdx=1 rcx=2 rbx=3 rsi=4 rdi=5 rbp=6 rsp=7 r8..r15=8..15 rip=16). + * mcontext_t is a pointer to _STRUCT_MCONTEXT; the GPRs live in Darwin's + * __darwin_x86_thread_state64 (__ss), named __rax, __rbx, … __rip. */ + +#include <stddef.h> +#include <stdint.h> +#include <string.h> + +#include "env_posix.h" + +static mcontext_t dbg_mcontext(const ucontext_t* uc) { + mcontext_t mc; + memcpy(&mc, (const char*)uc + offsetof(ucontext_t, uc_mcontext), sizeof(mc)); + return mc; +} + +void dbg_ucontext_to_frame(const ucontext_t* uc, KitUnwindFrame* f) { + mcontext_t mc = dbg_mcontext(uc); + const struct __darwin_x86_thread_state64* ss = &mc->__ss; + memset(f, 0, sizeof(*f)); + f->regs[0] = (uint64_t)ss->__rax; + f->regs[1] = (uint64_t)ss->__rdx; + f->regs[2] = (uint64_t)ss->__rcx; + f->regs[3] = (uint64_t)ss->__rbx; + f->regs[4] = (uint64_t)ss->__rsi; + f->regs[5] = (uint64_t)ss->__rdi; + f->regs[6] = (uint64_t)ss->__rbp; + f->regs[7] = (uint64_t)ss->__rsp; + f->regs[8] = (uint64_t)ss->__r8; + f->regs[9] = (uint64_t)ss->__r9; + f->regs[10] = (uint64_t)ss->__r10; + f->regs[11] = (uint64_t)ss->__r11; + f->regs[12] = (uint64_t)ss->__r12; + f->regs[13] = (uint64_t)ss->__r13; + f->regs[14] = (uint64_t)ss->__r14; + f->regs[15] = (uint64_t)ss->__r15; + f->regs[16] = (uint64_t)ss->__rip; + f->pc = (uint64_t)ss->__rip; + f->cfa = (uint64_t)ss->__rsp; +} + +void dbg_frame_to_ucontext(const KitUnwindFrame* f, ucontext_t* uc) { + mcontext_t mc = dbg_mcontext(uc); + struct __darwin_x86_thread_state64* ss = &mc->__ss; + ss->__rax = f->regs[0]; + ss->__rdx = f->regs[1]; + ss->__rcx = f->regs[2]; + ss->__rbx = f->regs[3]; + ss->__rsi = f->regs[4]; + ss->__rdi = f->regs[5]; + ss->__rbp = f->regs[6]; + ss->__rsp = f->regs[7]; + ss->__r8 = f->regs[8]; + ss->__r9 = f->regs[9]; + ss->__r10 = f->regs[10]; + ss->__r11 = f->regs[11]; + ss->__r12 = f->regs[12]; + ss->__r13 = f->regs[13]; + ss->__r14 = f->regs[14]; + ss->__r15 = f->regs[15]; + ss->__rip = f->pc; +} diff --git a/mk/env.mk b/mk/env.mk @@ -138,6 +138,8 @@ DRIVER_ENV_UCTX_SRC := ifeq ($(HOST_OS),darwin) ifeq ($(HOST_ARCH),aarch64) DRIVER_ENV_UCTX_SRC := driver/env/uctx_aarch64_macos.c +else ifeq ($(HOST_ARCH),x86_64) +DRIVER_ENV_UCTX_SRC := driver/env/uctx_x86_64_macos.c endif else ifeq ($(HOST_OS),linux) ifeq ($(HOST_ARCH),aarch64) diff --git a/scripts/kit_cross.sh b/scripts/kit_cross.sh @@ -88,9 +88,17 @@ else ct="$(clang_triple)" if [ "$os" = macos ]; then sdk="$(xcrun --show-sdk-path 2>/dev/null || true)" + # -arch selects the slice (x86_64 cross-builds on an arm64 host run under + # Rosetta); kit's `aarch64` tag is Apple's `arm64`. Without this the wrapper + # silently builds the native slice while env.mk selects HOST_ARCH sources. + case "$carch" in + aarch64) maarch=arm64 ;; + x86_64) maarch=x86_64 ;; + *) die "bad macos arch '$carch'" ;; + esac cat > "$TCDIR/cc" <<EOF #!/bin/sh -exec clang ${sdk:+-isysroot "$sdk"} "\$@" +exec clang -arch $maarch ${sdk:+-isysroot "$sdk"} "\$@" EOF else command -v ld.lld >/dev/null 2>&1 || command -v lld >/dev/null 2>&1 || die "lld not found (needed for clang cross-link)"