summaryrefslogtreecommitdiffstats
path: root/tools/valgrind/valgrind_analyze.py
diff options
context:
space:
mode:
authordkegel@google.com <dkegel@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2009-03-27 17:53:14 +0000
committerdkegel@google.com <dkegel@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2009-03-27 17:53:14 +0000
commit44e780297e2c5ba8705c3c6c8d9ca5ea392c3a4c (patch)
tree180b368bdfc737458fb1d94ed7beb101413f5ff0 /tools/valgrind/valgrind_analyze.py
parent18305dec20e5e99a7e36aaf0d624edc3cbccdab8 (diff)
downloadchromium_src-44e780297e2c5ba8705c3c6c8d9ca5ea392c3a4c.zip
chromium_src-44e780297e2c5ba8705c3c6c8d9ca5ea392c3a4c.tar.gz
chromium_src-44e780297e2c5ba8705c3c6c8d9ca5ea392c3a4c.tar.bz2
Support --track_origins option.
Review URL: http://codereview.chromium.org/53119 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@12667 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'tools/valgrind/valgrind_analyze.py')
-rwxr-xr-xtools/valgrind/valgrind_analyze.py126
1 files changed, 88 insertions, 38 deletions
diff --git a/tools/valgrind/valgrind_analyze.py b/tools/valgrind/valgrind_analyze.py
index 0a08306..4260fcd 100755
--- a/tools/valgrind/valgrind_analyze.py
+++ b/tools/valgrind/valgrind_analyze.py
@@ -53,6 +53,23 @@ SRC_FILE_DIR = "dir"
SRC_FILE_NAME = "file"
SRC_LINE = "line"
+def gatherFrames(node, source_dir):
+ frames = []
+ for frame in node.getElementsByTagName("frame"):
+ frame_dict = {
+ INSTRUCTION_POINTER : getTextOf(frame, INSTRUCTION_POINTER),
+ OBJECT_FILE : getTextOf(frame, OBJECT_FILE),
+ FUNCTION_NAME : getTextOf(frame, FUNCTION_NAME),
+ SRC_FILE_DIR : removeCommonRoot(
+ source_dir, getTextOf(frame, SRC_FILE_DIR)),
+ SRC_FILE_NAME : getTextOf(frame, SRC_FILE_NAME),
+ SRC_LINE : getTextOf(frame, SRC_LINE)
+ }
+ frames += [frame_dict]
+ if frame_dict[FUNCTION_NAME] in _TOP_OF_STACK_POINTS:
+ break
+ return frames
+
class ValgrindError:
''' Takes a <DOM Element: error> node and reads all the data from it. A
ValgrindError is immutable and is hashed on its pretty printed output.
@@ -67,41 +84,73 @@ class ValgrindError:
source_dir: Prefix that should be stripped from the <dir> node.
'''
- self._kind = getTextOf(error_node, "kind")
- self._what = getTextOf(error_node, "what")
-
- self._frames = []
- stack_node = error_node.getElementsByTagName("stack")[0]
-
- for frame in stack_node.getElementsByTagName("frame"):
- frame_dict = {
- INSTRUCTION_POINTER : getTextOf(frame, INSTRUCTION_POINTER),
- OBJECT_FILE : getTextOf(frame, OBJECT_FILE),
- FUNCTION_NAME : getTextOf(frame, FUNCTION_NAME),
- SRC_FILE_DIR : removeCommonRoot(
- source_dir, getTextOf(frame, SRC_FILE_DIR)),
- SRC_FILE_NAME : getTextOf(frame, SRC_FILE_NAME),
- SRC_LINE : getTextOf(frame, SRC_LINE)
- }
+ # Valgrind errors contain one <what><stack> pair, plus an optional
+ # <auxwhat><stack> pair, plus an optional <origin><what><stack></origin>.
+ # (Origin is nicely enclosed; too bad the other two aren't.)
+ # The most common way to see all three in one report is
+ # a syscall with a parameter that points to uninitialized memory, e.g.
+ # Format:
+ # <error>
+ # <unique>0x6d</unique>
+ # <tid>1</tid>
+ # <kind>SyscallParam</kind>
+ # <what>Syscall param write(buf) points to uninitialised byte(s)</what>
+ # <stack>
+ # <frame>
+ # ...
+ # </frame>
+ # </stack>
+ # <auxwhat>Address 0x5c9af4f is 7 bytes inside a block of ...</auxwhat>
+ # <stack>
+ # <frame>
+ # ...
+ # </frame>
+ # </stack>
+ # <origin>
+ # <what>Uninitialised value was created by a heap allocation</what>
+ # <stack>
+ # <frame>
+ # ...
+ # </frame>
+ # </stack>
+ # </origin>
- self._frames += [frame_dict]
-
- if frame_dict[FUNCTION_NAME] in _TOP_OF_STACK_POINTS:
- break
+ self._kind = getTextOf(error_node, "kind")
+ self._backtraces = []
+
+ # Iterate through the nodes, parsing <what|auxwhat><stack> pairs.
+ description = None
+ for node in error_node.childNodes:
+ if node.localName == "what" or node.localName == "auxwhat":
+ description = "".join([n.data for n in node.childNodes
+ if n.nodeType == n.TEXT_NODE])
+ elif node.localName == "stack":
+ self._backtraces.append([description, gatherFrames(node, source_dir)])
+ description = None
+ elif node.localName == "origin":
+ description = getTextOf(node, "what")
+ stack = node.getElementsByTagName("stack")[0]
+ frames = gatherFrames(stack, source_dir)
+ self._backtraces.append([description, frames])
+ description = None
+ stack = None
+ frames = None
def __str__(self):
- ''' Pretty print the type and stack frame of this specific error.'''
+ ''' Pretty print the type and backtrace(s) of this specific error.'''
output = self._kind + "\n"
- for frame in self._frames:
- output += (" " + (frame[FUNCTION_NAME] or frame[INSTRUCTION_POINTER]) +
- " (")
-
- if frame[SRC_FILE_DIR] != "":
- output += (frame[SRC_FILE_DIR] + "/" + frame[SRC_FILE_NAME] + ":" +
- frame[SRC_LINE])
- else:
- output += frame[OBJECT_FILE]
- output += ")\n"
+ for backtrace in self._backtraces:
+ output += backtrace[0] + "\n"
+ for frame in backtrace[1]:
+ output += (" " + (frame[FUNCTION_NAME] or frame[INSTRUCTION_POINTER]) +
+ " (")
+
+ if frame[SRC_FILE_DIR] != "":
+ output += (frame[SRC_FILE_DIR] + "/" + frame[SRC_FILE_NAME] + ":" +
+ frame[SRC_LINE])
+ else:
+ output += frame[OBJECT_FILE]
+ output += ")\n"
return output
@@ -109,13 +158,14 @@ class ValgrindError:
''' String to use for object identity. Don't print this, use str(obj)
instead.'''
rep = self._kind + " "
- for frame in self._frames:
- rep += frame[FUNCTION_NAME]
-
- if frame[SRC_FILE_DIR] != "":
- rep += frame[SRC_FILE_DIR] + "/" + frame[SRC_FILE_NAME]
- else:
- rep += frame[OBJECT_FILE]
+ for backtrace in self._backtraces:
+ for frame in backtrace[1]:
+ rep += frame[FUNCTION_NAME]
+
+ if frame[SRC_FILE_DIR] != "":
+ rep += frame[SRC_FILE_DIR] + "/" + frame[SRC_FILE_NAME]
+ else:
+ rep += frame[OBJECT_FILE]
return rep