Update the GDB monitor test documentation

The interactive GDB monitor test has changed recently. This patch updates
the documentation accordingly.

Fixes #126.
This commit is contained in:
Christian Prochaska 2012-02-24 16:18:58 +01:00 committed by Norman Feske
parent 7e00ef96ee
commit 77a7207b42
1 changed files with 60 additions and 106 deletions

View File

@ -247,14 +247,14 @@ Working with shared libraries
=============================
To get acquainted with GDB monitor, the 'ports' repository comes with two
example run scripts. The 'gdb_monitor.run' script executes a simple test
program via GDB monitor. The test program can be found at
example run scripts. The 'gdb_monitor_interactive.run' script executes a
simple test program via GDB monitor. The test program can be found at
'ports/src/test/gdb_monitor/'. When looking behind the scenes, the simple
program is not simple at all. It uses shared libraries (the libc and libc_log)
plugin and executes multiple threads. To it is a nice testbed for exercising
plugin and executes multiple threads. So it is a nice testbed for exercising
these aspects. The run script can be invoked right from the build directory
via 'make run/gdb_monitor'. It will execute the scenario on Qemu and use
the UART to communicate with GDB. Qemu is instructed to redirect the second
via 'make run/gdb_monitor_interactive'. It will execute the scenario on Qemu and
use the UART to communicate with GDB. Qemu is instructed to redirect the second
serial interface to a local socket (using the port 5555):
! -serial chardev:uart
! -chardev socket,id=uart,port=5555,host=localhost,server,nowait
@ -262,62 +262,30 @@ serial interface to a local socket (using the port 5555):
The used TCP port is then specified to the GDB as remote target:
! target remote localhost:5555
The 'gdb_monitor.run' script performs these steps for you and spawns GDB
in a new terminal window. From within your build directory, execute the
The 'gdb_monitor_interactive.run' script performs these steps for you and spawns
GDB in a new terminal window. From within your build directory, execute the
run script via:
! make run/gdb_monitor
! make run/gdb_monitor_interactive
On startup, GDB monitor halts the target program and waits for GDB to
connect. Once connected GDB will greet you with a prompt like this:
connect. Once connected, GDB will greet you with a prompt like this:
! Reading symbols from /open/build/genode/foc_x86_32/bin/test-gdb_monitor...done.
! Remote debugging using localhost:5555
! warning: Unable to find dynamic linker breakpoint function.
! GDB will be unable to debug shared library initializers
! and track explicitly loaded dynamic code.
! 0x00054ac0 in ?? ()
! (gdb)
! Breakpoint 2, main () at /.../ports/src/test/gdb_monitor/main.cc:67
! 67 {
! (gdb)
Since 'test-gdb_monitor' is a dynamically linked binary, Genode has started
the dynamic linker. Because neither the actual binary nor any shared library
has been loaded so far, GDB cannot determine symbol information. So let's
start executing the program using the 'c' (continue) command:
! (gdb) c
! Continuing.
The test program will start printing some messages via core's LOG service.
We can interrupt it by pressing Control-C in the GDB console.
! ^C
! Program received signal SIGINT, Interrupt.
! 0x0005396c in ?? ()
! (gdb)
Now that the program has been executed for a while, it is a good time to let
GDB figure out information about shared libraries using the 'sharedlibrary' command:
! (gdb) sharedlibrary
You will see several messages indicating where GDB fetches symbol information
for each shared library used by the program. To see, what GDB has found out,
use the 'info shared' command. GDB will respond with a table like this:
(gdb) info shared
! From To Syms Read Shared Object Library
! 0x0009c1b8 0x00100b64 Yes /.../build/var/libcache/libc/libc.lib.so
! 0x00007c5c 0x00007ecc Yes /.../build/var/libcache/libc_log/libc_log.lib.so
! 0x0003e704 0x00063748 Yes /.../build/var/libcache/ld/ld.lib.so
It is telling us the load location of each shared library and informs us
about having successfully obtained the symbol information for each library.
Now, with symbol information available, let's set a breakpoint to the 'printf'
function, which is repeatedly called by the test program using the 'breakpoint'
command:
! (gdb) b printf
! Breakpoint 1 at 0xd503c: file /.../stdio/printf.c, line 49.
After continuing the executing via 'c' (continue), you will see that the
At this point, GDB has acquired symbol information from the loaded shared
libraries and stopped the program at the beginning of its 'main()' function.
Now let's set a breakpoint to the 'puts' function, which is called by the test
program, by using the 'breakpoint' command:
! (gdb) b puts
! Breakpoint 3 at 0x106e120: file /.../libc-8.2.0/libc/stdio/puts.c, line 53.
After continuing the execution via 'c' (continue), you will see that the
breakpoint will trigger with a message like this:
! (gdb) c
! Continuing.
! [New Thread 2]
! [Switching to Thread 2]
!
! Breakpoint 1, printf (fmt=0x1004144 "Test thread is running, cnt=%d\n")
! at /.../stdio/printf.c:49
! 49 ret = vfprintf(stdout, fmt, ap);
! Breakpoint 3, puts (s=0x10039c0 "in func2()\n")
! at /.../libc-8.2.0/libc/stdio/puts.c:53
! 53 {
Now, you can inspect the source code of the function via the 'list' command,
inspect the function arguments ('info args' command) or start stepping
@ -326,68 +294,53 @@ backtrace including several functions located in different shared libraries,
set another breakpoint at the 'stdout_write' function. This function is
used by the 'libc_log' backend and provided by the dynamic linker. The
backtrace will reveal all the intermediate steps throughout the libc when
'printf' is called.
'puts' is called.
! (gdb) b stdout_write
! Breakpoint 1 at 0x55906: file /.../log_console.cc, line 101.
! Breakpoint 4 at 0x59d10: file /.../log_console.cc, line 108.
! (gdb) c
! Continuing.
! [New Thread 2]
! [Switching to Thread 2]
!
! Breakpoint 1, stdout_write (s=0x400ff434 "Test thread is running, cnt=8\n")
! at /.../genode/base/src/base/console/log_console.cc:101
! 101 {
! Breakpoint 4, stdout_write (s=0x1015860 "in func2()\n")
! at /.../genode/base/src/base/console/log_console.cc:108
! 108 {
! (gdb) bt
! #0 stdout_write (s=0x400ff434 "Test thread is running, cnt=8\n")
! at /.../genode/base/src/base/console/log_console.cc:101
! #1 0x0000799c in Libc::Log_plugin::write (this=0x8310, fd=0x114ba8,
! buf=0x3e60, count=30)
! at /.../genode/libports/src/lib/libc_log/plugin.cc:84
! #2 0x000f85f8 in _write (libc_fd=1, buf=0x3e60, count=30)
! at /.../genode/libports/src/lib/libc/file_operations.cc:379
! #3 0x000d737f in __swrite (cookie=0x105ca8,
! buf=0x3e60 "Test thread is running, cnt=8\n\006", n=30)
! at /.../stdio/stdio.c:71
! #4 0x000d7233 in _swrite (fp=0x105ca8,
! buf=0x3e60 "Test thread is running, cnt=8\n\006", n=30)
! at /.../stdio/stdio.c:133
! #5 0x000d04cb in __sflush (fp=0x105ca8)
! at /.../stdio/fflush.c:123
! #6 0x000d052a in __fflush (fp=0x400ff434)
! at /.../stdio/fflush.c:96
! #7 0x000d310b in __sfvwrite (fp=0x105ca8, uio=0x400ffdd8)
! at /.../stdio/fvwrite.c:194
! #8 0x000d7ea4 in __sprint (fp=0x400ff434, uio=0x400ffdd8)
! at /.../stdio/vfprintf.c:88
! #9 0x000dad08 in __vfprintf (fp=0x105ca8,
! fmt0=0x1003618 "Test thread is running, cnt=%d\n", ap=0x400ffe98 "\b")
! ---Type <return> to continue, or q <return> to quit---
! at /.../stdio/vfprintf.c:1179
! #10 0x000db29f in vfprintf (fp=0x105ca8,
! fmt0=0x1003618 "Test thread is running, cnt=%d\n", ap=0x400ffe98 "\b")
! at /.../stdio/vfprintf.c:351
! #11 0x000d61f0 in printf (fmt=0x1003618 "Test thread is running, cnt=%d\n")
! at /.../stdio/printf.c:49
! #12 0x0100086a in func3 (this=0x1015914)
! at /.../genode/ports/src/test/gdb_monitor/main.cc:28
! #13 Test_thread::entry (this=0x1015914)
! at /.../genode/ports/src/test/gdb_monitor/main.cc:38
! #14 0x00059333 in Genode::Thread_base::_thread_start ()
! at /.../genode/base-foc/src/base/thread/thread_bootstrap.cc:39
! #15 0x00000000 in ?? ()
! #0 stdout_write (s=0x1015860 "in func2()\n")
! at /.../genode/base/src/base/console/log_console.cc:108
! #1 0x010c3701 in (anonymous namespace)::Plugin::write (this=0x10c4378,
! fd=0x10c0fa8, buf=0x6590, count=11)
! at /.../genode/libports/src/lib/libc_log/plugin.cc:93
! #2 0x010937bf in _write (libc_fd=1, buf=0x6590, count=11)
! at /.../genode/libports/src/lib/libc/file_operations.cc:406
! #3 0x0106ec4f in __swrite (cookie=0x10a1048, buf=0x6590 "in func2()\n", n=11)
! at /.../genode/libports/contrib/libc-8.2.0/libc/stdio/stdio.c:71
! #4 0x0106ef5a in _swrite (fp=0x10a1048, buf=0x6590 "in func2()\n", n=11)
! at /.../genode/libports/contrib/libc-8.2.0/libc/stdio/stdio.c:133
! #5 0x01067598 in __sflush (fp=0x10a1048)
! at /.../genode/libports/contrib/libc-8.2.0/libc/stdio/fflush.c:123
! #6 0x010675f8 in __fflush (fp=0x10a1048)
! at /.../genode/libports/contrib/libc-8.2.0/libc/stdio/fflush.c:96
! #7 0x0106a223 in __sfvwrite (fp=0x10a1048, uio=0x1015a44)
! at /.../genode/libports/contrib/libc-8.2.0/libc/stdio/fvwrite.c:194
! #8 0x0106e1ad in puts (s=0x10039c0 "in func2()\n")
! at /.../genode/libports/contrib/libc-8.2.0/libc/stdio/puts.c:68
! #9 0x0100041d in func2 ()
! at /.../genode/ports/src/test/gdb_monitor/main.cc:51
! #10 0x01000444 in func1 ()
! at /.../genode/ports/src/test/gdb_monitor/main.cc:60
! #11 0x01000496 in main ()
! at /.../genode/ports/src/test/gdb_monitor/main.cc:70
To inspect a specific call frame, switch to a particular frame by using
the number printed in the backtrace. For example, to print the local
variables of the call frame 5:
! (gdb) f 5
! #5 0x000d04cb in __sflush (fp=0x105ca8)
! at /.../stdio/fflush.c:123
! 123 t = _swrite(fp, (char *)p, n);
! #5 0x01067598 in __sflush (fp=0x10a1048)
! at /.../libc-8.2.0/libc/stdio/fflush.c:123
! 123 t = _swrite(fp, (char *)p, n);
! (gdb) info locals
! p = 0x3e60 "Test thread is running, cnt=8\n\006"
! n = 30
! t = 1074787380
! p = 0x6590 "in func2()\n"
! n = 11
! t = <optimized out>
The test program consists of multiple threads. To see which threads there are,
use the 'info thread' command. To switch another thread, use the 'thread'
@ -398,7 +351,8 @@ Inspecting a Genode service
===========================
As a reference for debugging a native Genode service, the 'debug_nitpicker.run'
script provides a ready-to-use scenario. You can invoke it via 'make run/debug_nitpicker'.
script provides a ready-to-use scenario. You can invoke it via
'make run/debug_nitpicker'.
Nitpicker is a statically linked program. Hence, no special precautions are
needed to obtain its symbol information. As a stress test for GDB monitor,