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
bootandlaunchsubcommands inVPhoneCLI.swiftandVPhoneVMLaunchCLI.swift - Error handling throws
VPhoneError.invalidKernelDebugPortfor 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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →