This describes tools and techniques for debugging and testing Gimp.
- 1 Tests in the build system
- 2 Using a debugger
- 3 Generating stack traces
- 4 Testing for memory errors
- 5 Performance logs
- 6 Fuzzing
- 7 Other debugging tricks
Tests in the build system
There are 'test' targets in the Gimp build systems (automake or meson):
Using a debugger
The gdb debugger is the most common debugger on Linux. This may apply to other debuggers on other platforms.
Using a debugger on the GIMP app
You can use the gdb debugger by starting Gimp in the command line:
(gdb) run (or set breakpoints etc.)
It is usually best to have a "debug" build of gimp, that has not been stripped of debug symbols (using the "strip" command.)
Using a debugger on plugins
Plugins run as separate processes. Thus they won't appear in a gdb session for the main Gimp process.
You can still debug plugins. See the document "Debugging Plugins" in the GIMP repository.
The basic idea is a feature of gdb called "attaching to a running process." You start a gdb session and "attach" gdb to the PID of the running filter process. You start gdb giving it the filename of the plugin executable. The file is used to load symbols into the debugger. But you don't tell gdb to run the program file, instead you tell gdb to "attach" the already running program, wherever it is executing, i.e. wherever it's program counter is.
You can invoke a plugin using the Gimp GUI, say Filters>MyPlugin. While it is paused waiting for user input, you can attach gdb.
You can also tell GIMP that when it starts a particular plugin, the plugin should pause and print its PID, so that you can attach gdb.
When a plugin is not a C language program, but an interpreted language plugin, gdb will show interpreter code as well as plugin specific code.
Gdb works better when programs and libraries have been built with debug symbols and not stripped of debug symbols.
Generating stack traces
Generating stack traces on crashes for the GIMP app
The GIMP app can catch certain signals and generate stack traces, also called backtraces or crash dumps.
Such stack traces appear in a dialog.
This behavior can be configured using the menu item Edit>Preferences>Debugging.
Generating stack traces on crashes and warnings for plugins
By setting an environment variable, you can arrange that plugins catch certain signal and generate stack traces to stderr.
Set the environment variable GIMP_PLUGIN_DEBUG.
See the document "Debugging Plugins" in the GIMP repository.
You need to start the GIMP app in a console/terminal to see the stack trace.
An example is:
where ">" is a console prompt, and you define an environment variable just before invoking the GIMP app. (You could also export the environment variable into your shell or define it in your shell profile.)
Note that you use the filename of a plugin's executable file, not a PDB procedure name. Each plugin can implement many PDB procedures. Examples:
>GIMP_PLUGIN_DEBUG=warp,fatal-warnings gimp >GIMP_PLUGIN_DEBUG=foggify.py,fatal-warnings gimp
Where the first example is for a C language plugin and the second is for a Python plugin.
Note this doesn't work for ScriptFu plugin scripts, since ScriptFu is an extension, and scripts are not plugins in their own processes. TODO can you do this for the ScriptFu extension?
The stack-trace-mode option to the GIMP app
This option also affects how stack traces are printed, for both the GIMP app and plugins.
--stack-trace-mode [never, query, always]
>GIMP_PLUGIN_DEBUG=warp,fatal-warnings gimp --stack-trace-mode query
Generating stack traces on demand
Occasionally it may be too much trouble to use gdb to catch conditions and print a stack trace. In C code (of the GIMP app or a plugin), you can print a stack trace. GIMP code has a utility function implemented in libgimpbase/gimputils.c.
#include <stdio.h> #include <gio/gio.h> #include <libgimpbase/gimputils.h>
gimp_stack_trace_print(NULL, stderr, NULL);
Where you: include stdio.h for the "stderr" symbol, include gio.h for the GFile symbol used by gimp_stack_trace_print() and include gimputils.h as the header for gimp_stack_trace_print().
Reading a stack trace
A stack trace will show source file names and line numbers if you have built GIMP and libraries with debug symbols (for an automake build, the option --enable-debug.)
The top few lines of the stack trace will be the functions that implement stack trace printing.
Analyzing core dumps
On Linux systems, you can arrange that crashing programs leave a core dump that can be analyzed with gdb.
Testing for memory errors
Tools for testing for memory errors:
These tools are one kind of dynamic program analysis. They detect errors while Gimp is running.
These tools often produce spurious messages, and rarely find significant issues. To use them properly, you must have a deep understanding of a program's memory use, and you must spend much time interpreting messages.
Install the package: valgrind
Valgrind requires no recompilation of Gimp.
To run gimp inside valgrind:
>valgrind --track-origins=yes gimp
Using AddressSanitizer with automake build using gcc compiler
Install the package that includes the asan runtime library?
Rebuild gimp, define an environment variable to tell the gcc compiler to use address sanitizer:
CFLAGS="-fsanitize=address -fno-omit-frame-pointer" ./autogen.sh --disable-docs --enable-debug make -j4 make install
When you run gimp, tell the loader to load the asan runtime library first:
export LD_PRELOAD=$(gcc -print-file-name=libasan.so) /usr/local/bin/gimp-2.99
(Otherwise, when you run a plugin, it is not compiled with address sanitize, yet the Gimp libraries are, and AddressSanitizer complains that it wants to load its runtime library first, to catch all calls to malloc.)
Using AddressSanitizer with meson build using clang compiler
Install your distribution's packages that contain llvm tools [clang, lld]
Rebuild gimp, define environment variables to use clang compiler and llvm linker and use the shared kind of asan runtime library:
CC=clang CXX=clang++ CC_LD=/usr/bin/ld.lld CXX_LD=/usr/bin/ld.lld LDFLAGS=-shared-libasan meson _build \ --buildtype=debug \ ... -Db_sanitize=address
As of this writing, the meson build of gimp is experimental, not supported. As of this writing, the above fails to build.
Homepage for zzuf fuzzer Install package 'zzuf'
Although it usually stops early. TODO how to delay fuzzing til an image is loaded?
Other debugging tricks
This section lists more debugging aids.
That they are listed here does not imply they are useful in any given situation.
Running Gimp in verbose mode
You can make Gimp print more information about what it is doing, in a command line of a terminal:
Stopping at GLib warnings and errors
GIMP (the app and plugins) use GLib.
The environment variable G_DEBUG affects whether GLib stops on warnings or criticals. See Gnome documents.
export G_DEBUG=fatal-criticals or fatal-warnings
Enabling GLib logging
GIMP uses the logging facilities of GLib, but very lightly.
The environment variable G_MESSAGES_DEBUG affects whether logged messages of levels DEBUG and INFORMATIONAL are printed to stderr. See Gnome documents. From those documents: "G_MESSAGES_DEBUG: A space-separated list of log domains for which debug and informational messages are printed. By default these messages are not printed." Also, you can use the "all" domain.
The domains for GIMP are:
"gimp" "scriptfu" "LibGimp", "LibGimpBase", "LibGimpColor", "LibGimpConfig", "LibGimpMath", "LibGimpModule", "LibGimpThumb", "LibGimpWidgets"
The domains for GLib are:
"GLib", "GLib-GObject", "GLib-GIO",
TODO are the above correct?
export G_MESSAGES_DEBUG=all export G_MESSAGES_DEBUG=scriptfu
Debugging GObject usage
There is a pre-loading library that helps debug lifetimes of GObjects. This library inserts itself ahead of the usual g_object_new() similarly to the way a memory analyzer inserts itself ahead of malloc().