Page 1 of 1
Issues using QEMU and GDB
Posted: Thu Dec 02, 2021 9:54 pm
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
Re: Issues using QEMU and GDB
Posted: Thu Dec 02, 2021 10:20 pm
by Octocontrabass
Are you sure your bootloader can load your kernel at such a low address? Kernels are typically loaded at or above 0x100000.
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?
Re: Issues using QEMU and GDB
Posted: Fri Dec 03, 2021 12:24 am
by Je06
Octocontrabass wrote:
Are you sure your bootloader can load your kernel at such a low address? Kernels are typically loaded at or above 0x100000.
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
Re: Issues using QEMU and GDB
Posted: Mon Dec 06, 2021 12:00 am
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.
Re: Issues using QEMU and GDB
Posted: Tue Dec 07, 2021 3:09 pm
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
Re: Issues using QEMU and GDB
Posted: Wed Dec 08, 2021 1:42 am
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.").
Re: Issues using QEMU and GDB
Posted: Wed Dec 08, 2021 4:30 am
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.
Re: Issues using QEMU and GDB
Posted: Wed Dec 08, 2021 6:26 am
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.
Re: Issues using QEMU and GDB
Posted: Wed Dec 08, 2021 7:17 am
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.
Re: Issues using QEMU and GDB
Posted: Wed Dec 08, 2021 1:44 pm
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.
Re: Issues using QEMU and GDB
Posted: Wed Dec 08, 2021 3:25 pm
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.
Re: Issues using QEMU and GDB
Posted: Wed Dec 08, 2021 3:52 pm
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.
Re: Issues using QEMU and GDB
Posted: Wed Dec 08, 2021 8:55 pm
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.
Re: Issues using QEMU and GDB
Posted: Thu Dec 09, 2021 12:14 am
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?