4

I'm running qemu-system-i386 -s -S -singlestep (and sometimes qemu-system-x86_64), and I connect to it over TCP to address 127.0.0.1:1234 using the GDB remote protocol. I issue the g command to get (some) register values, including CS and EIP.

How do I get the current code bit size value (16 for real mode and 16-bit protected mode, 32 for 32-bit protected mode and 64 for long mode) using the GDB remote protocol?

I know that I can also get it from the segment descriptor of CS (it's in the DB flag) for protected mode, and I can detect protected mode by checking the PE bit of CR0. However, I can't find any (direct) way to get either the segment descriptor of CS or CR0 using the GDB remote protocol.

FYI The respose for the command qXfer:features:read:target.xml:0,4096 contains the constant <architecture>i386</architecture> no matter what the current mode is.

If the GDB server is gdb(1), then CR0 has register number 0x38 (for i386) or 0x48 (for amd64), so the command p38 or p48 returns its value. Also it's included in the result of g. Please note that in my case qemu-system-i386 is the GDB server, and it doesn't provide CR0 in g, and it doesn't support the p command.

8
  • 1
    Interesting question. With Bochs' built-in debugger, the debugger is aware of x86 modes and the current guest-CPU state. That's one reason it's usually the best choice for debugging mode switching code. But it would be nice to know if it's possible with GDB attached to QEMU as well. Commented Apr 16 at 23:20
  • Thank you for suggesting Bochs! However the program I'm debugging misbehaves in QEMU specifically, and I'd like to debug it in there. Commented Apr 16 at 23:23
  • 1
    Yeah, fair enough. One common cause of working on one emulator or real hardware but not another is relying on initial state (like segment bases) that isn't guaranteed; very little is actually guaranteed for an MBR bootloader: See Boot loader doesn't jump to kernel code (Michael Petch's tips for bootloader development). But of course being able to actually debug properly in two different environments would be great to confirm what's going on, whether or not your problem is one of the things that Michael mentions. Commented Apr 17 at 0:00
  • 2
    It does makes sense for the target description to be always the same regardless of the current mode (x86-64 is x86-64 machine, even in 16-bit mode). Also you CAN read CR0 and EFER, they are in general registers set so simple 'g' gives you their values. However, I don't see a way to get either actual current CPU mode, or current CS shadow segment through gdb protocol. You can get that through monitor, but apparently not through gdbstub. Commented Apr 17 at 1:36
  • 1
    Older qemu perhaps? Mine does, it would seem. However that wouldn't be enough anyways. Good idea about rcmd, "info registers" is what I was talking about in monitor. Commented Apr 17 at 7:20

1 Answer 1

4

It's possible to get the value of CR0 and the flags using the QEMU-specific GDB command qRcmd,696e666f20726567697374657273, where the hex string is the hex encoding of info registers, which is a QEMU monitor command. The response for that is multiple lines, including these:

CS =f000 ffff0000 0000ffff 00009b00
CR0=60000010 CR2=00000000 CR3=00000000 CR4=00000000

Knowing these values it's possible to figure out the mode.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.