Brief Installation Notes (from Frank Mueller)
The following modifications
to the GDB were made to demonstrate the TDI efficiency. The GDB as a TDI
client uses the abstract POSIX thread level view to debug threads. All
thread information will be generated by the TDI and is send back to the
Debugger via IPC. The TDI interface for the Gdb is the client library of
the TDI - libTDIClt.so
or
libTDIClt.a. The
client library contains all IPC stuff reqired to communicate with the TDI
kernel running on the application side. The client library is part of the
TDI distribution.
Major changes to the GDB (version 4.17) were made by adding a new file pthread.c, that contains the implementation af all thread debugging commands based on the TDI. The following new commands available are listed on the TDI home page.
Low Level Changes to the GDB
Minor changes were made
by modiffying the files infcmd.c, infrun.c and breakpoint.c and some target
specific header files:
|
|
|
step_1: The commands step, stepi, next and nexti are based on the function step_1. To provide the appropriate threadspecific commands named ptstep, ptstepi, ptnext and ptnexti we have to change the stop criterion used in step_1. If we stop in the next line or at the next instruction, we have to test the current thread. If it is not the same as before running the command (this means, that we have lost the control flow of the thread), we have to continue running the program until the former control flow is reached. |
|
wait_for_inferior: bugfix for recursive calls of wait_for_inferior:wait_for_inferior is the function called by proceed() to wait for any program event signalled by the operating system by making the function wait return. wait_for_inferior calls the function breakpoint_thread_match before deciding to proceed again, if it was the wrong thread. Calling the function breakpoint_thread_match can cause a TDI usage. If we debug an application using a User Space Implementation of the Pthreads, a function call is done in the target. The consequence of a target function call in this situation is a recursive call of wait_for_inferior. After target function call is completed, the flag breakpoint_inserted is unset. This is a wrong assignment, because the breakpoint we were calling breakpoint_thread_match at is not unset. The bugfix is very simple by setting the flag breakpoint_inserted.switch off scheduling while resetting the breakpoint:If the current breakpoint was reached from the wrong thread, we have to pass this breakpoint by resetting the instruction, single stepping and resetting the breakpoint after this single step. While single stepping the application, no breakpoint is set. This a critical point, because other threads can be scheduled in and pass the breakpoint without stop. To avoid this scenario, we switch off signal handling in user space implementations by changing the signal handing policy of the pthreads implementation. switching off is done by setting a flag in the target process. this flag is a symbol, that is defined in every TDI compliant pthread implementation. |
|
breakpoint_thread_match: breakpoint_thread_match is the function used by wait_for_inferior to test the validity of a threadspecific breakpoint. Because there is the abilty for the user to specify threadspecific breakpoints for POSIX threads now, some changes were made to test the validity of a POSIX threadspecific breakpoint.break_command_1: the keyword pthread is accepted by the break command. some parsing and assignment stuff is added. |
i.e. nm-i386sol2.h; nm-linux.h; nm-hppah.h; nm-sun4sol2.h |
definition of target_new_objfile: target_new_objfile is defined as a function call to pTDI_new_objfile to initialize the thread debugging. The GDB does a target_new_objfile on every object file load. The application has to know, whether it is thread debugged or not. If it is, it loads the TDI library and register it's TED functions (functions to access object attributes and iterate object sets). Because we have to set the thread debug mode of the application before running it, it's the best way to detect a pthread application while scanning the loaded object files for pthread symbols. Setting the debug mode is done by writing the global symbol pthread_debug_with_TDI, that has to be defined in a TDI compliant pthreads implementation. |
Gdb Patch
All changes to GDB are bundled in a patch (see TDI home page) applicable to the source tree of gdb. Download the patch and execute a
% patch -p0 < gdb-*-TDI.patch
in the directory containig the gdb source tree named gdb-version. After patching you have to configure and install the gdb according to the following installation guide.
!!! General information: Please try to compile the gdb first to fix all problems not referring to this patch. Some newer Linux distributions come up with a restructured include file hierarchy. These problems are not covered by this patch and should be fixed by you first. !!!
Installation
After patching the Gdb sources you have to reconfigure the gdb for TDI. The configure script and it's sources (configure.in, acconfig.h) were modified to configure for TDI now. To get TDI support execute the command:
% configure --enable-TDI
To compile and link the gdb
(with: make
&& make install)
successfully you have to install the TDI first (see the TDI INSTALL file).
The library libTDIClt.so
should be reachable by the linker and the header files tdi.h
and tdi-client.h
have to be installed properly.
last modified: 1999-Jul-26 |
authors: Daniel Schulz , Frank Mueller
|