Archive

Posts Tagged ‘debugging’

Setting up Pretty Printers in GDB

July 2nd, 2014 No comments

There’s an official page on gcc website: https://sourceware.org/gdb/wiki/STLSupport. And here is how to set up it under Ubuntu.

Under Ubuntu 12.04(Precise), simply install the libstdc++6 debug package. It includes the python script for pretty printers:

# sudo apt-get install libstdc++6-4.6-dbg

Create a .gdbinit file in your home directory, with the content:

python
import sys
sys.path.insert(0, '/usr/share/gcc-4.6/python')
from libstdcxx.v6.printers import register_libstdcxx_printers
register_libstdcxx_printers (None)
end

My test program looks like:

#include <string>
#include <vector>
using namespace std;

int main()
{
    string s = "test";
    vector<int> vi;
    vi.push_back(1);
    vi.push_back(2);
    vi.push_back(3);
    return 0;
}

Build it with debugging enabled(-g):

# g++ -g test.cpp -o test

Debug it with GDB:

# gdb -q test 
Reading symbols from /home/gonwan/test...done.
(gdb) b 12
Breakpoint 1 at 0x8048842: file test.cpp, line 12.
(gdb) r
Starting program: /home/gonwan/test 

Breakpoint 1, main () at test.cpp:12
12	    return 0;
(gdb) p s
$1 = "test"
(gdb) p vi
$2 = std::vector of length 3, capacity 4 = {1, 2, 3}
(gdb) 

Without pretty printers, the output is tedious and hard to understand:

$ gdb -q test 
Reading symbols from /home/gonwan/test...done.
(gdb) set print pretty
(gdb) b 12
Breakpoint 1 at 0x8048842: file test.cpp, line 12.
(gdb) r
Starting program: /home/gonwan/test 

Breakpoint 1, main () at test.cpp:12
12	    return 0;
(gdb) p s
$1 = {
  static npos = <optimized out>, 
  _M_dataplus = {
    <std::allocator<char>> = {
      <__gnu_cxx::new_allocator<char>> = {<No data fields>}, <No data fields>}, 
    members of std::basic_string<char, std::char_traits<char>, std::allocator<char> >::_Alloc_hider: 
    _M_p = 0x804c014 "test"
  }
}
(gdb) p vi
$2 = {
  <std::_Vector_base<int, std::allocator<int> >> = {
    _M_impl = {
      <std::allocator<int>> = {
        <__gnu_cxx::new_allocator<int>> = {<No data fields>}, <No data fields>}, 
      members of std::_Vector_base<int, std::allocator<int> >::_Vector_impl: 
      _M_start = 0x804c040, 
      _M_finish = 0x804c04c, 
      _M_end_of_storage = 0x804c050
    }
  }, <No data fields>}
(gdb) 

Under Ubuntu 14.04(Trusty), the 4.8 version of debug package should be installed:

# sudo apt-get install libstdc++6-4.8-dbg

There’s an additional step. Since GDB in Trusty is built with python3, not python2, and the python scripts for pretty printers are in python2 syntax. A simple conversion is required:

# sudo 2to3 -w /usr/share/gcc-4.8/python/libstdcxx/v6/printers.py

Backup it before conversion if neccessary.

Categories: C/C++ Tags: ,

Setting up Serial Console on VirtualBox

April 7th, 2014 1 comment

I’m running Ubuntu 12.04 as host, with VirtualBox 4.2.22. This tutorial should cover guests including Windows XP, CentOS and Ubuntu.

1. Settings in VirtualBox

In the settings page, Check “Enable Serial Port”, set “Port Number” to “COM1”. This is the port number in the guest. If the guest is a Linux, COM1 is shown as /dev/ttyS0, and COM2 is shown as /dev/ttyS1.

Set “Port Mode” to “Host Pipe”, check “Create Pipe” and set “Port/File Path” to “/tmp/vbox”. Seems it utilizes a named pipe. These settings work even if the host does not have a physical serial device.

serial_console_1

2. Install minicom

# sudo apt-get install minicom
# sudo minicom -s

The second command setups minicom with an interactive menu. Select “Serial port setup”, and set “Serial Device” as “unix#/tmp/vbox”(without quotes). “Save setup as dfl” and “Exit from Minicom”.

3. Verity the serial device in guest

Now boot your Linux guest. Run the following command, and it should output something like:

# su
# stty -F /dev/ttyS0 -a
speed 9600 baud; rows 0; columns 0; line = 0;
intr = ^C; quit = ^; erase = ^?; kill = ^U; eof = ^D; eol = <undef>;
eol2 = <undef>; swtch = <undef>; start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R;
werase = ^W; lnext = ^V; flush = ^O; min = 1; time = 0;
...

The guest here is CentOS5, and the serial device is /dev/ttyS0.

4. Communication via serial device

Start minicom on your host:

# minicom

Echo something from your guest and redirect to /dev/ttyS0. You host should get the message in minicom.

# echo "sent from rhel5 guest" > /dev/ttyS0

To read from the host, cat the device in guest so that you can do the input in minicom:

# cat /dev/ttyS0

serial_console_2

5. Kernel configuration

CentOS5 comes with grub1, /etc/grub.conf is modified directly to allow the boot information to also be sent to our serial device. The original boot entry looks like:

title CentOS (2.6.18-371.6.1.el5)
        root (hd0,0)
        kernel /boot/vmlinuz-2.6.18-371.6.1.el5 ro root=LABEL=/
        initrd /boot/initrd-2.6.18-371.6.1.el5.img

Change to add console= parameter:

title CentOS (2.6.18-371.6.1.el5)
        root (hd0,0)
        kernel /boot/vmlinuz-2.6.18-371.6.1.el5 ro root=LABEL=/ console=tty0 console=ttyS0,9600
        initrd /boot/initrd-2.6.18-371.6.1.el5.img

That’s all for CentOS 5/6. There’s no need to modify /etc/inittab or /etc/securetty file as required in ArchLinux. These OS will do it for you.

Now, reboot your guest CentOS. The boot information should now displayed in your minicom. Finally, it will provide you with a login shell.

serial_console_3
You can verify that there’s a new line added into /etc/inittab to enable getty(8) and execute a login shell:

co:2345:respawn:/sbin/agetty ttyS0 9600 vt100-nav

And ttyS0 is also added into /etc/securetty.

6. Ubuntu guest settings

Ubuntu 12.04 come with grub2. We do not modify /boot/grub/grub.cfg, we modify /etc/default/grub instead, so that the serial console parameters will remain even after you update your kernel. Open it, modify the following line to:

GRUB_CMDLINE_LINUX="console=tty0 console=ttyS0,115200n8"

And update grub:

# sudo update-grub

One additional step for Ubuntu, is to enable getty(8) for serial console by your own. Ubuntu uses upstart init system, we need to create a file called /etc/init/ttyS0.conf containing the following:

# ttyS0 - getty
#
# This service maintains a getty on ttyS0 from the point the system is
# started until it is shut down again.

start on stopped rc or RUNLEVEL=[12345]
stop on runlevel [!12345]

respawn
exec /sbin/getty -L 115200 ttyS0 vt102

Reboot you Ubuntu guest, and the serial device should work as it is with CentOS. More info, please refer to the official wiki.

7. Windows guest settings

The serial device shows as COM1 in Windows XP as previously set. With a simple echo and redirect, our host can receive the message.

serial_console_4

8. Windows as host

Settings of VirtualBox under Windows is almost the same as that under Linux. But we set “Port/File Path” to “\\.\pipe\vbox”, instead of “/tmp/vbox”. After the configuration of kernel and getty(8), we can use PuTTY to connect. Simply set “Connection type” to “Serial”, and “Serial line” to “\\.\pipe\vbox”.
serial_console_5

Categories: Tools Tags: ,

Debug Qt Libraries with Ubuntu Debug Packages

March 28th, 2011 No comments

In previous articles, I was not able to use Qt’s debug package provided by Ubuntu. Now, I will explain how to use them.

Our simple application:

// main.cpp
#include <QtCore/QString>
int main() {
    QString s = "1234567";
    int i = s.indexOf('3');
    return i != 2;
}

Our *.pro file, you should enable the debug build:

# DebugQt.pro
TARGET = DebugQt
TEMPLATE = app
SOURCES += main.cpp
QT -= gui
CONFIG += console debug_and_release

1. Build your debug version of application:

# qmake-qt4
# make debug

2. Install Qt’s debug package:

# sudo apt-get install libqt4-debug

3. Install the Qt source:

# sudo apt-get source libqt4-debug

Now you can start debugging your application. Since Qt’s debug symbols are installed in /usr/lib, It does not follow the GDB’s global debug directory described here. We should tell GDB to load these symbols manually:

# gdb ./DebugQt
GNU gdb 6.8-debian
...
(gdb) b main
Breakpoint 1 at 0x8048696: file main.cpp, line 3.
(gdb) r
Starting program: /home/binson/DebugQt/DebugQt 
[Thread debugging using libthread_db enabled]
[New Thread 0xb71d36c0 (LWP 11138)]
[Switching to Thread 0xb71d36c0 (LWP 11138)]

Breakpoint 1, main () at main.cpp:3
3     QString s = "1234567";
(gdb) info sharedlibrary
From        To          Syms Read   Shared Object Library
0xb77a47f0  0xb77b96df  Yes         /lib/ld-linux.so.2
0xb7652510  0xb7740904  Yes         /usr/lib/libQtCore.so.4
0xb7605210  0xb7610a04  Yes         /lib/tls/i686/cmov/libpthread.so.0
0xb754fa60  0xb75ccb14  Yes         /usr/lib/libstdc++.so.6
0xb74eb440  0xb7505414  Yes         /lib/tls/i686/cmov/libm.so.6
0xb74de970  0xb74e5e04  Yes         /lib/libgcc_s.so.1
0xb73a4230  0xb74a4ea4  Yes         /lib/tls/i686/cmov/libc.so.6
0xb7368470  0xb7380684  Yes         /usr/lib/libfontconfig.so.1
0xb7350910  0xb735e3e4  Yes         /usr/lib/libz.so.1
0xb734a180  0xb734b804  Yes         /usr/lib/libgthread-2.0.so.0
0xb7341990  0xb7345ee4  Yes         /lib/tls/i686/cmov/librt.so.1
0xb72a0620  0xb72fe114  Yes         /usr/lib/libglib-2.0.so.0
0xb728ba70  0xb728ca74  Yes         /lib/tls/i686/cmov/libdl.so.2
0xb72249f0  0xb7276264  Yes         /usr/lib/libfreetype.so.6
0xb71fe190  0xb7214384  Yes         /usr/lib/libexpat.so.1
0xb71d5ef0  0xb71f1da4  Yes         /usr/lib/libpcre.so.3

We set a breakpoint at the beginning of main function to load all shared libraries. Next, we will load symbols for libQtCore.so.4. The symbol will be loaded in the start address of it (0xb7652510):

(gdb) add-symbol-file /usr/lib/libQtCore.so.4.3.4.debug 0xb7652510
add symbol table from file "/usr/lib/libQtCore.so.4.3.4.debug" at
 .text_addr = 0xb7652510
(y or n) y
Reading symbols from /usr/lib/libQtCore.so.4.3.4.debug...done.

Now, you are able to step into the Qt library, but no source is attached:

(gdb) b 4
Breakpoint 2 at 0x80486a9: file main.cpp, line 4.
(gdb) c
Continuing.

Breakpoint 2, main () at main.cpp:4
4     int i = s.indexOf('3');
(gdb) s
QChar (this=0xbfb1ec0e, ch=51 '3') at tools/qchar.cpp:432
432 tools/qchar.cpp: No such file or directory.
 in tools/qchar.cpp

Source files are attached by:

(gdb) dir ~/qt4-x11-4.3.4/src/corelib
Source directories searched: /home/binson/qt4-x11-4.3.4/src/corelib:$cdir:$cwd
(gdb) l
427 
428 /*!
429     Constructs a QChar corresponding to ASCII/Latin-1 character \a
430     ch.
431 */
432 QChar::QChar(char ch)
433 {
434 #ifndef QT_NO_CODEC_FOR_C_STRINGS
435     if (QTextCodec::codecForCStrings())
436         // #####
(gdb) bt
#0  QChar (this=0xbfb1ec0e, ch=51 '3') at tools/qchar.cpp:432
#1  0x080486bc in main () at main.cpp:4

See the source and backtrace? 🙂

Categories: C/C++ Tags: , , ,

Using Ubuntu Debug Packages in GDB (2)

July 7th, 2010 No comments

From last blog, I’ve demostrated the usage of Ubuntu *-dbg packages. However, not all *-dbg packages seem to work as libssl0.9.8-dbg. For instance, libcurl3-dbg and libqt4-dbg packages do not work. I’m afraid some debug info are missing in these two packages. I’m not sure.

I googled a lot, but was not able to find a solution. So I decided to build the debug version of the two library myself. Here are steps for libcurl:

# sudo apt-get source libcurl3-dbg
# cd curl-7.19.7/
# ./configure --prefix=/usr/local --enable-debug --enable-static=0
# make

After all, the compiled binary is located in /home/gonwan/testgdb/curl-7.19.7/lib/.libs/. Note, this is a hidden folder.

Here comes our test code:

#include <curl/curl.h>
int main() {
    curl_easy_init();
    return 0;
}

Build commands:

# gcc -g testcurl.c -o testcurl /usr/lib/libcurl.so.4

I use /usr/lib/libcurl.so.4 instead of lcurl, since lcurl will link the binary to /usr/lib/libcurl-gnutls.so.4. But I currently cannot afford it :(. Last, start our GDB:

# LD_LIBRARY_PATH=/home/gonwan/testgdb/curl-7.19.7/lib/.libs/ gdb ./testcurl
GNU gdb (GDB) 7.1-ubuntu
...
Reading symbols from /home/gonwan/testgdb/testcurl...done.
(gdb) b 3
Breakpoint 1 at 0x8048572: file testcurl.c, line 3.
(gdb) r
Starting program: /home/gonwan/testgdb/testcurl
[Thread debugging using libthread_db enabled]
Breakpoint 1, main () at testcurl.c:3
3           curl_easy_init();
(gdb) s
curl_easy_init () at easy.c:372
372         if(!initialized) {
(gdb) bt
#0  curl_easy_init () at easy.c:372
#1  0x08048577 in main () at testcurl.c:3
(gdb)

It prints the backtrace now, though I’m not so accustomed to console debugging. I add the LD_LIBRARY_PATH environment to let our test program find our homemade version of libcurl.so.4. In fact, we can run ldd like following lines. You see the re-direction?

# ldd ./testcurl | grep libcurl
    libcurl.so.4 => /usr/lib/libcurl.so.4 (0x00943000)
# LD_LIBRARY_PATH=/home/gonwan/testgdb/curl-7.19.7/lib/.libs/ ldd ./testcurl | grep libcurl
    libcurl.so.4 => /home/gonwan/testgdb/curl-7.19.7/lib/.libs/libcurl.so.4 (0x00318000)

Later, I successfully made it possible to debug Qt source code in IDE. I chose QtCreator, since it has both windows and linux version, and it’s easy to install and configure. I also built my homemade version of Qt:

# sudo apt-get source libqt4-dbg
# cd qt4-x11-4.6.2/
# ./configure -prefix /usr/local -debug-and-release -no-qt3support -no-webkit -no-script -no-scripttools -no-xmlpatterns -no-phonon -no-multimedia -no-declarative -make libs -nomake tools -nomake examples -nomake demos -nomake docs -nomake translations -fast
# make

I only built the most common modules, excluding webkit, script, xmlpatterns, phonon, multimedia and declarative modules. It took only 25 minutes to finish (An entire build under windows may take 3 – 4 hours.). After all, start your QtCreator, create a Qt console project with the source below:

#include <QtCore/QString>
int main() {
    QString s = "1234567";
    int i = s.indexOf('3');
    return i != 2;
}

Build the project in debug mode. And now, here’s the magic: Go to Project tab –> Run Settings –> Run Environment, append our homemade Qt library path to LD_LIBRARY_PATH. In my example, it’s /home/gonwan/testgdb/qt4-x11-4.6.2/lib. Ok, you’re almost done! Go back to the Edit tab, set a breakpoint at line 4 (or line 3 as you like), press F5 to start debugging the project. Then continue pressing F11, you will find GDB has stepped into Qt source code! Let me take a screenshot:

qtcreator_qt4debug

In order to load our homemade *.so, we can also run “make install”.

Categories: Linux Tags: , , ,

Using Ubuntu Debug Packages in GDB

July 7th, 2010 No comments

I will use openssl library as example. Here’s a simplest source:

#include <openssl/ssl.h>
int main() {
    SSL_library_init();
    return 0;
}

Now build and start your GDB, note the ‘-g’ option is necessary:

# gcc -g testopenssl.c -o testopenssl -lssl
# gdb ./testopenssl
GNU gdb 6.8-debian
...
(gdb) b 3
Breakpoint 1 at 0x8048495: file testopenssl.c, line 3.
(gdb) r
Starting program: /home/binson/testgdb/testopenssl
Breakpoint 1, main () at testopenssl.c:3
3       SSL_library_init();
(gdb) s
4       return 0;
(gdb)

GDB cannot step into openssl source code, since there’s no debug symbol found. In Ubuntu, we can install it using apt-get. I’m using Hardy(8.04):

# sudo apt-get install libssl0.9.8-dbg

Launch our GDB again:

# gdb ./testopenssl
GNU gdb 6.8-debian
...
(gdb) b 3
Breakpoint 1 at 0x8048495: file testopenssl.c, line 3.
(gdb) r
Starting program: /home/binson/testgdb/testopenssl
Breakpoint 1, main () at testopenssl.c:3
3       SSL_library_init();
(gdb) s
SSL_library_init () at ssl_algs.c:68
68  ssl_algs.c: No such file or directory.
    in ssl_algs.c
(gdb)

Symbols are found, GDB prompt for missing source files! We can install by typing:

# sudo apt-get source libssl0.9.8

The source files will be downloaded and extracted in openssl-0.9.8g folder. Now we wanna attach the source files when debugging.

# gdb ./testopenssl
GNU gdb 6.8-debian
...
(gdb) dir openssl-0.9.8g/ssl/
Source directories searched: /home/binson/testgdb/openssl-0.9.8g/ssl:$cdir:$cwd
(gdb) b 3
Breakpoint 1 at 0x8048495: file testopenssl.c, line 3.
(gdb) r
Starting program: /home/binson/testgdb/testopenssl
Breakpoint 1, main () at testopenssl.c:3
3       SSL_library_init();
(gdb) s
SSL_library_init () at ssl_algs.c:68
68      EVP_add_cipher(EVP_des_cbc());
(gdb) bt
#0  SSL_library_init () at ssl_algs.c:68
#1  0x0804849a in main () at testopenssl.c:3
(gdb)

Oh! Everything works!

Categories: Linux Tags: , ,