GDB

From ReactOS Wiki
Jump to: navigation, search

This HOWTO describes the installation and setup of GDB versions as kernel debuggers for ReactOS. It focuses on the CygWin GDB since it comes with a GUI in the form of the "insight" executable, however most of the information should be applicable to other GDB versions too. Note that it is also possible to debug user mode code using this setup, you can jump between kernel mode and user mode.

Hardware setup

Since we're using the "remote" capabilities of GDB, we have to make a serial connection from the host (where GDB is running) to the target (where ReactOS is running), using a null modem cable. A cable with the following layout works (DB9 connectors):

  • On each connector, tie 1, 4 and 6 (DTR, CD, DSR) together
  • Cross 2 and 3 from one connector to 3 and 2 on the other one (Rx, Tx)
  • Connect 5 on both connectors (GND)
  • Cross 7 and 8 from one connector to 8 and 7 on the other one (RTS, CTS)

The target machine can be another computer, or it can be a VMware virtual machine. To use a VMware virtual machine install VmwareGateway from http://l4ka.org/tools/vmwaregateway.php and attach GDB to tcp\ip port:

target remote localhost:567

Installing CygWin for Windows users

Download http://www.cygwin.com/setup.exe and start it. You can use default options throughout, only make sure you select "gdb" from the "Devel" category in the package selection dialog.

Icon speedy deletion.png Warning: The patched version described below is probably outdated, the regular one should be fine


Although the standard CygWin gdb/insight should work, there is a slightly modified version available at http://svn.reactos.org/downloads/gdb/gdb_reactos.zip

Changes in the modified version:

  • Fix to allow hardware watchpoints for remote i386 targets
  • Removed a check to allow stack back tracing from kernel mode back into user mode
  • Mark insight.exe as a Windows subsystem executable (as opposed to a console subsys executable)

You can download the .zip file and replace the CygWin gdb.exe, gdbtui.exe and insight.exe (if you used defaults they will be located in C:\cygwin\bin) with the versions in the .zip file. If you use the modified version, you still need to install the CygWin gdb package, since it contains some support files that are not included in the .zip

For instructions on how to build the modified version from source see the end of this document.

GDB for Linux users

By default, GDB is compiled to handle ELF executables. In order to get the best debugging experience with GDB, getting a version able to support Windows executable is highly recommended. The easiest way is to install the mingw-w64 version of GDB provided by your Linux distribution. If your distribution doesn't have one, you can compile it from source. Run those commands:

wget http://ftp.gnu.org/gnu/gdb/gdb-9.1.tar.xz
tar xf gdb-9.1.tar.xz
cd gdb-9.1
mkdir build
cd build
../configure --prefix=/opt/pe-gdb --target=i686-w64-mingw32 --enable-lto --with-python=/usr/bin/python --with-system-readline --with-expat
make
sudo make install

Then you can launch GDB with

/opt/pe-gdb/bin/i686-w64-mingw32-gdb

Preparing ReactOS

ReactOS has a new GDB stub in a form of a KDCOM module. But, since KDCOM is disabled by default in GCC builds, it must be enabled. The cleanest way to achieve this is to create a new build directory, and run inside a RosBE session:

cd output-i686-mingw-newbuild
/path/to/reactos/configure.sh -D_WINKD_:BOOL=TRUE -DGDB:BOOL=TRUE -DSEPARATE_DBG:BOOL=TRUE -DKDBG:BOOL=FALSE
ninja bootcd

A new bootcd with GDB debugging enabled is ready to be installed. Note that you must attach gdb to the installer too.

If you want to keep your current build directory, you can just set the variables in the CMakeCache.txt of the build folder

Starting a debug session

Before debugging ReactOS, make sure it can find debug symbols. They are located in /path/to/build/symbols. Enter:

set solib-search-path /path/to/build/symbols

Then connect to the server with:

target remote localhost:567

GDB should break at the debug trap function, type "c" to continue execution. Then you can enter the debugger by typing "Tab+K" into ReactOS console, or "Ctrl+C" into GDB. GDB show a lot of started threads, because the stub started to list all the threads running in the system.

Type bt to view the stack trace, which should look like something like this:

(gdb) bt
#0  RtlpBreakWithStatusInstruction@0 () at /home/sdever/Documents/ReactOS/reactos/sdk/lib/rtl/i386/debug_asm.S:56
#1  0x80895ee9 in @KeUpdateSystemTime@12 (TrapFrame=0x809e6ca4 <P0BootStackData+11428>, Increment=149952, Irql=2 '\002') at /home/sdever/Documents/ReactOS/reactos/ntoskrnl/ke/time.c:101
#2  0x802eb7b4 in @HalpProfileInterruptHandler@4 (TrapFrame=0x809e6ca4 <P0BootStackData+11428>) at /home/sdever/Documents/ReactOS/reactos/hal/halx86/generic/timer.c:199
#3  0x802ec9f7 in _stricmp (s1=0x249c0 '?' <repeats 200 times>..., s2=0x20ac <error: Cannot access memory at address 0x20ac>) at /home/sdever/Documents/ReactOS/reactos/sdk/lib/crt/string/stricmp.c:10
#4  0x802eb4f2 in HalSetProfileInterval@4 (Interval=10382640) at /home/sdever/Documents/ReactOS/reactos/hal/halx86/generic/profil.c:102
#5  0x8090cf47 in @PopIdle0@4 (PowerState=<optimized out>) at /home/sdever/Documents/ReactOS/reactos/ntoskrnl/po/power.c:484
#6  0x80937852 in @KiIdleLoop@0 () at /home/sdever/Documents/ReactOS/reactos/ntoskrnl/ke/i386/thrdini.c:320
#7  0x8098b8b7 in KiSystemStartupBootStack@0 () at /home/sdever/Documents/ReactOS/reactos/ntoskrnl/ke/i386/kiinit.c:686
#8  0x0000000e in ?? ()
#9  0x00000000 in ?? ()

At this point, only ntoskrnl.exe and hal.dll symbols are loaded. If you want to put breakpoints into other drivers, you must load symbols with sharedlibrary command.

You can also examine kernel structures, for instance:

(gdb) print ((KPCR*)0xffdff000)->Prcb->CurrentThread->Process
$2 = (_KPROCESS *) 0x809ec080 <KiInitialProcess>
(gdb) print (_EPROCESS *)$2->ImageFileName
There is no member named ImageFileName.
(gdb) print ((_EPROCESS *)$2)->ImageFileName
$3 = "Idle", '\000' <repeats 11 times>

Debugging the early boot process

It is possible to debug the boot process using GDB with QEMU in the following way;

Start QEMU like this

qemu-system-i386 -s -S -m 512 -hda "$HOME/VirtualBox VMs/reactos/reactos.qcow"
  • -s will open a gdbserver at tcp port 1234
  • -S will not start the CPU at startup of qemu
  • -m 512 sets the ram size to 512 MB
  • -hda <path> specified the hard disk image

Create a ~/.gdbinit which looks like this. (you can also enter these commands at the gdb prompt instead):

set disassembly-flavor intel
layout asm
layout regs
target remote localhost:1234
set architecture i8086
break *0x7c00
break *0x7e00

Now start gdb. It will automatically execute the commands from the ~/.gdbinit file.

As the bios will load the MBR at memory location 0x0000:0x7c00, and you have set a breakpoint, you can simply enter c or cont to jump to the start of the bootstrap code.

The reactos bootstrap code in the MBR will relocate itself to 0x1FE0:0x7c00 and load the bootrecord of the active partition at 0x0000:0x0600 and jumps to that location. The same breakpoint will hit, so we can enter c again. Note that gdb did not update the disassembly. You can enter layout asm and layout regs to fix this, but the correct code will be executed, even if you don't do that.

The bootstrap code in the bootrecord, will load sector 14 of a FAT32 volume to 0x0000:0x7e00 and continue executing there. Entering c will hit that breakpoint.

freeldr.sys will be loaded at 0x0000:0xF800, so you can set a breakpoint there too, to continue there.