aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog45
-rw-r--r--INSTALL27
-rw-r--r--Makeconfig76
-rw-r--r--Makerules46
-rw-r--r--NEWS5
-rw-r--r--README.pretty-printers169
-rw-r--r--Rules44
-rw-r--r--manual/install.texi30
-rw-r--r--nptl/Makefile18
-rw-r--r--nptl/nptl-printers.py633
-rw-r--r--nptl/nptl_lock_constants.pysym75
-rw-r--r--nptl/test-cond-printers.c57
-rw-r--r--nptl/test-cond-printers.py50
-rw-r--r--nptl/test-condattr-printers.c94
-rw-r--r--nptl/test-condattr-printers.py71
-rw-r--r--nptl/test-mutex-printers.c151
-rw-r--r--nptl/test-mutex-printers.py97
-rw-r--r--nptl/test-mutexattr-printers.c144
-rw-r--r--nptl/test-mutexattr-printers.py101
-rw-r--r--nptl/test-rwlock-printers.c78
-rw-r--r--nptl/test-rwlock-printers.py64
-rw-r--r--nptl/test-rwlockattr-printers.c98
-rw-r--r--nptl/test-rwlockattr-printers.py73
-rw-r--r--scripts/gen-py-const.awk118
-rw-r--r--scripts/test_printers_common.py364
-rw-r--r--scripts/test_printers_exceptions.py61
26 files changed, 2769 insertions, 20 deletions
diff --git a/ChangeLog b/ChangeLog
index 57ce74d446..d5ef99ce8d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,48 @@
+2016-12-08 Martin Galvan <martin.galvan@tallertechnologies.com>
+
+ * INSTALL: Regenerated.
+ * Makeconfig: Add comments and whitespace to make the control flow
+ clearer.
+ (+link-printers-tests, +link-pie-printers-tests,
+ CFLAGS-printers-tests, installed-rtld-LDFLAGS,
+ built-rtld-LDFLAGS, link-libc-rpath,
+ link-libc-tests-after-rpath-link,
+ link-libc-printers-tests): New.
+ (rtld-LDFLAGS, rtld-tests-LDFLAGS, link-libc-tests-rpath-link,
+ link-libc-tests): Use the new variables as required.
+ * Makerules ($(py-const)): New rule.
+ generated: Add $(py-const).
+ * README.pretty-printers: New file.
+ * Rules (tests-printers-programs, tests-printers-out, py-env): New.
+ (others): Depend on $(py-const).
+ (tests): Depend on $(tests-printers-programs) or
+ $(tests-printers-out),
+ as required. Pass $(tests-printers) to merge-test-results.sh.
+ * manual/install.texi: Add requirements for testing the pretty
+ printers.
+ * nptl/Makefile (gen-py-const-headers, pretty-printers,
+ tests-printers, CFLAGS-test-mutexattr-printers.c
+ CFLAGS-test-mutex-printers.c, CFLAGS-test-condattr-printers.c,
+ CFLAGS-test-cond-printers.c, CFLAGS-test-rwlockattr-printers.c
+ CFLAGS-test-rwlock-printers.c, tests-printers-libs): Define.
+ * nptl/nptl-printers.py: New file.
+ * nptl/nptl_lock_constants.pysym: Likewise.
+ * nptl/test-cond-printers.c: Likewise.
+ * nptl/test-cond-printers.py: Likewise.
+ * nptl/test-condattr-printers.c: Likewise.
+ * nptl/test-condattr-printers.py: Likewise.
+ * nptl/test-mutex-printers.c: Likewise.
+ * nptl/test-mutex-printers.py: Likewise.
+ * nptl/test-mutexattr-printers.c: Likewise.
+ * nptl/test-mutexattr-printers.py: Likewise.
+ * nptl/test-rwlock-printers.c: Likewise.
+ * nptl/test-rwlock-printers.py: Likewise.
+ * nptl/test-rwlockattr-printers.c: Likewise.
+ * nptl/test-rwlockattr-printers.py: Likewise.
+ * scripts/gen-py-const.awk: Likewise.
+ * scripts/test_printers_common.py: Likewise.
+ * scripts/test_printers_exceptions.py: Likewise.
+
2016-12-07 Joseph Myers <joseph@codesourcery.com>
* scripts/build-many-glibcs.py (Context.__init__): Take strip
diff --git a/INSTALL b/INSTALL
index b5acedcc96..acb622a102 100644
--- a/INSTALL
+++ b/INSTALL
@@ -224,6 +224,33 @@ You can specify 'stop-on-test-failure=y' when running 'make check' to
make the test run stop and exit with an error status immediately when a
failure occurs.
+ The GNU C Library pretty printers come with their own set of scripts
+for testing, which run together with the rest of the testsuite through
+'make check'. These scripts require the following tools to run
+successfully:
+
+ * Python 2.7.6/3.4.3 or later
+
+ Python is required for running the printers' test scripts.
+
+ * PExpect 4.0
+
+ The printer tests drive GDB through test programs and compare its
+ output to the printers'. PExpect is used to capture the output of
+ GDB, and should be compatible with the Python version in your
+ system.
+
+ * GDB 7.8 or later with support for Python 2.7.6/3.4.3 or later
+
+ GDB itself needs to be configured with Python support in order to
+ use the pretty printers. Notice that your system having Python
+ available doesn't imply that GDB supports it, nor that your
+ system's Python and GDB's have the same version.
+
+If these tools are absent, the printer tests will report themselves as
+'UNSUPPORTED'. Notice that some of the printer tests require the GNU C
+Library to be compiled with debugging symbols.
+
To format the 'GNU C Library Reference Manual' for printing, type
'make dvi'. You need a working TeX installation to do this. The
distribution builds the on-line formatted version of the manual, as Info
diff --git a/Makeconfig b/Makeconfig
index a7858607b0..e9d8da9d60 100644
--- a/Makeconfig
+++ b/Makeconfig
@@ -416,6 +416,11 @@ $(+link-pie-before-libc) $(rtld-tests-LDFLAGS) $(link-libc-tests) \
$(+link-pie-after-libc)
$(call after-link,$@)
endef
+define +link-pie-printers-tests
+$(+link-pie-before-libc) $(built-rtld-LDFLAGS) $(link-libc-printers-tests) \
+ $(+link-pie-after-libc)
+$(call after-link,$@)
+endef
endif
# Command for statically linking programs with the C library.
ifndef +link-static
@@ -445,7 +450,8 @@ ifeq (yes,$(build-pie-default))
no-pie-ldflag = -no-pie
+link = $(+link-pie)
+link-tests = $(+link-pie-tests)
-else
++link-printers-tests = $(+link-pie-printers-tests)
+else # not build-pie-default
+link-before-libc = $(CC) -nostdlib -nostartfiles -o $@ \
$(sysdep-LDFLAGS) $(LDFLAGS) $(LDFLAGS-$(@F)) \
$(combreloc-LDFLAGS) $(relro-LDFLAGS) $(hashstyle-LDFLAGS) \
@@ -466,51 +472,87 @@ $(+link-before-libc) $(rtld-tests-LDFLAGS) $(link-libc-tests) \
$(+link-after-libc)
$(call after-link,$@)
endef
-endif
-else
+define +link-printers-tests
+$(+link-before-libc) $(built-rtld-LDFLAGS) $(link-libc-printers-tests) \
+ $(+link-after-libc)
+$(call after-link,$@)
+endef
+endif # build-pie-default
+else # build-static
+link = $(+link-static)
+link-tests = $(+link-static-tests)
-endif
-endif
++link-printers-tests = $(+link-static-tests)
+endif # build-shared
+endif # +link
+
+# The pretty printer test programs need to be compiled without optimizations
+# so they won't confuse gdb. We could use either the 'GCC optimize' pragma
+# or the 'optimize' function attribute to achieve this; however, at least on
+# ARM, gcc always produces different debugging symbols when invoked with
+# a -O greater than 0 than when invoked with -O0, regardless of anything else
+# we're using to suppress optimizations. Therefore, we need to explicitly pass
+# -O0 to it through CFLAGS.
+# Additionally, the build system will try to -include $(common-objpfx)/config.h
+# when compiling the tests, which will throw an error if some special macros
+# (such as __OPTIMIZE__ and IS_IN_build) aren't defined. To avoid this, we
+# tell gcc to define IS_IN_build.
+CFLAGS-printers-tests := -O0 -ggdb3 -DIS_IN_build
+
ifeq (yes,$(build-shared))
+# These indicate whether to link using the built ld.so or the installed one.
+installed-rtld-LDFLAGS = -Wl,-dynamic-linker=$(rtlddir)/$(rtld-installed-name)
+built-rtld-LDFLAGS = -Wl,-dynamic-linker=$(elf-objpfx)ld.so
+
ifndef rtld-LDFLAGS
-rtld-LDFLAGS = -Wl,-dynamic-linker=$(rtlddir)/$(rtld-installed-name)
+rtld-LDFLAGS = $(installed-rtld-LDFLAGS)
endif
+
ifndef rtld-tests-LDFLAGS
ifeq (yes,$(build-hardcoded-path-in-tests))
-rtld-tests-LDFLAGS = -Wl,-dynamic-linker=$(elf-objpfx)ld.so
+rtld-tests-LDFLAGS = $(built-rtld-LDFLAGS)
else
-rtld-tests-LDFLAGS = $(rtld-LDFLAGS)
-endif
-endif
-endif
+rtld-tests-LDFLAGS = $(installed-rtld-LDFLAGS)
+endif # build-hardcoded-path-in-tests
+endif # rtld-tests-LDFLAGS
+
+endif # build-shared
+
ifndef link-libc
ifeq (yes,$(build-shared))
# We need the versioned name of libc.so in the deps of $(others) et al
# so that the symlink to libc.so is created before anything tries to
# run the linked programs.
+link-libc-rpath = -Wl,-rpath=$(rpath-link)
link-libc-rpath-link = -Wl,-rpath-link=$(rpath-link)
+
ifeq (yes,$(build-hardcoded-path-in-tests))
-link-libc-tests-rpath-link = -Wl,-rpath=$(rpath-link)
+link-libc-tests-rpath-link = $(link-libc-rpath)
else
link-libc-tests-rpath-link = $(link-libc-rpath-link)
-endif
+endif # build-hardcoded-path-in-tests
+
link-libc-before-gnulib = $(common-objpfx)libc.so$(libc.so-version) \
$(common-objpfx)$(patsubst %,$(libtype.oS),c) \
$(as-needed) $(elf-objpfx)ld.so \
$(no-as-needed)
link-libc = $(link-libc-rpath-link) $(link-libc-before-gnulib) $(gnulib)
+
+link-libc-tests-after-rpath-link = $(link-libc-before-gnulib) $(gnulib-tests)
link-libc-tests = $(link-libc-tests-rpath-link) \
- $(link-libc-before-gnulib) $(gnulib-tests)
+ $(link-libc-tests-after-rpath-link)
+# Pretty printer test programs always require rpath instead of rpath-link.
+link-libc-printers-tests = $(link-libc-rpath) \
+ $(link-libc-tests-after-rpath-link)
+
# This is how to find at build-time things that will be installed there.
rpath-dirs = math elf dlfcn nss nis rt resolv crypt mathvec
rpath-link = \
$(common-objdir):$(subst $(empty) ,:,$(patsubst ../$(subdir),.,$(rpath-dirs:%=$(common-objpfx)%)))
-else
+else # build-static
link-libc = $(common-objpfx)libc.a $(otherlibs) $(gnulib) $(common-objpfx)libc.a $(gnulib)
link-libc-tests = $(common-objpfx)libc.a $(otherlibs) $(gnulib-tests) $(common-objpfx)libc.a $(gnulib-tests)
-endif
-endif
+endif # build-shared
+endif # link-libc
# Differences in the linkers on the various platforms.
LDFLAGS-rpath-ORIGIN = -Wl,-rpath,'$$ORIGIN'
diff --git a/Makerules b/Makerules
index e865782b43..7214b2b43c 100644
--- a/Makerules
+++ b/Makerules
@@ -210,6 +210,52 @@ sed-remove-dotdot := -e 's@ *\([^ \/$$][^ \]*\)@ $$(..)\1@g' \
-e 's@^\([^ \/$$][^ \]*\)@$$(..)\1@g'
endif
+ifdef gen-py-const-headers
+# We'll use a static pattern rule to match .pysym files with their
+# corresponding generated .py files.
+# The generated .py files go in the submodule's dir in the glibc build dir.
+py-const-files := $(patsubst %.pysym,%.py,$(gen-py-const-headers))
+py-const-dir := $(objpfx)
+py-const := $(addprefix $(py-const-dir),$(py-const-files))
+py-const-script := $(..)scripts/gen-py-const.awk
+
+# This is a hack we use to generate .py files with constants for Python
+# pretty printers. It works the same way as gen-as-const.
+# See scripts/gen-py-const.awk for details on how the awk | gcc mechanism
+# works.
+#
+# $@.tmp and $@.tmp2 are temporary files we use to store the partial contents
+# of the target file. We do this instead of just writing on $@ because, if the
+# build process terminates prematurely, re-running Make wouldn't run this rule
+# since Make would see that the target file already exists (despite it being
+# incomplete).
+#
+# The sed line replaces "@name@SOME_NAME@value@SOME_VALUE@" strings from the
+# output of 'gcc -S' with "SOME_NAME = SOME_VALUE" strings.
+# The '-n' option, combined with the '/p' command, makes sed output only the
+# modified lines instead of the whole input file. The output is redirected
+# to a .py file; we'll import it in the pretty printers file to read
+# the constants generated by gen-py-const.awk.
+# The regex has two capturing groups, for SOME_NAME and SOME_VALUE
+# respectively. Notice SOME_VALUE may be prepended by a special character,
+# depending on the assembly syntax (e.g. immediates are prefixed by a '$'
+# in AT&T x86, and by a '#' in ARM). We discard it using a complemented set
+# before the second capturing group.
+$(py-const): $(py-const-dir)%.py: %.pysym $(py-const-script) \
+ $(common-before-compile)
+ $(make-target-directory)
+ $(AWK) -f $(py-const-script) $< \
+ | $(CC) -S -o $@.tmp $(CFLAGS) $(CPPFLAGS) -x c -
+ echo '# GENERATED FILE\n' > $@.tmp2
+ echo '# Constant definitions for pretty printers.' >> $@.tmp2
+ echo '# See gen-py-const.awk for details.\n' >> $@.tmp2
+ sed -n -r 's/^.*@name@([^@]+)@value@[^[:xdigit:]Xx-]*([[:xdigit:]Xx-]+)@.*/\1 = \2/p' \
+ $@.tmp >> $@.tmp2
+ mv -f $@.tmp2 $@
+ rm -f $@.tmp
+
+generated += $(py-const)
+endif # gen-py-const-headers
ifdef gen-as-const-headers
# Generating headers for assembly constants.
diff --git a/NEWS b/NEWS
index c2e973d183..922a5004ff 100644
--- a/NEWS
+++ b/NEWS
@@ -141,6 +141,11 @@ Version 2.25
variable for a particular architecture in the GCC source file
'gcc/config.gcc'.
+* GDB pretty printers have been added for mutex and condition variable
+ structures in POSIX Threads. When installed and loaded in gdb these pretty
+ printers show various pthread variables in human-readable form when read
+ using the 'print' or 'display' commands in gdb.
+
Security related changes:
On ARM EABI (32-bit), generating a backtrace for execution contexts which
diff --git a/README.pretty-printers b/README.pretty-printers
new file mode 100644
index 0000000000..86629001e6
--- /dev/null
+++ b/README.pretty-printers
@@ -0,0 +1,169 @@
+README for the glibc Python pretty printers
+===========================================
+
+Pretty printers are gdb extensions that allow it to print useful, human-readable
+information about a program's variables. For example, for a pthread_mutex_t
+gdb would usually output something like this:
+
+(gdb) print mutex
+$1 = {
+ __data = {
+ __lock = 22020096,
+ __count = 0,
+ __owner = 0,
+ __nusers = 0,
+ __kind = 576,
+ __spins = 0,
+ __elision = 0,
+ __list = {
+ __prev = 0x0,
+ __next = 0x0
+ }
+ },
+ __size = "\000\000P\001", '\000' <repeats 12 times>, "@\002", '\000' <repeats 21 times>,
+ __align = 22020096
+}
+
+However, with a pretty printer gdb will output something like this:
+
+(gdb) print mutex
+$1 = pthread_mutex_t = {
+ Type = Normal,
+ Status = Unlocked,
+ Robust = No,
+ Shared = No,
+ Protocol = Priority protect,
+ Priority ceiling = 42
+}
+
+Before printing a value, gdb will first check if there's a pretty printer
+registered for it. If there is, it'll use it, otherwise it'll print the value
+as usual. Pretty printers can be registered in various ways; for our purposes
+we register them for the current objfile by calling
+gdb.printing.register_pretty_printer().
+
+Currently our printers are based on gdb.RegexpCollectionPrettyPrinter, which
+means they'll be triggered if the type of the variable we're printing matches
+a given regular expression. For example, MutexPrinter will be triggered if
+our variable's type matches the regexp '^pthread_mutex_t$'.
+
+Besides the printers themselves, each module may have a constants file which the
+printers will import. These constants are generated from C headers during the
+build process, and need to be in the Python search path when loading the
+printers.
+
+
+Installing and loading
+----------------------
+
+The pretty printers and their constant files may be installed in different paths
+for each distro, though gdb should be able to automatically load them by itself.
+When in doubt, you can use the 'info pretty-printer' gdb command to list the
+loaded pretty printers.
+
+If the printers aren't automatically loaded for some reason, you should add the
+following to your .gdbinit:
+
+python
+import sys
+sys.path.insert(0, '/path/to/constants/file/directory')
+end
+
+source /path/to/printers.py
+
+If you're building glibc manually, '/path/to/constants/file/directory' should be
+'/path/to/glibc-build/submodule', where 'submodule' is e.g. nptl.
+
+
+Testing
+-------
+
+The pretty printers come with a small test suite based on PExpect, which is a
+Python module with Expect-like features for spawning and controlling interactive
+programs. Each printer has a corresponding C program and a Python script
+that uses PExpect to drive gdb through the program and compare its output to
+the expected printer's.
+
+The tests run on the glibc host, which is assumed to have both gdb and PExpect;
+if any of those is absent the tests will fail with code 77 (UNSUPPORTED).
+Native builds can be tested simply by doing 'make check'; cross builds must use
+cross-test-ssh.sh as test-wrapper, like this:
+
+make test-wrapper='/path/to/scripts/cross-test-ssh.sh user@host' check
+
+(Remember to share the build system's filesystem with the glibc host's through
+NFS or something similar).
+
+Running 'make check' on a cross build will only compile the test programs,
+without running the scripts.
+
+
+Adding new pretty printers
+--------------------------
+
+Adding new pretty printers to glibc requires following these steps:
+
+1. Identify which constants must be generated from C headers, and write the
+corresponding .pysym file. See scripts/gen-py-const.awk for more information
+on how this works. The name of the .pysym file must be added to the
+'gen-py-const-headers' variable in your submodule's Makefile (without the .pysym
+extension).
+
+2. Write the pretty printer code itself. For this you can follow the gdb
+Python API documentation, and use the existing printers as examples. The printer
+code must import the generated constants file (which will have the same name
+as your .pysym file). The names of the pretty printer files must be added
+to the 'pretty-printers' variable in your submodule's Makefile (without the .py
+extension).
+
+3. Write the unit tests for your pretty printers. The build system calls each
+test script passing it the paths to the test program source, the test program
+binary, and the printer files you added to 'pretty-printers' in the previous
+step. The test scripts, in turn, must import scripts/test_printers_common
+and call the init_test function passing it, among other things, the name of the
+set of pretty printers to enable (as seen by running 'info pretty-printer').
+You can use the existing unit tests as examples.
+
+4. Add the names of the pretty printer tests to the 'tests-printers' variable
+in your submodule's Makefile (without extensions). In addition, for each test
+program you must define a corresponding CFLAGS-* variable and set it to
+$(CFLAGS-printers-tests) to ensure they're compiled correctly. For example,
+test-foo-printer.c requires the following:
+
+CFLAGS-test-foo-printer.c := $(CFLAGS-printers-tests)
+
+Finally, if your programs need to be linked with a specific library, you can add
+its name to the 'tests-printers-libs' variable in your submodule's Makefile.
+
+
+Known issues
+------------
+
+* Pretty printers are inherently coupled to the code they're targetting, thus
+any changes to the target code must also update the corresponding printers.
+On the plus side, the printer code itself may serve as a kind of documentation
+for the target code.
+
+* Older versions of the gdb Python API have a bug where
+gdb.RegexpCollectionPrettyPrinter would not be able to get a value's real type
+if it was typedef'd. This would cause gdb to ignore the pretty printers for
+types like pthread_mutex_t, which is defined as:
+
+typedef union
+{
+ ...
+} pthread_mutex_t;
+
+This was fixed in commit 1b588015839caafc608a6944a78aea170f5fb2f6, and released
+as part of gdb 7.8. However, typedef'ing an already typedef'd type may cause
+a similar issue, e.g.:
+
+typedef pthread_mutex_t mutex;
+mutex a_mutex;
+
+Here, trying to print a_mutex won't trigger the pthread_mutex_t printer.
+
+* The test programs must be compiled without optimizations. This is necessary
+because the test scripts rely on the C code structure being preserved when
+stepping through the programs. Things like aggressive instruction reordering
+or optimizing variables out may make this kind of testing impossible.
diff --git a/Rules b/Rules
index 466db076f0..714e917de4 100644
--- a/Rules
+++ b/Rules
@@ -108,17 +108,28 @@ endif
.PHONY: others tests bench bench-build
+# Test programs for the pretty printers.
+tests-printers-programs := $(addprefix $(objpfx),$(tests-printers))
+
+# .out files with the output of running the pretty printer tests.
+tests-printers-out := $(patsubst %,$(objpfx)%.out,$(tests-printers))
+
ifeq ($(build-programs),yes)
others: $(addprefix $(objpfx),$(others) $(sysdep-others) $(extra-objs))
else
others: $(addprefix $(objpfx),$(extra-objs))
endif
+
+# Generate c