home *** CD-ROM | disk | FTP | other *** search
- #!/usr/bin/python
-
- # Use the coredump in a crash report to regenerate the stack traces. This is
- # helpful to get a trace with debug symbols.
- #
- # Copyright (c) 2006 Canonical Ltd.
- # Author: Martin Pitt <martin.pitt@ubuntu.com>
- #
- # This program is free software; you can redistribute it and/or modify it
- # under the terms of the GNU General Public License as published by the
- # Free Software Foundation; either version 2 of the License, or (at your
- # option) any later version. See http://www.gnu.org/copyleft/gpl.html for
- # the full text of the license.
-
- import sys, os, os.path, subprocess, optparse
- import tempfile, shutil
- import problem_report
-
- # parse options
- optparser = optparse.OptionParser('%prog [options] <apport problem report>')
- optparser.add_option('-c', '--remove-core',
- help='Remove the core dump from the report after stack trace regeneration',
- action="store_true", dest="removecore", default=False)
- optparser.add_option('-s', '--stdout',
- help='Do not put the new traces into the report, but write them to stdout.',
- action="store_true", dest="stdout", default=False)
- optparser.add_option('-o', '--output',
- help='Write modified report to given file instead of changing the original report',
- action="store", type="string", dest="output", metavar="FILE", default=None)
- (options, args) = optparser.parse_args()
-
- if len(args) != 1:
- optparser.error("incorrect number of arguments; use --help for a short online help")
- sys.exit(1)
- reportfile = args[0]
-
- # load the report
- report = problem_report.ProblemReport()
- report.load(open(reportfile))
-
- # sanity checks
- if not report.has_key('CoreDump'):
- print >> sys.stderr, 'report file does not contain a core dump'
- sys.exit(1)
-
- package = report['Package'].split()[0]
- if subprocess.call(['dpkg', '-s', package], stdout=subprocess.PIPE, stderr=subprocess.PIPE) != 0:
- print >> sys.stderr, 'crash is in package %s which is not installed' % package
- sys.exit(1)
-
- assert os.path.exists(report['ExecutablePath'])
-
- # write core dump into temporary file
- (fd, coredumppath) = tempfile.mkstemp()
- os.write(fd, report['CoreDump'])
- os.close(fd)
-
- # call gdb to get new stack traces
- gdb = subprocess.Popen(['gdb', '--batch', '--ex', 'bt full',
- report['ExecutablePath'], coredumppath], stdout=subprocess.PIPE,
- stderr=subprocess.PIPE)
- bt = gdb.communicate()[0].replace('\n\n', '\n.\n').strip()
- gdb2 = subprocess.Popen(['gdb', '--batch', '--ex', 'thread apply all bt full',
- report['ExecutablePath'], coredumppath], stdout=subprocess.PIPE,
- stderr=subprocess.PIPE)
- threadbt = gdb2.communicate()[0].replace('\n\n', '\n.\n').strip()
- os.unlink(coredumppath)
- assert gdb.returncode == 0
- assert gdb2.returncode == 0
-
- modified = False
-
- if options.removecore:
- report['CoreDump'] = 'removed'
- modified = True
-
- if options.stdout:
- print '--- stack trace ---'
- print bt
- print '--- thread stack trace ---'
- print threadbt
- else:
- report['Stacktrace'] = bt
- report['ThreadStacktrace'] = threadbt
- modified = True
-
- if modified:
- if options.output == None:
- out = open(reportfile, 'w')
- elif options.output == '-':
- out = sys.stdout
- else:
- out = open(options.output, 'w')
-
- report.write(out)
-