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

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

Issue 16583: Make a valgrind tool in the same vein as the purify one. (Closed)
Patch Set: STOP! Grammar time! Created 11 years, 11 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
« no previous file with comments | « tools/valgrind/suppressions.txt ('k') | tools/valgrind/valgrind_test.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 #!/usr/bin/python
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
4 # found in the LICENSE file.
5
6 # valgrind_analyze.py
7
8 ''' Given a valgrind XML file, parses errors and uniques them.'''
9
10 import logging
11 import optparse
12 import os
13 import sys
14 from xml.dom.minidom import parse
15
16 # These are functions (using C++ mangled names) that we look for in stack
17 # traces. We don't show stack frames while pretty printing when they are below
18 # any of the following:
19 _TOP_OF_STACK_POINTS = [
20 # Don't show our testing framework.
21 "testing::Test::Run()",
22 # Also don't show the internals of libc/pthread.
23 "start_thread"
24 ]
25
26 def getTextOf(top_node, name):
27 ''' Returns all text in all DOM nodes with a certain |name| that are children
28 of |top_node|.
29 '''
30
31 text = ""
32 for nodes_named in top_node.getElementsByTagName(name):
33 text += "".join([node.data for node in nodes_named.childNodes
34 if node.nodeType == node.TEXT_NODE])
35 return text
36
37 def removeCommonRoot(source_dir, directory):
38 '''Returns a string with the string prefix |source_dir| removed from
39 |directory|.'''
40 if source_dir:
41 # Do this for safety, just in case directory is an absolute path outside of
42 # source_dir.
43 prefix = os.path.commonprefix([source_dir, directory])
44 return directory[len(prefix) + 1:]
45
46 return directory
47
48 # Constants that give real names to the abbreviations in valgrind XML output.
49 INSTRUCTION_POINTER = "ip"
50 OBJECT_FILE = "obj"
51 FUNCTION_NAME = "fn"
52 SRC_FILE_DIR = "dir"
53 SRC_FILE_NAME = "file"
54 SRC_LINE = "line"
55
56 class ValgrindError:
57 ''' Takes a <DOM Element: error> node and reads all the data from it. A
58 ValgrindError is immutable and is hashed on its pretty printed output.
59 '''
60
61 def __init__(self, source_dir, error_node):
62 ''' Copies all the relevant information out of the DOM and into object
63 properties.
64
65 Args:
66 error_node: The <error></error> DOM node we're extracting from.
67 source_dir: Prefix that should be stripped from the <dir> node.
68 '''
69
70 self._kind = getTextOf(error_node, "kind")
71 self._what = getTextOf(error_node, "what")
72
73 self._frames = []
74 stack_node = error_node.getElementsByTagName("stack")[0]
75
76 for frame in stack_node.getElementsByTagName("frame"):
77 frame_dict = {
78 INSTRUCTION_POINTER : getTextOf(frame, INSTRUCTION_POINTER),
79 OBJECT_FILE : getTextOf(frame, OBJECT_FILE),
80 FUNCTION_NAME : getTextOf(frame, FUNCTION_NAME),
81 SRC_FILE_DIR : removeCommonRoot(
82 source_dir, getTextOf(frame, SRC_FILE_DIR)),
83 SRC_FILE_NAME : getTextOf(frame, SRC_FILE_NAME),
84 SRC_LINE : getTextOf(frame, SRC_LINE)
85 }
86
87 self._frames += [frame_dict]
88
89 if frame_dict[FUNCTION_NAME] in _TOP_OF_STACK_POINTS:
90 break
91
92 def __str__(self):
93 ''' Pretty print the type and stack frame of this specific error.'''
94 output = self._kind + "\n"
95 for frame in self._frames:
96 output += (" " + (frame[FUNCTION_NAME] or frame[INSTRUCTION_POINTER]) +
97 " (")
98
99 if frame[SRC_FILE_DIR] != "":
100 output += (frame[SRC_FILE_DIR] + "/" + frame[SRC_FILE_DIR] + ":" +
101 frame[SRC_LINE])
102 else:
103 output += frame[OBJECT_FILE]
104 output += ")\n"
105
106 return output
107
108 def UniqueString(self):
109 ''' String to use for object identity. Don't print this, use str(obj)
110 instead.'''
111 rep = self._kind + " "
112 for frame in self._frames:
113 rep += frame[FUNCTION_NAME]
114
115 if frame[SRC_FILE_DIR] != "":
116 rep += frame[SRC_FILE_DIR] + "/" + frame[SRC_FILE_NAME]
117 else:
118 rep += frame[OBJECT_FILE]
119
120 return rep
121
122 def __hash__(self):
123 return hash(self.UniqueString())
124 def __eq__(self, rhs):
125 return self.UniqueString() == rhs
126
127 class ValgrindAnalyze:
128 ''' Given a set of Valgrind XML files, parse all the errors out of them,
129 unique them and output the results.'''
130
131 def __init__(self, source_dir, files):
132 '''Reads in a set of files.
133
134 Args:
135 source_dir: Path to top of source tree for this build
136 files: A list of filenames.
137 '''
138
139 self._errors = set()
140 for file in files:
141 raw_errors = parse(file).getElementsByTagName("error")
142 for raw_error in raw_errors:
143 self._errors.add(ValgrindError(source_dir, raw_error))
144
145 def Report(self):
146 if self._errors:
147 logging.error("FAIL! There were %s errors: " % len(self._errors))
148
149 for error in self._errors:
150 logging.error(error)
151
152 return -1
153
154 logging.info("PASS! No errors found!")
155 return 0
156
157 def _main():
158 '''For testing only. The ValgrindAnalyze class should be imported instead.'''
159 retcode = 0
160 parser = optparse.OptionParser("usage: %prog [options] <files to analyze>")
161 parser.add_option("", "--source_dir",
162 help="path to top of source tree for this build"
163 "(used to normalize source paths in baseline)")
164
165 (options, args) = parser.parse_args()
166 if not len(args) >= 1:
167 parser.error("no filename specified")
168 filenames = args
169
170 analyzer = ValgrindAnalyze(options.source_dir, filenames)
171 retcode = analyzer.Report()
172
173 sys.exit(retcode)
174
175 if __name__ == "__main__":
176 _main()
OLDNEW
« no previous file with comments | « tools/valgrind/suppressions.txt ('k') | tools/valgrind/valgrind_test.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698