Difference between revisions of "GDB Debugger Tips"

From Lazarus wiki
Jump to navigationJump to search
Line 148: Line 148:
 
and for the length of array (minus 4)
 
and for the length of array (minus 4)
 
<delphi>^LONGINT(^LONGINT(@t)^-4)^</delphi>
 
<delphi>^LONGINT(^LONGINT(@t)^-4)^</delphi>
 +
 +
== Windows ==
 +
-----
 +
-----
 +
 +
=== Error 193 (Error creating process / Exe not found  ===
 +
 +
For details see [[http://bugs.freepascal.org/view.php?id=18238 here]].
 +
This issue has been observed under Win XP and appears to be a 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.
 +
:Your app: C:\test folder\project1.exe
 +
:Some file: C:\test
 +
  
 
== Win 64 bit ==
 
== Win 64 bit ==

Revision as of 22:51, 30 July 2011

Introduction



Lazarus comes with GDB as default debugger.

Currently (Lazarus 0.9.30) not all features are implemented, and some things are not supported by GDB. Development is ongoing.

Below are a few of the existing issues (including workarounds where available), that can be encountered while using the debugger.

General



Debug Info Type

Stabs

-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.

Dwarf

-gw

use with -godwarfsets if you have a recent gdb. Otherwise sets are not displayed correctly.


Inspecting Data-types (Watch/Hint)

Strings

If you inspect strings and whis to inspect individual chars by index (mystring[10]), then you must unfortunately specify the index 0-based. That is one less than you would normally: mystring[10-1]

This is because gdb thinks the index is 0-based. This problem will be fixed in some future release.

Properties

Currently the debugger does not support any method execution. Therefore only properties that refer directly to a variable can be inspected.

<delphi>TFoo = Class private

 FBar: Integer;
 function GetValue: Integer;

public

 property Bar: Integer read FBar;        // Can be inspected
 property Value: Integer read GetValue;  // Can *not* be inspected

end;</delphi>

Nested Procedures / Function

<delphi>procedure SomeObject.Outer(NumText: String); var

 OuterVarInScope: integer;

procedure Nested; var

 i: Integer;

begin

 writeln(OuterVarInScope);  

end;

var

 OuterVarOutsideScope: integer;

begin

 Nested;

end;</delphi>

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.

Variables treated as pointer (Objects/Dyn-Array/Var-Param...)

Sometimes Variables are pointers in GDB, where they are not in Pascal.

The IDE tries to correct this in many cases. If not you still have to fix it yourself. (One reasone why this might not be corrected by the IDE can be mixed stabs and dwarf debug info)

if you type SomeObject as a watch it may just say "TSomeClass 0x23ab76". Try typing SomeObject^

Arrays

Arrays are not always shown correctly. Furthermore the same type of array may be shown correctly if it is a global var, but not if it is a local var; or vice versa.

Sometimes it helps if there is a type name for the array

 type 
   TIntArray = Array of integer;
 var 
   x1: TIntArray;
   x2: Array of integer;

x1 may have better chances to be displayed correctly

Static Arrays
 Array [x..y] of Integer;

shows as chars, instead of int. Only gdb 7.2 or up seems to handle it correct.

Also some static array only show correct with fpc trunk, but not 2.4.2


Dynamic Arrays

Dynamic Arrays are internally pointers. This is not always recolonized. Instead of

 FooArray[1]

you may need to write

 FooArray^[1]

(In 0.9.31, this is partly corrected)

Showing the entire array is not possible, and will either show a pointer, or empty


Older Workarounds

You can always try complex typecasts to pointer.... But that is for desperate needs only....


See the following post for a workaround (it may be too complex for every day use, but it may help for desperate occasions) http://forum.lazarus.freepascal.org/index.php/topic,4763.msg22954.html#msg22954

to look at Array of String try this:

<delphi>PChar(^LONGINT(^LONGINT(@t)^+0)^) PChar(^LONGINT(^LONGINT(@t)^+4)^) PChar(^LONGINT(^LONGINT(@t)^+8)^)</delphi>

Each string needs an increase of 4 in the offset, so the above are the string at index: 0, 1, 2

and for the length of array (minus 4) <delphi>^LONGINT(^LONGINT(@t)^-4)^</delphi>

Windows



Error 193 (Error creating process / Exe not found

For details see [here]. This issue has been observed under Win XP and appears to be a 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.

Your app: C:\test folder\project1.exe
Some file: C:\test


Win 64 bit



Debugging on Win 64 bit is currently (0.9.30 / Apr 2011) broken due to: http://bugs.freepascal.org/view.php?id=16297

It works with fpc trunk only.

Lazarus Trunk and 0.9.30.1 fixes branch are known to work fpc trunk Lazarus 0.9.30 has not been tested, but may work (if it can be compiled with trunk)

In either case you need gdb 7.2.50 wich comes with Lazarus 0.9.30 and up

To compile fixes branch with fpc trunk you need to merge the following revisions (or wait until they are included in 0.9.30.1): 30301: win32: fix win32dialogs compilation with recent fpc 2.5.1 on win64 30332: ideintf: fix compilation with new tkHelper element

Snapshots may be found at (no guarantee, if it isn't there anymore ...) ftp://ftp.hu.freepascal.org/pub/lazarus/snapshots/

Using Stabs

Made some success by compiling with -g only (and not -gw). Must recompile LCL with -g (and not -gw) too (Using Tools/"Configure build Lazarus", putting -g -gl in the option field). Not fully tested, but was able to set breakpoints in various units, and single step

Using 32 bit Lazarus on 64 bit Windows

Alternatively it should be possible to debug apps as 32 bit apps (using the 32bit version of gdb). Once successfully debugged the app can then be cross-compiled to 64 bit. (or a 2nd Lazarus installation can be used, but it must be ensured they use different configuration --primary-config-path option)

If installing the 32 bit Lazarus, ensure you change configuration so the correct fpc, and gdb are used.

Mac OSX



Under OSX you usually install GDB with the Apple developer tools. The version of GDB available at the time of writing this is 6.3.50

This section is a first approach to collect information about known issues and workarounds. The information provided here depends a lot on feedback from OSX users.

Known Problems

Debugging 32 bit app on 64 bit architecture

It is possible and maybe sometime necessary to debug a 32 bit exe on a 64 bit system.

This is only possible with Lazarus 0.9.29 rev 28640 and up. As of Dec 2010 this feature is relatively new, and little tested. You may experience problems.

Debug session freezes

  • This is for 0.9.30 and before - For 0.9.30.1, or 0.9.31 and later see "TimeOuts"

It appears that certain commands are not correctly (or incompletely) processed by gdb 6.3.50. GDB will not signal to the IDE that it finished the command, and the IDE will wait forever for gdb to return. Effectively your debug session becomes non-reactive. (Normally GDB finishes each command with a "<gdb>" prompt for the next command)

This has been observed with:

  • Certain Watch expressions (at least if the watched variable was not available in the current selected function)
  • [Fixed in rev 28640] 32 bit app on 64bit architecture raising an Exception

The only way to deal with this, is to define a time-out, and to assume if the time-out is reached, that the command indeed finished, and simply forgot to signal this fact. However it is impossible:

  • to predict how long a command really takes
  • to guarantee GDB will not later return some results from such a command
  • to guarantee that GDB's internal state is still valid

For those reasons this issue can not be properly fixed at current.

As a work around time-out have been added. To enable them recompile (use "make clean" to force the rebuild) the IDE with the following define: DBG_WITH_TIMEOUT ( -dDBG_WITH_TIMEOUT ) Please note:

  • There is no guarantee how well, or bad this works. You use that at your own risk. However a warning prompt will alert you if a time-out occurred
  • Time-outs have not yet been added to all functions. If you encounter uncaught time-outs (while having the define enabled), then please report them.

An alternative solution seems to be to use a newer version of GDB

In 0.9.31 timeout has become a configurable option. The define is no longer needed.

More info see her: [| http://bugs.freepascal.org/view.php?id=19262#c47944]

TimeOuts

This is the same as the above "freeze" issue. Lazarus 0.9.30.1 and 0.9.31 are detecting the freeze (in all cases known at the time of writing this) and report it as timeout.

This is a Mac 64 bit issue

Configuration 0.9.30.1 and 0.9.31 and up only

In the options dialog (Tools Menu) under "Debugger general", there are "Debugger specific options" (only shown if gdb is selected as debugger).

Warn On Timeout
True/False. Auto continue, after a timeout, do not show a warning.
TimeOutForEval
Set in milliseconds, how long until a timeout detection is triggered (the detection itself may take some more time.)

You may need to "RESET" the debugger after those changes are made

As stated the timeout is due to a bug in GDB and can not be fixed in the IDE. It can not be guaranteed that GDB continues to function well. However, so far it seems that it always does. If timeouts cannot be avoided, then you may as well switch the warning off, and set the detection time low (250)

Hardware exceptions under Mac OS X

When a hardware exception occurs under Mac OS X, such as an invalid pointer access (SIGSEGV) or an integer division-by-zero on Intel processors, the debugger will catch this exception at the Mach level. Normally, the system translates these Mach exceptions into Unix-style signals where the FPC run time library handles them. The debugger is however unable to propagate Mach exceptions in this way.

The practical upshot is that it is impossible under Mac OS X to continue a program in the debugger once a hardware exception has been triggered. This is not FPC-specific, and cannot be fixed by us.

Using Alternative Debuggers

You can download GDB 7.1 (or later) from MacPorts

The following observations have been made:

  • MacPort GDB 7.1 seems to have issues with the stabs debug info from fpc.
Make sure you select "generate dwarf debug information (-gw)" on the linking tab of the project options
Watch out for the linker warnings about "unknown stabs"
If you still have problems ensure that no code at all, is compiled with stabs. Your LCL may contain stabs, and this will end up in your app, even if you compile the app with -gw. So you may have to recompile your LCL with -gw (or without any debug info). Same for any other unit, package, rtl, .... that may have stabs
  • MacPort GDB 7.1 seems to be unable to handle application-bundles. In order to debug your app, you must use "run param" to specify the actual executable inside the app-bundle ( project.app/Content/MacOs/project or similar)

Even with those rules followed, MacPort GDB does not always work with fpc compiled apps.


Those observations may be incomplete or wrong, please update them, if you have more information.

Links

  • Mac OS X comes with a lot of useful tools for debugging and profiling. Just start /Developer/Applications/Instruments.app and try them out.

Reporting Bugs



Check existing Reports

Please check each of the following links

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.

Basic Information

  • 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 eithe -g or -gw is used)
Smart Link (-XX); This must be OFF
Strip Symbols (-Xs); This must be OFF

Log info for debug session

  • "Debug output"
Please open the "Debug output" window (from menu "View", "Debug windows").You must open this before you run your app (F9).
Run your app, with this window open, then once the error occurs, copy, zip, and attach the content of the "debug output" window
  • "Log file"
Start Lazarus with -debug-log option (you can do this for the same run as above):
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" to the command line.
On Linux
start Lazarus from a shell and append " --debug-log=/home/yourname/laz.log" to the command line
On Mac/OSX
start Lazarus from a shell /path/to/lazarus/lazarus.app/Content/MacOS/lazarus --debug-log=/path/to/yourfiles/laz.log
Attach the log file after reproducing the error.
If possible, before producing the log file, please recompile the IDE with:
-dDBG_VERBOSE -dDBGMI_QUEUE_DEBUG
You need to use the option "clean all" to recompile.