Blame manual/README.pretty-printers

Packit Service 82fcde
README for the glibc Python pretty printers
Packit Service 82fcde
===========================================
Packit Service 82fcde
Packit Service 82fcde
Pretty printers are gdb extensions that allow it to print useful, human-readable
Packit Service 82fcde
information about a program's variables.  For example, for a pthread_mutex_t
Packit Service 82fcde
gdb would usually output something like this:
Packit Service 82fcde
Packit Service 82fcde
(gdb) print mutex
Packit Service 82fcde
$1 = {
Packit Service 82fcde
  __data = {
Packit Service 82fcde
    __lock = 22020096,
Packit Service 82fcde
    __count = 0,
Packit Service 82fcde
    __owner = 0,
Packit Service 82fcde
    __nusers = 0,
Packit Service 82fcde
    __kind = 576,
Packit Service 82fcde
    __spins = 0,
Packit Service 82fcde
    __elision = 0,
Packit Service 82fcde
    __list = {
Packit Service 82fcde
      __prev = 0x0,
Packit Service 82fcde
      __next = 0x0
Packit Service 82fcde
    }
Packit Service 82fcde
  },
Packit Service 82fcde
  __size = "\000\000P\001", '\000' <repeats 12 times>, "@\002", '\000' <repeats 21 times>,
Packit Service 82fcde
  __align = 22020096
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
However, with a pretty printer gdb will output something like this:
Packit Service 82fcde
Packit Service 82fcde
(gdb) print mutex
Packit Service 82fcde
$1 = pthread_mutex_t = {
Packit Service 82fcde
  Type = Normal,
Packit Service 82fcde
  Status = Not acquired,
Packit Service 82fcde
  Robust = No,
Packit Service 82fcde
  Shared = No,
Packit Service 82fcde
  Protocol = Priority protect,
Packit Service 82fcde
  Priority ceiling = 42
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
Before printing a value, gdb will first check if there's a pretty printer
Packit Service 82fcde
registered for it.  If there is, it'll use it, otherwise it'll print the value
Packit Service 82fcde
as usual.  Pretty printers can be registered in various ways; for our purposes
Packit Service 82fcde
we register them for the current objfile by calling
Packit Service 82fcde
gdb.printing.register_pretty_printer().
Packit Service 82fcde
Packit Service 82fcde
Currently our printers are based on gdb.RegexpCollectionPrettyPrinter, which
Packit Service 82fcde
means they'll be triggered if the type of the variable we're printing matches
Packit Service 82fcde
a given regular expression.  For example, MutexPrinter will be triggered if
Packit Service 82fcde
our variable's type matches the regexp '^pthread_mutex_t$'.
Packit Service 82fcde
Packit Service 82fcde
Besides the printers themselves, each module may have a constants file which the
Packit Service 82fcde
printers will import.  These constants are generated from C headers during the
Packit Service 82fcde
build process, and need to be in the Python search path when loading the
Packit Service 82fcde
printers.
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
Installing and loading
Packit Service 82fcde
----------------------
Packit Service 82fcde
Packit Service 82fcde
The pretty printers and their constant files may be installed in different paths
Packit Service 82fcde
for each distro, though gdb should be able to automatically load them by itself.
Packit Service 82fcde
When in doubt, you can use the 'info pretty-printer' gdb command to list the
Packit Service 82fcde
loaded pretty printers.
Packit Service 82fcde
Packit Service 82fcde
If the printers aren't automatically loaded for some reason, you should add the
Packit Service 82fcde
following to your .gdbinit:
Packit Service 82fcde
Packit Service 82fcde
python
Packit Service 82fcde
import sys
Packit Service 82fcde
sys.path.insert(0, '/path/to/constants/file/directory')
Packit Service 82fcde
end
Packit Service 82fcde
Packit Service 82fcde
source /path/to/printers.py
Packit Service 82fcde
Packit Service 82fcde
If you're building glibc manually, '/path/to/constants/file/directory' should be
Packit Service 82fcde
'/path/to/glibc-build/submodule', where 'submodule' is e.g. nptl.
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
Testing
Packit Service 82fcde
-------
Packit Service 82fcde
Packit Service 82fcde
The pretty printers come with a small test suite based on PExpect, which is a
Packit Service 82fcde
Python module with Expect-like features for spawning and controlling interactive
Packit Service 82fcde
programs.  Each printer has a corresponding C program and a Python script
Packit Service 82fcde
that uses PExpect to drive gdb through the program and compare its output to
Packit Service 82fcde
the expected printer's.
Packit Service 82fcde
Packit Service 82fcde
The tests run on the glibc host, which is assumed to have both gdb and PExpect;
Packit Service 82fcde
if any of those is absent the tests will fail with code 77 (UNSUPPORTED).
Packit Service 82fcde
Native builds can be tested simply by doing 'make check'; cross builds must use
Packit Service 82fcde
cross-test-ssh.sh as test-wrapper, like this:
Packit Service 82fcde
Packit Service 82fcde
make test-wrapper='/path/to/scripts/cross-test-ssh.sh user@host' check
Packit Service 82fcde
Packit Service 82fcde
(Remember to share the build system's filesystem with the glibc host's through
Packit Service 82fcde
NFS or something similar).
Packit Service 82fcde
Packit Service 82fcde
Running 'make check' on a cross build will only compile the test programs,
Packit Service 82fcde
without running the scripts.
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
Adding new pretty printers
Packit Service 82fcde
--------------------------
Packit Service 82fcde
Packit Service 82fcde
Adding new pretty printers to glibc requires following these steps:
Packit Service 82fcde
Packit Service 82fcde
1. Identify which constants must be generated from C headers, and write the
Packit Service 82fcde
corresponding .pysym file.  See scripts/gen-py-const.awk for more information
Packit Service 82fcde
on how this works.  The name of the .pysym file must be added to the
Packit Service 82fcde
'gen-py-const-headers' variable in your submodule's Makefile (without the .pysym
Packit Service 82fcde
extension).
Packit Service 82fcde
Packit Service 82fcde
2. Write the pretty printer code itself.  For this you can follow the gdb
Packit Service 82fcde
Python API documentation, and use the existing printers as examples.  The printer
Packit Service 82fcde
code must import the generated constants file (which will have the same name
Packit Service 82fcde
as your .pysym file).  The names of the pretty printer files must be added
Packit Service 82fcde
to the 'pretty-printers' variable in your submodule's Makefile (without the .py
Packit Service 82fcde
extension).
Packit Service 82fcde
Packit Service 82fcde
3. Write the unit tests for your pretty printers.  The build system calls each
Packit Service 82fcde
test script passing it the paths to the test program source, the test program
Packit Service 82fcde
binary, and the printer files you added to 'pretty-printers' in the previous
Packit Service 82fcde
step.  The test scripts, in turn, must import scripts/test_printers_common
Packit Service 82fcde
and call the init_test function passing it, among other things, the name of the
Packit Service 82fcde
set of pretty printers to enable (as seen by running 'info pretty-printer').
Packit Service 82fcde
You can use the existing unit tests as examples.
Packit Service 82fcde
Packit Service 82fcde
4. Add the names of the pretty printer tests to the 'tests-printers' variable
Packit Service 82fcde
in your submodule's Makefile (without extensions).  In addition, for each test
Packit Service 82fcde
program you must define a corresponding CFLAGS-* and CPPFLAGS-* variable and
Packit Service 82fcde
set it to $(CFLAGS-printers-tests) to ensure they're compiled correctly.  For
Packit Service 82fcde
example, test-foo-printer.c requires the following:
Packit Service 82fcde
Packit Service 82fcde
CFLAGS-test-foo-printer.c := $(CFLAGS-printers-tests)
Packit Service 82fcde
CPPFLAGS-test-foo-printer.c := $(CFLAGS-printers-tests)
Packit Service 82fcde
Packit Service 82fcde
Finally, if your programs need to be linked with a specific library, you can add
Packit Service 82fcde
its name to the 'tests-printers-libs' variable in your submodule's Makefile.
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
Known issues
Packit Service 82fcde
------------
Packit Service 82fcde
Packit Service 82fcde
* Pretty printers are inherently coupled to the code they're targetting, thus
Packit Service 82fcde
any changes to the target code must also update the corresponding printers.
Packit Service 82fcde
On the plus side, the printer code itself may serve as a kind of documentation
Packit Service 82fcde
for the target code.
Packit Service 82fcde
Packit Service 82fcde
* There's no guarantee that the information the pretty printers provide is
Packit Service 82fcde
complete, i.e. some details might be left off.  For example, the pthread_mutex_t
Packit Service 82fcde
printers won't report whether a thread is spin-waiting in an attempt to acquire
Packit Service 82fcde
the mutex.
Packit Service 82fcde
Packit Service 82fcde
* Older versions of the gdb Python API have a bug where
Packit Service 82fcde
gdb.RegexpCollectionPrettyPrinter would not be able to get a value's real type
Packit Service 82fcde
if it was typedef'd.  This would cause gdb to ignore the pretty printers for
Packit Service 82fcde
types like pthread_mutex_t, which is defined as:
Packit Service 82fcde
Packit Service 82fcde
typedef union
Packit Service 82fcde
{
Packit Service 82fcde
  ...
Packit Service 82fcde
} pthread_mutex_t;
Packit Service 82fcde
Packit Service 82fcde
This was fixed in commit 1b588015839caafc608a6944a78aea170f5fb2f6, and released
Packit Service 82fcde
as part of gdb 7.8.  However, typedef'ing an already typedef'd type may cause
Packit Service 82fcde
a similar issue, e.g.:
Packit Service 82fcde
Packit Service 82fcde
typedef pthread_mutex_t mutex;
Packit Service 82fcde
mutex a_mutex;
Packit Service 82fcde
Packit Service 82fcde
Here, trying to print a_mutex won't trigger the pthread_mutex_t printer.
Packit Service 82fcde
Packit Service 82fcde
* The test programs must be compiled without optimizations.  This is necessary
Packit Service 82fcde
because the test scripts rely on the C code structure being preserved when
Packit Service 82fcde
stepping through the programs.  Things like aggressive instruction reordering
Packit Service 82fcde
or optimizing variables out may make this kind of testing impossible.