How to Configure the Kernel GDB Debug Stub in vphone‑cli

The kernel GDB debug stub in vphone‑cli is configured via the private VZGDBDebugStubConfiguration API, with an optional explicit TCP port (6000–65535) or system‑assigned automatic port allocation.

vphone‑cli provides a GDB-compatible debug stub for low‑level kernel debugging of virtual iPhone instances. The stub leverages Apple's private VZGDBDebugStubConfiguration class within Virtualization.framework, exposed through dynamic runtime calls. This article breaks down exactly how the stub is configured, validated, and attached to the VM.

Kernel GDB Debug Stub Configuration Architecture

The debug stub configuration follows a two‑tier design: explicit port mode and system‑assigned port mode. Both paths are implemented in VPhoneVirtualMachine.swift, while user-facing CLI options reside in VPhoneCLI.swift and VPhoneVMLaunchCLI.swift.

Explicit Port Configuration

When the --kernel-debug-port option is provided, vphone‑cli creates the stub with a user‑specified TCP port. The implementation validates the port range before instantiation.

// VPhoneVirtualMachine.swift – explicit port validation and stub creation
if let kernelDebugPort = options.kernelDebugPort {
    guard (6000...65535).contains(kernelDebugPort) else {
        throw VPhoneError.invalidKernelDebugPort(kernelDebugPort)
    }
    if let kernelDebugStub = Dynamic._VZGDBDebugStubConfiguration(port: kernelDebugPort).asObject {
        Dynamic(config)._setDebugStub(kernelDebugStub)
        print("[vphone] Kernel GDB debug stub: tcp://127.0.0.1:\(kernelDebugPort)")
    } else {
        // Fallback to system-assigned if private API fails
        Dynamic(config)._setDebugStub(Dynamic._VZGDBDebugStubConfiguration().asObject)
        print("[vphone] Kernel GDB debug stub enabled (system‑assigned port)")
    }
}

Key validation: Ports outside 6000–65535 trigger VPhoneError.invalidKernelDebugPort, preventing bind failures or privileged port conflicts.

System‑Assigned Port Configuration

When no port is specified, or when the explicit stub creation fails, vphone‑cli invokes Dynamic._VZGDBDebugStubConfiguration() with no arguments. This delegates port selection to macOS, which allocates an available ephemeral port.

// VPhoneVirtualMachine.swift – system-assigned stub fallback
} else {
    Dynamic(config)._setDebugStub(Dynamic._VZGDBDebugStubConfiguration().asObject)
    print("[vphone] Kernel GDB debug stub enabled (system‑assigned port)")
}

Runtime Port Discovery on macOS 26+

On macOS 26 and later, vphone‑cli can query the actual listening port after VM startup. This resolves the ambiguity of system‑assigned ports.

// VPhoneVirtualMachine.swift – retrieving auto-assigned port post-launch
if ProcessInfo.processInfo.operatingSystemVersion.majorVersion >= 26,
   let debugStub = Dynamic(vm)._configuration._debugStub.asAnyObject,
   let port = Dynamic(debugStub).port.asInt, port > 0 {
    print("[vphone] Kernel GDB debug stub listening on tcp://127.0.0.1:\(port)")
}

The Dynamic(vm)._configuration._debugStub property exposes the configured stub object, and .port.asInt retrieves the bound TCP port.

CLI Option Definitions

The --kernel-debug-port option is surfaced through two command entry points depending on the operational mode.

Boot Command (VPhoneCLI.swift)

// VPhoneCLI.swift – boot subcommand option
@Option(help: "Kernel GDB debug stub port on host (omit for system-assigned port; valid: 6000...65535)")
var kernelDebugPort: Int?

Launch Command (VPhoneVMLaunchCLI.swift)

// VPhoneVMLaunchCLI.swift – launch subcommand option
@Option(help: "Kernel GDB debug stub port on host (omit for system-assigned; valid: 6000...65535)")
var kernelDebugPort: Int?

Both options forward the value to VPhoneVMOption struct, which VPhoneVirtualMachine.swift consumes during VM construction.

Practical Usage Examples

Launch with Explicit GDB Stub Port

Bind the stub to a fixed port for predictable debugger attachment:

vphone-cli boot --config ./config.plist --kernel-debug-port 6001

Expected output:


[vphone] Kernel GDB debug stub: tcp://127.0.0.1:6001

Launch with System‑Assigned Port

Omit the flag to let macOS allocate the port automatically:

vphone-cli boot --config ./config.plist

Expected output (macOS 26+):


[vphone] Kernel GDB debug stub enabled (system‑assigned port)
[vphone] Kernel GDB debug stub listening on tcp://127.0.0.1:52713

Connecting GDB to the Stub

Attach GDB to the exposed stub endpoint:

gdb -ex "target remote 127.0.0.1:52713" \
    -ex "symbol-file /path/to/kernel.symbols" \
    -ex "continue"

Replace 52713 with your actual port number.

Source File Reference

File Responsibility
VPhoneVirtualMachine.swift Core stub configuration, validation, and runtime port query
VPhoneCLI.swift --kernel-debug-port option for boot subcommand
VPhoneVMLaunchCLI.swift --kernel-debug-port option for launch subcommand

Summary

  • Explicit ports (6000–65535) are validated and passed to Dynamic._VZGDBDebugStubConfiguration(port:)
  • System-assigned ports use the parameterless Dynamic._VZGDBDebugStubConfiguration() initializer
  • macOS 26+ allows post-startup port discovery via Dynamic(vm)._configuration._debugStub.port
  • CLI exposure is unified across boot and launch subcommands in VPhoneCLI.swift and VPhoneVMLaunchCLI.swift
  • Error handling throws VPhoneError.invalidKernelDebugPort for out-of-range values

Frequently Asked Questions

What is the valid port range for the kernel GDB debug stub?

The valid range is 6000 to 65535 inclusive. Ports below 6000 are rejected to avoid conflicts with well-known services, and the upper bound matches the maximum TCP port number. Supplying a port outside this range triggers VPhoneError.invalidKernelDebugPort.

How do I find the system-assigned port on older macOS versions?

On macOS versions prior to 26, vphone‑cli cannot query the auto-assigned port at runtime. You must either use an explicit port (--kernel-debug-port), or inspect system network state with lsof -iTCP -sTCP:LISTEN -P | grep vphone or similar tools to identify the listening port.

Why does vphone‑cli use private APIs for the debug stub?

Apple does not expose VZGDBDebugStubConfiguration in the public Virtualization.framework headers. Vphone‑cli accesses this functionality through dynamic Objective-C runtime calls (Dynamic._VZGDBDebugStubConfiguration), which enables kernel debugging capabilities otherwise unavailable to sandboxed or standard API usage.

Can I disable the kernel GDB debug stub entirely?

No—the current implementation in VPhoneVirtualMachine.swift always attaches a stub. When --kernel-debug-port is omitted, a system-assigned stub is configured automatically. There is no explicit "disable" flag in the source code.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →