Skip to content

Grabbing a useful backtrace

wodim edited this page Jan 23, 2018 · 4 revisions

How to create a useful backtrace

A backtrace (or stack trace) is a simple textual log of what a software is doing in that exact moment. For developers, having a backtrace of KVIrc in the moment when a bug occurs means being able to understand where the bug is situated in the source code (and eventually solve it).

First of all, to create an useful backtrace you need to compile KVIrc with debug symbols enabled: this means that you'll have to take a fresh copy of KVIrc out of git and compile it using a flag that will tell the compiler to add extra informations about the code compiled. To download a git copy of KVIrc, please refer to INSTALL file. Note that if you already have KVIrc installed, you'd better uninstall it before installing this new version to avoid multiple installations to interfere one each other.

Download the KVIrc source code from git and proceed with a normal compilation; the only more thing you have to care is to pass the -DDEBUG=1 flag to CMake:

git clone https://github.com/kvirc/KVIrc.git kvirc-trunk
cd kvirc-trunk
mkdir build
cd build
cmake .. -DDEBUG=1
(cmake messages...)
make 
(sudo) make install

Once you have a debug-enabled version of KVIrc installed, you can start KVIrc from inside gdb, The GNU debugger: call gdb passing kvirc as a parameter

bash-3.1$ gdb kvirc
GNU gdb 6.8
Copyright (C) 2008 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-slamd64-linux"...

You are now inside the gdb console: from here you can start the KVIrc process using "r" (run) and pressing enter. If you need to pass some extra parameters to the KVIrc executable, append them to the "r" command. For example, if you want to use a separate configuration file, use the "r" command like this:

(gdb) r -f -n /home/you/.kvirc-test-config
Starting program: /usr/local/bin/kvirc
[Thread debugging using libthread_db enabled]
[New Thread 0x7fb1a44da700 (LWP 25651)]

Once KVIrc is running, try to reproduce the behavior that triggers the bug for you: eg. if your KVIrc copy always crashes when you open a certain option window, try to do it now. If KVIrc crashes, you'll see its window freezing and you'll be back to the gdb console.

Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0xb574a700 (LWP 16179)]        
0xb1e6671e in ~KviTextIconsOptionsWidget (this=0x9445b80) at /home/you/kvirc-trunk/src/modules/options/optw_texticons.cpp:134
134                     delete m_pIconButton; 
(gdb) 

gdb is currently informing us that KVIrc received a "segmentation fault" signal, that is a signal sent to us by the operating system meaning "you've made something so bad that I have to kill your process now". A segmentation fault, more precisely, is a severe error in memory management. Gdb then tells us the exact point where the bug has occurred: in the file optw_texticons.cpp, at line 134, and shows us the contents of that file at that line.

Now we'll ask KVIrc to produce a full backtrace, using the "bt full" (backtrace full) command and pressing enter:

(gdb) bt full
#0  0xb1e6671e in ~KviTextIconsOptionsWidget (this=0x9445b80) at /home/you/kvirc-trunk/src/modules/options/optw_texticons.cpp:134
No locals.
#1  0xb1e0cb3c in KviOptionsDialog::recursiveCommit (this=0x9359060, it=0x9444f60) at /home/you/kvirc-trunk/src/modules/options/dialog.cpp:665
        count = <value optimized out>
#2  0xb1e0cb11 in KviOptionsDialog::recursiveCommit (this=0x9359060, it=0x94425c0) at /home/you/kvirc-trunk/src/modules/options/dialog.cpp:658
        i = 9
        count = <value optimized out>
#3  0xb1e0cb11 in KviOptionsDialog::recursiveCommit (this=0x9359060, it=0x9435e80) at /home/you/kvirc-trunk/src/modules/options/dialog.cpp:658  
        i = 4
        count = <value optimized out>
#4  0xb1e0cd9c in KviOptionsDialog::apply (this=0x9359060, bDialogAboutToClose=true) at /home/you/kvirc-trunk/src/modules/options/dialog.cpp:619        
        i = 4
        count = <value optimized out>
#5  0xb1e0ce1a in KviOptionsDialog::okClicked (this=0x9359060) at /home/you/kvirc-trunk/src/modules/options/dialog.cpp:635
No locals.
#6  0xb1e6d4c3 in KviOptionsDialog::qt_metacall (this=0x9359060, _c=QMetaObject::InvokeMetaMethod, _id=2, _a=0xbf91c9cc) at /home/you/kvirc-trunk/release/src/modules/options/moc_dialog.cxx:119
No locals.               
#7  0xb6a5677b in QMetaObject::activate () from /usr/lib/libQtCore.so.4
No symbol table info available.
#8  0xb6a56a50 in QMetaObject::activate () from /usr/lib/libQtCore.so.4
No symbol table info available.
#9  0xb7534111 in QAbstractButton::clicked () from /usr/lib/libQtGui.so.4
No symbol table info available.
#10 0xb72c57b9 in ?? () from /usr/lib/libQtGui.so.4
No symbol table info available.
#11 0x09375e70 in ?? ()
No symbol table info available.
#12 0x00000000 in ?? ()
No symbol table info available. 

As you can see, a backtrace is an ordered list of addresses. At each address corresponds a nested instruction inside the code of kvirc or one of its libraries.

Now you just have to copy this last text and save it inside a text file, attaching it to the bug ticket. Then, you can quit gdb using the "q" (quit) command. It will probably ask if you want to kill the running executable (aka the crashed KVIrc instance): just answer y (yes).