Towards better x86 system debugging support

Jan Kiszka
2009-01-04T13:34:17Z

[-- Attachment #1: Type: text/plain, Size: 3521 bytes --]

Hi,

as many of you may know, there is a gdb server in QEMU that allows to
debug kernels, boot loaders and other low-level stuff without real
target hardware. I'm e.g. using it heavily for analyzing Linux kernel
issues on x86 targets (thanks to KVM, you can even debug weird SMP races
in NMI-using kernel debuggers...).

Unfortunately, the x86 support is incomplete in so far that neither the
gdb remote protocol nor the gdb backend are aware of most special
registers x86 system-level software uses. This comes with several drawbacks:

o Current code bit width (16, 32 or 64) is unknown to the debugger,
so correct disassembling is not automatically possible
o Real mode cannot be detected, which would include setting 16 bit
disassembly mode and calculating segment bases appropriately
o Manually setting the architecture (set arch i8086/i386/i386:x86-64)
influences the register set layout of the remote protocol, preventing
straightforward switches from 16-bit bootloader/BIOS code to 64-bit
kernel code (to give just one example)
o Only flat memory models are supported and debugging becomes very
hairy when some segment uses a non-zero base address - note that this
also prevents support for TLS variable lookup (which is GS or
FS-based)

As a first step toward enhanced x86 support, I think there is a need for
an extended register set in the remote protocol. The following registers
should be added:

o GDTR, LDTR, IDTR, TR (visible part, ie. selector value)
o CR0..4
o DR0..7
o selected MSRs, at least
- IA32_EFER (64-bit mode detection)
- IA32_FS_Base (TLS)
- IA32_GS_Base (TLS)
- IA32_KernelGSbase (TLS)
o Shadow states of segment registers, GDTR, LDTR, IDTR and TR
(relevant for virtual targets where the VM often has access to these
hidden states, helpful when debugging targets that modify in-use
descriptor table entries)

If anyone thinks that there should be more registers or MSRs included,
please extend this list!

The question for me is how to extend the protocol precisely. I guess we
need some new qSupported feature. But should we then, if both sides
agreed on it, switch to a completely new register set or rather exchange
those additional registers separately, ie. via some new packet?

A related issue that was already the source of a lot of pain is the
register width. For 16 and 32 bit mode, gdb uses 32 bit registers in the
remote protocol. But we have a fairly different set for 64 bit mode. Now
I wonder if we should go for a full 64 bit set unconditionally with this
extension (even if the target only supports 32 bit), avoiding all
protocol problems related to switching from 64 bit to lower modes (*).
The only minor issue I see is suboptimal performance with 32 bit targets
over real serial lines - if that still matters...

Looking forward to comments, suggestions, (gdb) insights!

Jan

(*) QEMU recently decided to stick with 64 bit layout even if the x86-64
target is running in 16 or 32 bit mode. Before that the remote protocol
used to be switched between 32 and 64 bit dynamically, depending on the
current target mode. That solved many issues, but not all (manual 'set
arch' was required, and gdb became confused in a few cases). We are now
discussing again on qemu-devel how to deal with 16/32 bit system-level
debugging in 64 bit emulation environment: either try to improve gdb
quickly or reintroduce the old workaround, at least temporarily.

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 257 bytes --]