GSoC 2016 Reports: Split debug symbols for pkgsrc builds, part 2
Google Summer of Code 2016 is now over. We have polished the code and documentation and submitted the final term evaluation on 23rd of August 2016. The mentors evaluated us in the following week.
If you are impatient (and this time impatience is definitely a virtue!) please take a look to all The NetBSD Foundation GSoC 2016 projects' code submissions!
Introduction
In part 1 we have learned what happens under the hood when we split debugging symbols: how debugging information is stored/stripped off, the relevant ELF sections involved, various tools to dump that information, etc..
In particular, we have studied what happens on NetBSD when we set the
MKDEBUG* flags.
With this background we can finally try to implement this functionality in the
pkgsrc infrastructure. In this blog post we
will first give a practical look at PKG_DEBUGDATA and then we
will analyze the code that I have written in the first mid-term of the GSoC to
accomplish that.
PKG_DEBUGDATA in action
Before digging in the implementation of debugdata functionality let's see what it produces!
In part 1
we took as example a very simple program that just prints out the lyrics of
Ten Green Bottles song. After packaging it as
local/green-bottles
let's just build it without any special pkgsrc system variables set:
$ cd pkgsrc/local/green-bottles $ make install [...] $ green-bottles ten green bottles hanging on the wall [...] $ pkg_info -L green-bottles Information for green-bottles-0: Files: /usr/pkg/bin/green-bottles $ gdb `which green-bottles` GNU gdb (GDB) 7.10.1 Copyright (C) 2015 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> [...] Reading symbols from /usr/pkg/bin/green-bottles...(no debugging symbols found)...done. (gdb) quit
That's expected because we did not set any special CFLAGS nor
INSTALL_UNSTRIPPED.
Before setting PKG_DEBUGDATA to "yes" let's inspect its
documentation via the help target:
$ make help topic=PKG_DEBUGDATA ===> mk/bsd.debugdata.mk (keywords: INSTALL_UNSTRIPPED PKG_DEBUGLEVEL PKG_DEBUGDATA debug): # This Makefile fragment is included by bsd.pkg.mk and implements the # logic needed to strip debug symbols off the program/libraries. # # User-settable variables: # # PKG_DEBUGDATA # If "yes", install stripped debug symbols for all programs and shared # libraries. Please notice that if it is defined INSTALL_UNSTRIPPED will # be also defined internally. # # PKG_DEBUGLEVEL # Used to control the granularity of the debug information. Can be # "small", "default", "detailed". # TODO: the name of this variable should be changed because it can be # TODO: easily confused with PKG_DEBUG_LEVEL! # # See also: # INSTALL_UNSTRIPPED #
Now that we have finally an idea of what PKG_DEBUGDATA does, let's
set it and reinstall the green-bottles package:
$ make clean deinstall [...] $ PKG_DEBUGDATA=yes make install [...] ===> Installing for green-bottles-0 [...] => Stripping debug symbols => Installing debug data [...] => Checking for missing debug data in green-bottles-0 [...]
Apart from the various phases we can see three extra messages that are now printed out: stripping of debug symbols, installing of debug data and a check for missing debug data.
If we inspect the files installed we can now also see
green-bottles.debug:
$ pkg_info -L green-bottles Information for green-bottles-0: Files: /usr/pkg/bin/green-bottles.debug /usr/pkg/bin/green-bottles
Indeed if we now try to run it through gdb(1):
$ gdb `which green-bottles`
GNU gdb (GDB) 7.10.1
Copyright (C) 2015 Free Software Foundation, Inc.
[...]
Reading symbols from /usr/pkg/bin/green-bottles...Reading symbols from /usr/pkg/bin/green-bottles.debug...done.
done.
(gdb) b main
Breakpoint 1 at 0xad0: file green-bottles.c, line 29.
(gdb) run
Starting program: /usr/pkg/bin/green-bottles
Breakpoint 1, main () at green-bottles.c:29
29 {
(gdb)
[...]
green-bottles was installed as usual without requiring any changes
from MAINTAINERs, in fact the various .debug files
are generated, installed and added to the PLIST dynamically.
A look at mk/bsd.debugdata.mk and mk/check/check-debugdata.mk implementation
All the functionalities that implement stripping of the debug data from
installed programs and libraries are implemented entirely in
bsd.debugdata.mk.
check/check-debugdata.mk
checks that all programs and libraries have the debug
data correctly stripped into their corresponding *.debug files.
mk/bsd.debugdata.mk
The
first 23 lines of bsd.debugdata.mk contain a comment that is also
accessible via the help
target. In particular it describes all the user-settable variables:
-
PKG_DEBUGDATA: if "yes" it turns on debugdata functionality to generate the*.debugfiles and then install them as part of the package. -
PKG_DEBUGLEVEL: useful to control the granularity of the debug information, i.e. the-glevel flag passed to the compiler. It can be "small", "default" and "detailed".
Then _VARGROUPS and _USER_VARS.<vargroup>
are set accordingly. These are used by the show-all target (if you
are more curious regarding that please just try make show-all and/or
give a look to
mk/misc/show.mk).
After various definitions of some used variables (should be self-explainable)
_FIND_DEBUGGABLEDATA_ERE is defined as an Extended Regular
Expression that is used to match potential files that can be stripped.
_FIND_DEBUGGABLEDATA_ERE is then used to limit the file list
generated via
_FIND_DEBUGGABLEDATA_FILELIST_CMD
Lines 63-86 pass the appropriate debug flags and debug level to the compiler.
Then _PLIST_DEBUGDATA is added to the PLIST_SRC_DFLT
variable. PLIST_SRC_DFLT contains all the default
PLISTs that
usually resides in pkgsrc/category/PLIST* (e.g. PLIST,
PLIST.common, PLIST.NetBSD, etc.). If you are more
interested in how it works, please give a look to
mk/plist/plist.mk.
In this way all the *.debug files listed in
_PLIST_DEBUGDATA are dynamically appended to the package
PLIST.
In lines
90-111 generate-strip-debugdata target is defined. It
basically just does the operations we have explored in
part 1
with little adjustments for pkgsrc:
- Check if the current file is strippable via objdump(1)
-
If the current file is strippable
objcopy --only-keep-debug program|library program.debug|library.debugis invoked in order to populate the.debugfile. -
If the current file is strippable
objcopy --strip-debug -p -R .gnu_debuglink --add-gnu-debuglink=program.debug|library.debug program|libraryis invoked to delete the debug information from the current file (program or library) and to add the.gnu_debuglinkELF section to it so that the debugger knows where to pick the corresponding.debugfile. -
Append the
.debugpath and filename to the_PLIST_DEBUGDATAfile.
To accomplish that RUN is used to run all shell commands without
printing them. Please note that when RUN is used all shell commands
should be terminated with a semicolon. For more information regarding
RUN please take a look at make help topic=RUN.
In lines
113-122 install-strip-debugdata is defined. It just installs all
*.debug files via INSTALL_DATA.
install-strip-debugdata target will then be invoked after the
post-install phase.
mk/check/check-debugdata.mk
First 26 lines of check-debugdata.mk contain a comment for the pkgsrc online documentation. It describes the following user-settable variables:
-
CHECK_DEBUGDATA: if "yes" it enables debugdata checks (by default most checks are usually enabled only if PKG_DEVELOPER is "yes")
...and the following package-settable variables:
-
CHECK_DEBUGDATA_SKIP: list of shell patterns that should be excluded from the check. -
CHECK_DEBUGDATA_SUPPORTED: whether the check should be enabled for the package or not.
Like what it was done for
bsd.debugdata.mk, _VARGROUPS and
_{USER,PKG}_VARS.check-debugdata are defined accordingly.
Similarly to what was done for _FIND_DEBUGGABLEDATA_ERE and
_FIND_DEBUGGABLEDATA_FILELIST_CMD in
bsd.debugdata.mk,
_CHECK_DEBUGDATA_ERE and
_CHECK_DEBUGDATA_FILELIST_CMD
are defined.
In lines
54-103 _check-debugdata target is defined.
_check-debugdata performs the following checks, respectively:
- Check that the program/library is readable.
-
If the program/library is a file format recognizable by
objdump(1)
check if it has a
.gnu_debuglinkELF section. -
Check that the respective
.debugfile of the program/library is readable. -
Print a warning message if the
.debugfile does not contain a.debug_infoELF section.
Other minor changes in mk/*
In order to instruct pkgsrc to pick up bsd.debugdata.mk and
checks/check-debugdata.mk, nothing intrusive though:
-
Add
.include "bsd.debugdata.mk"inbsd.pkg.mk. -
Add
TOOLS_PLATFORM.objcopyandTOOLS_PLATFORM.objdumptomk/tools/tools.NetBSD.mk(otherOPSYSs will also needed to be adjusted similarly) -
Add
CHECK_DEBUGDATA_SUPPORTEDtocheck/bsd.check-vars.mk. -
Add
.include "check-debugdata.mk"incheck/bsd.check.mk.
Conclusion
In this blog post we have learned what PKG_DEBUGDATA does via a
practical example.
Then we have examinated how bsd.debugdata.mk and
checks/check-debugdata.mk are implemented.
PKG_DEBUGDATA is completely agnostic if a package uses
GNU configure, cmake, etc., and it is expected to work without any changes.
I have only tested it with simple packages also containing libraries and the
ones that uses libtool but I have still not tested it in the wild and some minor
adjustements can be probably needed.
Thanks again to Google for organizing Google Summer of Code, The NetBSD Foundation and in particular my mentors David Maxwell, Jöerg Sonnenberger, Taylor R. Campbell, Thomas Klausner and William J. Coldwell.
References
- The pkgsrc guide, Alistair Crooks, Hubert Feyrer, The pkgsrc Developers
-
PMake -- A Tutorial, Adam de Boor
(available under
/usr/share/doc/ref1/make/in PS and text format) - make(1)
- objdump(1)
- objcopy(1)
- gdb(1)
- pkgsrc/mk/misc/show.mk, 1.12
- pkgsrc/mk/plist/plist.mk, 1.49
- pkgsrc/mk/bsd.pkg.mk, 1.2021
- pkgsrc/mk/check/bsd.check-vars.mk 1.8
- pkgsrc/mk/check/bsd.check.mk 1.8
![[NetBSD Logo]](/tnf/resource/NetBSD-headerlogo.png)