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