~ubuntu-branches/ubuntu/edgy/apport/edgy

« back to all changes in this revision

Viewing changes to apport-retrace

  • Committer: Package Import Robot
  • Author(s): Martin Pitt
  • Date: 2006-08-11 15:40:05 UTC
  • Revision ID: package-import@ubuntu.com-20060811154005-rk27ie8x0lzfxx28
Tags: 0.10
* apport-gtk: Show report file size in bug report window.
* apport: Correctly handle relative paths to core dumps (use crashed
  process' cwd).
* Fix the GPL URLs in source file's copyright comments.
* debian/apport.cron.daily: Add -mindepth 1 to find commands to avoid
  attempting to remove the /var/crash/ directory. Closes: LP#55107
* problem_report.py:
  - Fix precise whitespace handling in continuation lines, add selftest.
  - Add selftest for reading a report, modifying fields, and writing it
    back.
  - Fix writing back binary data, adapt test suite to check it.
  - Fixed ProblemReport.load() to clean up old data, added selftest.
  - Restructure class to inherit from IterableUserDict and throw away all
    the now obsolete dictionary wrapper methods.
* debian/apport.init: Add colon to description to make output less
  confusing.
* Add apport-retrace and install it into apport: This tool takes a crash
  report and refreshes the stack traces in it. This is particularly useful
  if debug symbols are installed now, but haven't been at the time the crash
  occured.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#!/usr/bin/python
 
2
 
 
3
# Use the coredump in a crash report to regenerate the stack traces. This is
 
4
# helpful to get a trace with debug symbols.
 
5
#
 
6
# Copyright (c) 2006 Canonical Ltd.
 
7
# Author: Martin Pitt <martin.pitt@ubuntu.com>
 
8
#
 
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.
 
14
 
 
15
import sys, os, os.path, subprocess, optparse
 
16
import tempfile, shutil
 
17
import problem_report
 
18
 
 
19
# parse options
 
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()
 
31
 
 
32
if len(args) != 1:
 
33
    optparser.error("incorrect number of arguments; use --help for a short online help")
 
34
    sys.exit(1)
 
35
reportfile = args[0]
 
36
 
 
37
# load the report
 
38
report = problem_report.ProblemReport()
 
39
report.load(open(reportfile))
 
40
 
 
41
# sanity checks
 
42
if not report.has_key('CoreDump'):
 
43
    print >> sys.stderr, 'report file does not contain a core dump'
 
44
    sys.exit(1)
 
45
 
 
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
 
49
    sys.exit(1)
 
50
 
 
51
assert os.path.exists(report['ExecutablePath'])
 
52
 
 
53
# write core dump into temporary file
 
54
(fd, coredumppath) = tempfile.mkstemp()
 
55
os.write(fd, report['CoreDump'])
 
56
os.close(fd)
 
57
 
 
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
 
70
 
 
71
modified = False
 
72
 
 
73
if options.removecore:
 
74
    report['CoreDump'] = 'removed'
 
75
    modified = True
 
76
 
 
77
if options.stdout:
 
78
    print '--- stack trace ---'
 
79
    print bt
 
80
    print '--- thread stack trace ---'
 
81
    print threadbt
 
82
else:
 
83
    report['Stacktrace'] = bt
 
84
    report['ThreadStacktrace'] = threadbt
 
85
    modified = True
 
86
 
 
87
if modified:
 
88
    if options.output == None:
 
89
        out = open(reportfile, 'w')
 
90
    elif options.output == '-':
 
91
        out = sys.stdout
 
92
    else:
 
93
        out = open(options.output, 'w')
 
94
 
 
95
    report.write(out)