home *** CD-ROM | disk | FTP | other *** search
/ PC Welt 2006 November (DVD) / PCWELT_11_2006.ISO / casper / filesystem.squashfs / usr / bin / apport-retrace < prev    next >
Encoding:
Text File  |  2006-08-25  |  3.1 KB  |  96 lines

  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)
  96.