Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to use gdb and qemu to debug linux user space programs and kernel space simultaneously?

So far, with gdb + qemu, I can step into/over linux kernel source code. Is it possible to debug the user space programs simultaneously? For example, single step a program from user space to kernel space so I can observe the changes of registers on the qemu monitor by issuing info registers?

like image 585
Jeff Li Avatar asked Oct 09 '14 06:10

Jeff Li


People also ask

How to use gdb with QEMU?

To connect to QEMU's GDB server using your host GDB, you need to create a remote connection. Once you are connected, you can debug your emulated environment like you would debug any other program. Attempts to connect to host hostname on port port. If no hostname is specified, GDB will use localhost.

What are the tools that you have used for debugging the Linux kernel?

The kernel debugger kgdb, hypervisors like QEMU or JTAG-based hardware interfaces allow to debug the Linux kernel and its modules during runtime using gdb. Gdb comes with a powerful scripting interface for python.

How do I debug QEMU?

Setup a debugger connection to a Windows Image on QEMUDownload and install QEMU on Windows. Configure a target QEMU Virtual Windows Image to launch with the required network and BIOS/UEFI settings for debugging. Start the QEMU environment, using the configured launch script. Start the gdbserver on QEMU.


2 Answers

Minimal step-by-setep setup

Mahouk is right, but here is a fully automated QEMU + Buildroot example which presuposes that you already know how to debug the kernel with QEMU + gdb and a more detailed exaplanation:

readelf -h myexecutable | grep Entry

Gives:

  Entry point address:               0x4003a0

So inside GDB we need to do:

add-symbol-file myexecutable 0x4003a0
b main

And only then start the executable in QEMU:

myexecutable

A more reliable way to do that is to set myexecutable as the init process if you can do that.

add-symbol-file is also mentioned at: How to load multiple symbol files in gdb

Why would you ever want to do this instead of gdbserver?

I can only see one use case for this so far: debugging init: Debug init on Qemu using gdb

Otherwise, why not just use the following more reliable method, e.g. to step into a syscall:

  • start two remote GDBs:
    • one with qemu-system-* -s
    • the other gdbserver myexecutable as explained at: https://reverseengineering.stackexchange.com/questions/8829/cross-debugging-for-mips-elf-with-qemu-toolchain/16214#16214
  • step in gdbserver's GDB as close as possible to the system call, which often mean stepping into the libc
  • on the QEMU's GDB, do e.g. b sys_read for the read syscall
  • back on gdbserver, do continue

I propose this because:

  • using the QEMU GDB for userland can lead to random jumps as the kernel context switches to another process that uses the same virtual addresses

  • I was not able to load shared libraries properly without gdbserver: attempting sharedlibrary directly gives:

    (gdb) sharedlibrary ../../staging/lib/libc.so.0
    No loaded shared libraries match the pattern `../../staging/lib/libc.so.0'.
    

    As a consequence, since most kernel interactions go through the stdib, you would need to do a lot of smart assembly stepping to find the kernel entry, which could be impractical.

    Until, that is, someone writes a smarter GDB scripts that steps every instruction until a context switch happens or until source become available. I wonder if such scripts would't be too slow, as the naive approach has the overhead of communication to-from GDB for every instruction.

    This might get you started: Tell gdb to skip standard files

Parsing Linux kernel data structures

To do userland process debug properly, that's what we would have to do eventually: thread-aware gdb for the Linux kernel


I achieve it by using the gdb command add-symbol-file to add userspace programs debugging information. But you must know these programs loading addresses. so to be precise, you have to launch the kernel debugging by connecting gdb to gdbserver as usual; and then, you can add those program debugging information. You can also use .gdbinit script though. Read this

like image 36
Mahouk Avatar answered Oct 17 '22 09:10

Mahouk