MeeGo 1.2 Harmattan Developer Documentation Develop for the Nokia N9

Debugging with GDB in Scratchbox


This section explains how to use the GNU Debugger (GDB) in MeeGo 1.2 Harmattan Platform SDK environment running the Scratchbox cross-compilation engine. It is targeted at beginner-level MeeGo 1.2 Harmattan application developers who debug applications in the Platform SDK environment.

This section explains how to set up and configure the SDK environment to be used with GDB, and how debugging with GDB in Scratchbox differs from debugging with GDB in the host without a Scratchbox environment. Tutorials and books that explain how to use GDB are available online. A good starting point is to read the material available on the official home page of the GNU Project Debugger.

Prerequisites

  • You know how to develop software in the Linux environment using C or C++ language.
  • You know how to use GDB and understand the basic debugging concepts.
  • You are familiar with both common and Harmattan-specific cross-compilation terminology (for example, understand what terms like cross-compiler, rootstrap or target file system, and target mean).
  • You have installed Platform SDK on your Linux host system.

To follow the remote debugging examples, you also need the following:

  • Harmattan device
  • USB cable to connect the device with the Linux host system
  • connection between the Linux host system and the device using USB or WLAN

Debugging on Scratchbox X86 target

Note: QEMU is not available for debugging applications in the i386 target.

Creating and compiling an application

This section describes how to debug a Harmattan MeeGo Touch application using a a simple GUI example application.

1. Fetch the sample code.

2. To enter the project directory, enter the following commands:

[sbox-HARMATTAN_X86: ~] > cd meego-helloworld-1.0
[sbox-HARMATTAN_X86: ~/meego-helloworld-1.0/src] > ls
com.meego.meego-helloworld.service  helloworld.h  meego-helloworld.desktop
helloworld.cpp                      main.cpp      src.pro
[sbox-HARMATTAN_X86: ~/meego-helloworld-1.0/src] >

3. To build the application, enter the following commands:

[sbox-HARMATTAN_X86: ~/meego-helloworld-1.0] > dpkg-buildpackage -rfakeroot
[sbox-HARMATTAN_X86: ~/meego-helloworld-1.0] > cd ..
[sbox-HARMATTAN_X86: ~/meego-helloworld-1.0] > dpkg -i meego-helloworld_0.1-1_i386.deb

Note: If you are debugging your own application, enable the debug flag in the application's src.pro file as follows:

CONFIG += debug

Launching Harmattan UI

1. To launch Xephyr window, enter the following command outside Scratchbox:

user@user:~$ Xephyr :2 -host-cursor -screen 480x854x16 -dpi 96 -ac -kb &

2. Inside Scratchbox, start the Harmattan homescreen. Enter the following command:

  [sbox-HARMATTAN_X86: ~] > meego-sb-session start

You now have the Xephyr window up and running with the Harmattan homescreen. The following figure illustrates the displayed Xephyr window.

Harmattan homescreen in the Xephyr window

Using GDB client

1. To start the application binary with CGDB (curses-based interface to the GNU Debugger), enter the following command:

[sbox-HARMATTAN_X86: ~/meego-helloworld-1.0] > meego-run cgdb ./meego-helloworld  
Desktop's log can be viewed in /var/log/meego-sb-session.log
Desktop start up will take some time at first run
MInputContext: InputContext: service owner changed. Registering callback again 
GNU gdb (GDB) 7.0.1-debian
Copyright (C) 2009 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 "i486-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /home/<username>/test-meego-helloworld/helloworld...done.
(gdb)

CGDB starts.

2. Set a breakpoint to the method HelloWorld::hello:

(gdb) break HelloWorld::hello
Breakpoint 1 at 0x804c588: file helloworld.cpp, line 56.
(gdb)

Tip: To show all from the namespace, type break Hell" and press tab three times. Then type hello and press Enter.

3. To move the execution back to the helloworld binary, enter the following command:


(gdb)r
..
..
MAssembly: Stylesheet missing "/usr/share/themes/base/meegotouch/meego-helloworld/style/meego-he
lloworld.css"
[New Thread 0xb7dd0b70 (LWP 12559)]
X Error: BadMatch (invalid parameter attributes) 8
  Extension:    144 (Uknown extension)
  Minor opcode: 30 (Unknown request)
  Resource id:  0xe2
mstylesheet.cpp: Property navigationBarStyleName was left uninitialized in MApplicationWindowSty
le
mstylesheet.cpp: Property contentOpacity was left uninitialized in MButtonIconStyle
mstylesheet.cpp: Property contentOpacity was left uninitialized in MButtonIconStyle
mstylesheet.cpp: Property contentOpacity was left uninitialized in MButtonIconStyle
QGraphicsLayout::addChildLayoutItem: MToolBar "" in wrong parent; moved to correct parent
mstylesheet.cpp: Property contentOpacity was left uninitialized in MButtonIconStyle
mstylesheet.cpp: Property contentOpacity was left uninitialized in MButtonIconStyle
MThemePrivate: pixmapChangedSlot - pixmap reload failed (null handle): "default_pixmap_meegotouc
h-navigationbar-toolbar-portrait-background_0_0"

The simple Harmattan application can now be used inside Xephyr and it reacts to user input.

4. Click the Increment Counter button. Since the breakpoint has been set to a method that is called when the button is clicked, the execution moves to the debugger. You can now use GDB normally for debugging and perform any operation.

5. Enter the following command:

(gdb) where
..
..
#43 0x00616bef in QApplication::x11ProcessEvent (this=0xbffff3b0, event=0xbffff060) at kernel/qa
pplication_x11.cpp:3870
#44 0x00645df8 in x11EventSourceDispatch (s=0x805ad40, callback=0, user_data=0x0) at kernel/qgui
eventdispatcher_glib.cpp:146
#45 0x01a311bb in g_main_context_dispatch () from /lib/libglib-2.0.so.0
#46 0x01a35169 in ?? () from /lib/libglib-2.0.so.0
#47 0x01a352e9 in g_main_context_iteration () from /lib/libglib-2.0.so.0
#48 0x0113dcce in QEventDispatcherGlib::processEvents (this=0x8057bf8, flags=...) at kernel/qeve
ntdispatcher_glib.cpp:422
#49 0x006456cb in QGuiEventDispatcherGlib::processEvents (this=0x8057bf8, flags=...) at kernel/q
guieventdispatcher_glib.cpp:204
#50 0x0110a521 in QEventLoop::processEvents (this=0xbffff334, flags=...) at kernel/qeventloop.cp
p:149
#51 0x0110a998 in QEventLoop::exec (this=0xbffff334, flags=...) at kernel/qeventloop.cpp:201
#52 0x0110e1a1 in QCoreApplication::exec () at kernel/qcoreapplication.cpp:1064
#53 0x0057dbf9 in QApplication::exec () at kernel/qapplication.cpp:3736
#54 0x0804bcc1 in main (argc=1, argv=0xbffff494) at main.cpp:36
(gdb)

This prints the backtrace:


(gdb)bt
..
..
#43 0x00616bef in QApplication::x11ProcessEvent (this=0xbffff3b0, event=0xbffff060) at kernel/qa
pplication_x11.cpp:3870
#44 0x00645df8 in x11EventSourceDispatch (s=0x805ad40, callback=0, user_data=0x0) at kernel/qgui
eventdispatcher_glib.cpp:146
#45 0x01a311bb in g_main_context_dispatch () from /lib/libglib-2.0.so.0
#46 0x01a35169 in ?? () from /lib/libglib-2.0.so.0
#47 0x01a352e9 in g_main_context_iteration () from /lib/libglib-2.0.so.0
#48 0x0113dcce in QEventDispatcherGlib::processEvents (this=0x8057bf8, flags=...) at kernel/qeve
ntdispatcher_glib.cpp:422
#49 0x006456cb in QGuiEventDispatcherGlib::processEvents (this=0x8057bf8, flags=...) at kernel/q
guieventdispatcher_glib.cpp:204
#50 0x0110a521 in QEventLoop::processEvents (this=0xbffff334, flags=...) at kernel/qeventloop.cp
p:149
#51 0x0110a998 in QEventLoop::exec (this=0xbffff334, flags=...) at kernel/qeventloop.cpp:201
#52 0x0110e1a1 in QCoreApplication::exec () at kernel/qcoreapplication.cpp:1064
#53 0x0057dbf9 in QApplication::exec () at kernel/qapplication.cpp:3736
#54 0x0804bcc1 in main (argc=1, argv=0xbffff494) at main.cpp:36
(gdb) 

To move the execution back to the helloworld binary, enter the cont command.

6. Enter the step command:

(gdb) step
(gdb) step
QString::number (n=1, base=10) at tools/qstring.cpp:6016
6016    tools/qstring.cpp: No such file or directory.
        in tools/qstring.cpp
(gdb) step
QString (n=1, base=10) at ../../include/QtCore/../../src/corelib/tools/qstring.h:882
882     ../../include/QtCore/../../src/corelib/tools/qstring.h: No such file or directory.
        in ../../include/QtCore/../../src/corelib/tools/qstring.h
(gdb) step
ref (n=1, base=10) at ../../include/QtCore/../../src/corelib/arch/qatomic_i386.h:120
120     ../../include/QtCore/../../src/corelib/arch/qatomic_i386.h: No such file or directory.
        in ../../include/QtCore/../../src/corelib/arch/qatomic_i386.h
(gdb) cont
Continuing.

This means that you have stepped into the qstring.h module. Since it is not part of the compiled source code, only limited information is provided. The value of the label in the test application is now incremented to 1 and can be seen in Xephyr.

To move the execution back to the example binary, enter the following command:


(gdb) cont
Continuing.

Remote debugging using Scratchbox ARMEL targets

Debugging ARM binaries with the standalone i386 or ARMEL GDB is not possible due to limitations in the QEMU user-mode emulator. However, QEMU emulator itself includes a built-in GDB server that makes it relatively easy to debug ARM binaries inside the emulator.

Debugging-related issues in ARMEL targets

Note the following when debugging on the ARM architecture:

  • To make backtraces work properly on the ARM side, you need to install the dbg packages of the libraries your application uses. Profiling and debugging (GDB) tools require code to have either framepointers or debugging symbols to unwind stack. This is needed for showing backtraces or call graphs.
  • C language functions with the __attribute__((__noreturn__)) statements need to be compiled with the GCC option -fno-omit-frame-pointer. You cannot get backtrace through "noreturn" functions without framepointers. In practice, using the bt command produces an infinite repeat of this kind of function.
  • In addition, GDB also needs access to the debug symbols to display correct function names during debugging. Without these symbols GDB shows the preceding exported function name for the given address.

Creating and compiling an application

This example uses a simple MeeGo Touch application to demonstrate remote debugging.

1. Fetch the sources.

2. To enter the project directory, enter the following commands:

[sbox-HARMATTAN_ARMEL: ~] > cd meego-helloworld-1.0
[sbox-HARMATTAN_ARMEL: ~/meego-helloworld-0.1/src] > ls
com.meego.meego-helloworld.service  helloworld.cpp  helloworld.h  main.cpp  meego-helloworld.desktop  src.pro
[sbox-HARMATTAN_ARMEL: ~/meego-helloworld-0.1 > 

3. To build the application, enter the following command:

[sbox-HARMATTAN_ARMEL: ~/meego-helloworld-1.0] > dpkg-buildpackage -rfakeroot

[sbox-HARMATTAN_ARMEL: ~/meego-helloworld-1.0] > cd ..

Transferring and installing the binary package to the device

1. To transfer the binary, enter the following command:

[sbox-HARMATTAN_ARMEL: ~/] > scp meego-helloworld*ar*deb developer@192.168.2.15:/home/developer/
The authenticity of host '192.168.2.15 (192.168.2.15)' can't be established.
RSA key fingerprint is 9b:6c:c0:2e:4e:a6:2a:af:d3:0d:9f:29:e7:a5:06:d5.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '192.168.2.15' (RSA) to the list of known hosts.
developer@192.168.2.15's password: 
meego-helloworld_1.0-1_armel.deb                          100%   21KB  20.6KB/s   00:00    
[sbox-HARMATTAN_ARMEL: ~/] >

2. To install the package on the device, enter the following command:

/home/developer $ devel-su - root
Password:<enter the root password. Default password is rootme>
XX-XX:~#cd /home/developer/
XX-XX:/home/developer#dpkg -i meego-helloworld_1.0-1_armel.deb 
Selecting previously deselected package meego-helloworld.
(Reading database ... 41159 files and directories currently installed.)
Unpacking meego-helloworld (from meego-helloworld_1.0-1_armel.deb) ...
aegis-installing meego-helloworld (from '')
Setting up meego-helloworld (1.0-1) ...
Processing triggers for desktop-file-utils ...
XX-XX:/home/developer#

Running GDB server on the device

To start the debugging session, start the GDB server inside the device with the Hello World application. Enter the following command:

:/home/developer# gdbserver 192.168.2.14:1234 meego-helloworld 
Process helloworld created; pid = 5837
Listening on port 1234

Using the GDB client inside Scratchbox

1. To start CGDB inside Scratchbox ARMEL target, enter the following command:

[sbox-HARMATTAN_ARMEL: ~/meego-helloworld-1.0] > cgdb meego-helloworld
GNU gdb (GDB) 7.0.1-debian
Copyright (C) 2009 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 "arm-linux-gnueabi".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /home/<username>/meego-helloworld-1.0/meego-helloworld...done.
(gdb)

2. To establish the connection to the GDB server, enter the following command.

(gdb) target remote 192.168.2.15:1234
Remote debugging using 192.168.2.15:1234
Reading symbols from /lib/ld-linux.so.3...Reading symbols from /targets/HARMATTAN_ARMEL/usr/lib/debug/lib/ld-2.10.1.so...done.
done.
Loaded symbols for /lib/ld-linux.so.3
0x3aaab880 in _start () from /lib/ld-linux.so.3
(gdb)

3. Set the breakpoint at the action when a user clicks the Increment Counter button.

(gdb)break HelloWorld::hello
Breakpoint 1 at 0xc958: file helloworld.cpp, line 56.
(gdb)

Tip: To list the available methods, type break Hell and press tab three times. Then type break HelloWorld::hello and press Enter.

4. To continue to run the application, enter the following command:

(gdb) c
Continuing.

5. The application is now waiting for user input. Click the Increment Counter button and check that it pauses at the breakpoint. After it pauses at the breakpoint, continue debugging as follows:

(gdb) 
Continuing.
Breakpoint 1, HelloWorld::hello (this=0xaeccdb44) at helloworld.cpp:56
(gdb) list
51      {
52      }
53
54      void HelloWorld::hello()
55      {
56          clicks++;
57          clicksLabel->setText(QString::number(clicks));
58      }
(gdb)bt

...
..
#33 0x3af76414 in QETWidget::sendMouseEvent (this=0xaeccdb68, xtype=<value optimized out>, window=<value optimized out>, type=QEvent::MouseButtonRelease, pos=..., globalPos=..., button=Qt::LeftButton, button
s=..., modifiers=...) at kernel/qapplication_x11.cpp:4968
#34 0x3af82510 in QETWidget::translateXI2Event (this=<value optimized out>, xievent=0x1deff0) at kernel/qapplication_x11.cpp:5378
#35 0x3af838cc in QETWidget::translateMouseEvent (this=0xaeccdb68, event=0xaeccd920) at kernel/qapplication_x11.cpp:4652
#36 0x3af80dd4 in QApplication::x11ProcessEvent (this=<value optimized out>, event=0xaeccd920) at kernel/qapplication_x11.cpp:3870
#37 0x3afacc40 in x11EventSourceDispatch (s=0x22be8, callback=<value optimized out>, user_data=<value optimized out>) at kernel/qguieventdispatcher_glib.cpp:146
#38 0x3c250e58 in g_main_context_dispatch () from /lib/libglib-2.0.so.0
#39 0x000002e0 in ?? ()
#40 0x000002e0 in ?? ()
Backtrace stopped: previous frame identical to this frame (corrupt stack?)
(gdb)

(gdb) c   
Continuing.

(gdb) q

[sbox-HARMATTAN_ARMEL: ~/meego-helloworld-1.0] >

Debugging core files on the device

This section explains how to debug core files on the device. The default location for core dumps is /home/user/MyDocs/core-dumps. There can be a limit for core dump size.

To check whether there is a limit for core dump size, enter the following commands:

:/home/user# ulimit -c
unlimited
:/home/user#

If the limit is too low, you can increase it. For example:

:/home/user# ulimit -c unlimited

Creating the core dump

This section explains how to debug the core file of the small example application meego-helloworld.

1. Compile the meego-helloworld in the Scratchbox ARMEL target, and copy and install the deb package on the device with scp.

2. To start the meego-helloworld in the device, enter the following command:

 
:/home/user#su - user
~ $meego-helloworld &


The meego-helloworld is now running in the background, and it starts to dump its output to the screen.

3. Generate a core dump. If the process is referred to as %1, enter the following kill command and press Enter a couple of times:

 
~ $ kill -SIGSEGV %1
~ $ 
[1]+  Segmentation fault (core dumped) meego-helloworld
~ $ 
~ $ 


You now have a compressed core dump data file under the /home/user/MyDocs/core-dumps/ directory. Its name includes the name of the file and ends with the PID number of the meego-helloworld program.

4. Check that the PID number is included. The number depends on your environment. The following example shows a dump file in which PID number is 2776.

 
:/home/user/MyDocs/core-dumps# ls meego-helloworld*
meego-helloworld-004402132923701-11-2217.rcore.lzo
:/home/user/MyDocs/core-dumps#


5. Extract the compressed data to use it with GDB. Install the sp-rich-core-postproc package and enter the extract command, which creates a new directory (given as a second parameter) for extracting data:

 
:/home/user/MyDocs/core-dumps#apt-get install sp-rich-core-postproc
... snip ...
:/home/user/MyDocs/core-dumps# rich-core-extract meego-helloworld-004402132923701-11-2217.rcore.lzo coredir
:/home/user/MyDocs/core-dumps# ls
coredir                          meego-helloworld-004402132923701-11-2217.rcore.lzo
:/home/user/MyDocs/core-dumps#

The created coredir includes a lot of system information in several files. The file that you must pass for GDB is named coredump.

If you also want to resolve symbols for the library during debugging, it is recommended to install the libraries that your application is linked against.

Debugging the core file

You can debug the core file together with the meego-helloworld binary that you compiled.

1. Check where the execution of the meego-helloworld was when you used the -SIGSEGV signal.

2. Start GDB and give meego-helloworld as the first parameter and the core file as the second parameter. Enter the following command:

:/home/user/MyDocs/core-dumps# gdb /usr/bin/meego-helloworld ./coredir/coredump 
GNU gdb (GDB) 7.2-debian
Copyright (C) 2010 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 "arm-linux-gnueabi".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /usr/bin/meego-helloworld...done.

warning: core file may not match specified executable file.
[New Thread 2217]
[New Thread 2218]
Reading symbols from /usr/lib/libmeegotouchcore.so.0...Reading symbols from /usr/lib/debug/usr/lib/libmeegotouchcore.so.0.20.99...done.
done.
Loaded symbols for /usr/lib/libmeegotouchcore.so.0
Reading symbols from /usr/lib/libQtGui.so.4...Reading symbols from /usr/lib/debug/usr/lib/libQtGui.so.4.7.4...done.
done.
Loaded symbols for /usr/lib/libQtGui.so.4
Reading symbols from /usr/lib/libQtCore.so.4...Reading symbols from /usr/lib/debug/usr/lib/libQtCore.so.4.7.4...done.
done.
 .. Snip ..
(gdb)

The above example shows that GDB is now using debug symbols from the respective libraries. The information on debug symbols is only available if the libraries have been installed. GDB is now waiting for a command.

3. Enter the bt (backtrace) command. The following output is generated:

(gdb) bt
#0  0x3bc876f4 in __poll (fds=0x198a98, nfds=8, timeout=-1) at ../sysdeps/unix/sysv/linux/poll.c:87
#1  0x3c2a5cb0 in g_main_context_poll (context=0x22400, block=<value optimized out>, dispatch=<value optimized out>, self=<value optimized out>)
    at /home/bifh6/cs2009q3-armel/work/glib2.0-2.28.4/./glib/gmain.c:3404
#2  g_main_context_iterate (context=0x22400, block=<value optimized out>, dispatch=<value optimized out>, self=<value optimized out>) at /home/bifh6/cs2009q3-armel/work/glib2.0-2.28.4/./glib/gmain.c:3086
#3  0x3c2a5fbc in g_main_context_iteration (context=0x22400, may_block=1) at /home/bifh6/cs2009q3-armel/work/glib2.0-2.28.4/./glib/gmain.c:3154
.. Snip ...
(gdb)

Note: For this simple example, the available library package was installed before starting to debug the application. Backtraces only work if debug packages are also installed for the libraries through which the backtrace goes.

The output differs according to when you give the kill -SIGSEGV command.