Difference between revisions of "Development/Tutorials/Debugging/Debugging symbols"

Jump to: navigation, search
(Where are they?)
m (And make?: markup)
 
(7 intermediate revisions by 4 users not shown)
Line 1: Line 1:
= Overview =
+
== Overview ==
Debugging symbols allow you to debug your application better. Debugging symbols are added to your binary by the compiler. You have to decide during the cmake step if you want debugging symbols or not. To compile your application with debugging symbols, use
+
Debugging symbols allow you to debug your application better. They are added to your binary by the compiler. For KDE, you have to decide during the cmake step if you want debugging symbols or not. To compile your application with debugging symbols, use
cmake . -DCMAKE_BUILD_TYPE=debugfull
+
<pre>
 +
cmake . -DCMAKE_BUILD_TYPE=debugfull
 +
</pre>
 
to compile it without debugging symbols, use
 
to compile it without debugging symbols, use
cmake . -DCMAKE_BUILD_TYPE=release
+
<pre>
 +
cmake . -DCMAKE_BUILD_TYPE=release
 +
</pre>
 
Depending on your decision, output generated with the command kDebug will also be (debugfull) or not be (release) added to your application.
 
Depending on your decision, output generated with the command kDebug will also be (debugfull) or not be (release) added to your application.
  
= Example app =
+
== Example app ==
 
As an example, let's write an application that crashes:
 
As an example, let's write an application that crashes:
  
 
'''main.cpp'''
 
'''main.cpp'''
                   
+
<syntaxhighlight lang="cpp-qt">     
<pre>     
+
 
#include <KApplication>
 
#include <KApplication>
 
#include <KAboutData>
 
#include <KAboutData>
Line 40: Line 43:
 
     return 0;
 
     return 0;
 
}
 
}
</pre>
+
</syntaxhighlight>
 +
 
 
'''CMakeLists.txt'''
 
'''CMakeLists.txt'''
 
<pre>
 
<pre>
Line 53: Line 57:
 
</pre>
 
</pre>
 
Now let's compile this without debugging symbols:
 
Now let's compile this without debugging symbols:
cmake . -DCMAKE_BUILD_TYPE=release && make -j4
+
<pre>
 +
cmake . -DCMAKE_BUILD_TYPE=release && make
 +
</pre>
 
We see that the resulting file is small:
 
We see that the resulting file is small:
# ll tutorial1
+
<pre>
-rwxr-xr-x 1 root root 18879 Jul 11 18:07 tutorial1
+
# ls -lh tutorial1
 +
-rwxr-xr-x 1 user user 15K Jul 11 18:07 tutorial1
 +
</pre>
 
With debugging symbols, the file is bigger:
 
With debugging symbols, the file is bigger:
cmake . -DCMAKE_BUILD_TYPE=debugfull && make
+
<pre>
# ll tutorial1
+
cmake . -DCMAKE_BUILD_TYPE=debugfull && make
-rwxr-xr-x 1 root root 256622 Jul 11 18:09 tutorial1
+
# ls -lh tutorial1
 +
-rwxr-xr-x 1 root root 250K Jul 11 18:09 tutorial1
 +
</pre>
  
= Backtraces =
+
== Backtraces ==
 
Now let's start the application and look at the backtrace:
 
Now let's start the application and look at the backtrace:
cmake . -DCMAKE_BUILD_TYPE=release && make -j4
+
<pre>
 +
cmake . -DCMAKE_BUILD_TYPE=release && make
 +
</pre>
 
Gives you the backtrace
 
Gives you the backtrace
Application: Tutorial 1 (tutorial1), signal SIGSEGV
+
<pre>
�[?1034h[Thread debugging using libthread_db enabled]
+
Application: Tutorial 1 (tutorial1), signal SIGSEGV
0x00007f58abba4cb0 in nanosleep () from /lib64/libc.so.6
+
�[?1034h[Thread debugging using libthread_db enabled]
[Current thread is 1 (Thread 0x7f58b0cfd750 (LWP 21264))]
+
0x00007f58abba4cb0 in nanosleep () from /lib64/libc.so.6
+
[Current thread is 1 (Thread 0x7f58b0cfd750 (LWP 21264))]
Thread 1 (Thread 0x7f58b0cfd750 (LWP 21264)):
+
 
[KCrash Handler]
+
Thread 1 (Thread 0x7f58b0cfd750 (LWP 21264)):
'''#5  0x00000000004016aa in main ()'''
+
[KCrash Handler]
 +
'''#5  0x00000000004016aa in main ()'''
 +
</pre>
 
The debugging build
 
The debugging build
cmake . -DCMAKE_BUILD_TYPE=debugfull && make -j4
+
<pre>
 +
cmake . -DCMAKE_BUILD_TYPE=debugfull && make
 +
</pre>
 
Gives you the backtrace
 
Gives you the backtrace
Application: Tutorial 1 (tutorial1), signal SIGSEGV
+
<pre>
�[?1034h[Thread debugging using libthread_db enabled]
+
Application: Tutorial 1 (tutorial1), signal SIGSEGV
0x00007fd0b8161cb0 in nanosleep () from /lib64/libc.so.6
+
�[?1034h[Thread debugging using libthread_db enabled]
[Current thread is 1 (Thread 0x7fd0bd2ba750 (LWP 21327))]
+
0x00007fd0b8161cb0 in nanosleep () from /lib64/libc.so.6
+
[Current thread is 1 (Thread 0x7fd0bd2ba750 (LWP 21327))]
Thread 1 (Thread 0x7fd0bd2ba750 (LWP 21327)):
+
 
[KCrash Handler]
+
Thread 1 (Thread 0x7fd0bd2ba750 (LWP 21327)):
'''#5  0x0000000000401625 in main (argc=1, argv=0x7fffc52f5138) at /root/kdehello/main.cpp:25'''
+
[KCrash Handler]
 +
'''#5  0x0000000000401625 in main (argc=1, argv=0x7fffc52f5138) at /root/kdehello/main.cpp:25'''
 +
</pre>
 
So you see: with debugging symbols, you see the line number where the crash occurred. Without, you do not see this.
 
So you see: with debugging symbols, you see the line number where the crash occurred. Without, you do not see this.
  
= Where are they? =
+
== Where are they? ==
 
Where are the debugging symbols stored? Use objdump -g to find out:
 
Where are the debugging symbols stored? Use objdump -g to find out:
# objdump  -g tutorial1-release | wc -l
+
<pre>
511
+
# objdump  -g tutorial1-release | wc -l
# objdump  -g tutorial1-debugfull | wc -l
+
511
40943
+
# objdump  -g tutorial1-debugfull | wc -l
 +
40943
 +
</pre>
 
It is important to know that the code lines (in assembler) to be executed actually do not differ a lot. We see this when disassembling the code:
 
It is important to know that the code lines (in assembler) to be executed actually do not differ a lot. We see this when disassembling the code:
# objdump -d tutorial1-debugfull | wc -l
+
<pre>
658
+
# objdump -d tutorial1-debugfull | wc -l
# objdump -d tutorial1-release | wc -l
+
658
697
+
# objdump -d tutorial1-release | wc -l
 +
697
 +
</pre>
 
This gives us hope that there will be no major speed difference between a debug- and a release-version of a binary.
 
This gives us hope that there will be no major speed difference between a debug- and a release-version of a binary.
  
= And make? =
+
== Speed implications ==
How does cmake propagate to make if a debug version is wanted? Do a
+
cmake . -DCMAKE_BUILD_TYPE=debugfull && make VERBOSE=1
+
You will find a difference during the link step. The parameters
+
-DNDEBUG -DQT_NO_DEBUG
+
are unique for the release-version. There are further differences like the O2 optimization.
+
 
+
= Speed implications =
+
 
We remove the lines that cause the crash and the messagebox. Then we execute the program 100 times:
 
We remove the lines that cause the crash and the messagebox. Then we execute the program 100 times:
cmake . -DCMAKE_BUILD_TYPE=debugfull && make -j4
+
<pre>
time for i in $(seq 1 1 100); do ./tutorial1; done
+
cmake . -DCMAKE_BUILD_TYPE=debugfull && make -j4
 +
time for i in $(seq 1 1 100); do ./tutorial1; done
 
   
 
   
real    0m6.201s
+
real    0m6.201s
user    0m4.368s
+
user    0m4.368s
sys    0m1.320s
+
sys    0m1.320s
 +
</pre>
 
Lasts 6 seconds. Now with the release version:
 
Lasts 6 seconds. Now with the release version:
cmake . -DCMAKE_BUILD_TYPE=release && make -j4
+
<pre>
time for i in $(seq 1 1 100); do ./tutorial1; done
+
cmake . -DCMAKE_BUILD_TYPE=release && make -j4
 +
time for i in $(seq 1 1 100); do ./tutorial1; done
 
   
 
   
real    0m6.259s
+
real    0m6.259s
user    0m4.368s
+
user    0m4.368s
sys    0m1.328s
+
sys    0m1.328s
 +
</pre>
 
Also lasts 6 seconds. So the main difference is in the binaries size.
 
Also lasts 6 seconds. So the main difference is in the binaries size.
 +
 +
== And make? ==
 +
How does cmake propagate to make if a debug version is wanted? Do a
 +
<pre>
 +
cmake . -DCMAKE_BUILD_TYPE=debugfull && make VERBOSE=1
 +
</pre>
 +
You will find a difference during the link step. The parameters
 +
<pre>
 +
-DNDEBUG -DQT_NO_DEBUG
 +
</pre>
 +
are unique for the release-version. There are further differences like the <tt>O2</tt> optimization.

Latest revision as of 16:51, 27 June 2011

Contents

[edit] Overview

Debugging symbols allow you to debug your application better. They are added to your binary by the compiler. For KDE, you have to decide during the cmake step if you want debugging symbols or not. To compile your application with debugging symbols, use

cmake . -DCMAKE_BUILD_TYPE=debugfull

to compile it without debugging symbols, use

cmake . -DCMAKE_BUILD_TYPE=release

Depending on your decision, output generated with the command kDebug will also be (debugfull) or not be (release) added to your application.

[edit] Example app

As an example, let's write an application that crashes:

main.cpp

 
#include <KApplication>
#include <KAboutData>
#include <KCmdLineArgs>
#include <KMessageBox>
#include <iostream>
 
using namespace std;
 
int main (int argc, char *argv[])
{
    KAboutData aboutData( "tutorial1", 0, ki18n("Tutorial 1"), "1.0",
                          ki18n("Displays a KMessageBox popup"),
                          KAboutData::License_GPL,
                          ki18n("(c) 2009"), ki18n("Some text..."),
                          "http://tutorial.com/",
                          "submit@bugs.kde.org");
 
    KCmdLineArgs::init( argc, argv, &aboutData );
    KApplication app;
 
    KMessageBox::questionYesNo( 0, i18n( "Hello World" ) );
    int* i;
    cout << "i is at " << i << " value " << *i << endl;
    i=(int*)0x0;
    cout << "i is at " << i << " value " << *i << endl;
 
    return 0;
}

CMakeLists.txt

project (tutorial1)
find_package(KDE4 REQUIRED)
include (KDE4Defaults)
include_directories(${KDE4_INCLUDES})
set(tutorial1_SRCS main.cpp)
kde4_add_executable(tutorial1 ${tutorial1_SRCS})
target_link_libraries(tutorial1 ${KDE4_KDEUI_LIBS})
install(TARGETS tutorial1  ${INSTALL_TARGETS_DEFAULT_ARGS})

Now let's compile this without debugging symbols:

cmake . -DCMAKE_BUILD_TYPE=release && make

We see that the resulting file is small:

# ls -lh tutorial1
-rwxr-xr-x 1 user user 15K Jul 11 18:07 tutorial1

With debugging symbols, the file is bigger:

cmake . -DCMAKE_BUILD_TYPE=debugfull && make
# ls -lh tutorial1
-rwxr-xr-x 1 root root 250K Jul 11 18:09 tutorial1

[edit] Backtraces

Now let's start the application and look at the backtrace:

cmake . -DCMAKE_BUILD_TYPE=release && make

Gives you the backtrace

Application: Tutorial 1 (tutorial1), signal SIGSEGV
�[?1034h[Thread debugging using libthread_db enabled]
0x00007f58abba4cb0 in nanosleep () from /lib64/libc.so.6
[Current thread is 1 (Thread 0x7f58b0cfd750 (LWP 21264))]

Thread 1 (Thread 0x7f58b0cfd750 (LWP 21264)):
[KCrash Handler]
'''#5  0x00000000004016aa in main ()'''

The debugging build

cmake . -DCMAKE_BUILD_TYPE=debugfull && make

Gives you the backtrace

Application: Tutorial 1 (tutorial1), signal SIGSEGV
�[?1034h[Thread debugging using libthread_db enabled]
0x00007fd0b8161cb0 in nanosleep () from /lib64/libc.so.6
[Current thread is 1 (Thread 0x7fd0bd2ba750 (LWP 21327))]

Thread 1 (Thread 0x7fd0bd2ba750 (LWP 21327)):
[KCrash Handler]
'''#5  0x0000000000401625 in main (argc=1, argv=0x7fffc52f5138) at /root/kdehello/main.cpp:25'''

So you see: with debugging symbols, you see the line number where the crash occurred. Without, you do not see this.

[edit] Where are they?

Where are the debugging symbols stored? Use objdump -g to find out:

# objdump  -g tutorial1-release | wc -l
511
# objdump  -g tutorial1-debugfull | wc -l
40943

It is important to know that the code lines (in assembler) to be executed actually do not differ a lot. We see this when disassembling the code:

# objdump -d tutorial1-debugfull | wc -l
658
# objdump -d tutorial1-release | wc -l
697

This gives us hope that there will be no major speed difference between a debug- and a release-version of a binary.

[edit] Speed implications

We remove the lines that cause the crash and the messagebox. Then we execute the program 100 times:

cmake . -DCMAKE_BUILD_TYPE=debugfull && make -j4
time for i in $(seq 1 1 100); do ./tutorial1; done
 
real    0m6.201s
user    0m4.368s
sys     0m1.320s

Lasts 6 seconds. Now with the release version:

cmake . -DCMAKE_BUILD_TYPE=release && make -j4
time for i in $(seq 1 1 100); do ./tutorial1; done
 
real    0m6.259s
user    0m4.368s
sys     0m1.328s

Also lasts 6 seconds. So the main difference is in the binaries size.

[edit] And make?

How does cmake propagate to make if a debug version is wanted? Do a

cmake . -DCMAKE_BUILD_TYPE=debugfull && make VERBOSE=1 

You will find a difference during the link step. The parameters

-DNDEBUG -DQT_NO_DEBUG 

are unique for the release-version. There are further differences like the O2 optimization.


This page was last modified on 27 June 2011, at 16:51. This page has been accessed 8,030 times. Content is available under Creative Commons License SA 3.0 as well as the GNU Free Documentation License 1.2.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V.Legal