- I want to know more about the Guest Debugger feature in Parallels Desktop for Mac Pro Edition.
Parallels Guest Debugger is used to debug any guest OS kernel and system part, and can be used for userspace debugging (with some limitations).
Guest Debugger is enabled on every VM separately, and several VMs can be debugged simultaneously if needed. By default, the debugger is turned off, but once turned on, it will remain on until the VM is shutdown or suspended.
To use the debugger you need:
NOTE: Lower versions and all other debugging utilities are not supported and may crash your VM by executing invalid debugging commands, so be careful. Keep in mind that debugging is an invasive process which impacts guest OS performance, stability, and security. Incorrect debugging commands will crash your VM and may render it unusable in the future, so make a backup of valuable data before starting.
Starting the debug
To start debugging, use the dedicated GUI button DBG in the Control Center near the specific VM you want to debug:
Terminal with LLDB will open automatically, debugger will attach to guest, stop it execution and will be waiting for further commands.
- Start debugging session in GDB, open terminal, run gdb there and connect to guest VM using command: target remote localhost:XXXX or
- Start debugging session in LLDB, open terminal, run lldb there and connect to guest VM using command: gdb-remote localhost:XXXX
,where XXXX - is a specified port (port 1883 is used by default).
Then execute the following command in Terminal:
prlctl guest-debugger <VM UUID> [--port XXXX]
Note: Only running VMs can be debugged. VMs which are paused, stopped, suspended or in transition states (i.e. while resuming, reverting, etc.) cannot be debugged also.
- Paused or freezed VMs cannot be debugged, if you revert to snapshot, your debugging session will be closed too.
- If guest bitness changed (e.g. you stopped guest, while it was in 32-bit mode and next time stopped in 64-bit mode) debugger should be reattached, this is limitation of GDB protocol.
- Remote debugging is not supported, i.e. you can connect only from the same computer, that running VM (localhost).
- Watchpoints and breakpoints will not work, if the guest bit status changes.
- Software breakpoints are very limited and can fail because of context switching, please use hardware breakpoints wherever possible
- Debugging code and data with non-zero descriptor bases isn't supported, this is limitation of GDB protocol, i.e. you should be very careful, when debugging real mode, V86 mode, 16-bit protected mode, etc, since all addresses will be linear, not effective ones.
Some of the limitations can be tackled with additional debugging scripts, e.g. automatic reattachment on guest bitness change.
To check if the guest bit status is changed, read fake register "addrmode", which contains 1 for 16-bit modes, 2 - for 32-bit mode and 3 - for 64-bit. You can output this register by issuing "read register addrmode" in LLDB or "info registers addrmode" in GDB console.
- Attaching and detaching for any guest OS
- Reading/writing general purpose registers (rax-r15, rflags, st0-st7, xmm0-xmm15, ymm0-ymm15), selectors can be only read
- Reading/writing virtual memory
- Hardware breakpoints for execution, read/write and write; software breakpoints are supported, but are very limited, avoid using them
- Single stepping, including stepping in/out
- Running/breaking guest at any point
- Additional CPU state output by remote target commands (GDB only, not supported in LLDB):
- Virtual CPUs are presented as threads in debugger and can be switched at any time guest OS is stopped
Additional remote target commands for GDB client
In GDB remote target commands should start with "monitor" reserved word:
- "monitor printcpu msr" - print syscall and sysenter msrs
- "monitor printcpu cr" - print all control registers
- "monitor printcpu dr" - print all debug registers
- "monitor printcpu instr" - prints current cpu instruction
- "monitor printcpu seg" - prints all selectors, their base and limits
- "monitor printcpu idt" - prints gdtr, idtr, tr, ldtr