Issues using QEMU and GDB

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
Je06
Posts: 11
Joined: Mon Dec 09, 2019 10:37 pm

Issues using QEMU and GDB

Post by Je06 »

I'm trying to debug using GDB. I've tried both dwarf and stabs+. With dwarf I get a Dwarf error: bad offset in compilation unit header. With stabs+, it reads my symbols just fine, but when connecting to QEMU using GDB, I try to print variable values but they show as 0. The same things happens with function arguments. I can print register values and set break pointes just fine. To compiling my C files, I use the command

Code: Select all

i686-elf-gcc -c <input file> -o <output file> -ffreestanding -Wall -Wextra -g
My linker file looks like

Code: Select all

ENTRY(_start)
 
SECTIONS
{
	. = 0x8000;
	
	.text BLOCK(4K) : ALIGN(4K)
	{
		*(.multiboot)
		*(.text)
	}
 
	.rodata BLOCK(4K) : ALIGN(4K)
	{
		*(.rodata)
	}
 
	.data BLOCK(4K) : ALIGN(4K)
	{
		*(.data)
	}
 
	.bss BLOCK(4K) : ALIGN(4K)
	{
		*(COMMON)
		*(.bss)
	}

	.stab BLOCK(4K) : ALIGN(4K)
	{
		*(.stab)
	}

	.stabstr BLOCK(4K) : ALIGN(4K)
	{
		*(.stabstr)
	}

	.eh_frame BLOCK(4K) : ALIGN(4K)
	{
		*(.eh_frame)
	}

	.eh_frame_hdr BLOCK(4K) : ALIGN(4K)
	{
		*(.eh_frame_hdr)
	}

	.debug_aranges BLOCK(4K) : ALIGN(4K)
	{
		*(.debug_aranges)
	}

	.debug_pubnames BLOCK(4K) : ALIGN(4K)
	{
		*(.debug_pubnames)
	}

	.debug_info BLOCK(4K) : ALIGN(4K)
	{
		*(.debug_info)
	}

	.debug_abbrev BLOCK(4K) : ALIGN(4K)
	{
		*(.debug_abbrev)
	}

	.debug_line BLOCK(4K) : ALIGN(4K)
	{
		*(.debug_line)
	}

	.debug_frame BLOCK(4K) : ALIGN(4K)
	{
		*(.debug_frame)
	}
	
	.debug_str BLOCK(4K) : ALIGN(4K)
	{
		*(.debug_str)
	}

	.debug_loc BLOCK(4K) : ALIGN(4K)
	{
		*(.debug_loc)
	}

	.debug_line_str BLOCK(4K) : ALIGN(4K)
	{
		*(.debug_line_str)
	}
}
To run QEMU I use

Code: Select all

qemu-system-x86_64.exe -s -S -cdrom .\boot.iso
To run GDB I use

Code: Select all

gdb
set arch i386:x86-64
file bootstrap.elf
target remote localhost:1234
Octocontrabass
Member
Member
Posts: 5563
Joined: Mon Mar 25, 2013 7:01 pm

Re: Issues using QEMU and GDB

Post by Octocontrabass »

Je06 wrote:

Code: Select all

	. = 0x8000;
Are you sure your bootloader can load your kernel at such a low address? Kernels are typically loaded at or above 0x100000.
Je06 wrote:

Code: Select all

set arch i386:x86-64
You're telling GDB to debug 64-bit code but your code is 32-bit. I'm not sure that's going to work.

How are you linking bootstrap.elf?
Je06
Posts: 11
Joined: Mon Dec 09, 2019 10:37 pm

Re: Issues using QEMU and GDB

Post by Je06 »

Octocontrabass wrote:
Je06 wrote:

Code: Select all

	. = 0x8000;
Are you sure your bootloader can load your kernel at such a low address? Kernels are typically loaded at or above 0x100000.
Je06 wrote:

Code: Select all

set arch i386:x86-64
You're telling GDB to debug 64-bit code but your code is 32-bit. I'm not sure that's going to work.

How are you linking bootstrap.elf?
What I'm debugging is a second stage bootloader, so 0x8000 works just fine.
As far as GDB, your right. My confusion came because I did not relies that QEMU had a separate VM for 32 bit x86 machines. Once I connected GDB to the 32 bit VM, everything worked just fine.

Still doesn't explain my issues with Dwarf, but stabs+ works just fine
Octocontrabass
Member
Member
Posts: 5563
Joined: Mon Mar 25, 2013 7:01 pm

Re: Issues using QEMU and GDB

Post by Octocontrabass »

Je06 wrote:What I'm debugging is a second stage bootloader, so 0x8000 works just fine.
I'm not sure GRUB will agree with you there. Why do you need a second stage bootloader?
Je06 wrote:My confusion came because I did not relies that QEMU had a separate VM for 32 bit x86 machines.
You don't need to use a different QEMU to debug 32-bit code. You do need to use a debugger that expects 32-bit code.
Je06
Posts: 11
Joined: Mon Dec 09, 2019 10:37 pm

Re: Issues using QEMU and GDB

Post by Je06 »

Octocontrabass wrote:
Je06 wrote:What I'm debugging is a second stage bootloader, so 0x8000 works just fine.
I'm not sure GRUB will agree with you there. Why do you need a second stage bootloader?
I forgot to mention that I'm rolling my own BIOS bootloader right now.
Octocontrabass wrote:
Je06 wrote:My confusion came because I did not relies that QEMU had a separate VM for 32 bit x86 machines.
You don't need to use a different QEMU to debug 32-bit code. You do need to use a debugger that expects 32-bit code.
I'm loading a symbols elf file and the elf file is a 32 bit elf. I double checked with objdump. When connecting to the qemu x86_64 remote target, gdb says that the

Code: Select all

Selected architecture i386 is not compatible with reported target architecture: i386:x86-64
Accord to a stack overflow post https://stackoverflow.com/a/48797740, it is suggested that the qemu i386 VM is what should be used when debugging 32 bit code
davmac314
Member
Member
Posts: 121
Joined: Mon Jul 05, 2021 6:57 pm

Re: Issues using QEMU and GDB

Post by davmac314 »

Octocontrabass wrote:You don't need to use a different QEMU to debug 32-bit code. You do need to use a debugger that expects 32-bit code.
I'm curious about what you mean by this. From my own experience (just tested again) I need to run qemu-system-i386 if I want to debug 32-bit or 16-bit code (the latter by executing "set architecture i8086" after connecting). If I run qemu-system-x86_64 instead, I can only set "i386:x86-64" as the architecture in GDB, which causes it to decode 64-bit mode instructions. It possibly doesn't matter if you want to step through source code, but if you need to be able to debug at the instruction level and have the "disassemble" command work correctly for example, it really seems like you need to use qemu-system-i386 for non-64 bit code.

In both cases I am using the same version of gdb, so I don't think it's a matter of the debugger not supporting either mode. But if the target (qemu) architecture is x86_64, I can't convince gdb to disassemble 32-bit (or 16-bit) code no matter what I do:

Code: Select all

(gdb) target remote localhost:1234
Remote debugging using localhost:1234
0x000000000000fff0 in ?? ()
(gdb) set architecture i386
warning: Selected architecture i386 is not compatible with reported target architecture i386:x86-64
Architecture `i386' not recognized.
The target architecture is assumed to be i386
(gdb) disassemble $rip,+20
Dump of assembler code from 0xfff0 to 0x10004:
=> 0x000000000000fff0:	add    %al,(%rax)
   0x000000000000fff2:	add    %al,(%rax)
   0x000000000000fff4:	add    %al,(%rax)
   0x000000000000fff6:	add    %al,(%rax)
   0x000000000000fff8:	add    %al,(%rax)
   0x000000000000fffa:	add    %al,(%rax)
   0x000000000000fffc:	add    %al,(%rax)
   0x000000000000fffe:	add    %al,(%rax)
   0x0000000000010000:	add    %al,(%rax)
   0x0000000000010002:	add    %al,(%rax)
End of assembler dump.
(gdb)
(Just to be clear, using $eip instead of $rip doesn't work, either - "Value can't be converted to integer.").
User avatar
iansjack
Member
Member
Posts: 4703
Joined: Sat Mar 31, 2012 3:07 am
Location: Chichester, UK

Re: Issues using QEMU and GDB

Post by iansjack »

If you wish to debug early code at instruction level, I would suggest that you look at SimNow from AMD ( https://developer.amd.com/simnow-simulator/ ) which is far better suited to this purpose. Once you are running 32- or 64-bit code the qemu/gdb combination works just fine, using qemu-x86_64, for instruction- or source-level debugging. There is no need to use the 32-bit version of qemu.
davmac314
Member
Member
Posts: 121
Joined: Mon Jul 05, 2021 6:57 pm

Re: Issues using QEMU and GDB

Post by davmac314 »

iansjack wrote:If you wish to debug early code at instruction level, I would suggest that you look at SimNow from AMD ( https://developer.amd.com/simnow-simulator/ ) which is far better suited to this purpose. Once you are running 32- or 64-bit code the qemu/gdb combination works just fine, using qemu-x86_64, for instruction- or source-level debugging. There is no need to use the 32-bit version of qemu.
Once again, though, how do you debug 32-bit code at the instruction level using qemu-x86_64? See my post above; it doesn't work, unless there's some magic incantation or other detail I'm missing.
User avatar
iansjack
Member
Member
Posts: 4703
Joined: Sat Mar 31, 2012 3:07 am
Location: Chichester, UK

Re: Issues using QEMU and GDB

Post by iansjack »

It just works!

TBH, I don't see the need to use the disassemble command. I have the source of code I wrote and/or I use objdump to produce a source listing.

It's always possible that the gdb you use wasn't compiled with 32-bit support. In the end, if I can't get a tool to act in the way I want to, and a better tool is available, I choose to use the better tool.

One other possible difference is that the code I am debugging is an elf file.
Octocontrabass
Member
Member
Posts: 5563
Joined: Mon Mar 25, 2013 7:01 pm

Re: Issues using QEMU and GDB

Post by Octocontrabass »

davmac314 wrote:But if the target (qemu) architecture is x86_64, I can't convince gdb to disassemble 32-bit (or 16-bit) code no matter what I do:
GDB assumes the segment base is zero. In 16-bit mode, the segment base is usually not zero. This is a common enough problem that the QEMU manual explains how to use GDB to debug real-mode code.

Depending on how you're setting up your GDT, this might also be the reason why you're having trouble with 32-bit code.
davmac314
Member
Member
Posts: 121
Joined: Mon Jul 05, 2021 6:57 pm

Re: Issues using QEMU and GDB

Post by davmac314 »

iansjack wrote:It just works!

TBH, I don't see the need to use the disassemble command. I have the source of code I wrote and/or I use objdump to produce a source listing.
But you said:
iansjack wrote:the qemu/gdb combination works just fine, using qemu-x86_64, for instruction- or source-level debugging
What is "instruction level debugging" if not viewing the individual instructions (which doesn't "just work"). Also see the post at the head of this topic, by Je06. It doesn't just work for them, either, and I get the same issue, unless I explicitly set architecture to "i386:x86-64" before connecting.
iansjack wrote:It's always possible that the gdb you use wasn't compiled with 32-bit support.
As I already said, it works fine for debugging 16-bit code, 32-bit code and 64-bit code. But for 16/32 bit code, it only works if using qemu-i386 and not qemu-x86_64.
iansjack wrote:One other possible difference is that the code I am debugging is an elf file.
I have debugged 32-bit and 64-bit ELF files no worries, except for the limitation already discussed.
Octocontrabass wrote:... the QEMU manual explains how to use GDB to debug real-mode code
Yes, it says:

"Use set architecture i8086 to dump 16 bit code. Then use x/10i $cs*16+$eip to dump the code at the PC position."

But as I said earlier (also see the gdb output I included to demonstrate it), "set architecture i8086" doesn't allow dumping 16-bit code when using qemu-x86_64; it continues to dump code as if it were long mode code. It works fine with qemu-i386.
User avatar
iansjack
Member
Member
Posts: 4703
Joined: Sat Mar 31, 2012 3:07 am
Location: Chichester, UK

Re: Issues using QEMU and GDB

Post by iansjack »

I can only reiterate that debugging 32- or 64-bit code at instruction level works fine for me with qemu-x86_64 and gdb. Something must be different with your setup, but I've no idea what.

But you already have the solution - use the 32-bit qemu to debug the 16- and 32-bit code. Or, as I suggested, have a look at SimNow; it really is an excellent tool for debugging the level you are looking at.
davmac314
Member
Member
Posts: 121
Joined: Mon Jul 05, 2021 6:57 pm

Re: Issues using QEMU and GDB

Post by davmac314 »

iansjack wrote:I can only reiterate that debugging 32- or 64-bit code at instruction level works fine for me with qemu-x86_64 and gdb.
Ok, that's good to know - thanks. It wasn't totally clear to me (up until this point) that you had actually tried it.
iansjack wrote:But you already have the solution - use the 32-bit qemu to debug the 16- and 32-bit code.
Sure, this is what I've done; it's just slightly less than ideal, and when it was implied that it wasn't necessary, I wanted to know what the trick was.

It sounds now like there's no trick - that it just works, for some people. My guess at this stage is that it has to do with Qemu and/or GDB versions, so I'll look at upgrading both.
davmac314
Member
Member
Posts: 121
Joined: Mon Jul 05, 2021 6:57 pm

Re: Issues using QEMU and GDB

Post by davmac314 »

Well, upgrading didn't help.

Apparently this is a know issue in newer versions of Qemu and GDB:
https://gitlab.com/qemu-project/qemu/-/issues/141
https://sourceware.org/bugzilla/show_bug.cgi?id=22869

I guess then that those whom are saying it works are using quite old Qemu and/or GDB versions?
Post Reply