Debugging a Virtual Machine Using KDBG Protocol
By default, Parallels Desktop for Mac supports GDB for debugging virtual machines. However, there is a way to enable KDBG support and allow the use of clients like WinDbg or KD.
Known Limitations and Unsupported Commands
The current implementation of KDBG support in Parallels Desktop for Mac can only be used as a raw debugger, with little to no connection with the kernel itself.
The following commands are not supported or have limited support for now:
Software breakpoints (not supported).
Read and write I/O ports (not supported).
Read and write bus data (not supported).
Reboot and bugchecks (these will force a disconnection)
Special calls (not supported).
Enabling KDBG Support in Parallels Desktop
To enable KDBG support, you have to manually edit the configuration file for the target machine:
In the Control Center, right-click on the target machine and select Show in Finder.
Right-click on the virtual machine's
.pvm
file and select Show Package Contents.Right-click on the
config.pvs
file, select Open With, and choose your preferred text editor.Use the search functon to find the
<SystemFlags>
section, which should be empty by default, and populate it following the table below.Save the edits to the
config.pvs
file.
Here are the system flags that you may want to use:
vm.debug
Enable (1
) or disable (0
) the debugger.
vm.debug.protocol
Select the debug protocol that should be used: 0
for GDB protocol or 1
for KDBG/WinDbg protocol.
vm.debug.local_addr
Local IPv4 address to bind the UDP socket.
vm.debug.host_addr
Remote IPv4 address where the host is located.
vm.debug.windbg_stub.guest.port
UDP port used to communicate with the host.
vm.debug.key
A preset encryption key used to communicate with the host: a string of exactly four values in the format
<text>
.<text>
.<text>
.<text>
, where <text>
is a sequence of decimal digits or letters with a maximum size of 12 characters (i.e. regular expression: [0-9a-z]{1,12}).
Examples: 1a.2b.3c.4d
, or this.is.my.key
, or aaaaaaaaaaaa.bbbbbbbbbbbb.cccccccccccc.dddddddddddd
.
vm.efi.monitor
Enable (1
) or disable (0
) the monitor functions in the EFI BIOS.
vm.efi.kernel_address
Enable (1
) or disable (0
) the search for the kernel base address.
vm.efi.kernel_modules
Enable (1
) or disable (0
) the search for the list of modules loaded by the kernel.
Here is an example of a configuation:
<SystemFlags>
vm.efi.monitor=1;
vm.efi.kernel_address=1;
vm.efi.kernel_modules=1;
vm.debug=1;
vm.debug.protocol=1;
vm.debug.local_addr=192.168.1.189;
vm.debug.windbg_stub.guest.port=50000;
vm.debug.key=aaaaaaaaaaaa.bbbbbbbbbbbb.cccccccccccc.dddddddddddd;
vm.debug.host_addr=192.168.1.205;
</SystemFlags>
This configuration implies a host located at 192.168.1.205
using a pre-shared encryption key aaaaaaaaaaaa.bbbbbbbbbbbb.cccccccccccc.dddddddddddd
to debug a target at 192.168.1.189
via port 50000
.
You may forgo explicitly specifying the host address, in which case you will have to specify the target's address in the debugging software that you use, prompting the host to send a special "poke" packet first to help the target identify it.
Following a reboot, the target machine will start sending packets to the host, ready to be debugged.
What Happens When the Connection Gets Interrupted
KDBG protocol doesn’t have a mechanism to terminate a connection, so the Parallels implementation forces the disconnect after 16 bad packets, or no packets at all for 10 minutes.
Since all traffic is encrypted using a data channel/session key, attemting to reestablish a dropped connection is not feasible.
Since UDP is not the most reliable protocol, the data channel may sometimes get out of sync, in which case the debugger appears to freeze. When that happens, the only way to fix it is to wait for the 10 minutes for a forced disconnection.
Most Common Commands
These are the most common commands that you can use and that are supported:
r - read/write registers. Ex.: “r”, “r x0 = 0”
u - unassemble. Ex.: “u pc”
d - display memory. Ex.: “d sp”, “db sp” (display as bytes), “dw sp” (display as words)
e - edit memory. Ex.: “eb sp ff”, “ew x0 1234”
rdmsr - read machine specific register. Ex.: “rdmsr c100” (c100 = TTBR0)
wrmsr - write machine specific register. Ex.: “wrmsr c100 00000000`00000000” (c100 = TTBR0)
ba - set break on access. Ex: “ba 1 e ffffeeee” (break on execute, 1 byte at ffffeeee)
be - enable breakpoint. Ex: “be 0” (enable breakpoint 0)
bd - disable breakpoint. Ex: “bd 0” (disable breakpoint 0)
bl - list breakpoints. Ex.: “bl”
p - step. Ex.: “p”
~N - switch vcpu. Ex.: “~0”, “~1”
f - fill memory. Ex.: “f x0 L8 0 1 2 3” (fill 8 bytes at x0 with pattern 0 1 2 3)
s - search memory. Ex. “s sp L100 fe ff” (search for pattern fe ff at [sp, sp + 100])
Last updated