Author: Antonio Cuni <anto.c...@gmail.com> Branch: Changeset: r92895:77fff565d382 Date: 2017-11-01 10:51 +0100 http://bitbucket.org/pypy/pypy/changeset/77fff565d382/
Log: merge the branch keep-debug-symbols: - symbols are stripped from the executable and placed in a file libpypy-c.so.debug - we add a gnu-debug-link section to libpypy-c.so which points to .debug, so that it works transparently in gdb - this generates immensely more useful stack trace inside gdb; moreover, it is also potentially usable by vmprof - the .debug file is ~18MB. The tarball size goes from 22MB to 25MB. I claim that disk space and bandwidth are cheap, so we should just don't care, especially for nightly builds - if we REALLY care about the tarball size of official releases, we can simply remove the .debug from the tarball diff --git a/pypy/tool/release/package.py b/pypy/tool/release/package.py --- a/pypy/tool/release/package.py +++ b/pypy/tool/release/package.py @@ -21,6 +21,7 @@ import fnmatch import subprocess import glob +from pypy.tool.release.smartstrip import smartstrip if sys.version_info < (2,6): py.test.skip("requires 2.6 so far") @@ -212,15 +213,8 @@ old_dir = os.getcwd() try: os.chdir(str(builddir)) - if not options.nostrip: - for source, target in binaries: - if sys.platform == 'win32': - pass - elif sys.platform == 'darwin': - # 'strip' fun: see issue #587 for why -x - os.system("strip -x " + str(bindir.join(target))) # ignore errors - else: - os.system("strip " + str(bindir.join(target))) # ignore errors + for source, target in binaries: + smartstrip(bindir.join(target), keep_debug=options.keep_debug) # if USE_ZIPFILE_MODULE: import zipfile @@ -281,8 +275,8 @@ help='do not build and package the %r cffi module' % (key,)) parser.add_argument('--without-cffi', dest='no_cffi', action='store_true', help='skip building *all* the cffi modules listed above') - parser.add_argument('--nostrip', dest='nostrip', action='store_true', - help='do not strip the exe, making it ~10MB larger') + parser.add_argument('--no-keep-debug', dest='keep_debug', + action='store_false', help='do not keep debug symbols') parser.add_argument('--rename_pypy_c', dest='pypy_c', type=str, default=pypy_exe, help='target executable name, defaults to "pypy"') parser.add_argument('--archive-name', dest='name', type=str, default='', @@ -295,8 +289,8 @@ help='use as pypy exe instead of pypy/goal/pypy-c') options = parser.parse_args(args) - if os.environ.has_key("PYPY_PACKAGE_NOSTRIP"): - options.nostrip = True + if os.environ.has_key("PYPY_PACKAGE_NOKEEPDEBUG"): + options.keep_debug = False if os.environ.has_key("PYPY_PACKAGE_WITHOUTTK"): options.no_tk = True if not options.builddir: diff --git a/pypy/tool/release/smartstrip.py b/pypy/tool/release/smartstrip.py new file mode 100644 --- /dev/null +++ b/pypy/tool/release/smartstrip.py @@ -0,0 +1,32 @@ +""" +Strip symbols from an executable, but keep them in a .debug file +""" + +import sys +import os +import py + +def _strip(exe): + if sys.platform == 'win32': + pass + elif sys.platform == 'darwin': + # 'strip' fun: see issue #587 for why -x + os.system("strip -x " + str(exe)) # ignore errors + else: + os.system("strip " + str(exe)) # ignore errors + +def _extract_debug_symbols(exe, debug): + if sys.platform == 'linux2': + os.system("objcopy --only-keep-debug %s %s" % (exe, debug)) + os.system("objcopy --add-gnu-debuglink=%s %s" % (debug, exe)) + +def smartstrip(exe, keep_debug=True): + exe = py.path.local(exe) + debug = py.path.local(str(exe) + '.debug') + if keep_debug: + _extract_debug_symbols(exe, debug) + _strip(exe) + + +if __name__ == '__main__': + smartstrip(sys.argv[1]) diff --git a/pypy/tool/release/test/test_smartstrip.py b/pypy/tool/release/test/test_smartstrip.py new file mode 100644 --- /dev/null +++ b/pypy/tool/release/test/test_smartstrip.py @@ -0,0 +1,50 @@ +import pytest +import sys +import os +from commands import getoutput +from pypy.tool.release.smartstrip import smartstrip + +@pytest.fixture +def exe(tmpdir): + src = tmpdir.join("myprog.c") + src.write(""" + int foo(int a, int b) { + return a+b; + } + int main(void) { } + """) + exe = tmpdir.join("myprog") + ret = os.system("gcc -o %s %s" % (exe, src)) + assert ret == 0 + return exe + +def info_symbol(exe, symbol): + out = getoutput("gdb %s -ex 'info symbol %s' -ex 'quit'" % (exe, symbol)) + lines = out.splitlines() + return lines[-1] + +@pytest.mark.skipif(sys.platform == 'win32', + reason='strip not supported on windows') +class TestSmarStrip(object): + + def test_info_symbol(self, exe): + info = info_symbol(exe, "foo") + assert info == "foo in section .text" + + def test_strip(self, exe): + smartstrip(exe, keep_debug=False) + info = info_symbol(exe, "foo") + assert info.startswith("No symbol table is loaded") + + @pytest.mark.skipif(sys.platform != 'linux2', + reason='keep_debug not supported') + def test_keep_debug(self, exe, tmpdir): + smartstrip(exe, keep_debug=True) + debug = tmpdir.join("myprog.debug") + assert debug.check(file=True) + info = info_symbol(exe, "foo") + assert info == "foo in section .text of %s" % exe + # + debug.remove() + info = info_symbol(exe, "foo") + assert info.startswith("No symbol table is loaded") _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit