GDB Debugger Tips
Lazarus comes with GDB as default debugger.
- This page is for Lazarus 1.0. For older versions see previous version of this page
- Note on GDB 7.5: GDB 7.5 is not supported by the released 1.0. Fixes to support it were made in 1.1.
To get the best possible results, you must ensure that your IDE and Project are both correctly configured.
See Debugger Setup how to set up the IDE and your project in order to use the debugger.
Debug Info Type
When debugging 64 bit applications, it may be necessary to use dwarf.
-g or -gs
You should only use if your gdb version does not support dwarf. There are very few other cases where you need it.
You may need it with "var param" (param by ref) procedure foo(var a: integer); However the IDE deals with this in 99% of all cases.
This is the recommended setting.
This sets the format to Dwarf2 (-gw2 is equivalent to this setting)
use with -godwarfsets if you have a recent gdb. Otherwise sets are not displayed correctly.
This list is in no way complete:
Inspecting data types (Watch/Hint)
GDB does not know the Pascal string data type. The type information GDB returns does not currently allow for the IDE to differentiate between a PChar (index is 0 based) or a String (index is 1 based).
As a Result "mystring" could be the 10th char in a string, or 11th in a PChar.
Because the IDE can not be sure which one applies, it will show both. The 2 results will be prefixed String/PChar.
Currently the debugger does not support any method execution. Therefore only properties that refer directly to a variable can be inspected. (This only works if using dwarf)
Nested Procedures / Function
If you step into "Nested", then the IDE allows you to inspect variables from both stack frames.
This is you can inspect: I, OuterVarInScope, NumText (without having to change the current stack frame, in the stack window)
However there are some caveats:
You can also inspect: OuterVarOutsideScope. That is against Pascal scoping rules. This only matters if you have several nested levels, and they all contain a variable of the same name, but the Pascal scoping would hide the variable from the middle frame. Then you get to see the wrong value.
You can not evaluate statements across the 2 frames: "OuterVarnScope-I" does not work.
shows as chars, instead of int. Only gdb 7.2 or up seems to handle it correctly.
Additionally there may be issues when using arrays of (unnamed) records.
Dynamic Arrays will only show a limited amount of their data. As of Lazarus 1.1 the limit can be specified.
During startup program exited normally
In rare cases the IDE displays the message "During startup program exited normally". This message appears when the debugged application is closed. If this happens no breakpoints in the app will have been triggered, and the app will have run as if no debugger was present.
This error can happen for various reasons. There are at least 2 known:
There may be more. The 2nd only happens on repeated runs of the debugger.
The IDE tries to work around those, but it does not always succeed. It is likely that in cases where it currently fails, this must be worked around by user set config (see below).
Even if you can work around, please consider to send a logfile: #Log_info_for_debug_session
Ways to work around: (all on the options / debugger page)
go to the debugger options and in the field "debugger_startup_options" enter:
--eval-command="set auto-solib-add off"
This can only be used, if you do not debug within libraries (if you have not written your own lib)
It will add a very slight increase to the time it takes to start the debugger, as gdb must be reloaded each time.
Try any of the values available for "InternalStartBreak" (in the property grid of the options)
SIGFPE is a floating point unit exception.
Source: [forum thread]
SIGFPE exceptions are raised on the next FPU instruction; therefore the error line you get from Lazarus may be off/incorrect.
Delphi, and thus Freepascal, have a non standard FPEMask. A lot of C libraries don't use exceptions to check FPU problems but inspect the FPU status.
Workaround: try changing the mask with SetExceptionMask as early as possible in your program:
If you think there is something wrong in the FPC code, you can use the $SAFEFPUEXCEPTIONS directive. This will add a FWAIT after every store of a FPU value to memory. Most FPC float and double operations end with storing the result somewhere in memory so the outcome is that the debugger stops on the correct FPC line. FWAIT is a nop for the FPU but will cause an exception to be raised immediately instead of somewhere down your code. It is not done per default because it slows down floating point operations a lot.
Error 193 (Error creating process / Exe not found)
For details see here. This issue has been observed under Win XP and appears to be caused by Windows itself. The issue occurs if the path to your app has a space, and a 2nd path/file exists, with a name identical to the part of the path before the space, e.g.:
SigSegV - even with new, empty application
The following applies only, if you get a SigSegv, even with a new empty application (empty form, and no modifications made to unit1).
A SigSegV sometimes can be caused by an incompatibility between GDB and some other products. It is not known if this is a GDB issue or caused by the other product. There is no indication that any of the products listed is in any way at fault. The information provided may only apply to some versions of the named products:
SigSegV - and continue debugging
gdb.exe has stopped working
GDB itself has crashed. This will be due to a bug in gdb, and may not be fixable in Lazarus. Still it may be worth submitting info (see section "Reporting Bugs" below). Maybe Lazarus can avoid calling the failing function.
There is one already known situation. GDB (6.6 to 7.4 (latest at the time of testing)) may crash while your app is being started, or right after your app stopped. This happen while the libraries (DLL) for your app are loaded (watch the "Debug output" window). In this case go to the debugger options and in the field "debugger_startup_options" enter:
"PC register is not available" ("SuspendThread failed. (winerr 5)")
GDB may fail with this message. This is due to http://sourceware.org/bugzilla/show_bug.cgi?id=14018 If you get this issue you may want to downgrade to GDB 7.2
Can not insert breakpoint
For breakpoints with negative numbers, please see: http://forum.lazarus.freepascal.org/index.php/topic,10317.msg121818.html#msg121818
- Did you verify your Debugger Setup?
- Did you try Dwarf and Stabs
Check existing Reports
Please check each of the following links
- Search Mantis for category "debugger"
- Search Mantis for text "debugger"
- Search Mantis for text "gdb"
- Search Mantis for text "dwarf"
- Search Mantis for text "stabs"
Bugs in GDB
|win64 crash with bad dwarf2 symbols||win64||GDB 7.4 (maybe higher)||http://sourceware.org/bugzilla/show_bug.cgi?id=14014|
|Debuggee doesn't see environment variables set with set environment||win||Solved in GDB 7.4||http://sourceware.org/bugzilla/show_bug.cgi?id=10989|
| Win32 fails to continue with "winerr 5" (pc register not available)
*apparently* not present in 7.0 to 7.2
|win||GDP 7.3 and up (maybe 6.x too)||http://sourceware.org/bugzilla/show_bug.cgi?id=14018|
|Wrong array index with dwarf||*|| GDB 7.3 to 7.5 (maybe 7.6.0)
fixed in 7.6.1
| GDB crashes, if trying to inspect or watch resourcestrings
only tested on win32, not known for other platforms only, if using dwarf
|*||GDB 7.0 to 7.2.xx|
| Records (especially: pointer to record) may be mistaken for classes/objects
The data/values appear to be displayed correct / further tests pending
|*|| GDB 7.6.1 and up
(not tested for 7.5.9 or 7.6.0)
|gdb cannot continue after SIGFPE or SIGSEGV happen on windows||win||*||https://sourceware.org/bugzilla/show_bug.cgi?id=10004|
Issues with GDB 7.5.9 or 7.6
There are various reports (not confirmed) for different platforms about crashes in gdb 7.5.9 or 7.6.
It is highly recommended not to use those versions.
Create a new Report
If you have at any time in the past updated, changed, reinstalled your Lazarus then please check the "Options" dialog ("Environment" or "Tools" Menu) for the version of GDB and FPC used. They may still point to old settings.
- Your Operating system and Version
- Your CPU (Intel, Power, ...) 32 or 64 bit
- Version of
- Lazarus (Latest Release or SVN revision) (Include setting used to recompile LCL, packages or IDE (if a custom compile Lazarus is used))
- FPC, if different from default. Please check the "Options" dialog ("Environment" or "Tools" Menu)
- GDB, please check the "Options" dialog ("Environment" or "Tools" Menu)
- Compiler Settings: (Menu: "Project", "Project Options", indicate all settings you used )
- Page "Code generation"
- Optimization settings (-O???): Level (-O1 / ...) Other (-OR -Ou -Os) (Please always test with all optimizations disabled, and -O1)
- Page "Linking"
- Debug Info: (-g -gl -gw) (Please ensure that at least either -g or -gw is used)
- Smart Link (-XX); This must be OFF
- Strip Symbols (-Xs); This must be OFF
Log info for debug session
- Start Lazarus with the following options:
- On Windows
- you need to create a shortcut to the Lazarus exe (like the one on Desktop) and edit it's properties. Add " --debug-log=C:\laz.log --debug-enable=..." to the command line.
- On Linux
- start Lazarus from a shell and append " --debug-log=/home/yourname/laz.log --debug-enable=..." to the command line
- On Mac/OSX
- start Lazarus from a shell /path/to/lazarus/lazarus.app/Contents/MacOS/lazarus --debug-log=/path/to/yourfiles/laz.log --debug-enable=...
Attach the log file after reproducing the error.
If you can not generate a log file, you may try to open the "Debug output" window (from menu "View", "Debug windows").You must open this before you run your app (F9). And then run your app. Once the error occurs, copy, zip, and attach the content of the "debug output" window.
Experimental Debuggers in pascal
Those are work in progress:
- fpdebug in Lazarus/components/fpdebug and debugger/components/fpgdbmidebugger