3
# Use the coredump in a crash report to regenerate the stack traces. This is
4
# helpful to get a trace with debug symbols.
6
# Copyright (c) 2006 Canonical Ltd.
7
# Author: Martin Pitt <martin.pitt@ubuntu.com>
9
# This program is free software; you can redistribute it and/or modify it
10
# under the terms of the GNU General Public License as published by the
11
# Free Software Foundation; either version 2 of the License, or (at your
12
# option) any later version. See http://www.gnu.org/copyleft/gpl.html for
13
# the full text of the license.
15
import sys, os, os.path, subprocess, optparse
16
import tempfile, shutil
20
optparser = optparse.OptionParser('%prog [options] <apport problem report>')
21
optparser.add_option('-c', '--remove-core',
22
help='Remove the core dump from the report after stack trace regeneration',
23
action="store_true", dest="removecore", default=False)
24
optparser.add_option('-s', '--stdout',
25
help='Do not put the new traces into the report, but write them to stdout.',
26
action="store_true", dest="stdout", default=False)
27
optparser.add_option('-o', '--output',
28
help='Write modified report to given file instead of changing the original report',
29
action="store", type="string", dest="output", metavar="FILE", default=None)
30
(options, args) = optparser.parse_args()
33
optparser.error("incorrect number of arguments; use --help for a short online help")
38
report = problem_report.ProblemReport()
39
report.load(open(reportfile))
42
if not report.has_key('CoreDump'):
43
print >> sys.stderr, 'report file does not contain a core dump'
46
package = report['Package'].split()[0]
47
if subprocess.call(['dpkg', '-s', package], stdout=subprocess.PIPE, stderr=subprocess.PIPE) != 0:
48
print >> sys.stderr, 'crash is in package %s which is not installed' % package
51
assert os.path.exists(report['ExecutablePath'])
53
# write core dump into temporary file
54
(fd, coredumppath) = tempfile.mkstemp()
55
os.write(fd, report['CoreDump'])
58
# call gdb to get new stack traces
59
gdb = subprocess.Popen(['gdb', '--batch', '--ex', 'bt full',
60
report['ExecutablePath'], coredumppath], stdout=subprocess.PIPE,
61
stderr=subprocess.PIPE)
62
bt = gdb.communicate()[0].replace('\n\n', '\n.\n').strip()
63
gdb2 = subprocess.Popen(['gdb', '--batch', '--ex', 'thread apply all bt full',
64
report['ExecutablePath'], coredumppath], stdout=subprocess.PIPE,
65
stderr=subprocess.PIPE)
66
threadbt = gdb2.communicate()[0].replace('\n\n', '\n.\n').strip()
67
os.unlink(coredumppath)
68
assert gdb.returncode == 0
69
assert gdb2.returncode == 0
73
if options.removecore:
74
report['CoreDump'] = 'removed'
78
print '--- stack trace ---'
80
print '--- thread stack trace ---'
83
report['Stacktrace'] = bt
84
report['ThreadStacktrace'] = threadbt
88
if options.output == None:
89
out = open(reportfile, 'w')
90
elif options.output == '-':
93
out = open(options.output, 'w')