Re: Towards better x86 system debugging support

Mark Kettenis
2009-01-05T20:20:55Z

> Date: Sun, 04 Jan 2009 14:34:00 +0100
> From: Jan Kiszka <jan.kiszka@web.de>
>
> Hi,
>
> 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:

Yes there are some limitations. What's there is mostly adequeate for
debugging traditional C kernel code. And I for myself have always
considered implementing the bits needed for more low-level code an
effort too big to be worth it (how much 16-bit code is there in the
Linux kernel?). But if you think otherwise, feel free to contribute
the appropriate code.

> o Current code bit width (16, 32 or 64) is unknown to the debugger,
> so correct disassembling is not automatically possible

It's tricky to figure this out when running on real hardware, but I
suppose it would be trivial for an emulator like QEMU to tell GDB what
mode it's in. The idea has always been that GDB would become
multi-arch and that every frame would have an architecture associated
with it. Perhaps that's the way to go.

> o Real mode cannot be detected, which would include setting 16 bit
> disassembly mode and calculating segment bases appropriately

Sorry, what are you trying to say here?

> 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)

Even worse, it changes the layout of GDB's internal register cache.
And I'm not even sure it is feasable to unify the i386 and amd64
layouts in a meaningful way.

> 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)

This problem is not unique to the i386/amd64 targets. There are other
architectures that have more than one address space. Unfortunately, I
believe nobody has really implemented a satisfactory solution to
implement them properly in GDB.

Not that the TLS problem has been solved already (in a satisfactory
way I think). I'm not sure making GDB aware of %gs and %fs would
really help here. Systems use those registers in different ways, and
they don't really help when you want to look at variables in a
different thread than the one you're running isn't it?

> 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:

Sorry, but I think you're starting at the wrong end here. You should
probably first add support for additional registers to GDB's internal
register cache. It doen't make sense to worry about the remote
protocol until that's done.

> 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!

I don't think it is a good idea to start adding MSRs to GDB's internal
register cache. There are zillions of them. It is probably a better
idea to implement them as a seperate address space.

One thing that's probably a good idea before starting hacking on all
this is to fully decouple the layout of the internal register cache
from the remote protocol such that when you change things there, you
don't have to worry about breaking existing remote stubs.