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 MAINTAINER
s, 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*.debug
files and then install them as part of the package. -
PKG_DEBUGLEVEL
: useful to control the granularity of the debug information, i.e. the-g
level 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
PLIST
s 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.debug
is invoked in order to populate the.debug
file. -
If the current file is strippable
objcopy --strip-debug -p -R .gnu_debuglink --add-gnu-debuglink=program.debug|library.debug program|library
is invoked to delete the debug information from the current file (program or library) and to add the.gnu_debuglink
ELF section to it so that the debugger knows where to pick the corresponding.debug
file. -
Append the
.debug
path and filename to the_PLIST_DEBUGDATA
file.
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_debuglink
ELF section. -
Check that the respective
.debug
file of the program/library is readable. -
Print a warning message if the
.debug
file does not contain a.debug_info
ELF 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.objcopy
andTOOLS_PLATFORM.objdump
tomk/tools/tools.NetBSD.mk
(otherOPSYS
s will also needed to be adjusted similarly) -
Add
CHECK_DEBUGDATA_SUPPORTED
tocheck/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