Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(232)

Side by Side Diff: tools/valgrind/memcheck_analyze.py

Issue 211023: GDB wrapper refactoring for memcheck_analyze.py... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 11 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « tools/valgrind/gdb_helper.py ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #!/usr/bin/python 1 #!/usr/bin/python
2 # Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. 2 # Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be 3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file. 4 # found in the LICENSE file.
5 5
6 # memcheck_analyze.py 6 # memcheck_analyze.py
7 7
8 ''' Given a valgrind XML file, parses errors and uniques them.''' 8 ''' Given a valgrind XML file, parses errors and uniques them.'''
9 9
10 import gdb_helper
11
10 import logging 12 import logging
11 import optparse 13 import optparse
12 import os 14 import os
13 import re
14 import subprocess 15 import subprocess
15 import sys 16 import sys
16 import tempfile
17 import time 17 import time
18 from xml.dom.minidom import parse 18 from xml.dom.minidom import parse
19 from xml.parsers.expat import ExpatError 19 from xml.parsers.expat import ExpatError
20 20
21 # Global symbol table (yuck) 21 # Global symbol table (yuck)
22 TheAddressTable = None 22 TheAddressTable = None
23 23
24 GDB_LINE_RE = re.compile(r'Line ([0-9]*) of "([^"]*)".*')
25
26 def _GdbOutputToFileLine(output_line):
27 ''' Parse the gdb output line, return a pair (file, line num) '''
28 match = GDB_LINE_RE.match(output_line)
29 if match:
30 return match.groups()[1], match.groups()[0]
31 else:
32 return None
33
34 def ResolveAddressesWithinABinary(binary_name, load_address, address_list):
35 ''' For each address, return a pair (file, line num) '''
36 commands = tempfile.NamedTemporaryFile()
37 commands.write('add-symbol-file "%s" %s\n' % (binary_name, load_address))
38 for addr in address_list:
39 commands.write('info line *%s\n' % addr)
40 commands.write('quit\n')
41 commands.flush()
42 gdb_commandline = 'gdb -batch -x %s 2>/dev/null' % commands.name
43 gdb_pipe = os.popen(gdb_commandline)
44 result = gdb_pipe.readlines()
45
46 address_count = 0
47 ret = {}
48 for line in result:
49 if line.startswith('Line'):
50 ret[address_list[address_count]] = _GdbOutputToFileLine(line)
51 address_count += 1
52 if line.startswith('No line'):
53 ret[address_list[address_count]] = (None, None)
54 address_count += 1
55 gdb_pipe.close()
56 commands.close()
57 return ret
58
59 class _AddressTable(object):
60 ''' Object to do batched line number lookup. '''
61 def __init__(self):
62 self._load_addresses = {}
63 self._binaries = {}
64 self._all_resolved = False
65
66 def AddBinaryAt(self, binary, load_address):
67 ''' Register a new shared library or executable. '''
68 self._load_addresses[binary] = load_address
69
70 def Add(self, binary, address):
71 ''' Register a lookup request. '''
72 if binary == '':
73 logging.warn('adding address %s in empty binary?' % address)
74 if binary in self._binaries:
75 self._binaries[binary].append(address)
76 else:
77 self._binaries[binary] = [address]
78 self._all_resolved = False
79
80 def ResolveAll(self):
81 ''' Carry out all lookup requests. '''
82 self._translation = {}
83 for binary in self._binaries.keys():
84 if binary != '' and binary in self._load_addresses:
85 load_address = self._load_addresses[binary]
86 addr = ResolveAddressesWithinABinary(binary, load_address, self._binarie s[binary])
87 self._translation[binary] = addr
88 self._all_resolved = True
89
90 def GetFileLine(self, binary, addr):
91 ''' Get the (filename, linenum) result of a previously-registered lookup req uest. '''
92 if self._all_resolved:
93 if binary in self._translation:
94 if addr in self._translation[binary]:
95 return self._translation[binary][addr]
96 return (None, None)
97 24
98 # These are functions (using C++ mangled names) that we look for in stack 25 # These are functions (using C++ mangled names) that we look for in stack
99 # traces. We don't show stack frames while pretty printing when they are below 26 # traces. We don't show stack frames while pretty printing when they are below
100 # any of the following: 27 # any of the following:
101 _TOP_OF_STACK_POINTS = [ 28 _TOP_OF_STACK_POINTS = [
102 # Don't show our testing framework. 29 # Don't show our testing framework.
103 "testing::Test::Run()", 30 "testing::Test::Run()",
104 # Also don't show the internals of libc/pthread. 31 # Also don't show the internals of libc/pthread.
105 "start_thread" 32 "start_thread"
106 ] 33 ]
(...skipping 280 matching lines...) Expand 10 before | Expand all | Expand 10 after
387 # Collect these and print them at the end. 314 # Collect these and print them at the end.
388 # 315 #
389 # With our patch for https://bugs.kde.org/show_bug.cgi?id=205000 in, 316 # With our patch for https://bugs.kde.org/show_bug.cgi?id=205000 in,
390 # the file also includes records of the form 317 # the file also includes records of the form
391 # <load_obj><obj>/usr/lib/libgcc_s.1.dylib</obj><ip>0x27000</ip></load_obj> 318 # <load_obj><obj>/usr/lib/libgcc_s.1.dylib</obj><ip>0x27000</ip></load_obj>
392 # giving the filename and load address of each binary that was mapped 319 # giving the filename and load address of each binary that was mapped
393 # into the process. 320 # into the process.
394 321
395 global TheAddressTable 322 global TheAddressTable
396 if use_gdb: 323 if use_gdb:
397 TheAddressTable = _AddressTable() 324 TheAddressTable = gdb_helper.AddressTable()
398 self._errors = set() 325 self._errors = set()
399 self._suppcounts = {} 326 self._suppcounts = {}
400 badfiles = set() 327 badfiles = set()
401 start = time.time() 328 start = time.time()
402 self._parse_failed = False 329 self._parse_failed = False
403 for file in files: 330 for file in files:
404 # Wait up to three minutes for valgrind to finish writing all files, 331 # Wait up to three minutes for valgrind to finish writing all files,
405 # but after that, just skip incomplete files and warn. 332 # but after that, just skip incomplete files and warn.
406 f = open(file, "r+") 333 f = open(file, "r+")
407 found = False 334 found = False
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
521 parser.error("no filename specified") 448 parser.error("no filename specified")
522 filenames = args 449 filenames = args
523 450
524 analyzer = MemcheckAnalyze(options.source_dir, filenames, use_gdb=True) 451 analyzer = MemcheckAnalyze(options.source_dir, filenames, use_gdb=True)
525 retcode = analyzer.Report() 452 retcode = analyzer.Report()
526 453
527 sys.exit(retcode) 454 sys.exit(retcode)
528 455
529 if __name__ == "__main__": 456 if __name__ == "__main__":
530 _main() 457 _main()
OLDNEW
« no previous file with comments | « tools/valgrind/gdb_helper.py ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698