15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#!/usr/bin/env python 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Copyright (c) 2011 The Chromium Authors. All rights reserved. 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Use of this source code is governed by a BSD-style license that can be 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# found in the LICENSE file. 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# memcheck_analyze.py 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)''' Given a valgrind XML file, parses errors and uniques them.''' 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import gdb_helper 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)from collections import defaultdict 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import hashlib 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import logging 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import optparse 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import os 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import re 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import subprocess 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import sys 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import time 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)from xml.dom.minidom import parse 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)from xml.parsers.expat import ExpatError 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import common 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Global symbol table (yuck) 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TheAddressTable = None 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# These are regexps that define functions (using C++ mangled names) 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# we don't want to see in stack traces while pretty printing 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# or generating suppressions. 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Just stop printing the stack/suppression frames when the current one 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# matches any of these. 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)_BORING_CALLERS = common.BoringCallers(mangled=True, use_re_wildcards=True) 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def getTextOf(top_node, name): 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ''' Returns all text in all DOM nodes with a certain |name| that are children 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) of |top_node|. 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ''' 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) text = "" 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for nodes_named in top_node.getElementsByTagName(name): 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) text += "".join([node.data for node in nodes_named.childNodes 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if node.nodeType == node.TEXT_NODE]) 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return text 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def getCDATAOf(top_node, name): 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ''' Returns all CDATA in all DOM nodes with a certain |name| that are children 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) of |top_node|. 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ''' 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) text = "" 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for nodes_named in top_node.getElementsByTagName(name): 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) text += "".join([node.data for node in nodes_named.childNodes 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if node.nodeType == node.CDATA_SECTION_NODE]) 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (text == ""): 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return None 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return text 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def shortenFilePath(source_dir, directory): 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) '''Returns a string with the string prefix |source_dir| removed from 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) |directory|.''' 637dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch prefixes_to_cut = ["build/src/", "valgrind/coregrind/", "out/Release/../../"] 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if source_dir: 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) prefixes_to_cut.append(source_dir) 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for p in prefixes_to_cut: 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) index = directory.rfind(p) 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if index != -1: 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) directory = directory[index + len(p):] 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return directory 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Constants that give real names to the abbreviations in valgrind XML output. 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)INSTRUCTION_POINTER = "ip" 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)OBJECT_FILE = "obj" 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)FUNCTION_NAME = "fn" 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SRC_FILE_DIR = "dir" 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SRC_FILE_NAME = "file" 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SRC_LINE = "line" 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def gatherFrames(node, source_dir): 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) frames = [] 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for frame in node.getElementsByTagName("frame"): 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) frame_dict = { 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) INSTRUCTION_POINTER : getTextOf(frame, INSTRUCTION_POINTER), 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OBJECT_FILE : getTextOf(frame, OBJECT_FILE), 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FUNCTION_NAME : getTextOf(frame, FUNCTION_NAME), 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SRC_FILE_DIR : shortenFilePath( 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) source_dir, getTextOf(frame, SRC_FILE_DIR)), 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SRC_FILE_NAME : getTextOf(frame, SRC_FILE_NAME), 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SRC_LINE : getTextOf(frame, SRC_LINE) 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # Ignore this frame and all the following if it's a "boring" function. 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) enough_frames = False 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for regexp in _BORING_CALLERS: 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if re.match("^%s$" % regexp, frame_dict[FUNCTION_NAME]): 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) enough_frames = True 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if enough_frames: 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) frames += [frame_dict] 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) global TheAddressTable 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if TheAddressTable != None and frame_dict[SRC_LINE] == "": 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # Try using gdb 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TheAddressTable.Add(frame_dict[OBJECT_FILE], 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) frame_dict[INSTRUCTION_POINTER]) 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return frames 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ValgrindError: 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ''' Takes a <DOM Element: error> node and reads all the data from it. A 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ValgrindError is immutable and is hashed on its pretty printed output. 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ''' 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def __init__(self, source_dir, error_node, commandline, testcase): 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ''' Copies all the relevant information out of the DOM and into object 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) properties. 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Args: 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_node: The <error></error> DOM node we're extracting from. 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) source_dir: Prefix that should be stripped from the <dir> node. 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) commandline: The command that was run under valgrind 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) testcase: The test case name, if known. 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ''' 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # Valgrind errors contain one <what><stack> pair, plus an optional 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # <auxwhat><stack> pair, plus an optional <origin><what><stack></origin>, 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # plus (since 3.5.0) a <suppression></suppression> pair. 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # (Origin is nicely enclosed; too bad the other two aren't.) 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # The most common way to see all three in one report is 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # a syscall with a parameter that points to uninitialized memory, e.g. 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # Format: 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # <error> 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # <unique>0x6d</unique> 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # <tid>1</tid> 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # <kind>SyscallParam</kind> 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # <what>Syscall param write(buf) points to uninitialised byte(s)</what> 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # <stack> 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # <frame> 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # ... 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # </frame> 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # </stack> 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # <auxwhat>Address 0x5c9af4f is 7 bytes inside a block of ...</auxwhat> 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # <stack> 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # <frame> 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # ... 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # </frame> 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # </stack> 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # <origin> 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # <what>Uninitialised value was created by a heap allocation</what> 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # <stack> 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # <frame> 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # ... 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # </frame> 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # </stack> 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # </origin> 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # <suppression> 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # <sname>insert_a_suppression_name_here</sname> 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # <skind>Memcheck:Param</skind> 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # <skaux>write(buf)</skaux> 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # <sframe> <fun>__write_nocancel</fun> </sframe> 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # ... 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # <sframe> <fun>main</fun> </sframe> 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # <rawtext> 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # <![CDATA[ 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # { 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # <insert_a_suppression_name_here> 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # Memcheck:Param 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # write(buf) 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # fun:__write_nocancel 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # ... 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # fun:main 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # } 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # ]]> 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # </rawtext> 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # </suppression> 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # </error> 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # Each frame looks like this: 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # <frame> 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # <ip>0x83751BC</ip> 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # <obj>/data/dkegel/chrome-build/src/out/Release/base_unittests</obj> 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # <fn>_ZN7testing8internal12TestInfoImpl7RunTestEPNS_8TestInfoE</fn> 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # <dir>/data/dkegel/chrome-build/src/testing/gtest/src</dir> 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # <file>gtest-internal-inl.h</file> 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # <line>655</line> 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # </frame> 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # although the dir, file, and line elements are missing if there is 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # no debug info. 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self._kind = getTextOf(error_node, "kind") 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self._backtraces = [] 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self._suppression = None 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self._commandline = commandline 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self._testcase = testcase 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self._additional = [] 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # Iterate through the nodes, parsing <what|auxwhat><stack> pairs. 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) description = None 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for node in error_node.childNodes: 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if node.localName == "what" or node.localName == "auxwhat": 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) description = "".join([n.data for n in node.childNodes 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if n.nodeType == n.TEXT_NODE]) 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) elif node.localName == "xwhat": 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) description = getTextOf(node, "text") 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) elif node.localName == "stack": 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert description 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self._backtraces.append([description, gatherFrames(node, source_dir)]) 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) description = None 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) elif node.localName == "origin": 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) description = getTextOf(node, "what") 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stack = node.getElementsByTagName("stack")[0] 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) frames = gatherFrames(stack, source_dir) 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self._backtraces.append([description, frames]) 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) description = None 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stack = None 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) frames = None 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) elif description and node.localName != None: 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # The lastest description has no stack, e.g. "Address 0x28 is unknown" 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self._additional.append(description) 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) description = None 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if node.localName == "suppression": 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self._suppression = getCDATAOf(node, "rawtext"); 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def __str__(self): 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ''' Pretty print the type and backtrace(s) of this specific error, 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) including suppression (which is just a mangled backtrace).''' 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) output = "" 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (self._commandline): 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) output += self._commandline + "\n" 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) output += self._kind + "\n" 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for backtrace in self._backtraces: 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) output += backtrace[0] + "\n" 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) filter = subprocess.Popen("c++filt -n", stdin=subprocess.PIPE, 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stdout=subprocess.PIPE, 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stderr=subprocess.STDOUT, 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shell=True, 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) close_fds=True) 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buf = "" 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for frame in backtrace[1]: 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buf += (frame[FUNCTION_NAME] or frame[INSTRUCTION_POINTER]) + "\n" 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (stdoutbuf, stderrbuf) = filter.communicate(buf.encode('latin-1')) 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) demangled_names = stdoutbuf.split("\n") 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i = 0 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for frame in backtrace[1]: 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) output += (" " + demangled_names[i]) 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i = i + 1 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) global TheAddressTable 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if TheAddressTable != None and frame[SRC_FILE_DIR] == "": 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # Try using gdb 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) foo = TheAddressTable.GetFileLine(frame[OBJECT_FILE], 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) frame[INSTRUCTION_POINTER]) 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if foo[0] != None: 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) output += (" (" + foo[0] + ":" + foo[1] + ")") 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) elif frame[SRC_FILE_DIR] != "": 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) output += (" (" + frame[SRC_FILE_DIR] + "/" + frame[SRC_FILE_NAME] + 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ":" + frame[SRC_LINE] + ")") 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else: 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) output += " (" + frame[OBJECT_FILE] + ")" 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) output += "\n" 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for additional in self._additional: 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) output += additional + "\n" 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert self._suppression != None, "Your Valgrind doesn't generate " \ 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "suppressions - is it too old?" 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if self._testcase: 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) output += "The report came from the `%s` test.\n" % self._testcase 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) output += "Suppression (error hash=#%016X#):\n" % self.ErrorHash() 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) output += (" For more info on using suppressions see " 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "http://dev.chromium.org/developers/tree-sheriffs/sheriff-details-chromium/memory-sheriff#TOC-Suppressing-memory-reports") 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # Widen suppression slightly to make portable between mac and linux 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # TODO(timurrrr): Oops, these transformations should happen 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # BEFORE calculating the hash! 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) supp = self._suppression; 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) supp = supp.replace("fun:_Znwj", "fun:_Znw*") 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) supp = supp.replace("fun:_Znwm", "fun:_Znw*") 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) supp = supp.replace("fun:_Znaj", "fun:_Zna*") 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) supp = supp.replace("fun:_Znam", "fun:_Zna*") 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # Make suppressions even less platform-dependent. 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for sz in [1, 2, 4, 8]: 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) supp = supp.replace("Memcheck:Addr%d" % sz, "Memcheck:Unaddressable") 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) supp = supp.replace("Memcheck:Value%d" % sz, "Memcheck:Uninitialized") 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) supp = supp.replace("Memcheck:Cond", "Memcheck:Uninitialized") 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # Split into lines so we can enforce length limits 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) supplines = supp.split("\n") 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) supp = None # to avoid re-use 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # Truncate at line 26 (VG_MAX_SUPP_CALLERS plus 2 for name and type) 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # or at the first 'boring' caller. 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # (https://bugs.kde.org/show_bug.cgi?id=199468 proposes raising 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # VG_MAX_SUPP_CALLERS, but we're probably fine with it as is.) 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) newlen = min(26, len(supplines)); 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # Drop boring frames and all the following. 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) enough_frames = False 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for frameno in range(newlen): 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for boring_caller in _BORING_CALLERS: 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if re.match("^ +fun:%s$" % boring_caller, supplines[frameno]): 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) newlen = frameno 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) enough_frames = True 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if enough_frames: 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (len(supplines) > newlen): 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) supplines = supplines[0:newlen] 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) supplines.append("}") 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for frame in range(len(supplines)): 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # Replace the always-changing anonymous namespace prefix with "*". 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) m = re.match("( +fun:)_ZN.*_GLOBAL__N_.*\.cc_" + 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "[0-9a-fA-F]{8}_[0-9a-fA-F]{8}(.*)", 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) supplines[frame]) 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if m: 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) supplines[frame] = "*".join(m.groups()) 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) output += "\n".join(supplines) + "\n" 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return output 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def UniqueString(self): 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ''' String to use for object identity. Don't print this, use str(obj) 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) instead.''' 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rep = self._kind + " " 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for backtrace in self._backtraces: 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for frame in backtrace[1]: 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rep += frame[FUNCTION_NAME] 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if frame[SRC_FILE_DIR] != "": 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rep += frame[SRC_FILE_DIR] + "/" + frame[SRC_FILE_NAME] 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else: 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rep += frame[OBJECT_FILE] 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return rep 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # This is a device-independent hash identifying the suppression. 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # By printing out this hash we can find duplicate reports between tests and 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # different shards running on multiple buildbots 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def ErrorHash(self): 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return int(hashlib.md5(self.UniqueString()).hexdigest()[:16], 16) 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def __hash__(self): 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return hash(self.UniqueString()) 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def __eq__(self, rhs): 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return self.UniqueString() == rhs 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def log_is_finished(f, force_finish): 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) f.seek(0) 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) prev_line = "" 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while True: 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) line = f.readline() 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if line == "": 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if not force_finish: 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return False 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # Okay, the log is not finished but we can make it up to be parseable: 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if prev_line.strip() in ["</error>", "</errorcounts>", "</status>"]: 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) f.write("</valgrindoutput>\n") 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return True 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return False 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if '</valgrindoutput>' in line: 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # Valgrind often has garbage after </valgrindoutput> upon crash. 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) f.truncate() 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return True 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) prev_line = line 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class MemcheckAnalyzer: 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ''' Given a set of Valgrind XML files, parse all the errors out of them, 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unique them and output the results.''' 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SANITY_TEST_SUPPRESSIONS = { 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Memcheck sanity test 01 (memory leak).": 1, 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Memcheck sanity test 02 (malloc/read left).": 1, 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Memcheck sanity test 03 (malloc/read right).": 1, 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Memcheck sanity test 04 (malloc/write left).": 1, 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Memcheck sanity test 05 (malloc/write right).": 1, 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Memcheck sanity test 06 (new/read left).": 1, 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Memcheck sanity test 07 (new/read right).": 1, 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Memcheck sanity test 08 (new/write left).": 1, 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Memcheck sanity test 09 (new/write right).": 1, 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Memcheck sanity test 10 (write after free).": 1, 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Memcheck sanity test 11 (write after delete).": 1, 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Memcheck sanity test 12 (array deleted without []).": 1, 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Memcheck sanity test 13 (single element deleted with []).": 1, 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Memcheck sanity test 14 (malloc/read uninit).": 1, 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Memcheck sanity test 15 (new/read uninit).": 1, 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # Max time to wait for memcheck logs to complete. 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG_COMPLETION_TIMEOUT = 180.0 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def __init__(self, source_dir, show_all_leaks=False, use_gdb=False): 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) '''Create a parser for Memcheck logs. 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Args: 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) source_dir: Path to top of source tree for this build 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) show_all_leaks: Whether to show even less important leaks 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) use_gdb: Whether to use gdb to resolve source filenames and line numbers 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) in the report stacktraces 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ''' 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self._source_dir = source_dir 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self._show_all_leaks = show_all_leaks 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self._use_gdb = use_gdb 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # Contains the set of unique errors 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self._errors = set() 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # Contains the time when the we started analyzing the first log file. 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # This variable is used to skip incomplete logs after some timeout. 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self._analyze_start_time = None 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def Report(self, files, testcase, check_sanity=False): 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) '''Reads in a set of files and prints Memcheck report. 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Args: 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) files: A list of filenames. 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) check_sanity: if true, search for SANITY_TEST_SUPPRESSIONS 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ''' 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # Beyond the detailed errors parsed by ValgrindError above, 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # the xml file contain records describing suppressions that were used: 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # <suppcounts> 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # <pair> 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # <count>28</count> 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # <name>pango_font_leak_todo</name> 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # </pair> 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # <pair> 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # <count>378</count> 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # <name>bug_13243</name> 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # </pair> 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # </suppcounts 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # Collect these and print them at the end. 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # With our patch for https://bugs.kde.org/show_bug.cgi?id=205000 in, 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # the file also includes records of the form 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # <load_obj><obj>/usr/lib/libgcc_s.1.dylib</obj><ip>0x27000</ip></load_obj> 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # giving the filename and load address of each binary that was mapped 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # into the process. 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) global TheAddressTable 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if self._use_gdb: 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TheAddressTable = gdb_helper.AddressTable() 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else: 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TheAddressTable = None 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cur_report_errors = set() 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) suppcounts = defaultdict(int) 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) badfiles = set() 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if self._analyze_start_time == None: 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self._analyze_start_time = time.time() 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) start_time = self._analyze_start_time 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) parse_failed = False 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for file in files: 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # Wait up to three minutes for valgrind to finish writing all files, 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # but after that, just skip incomplete files and warn. 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) f = open(file, "r+") 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pid = re.match(".*\.([0-9]+)$", file) 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if pid: 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pid = pid.groups()[0] 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) found = False 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) running = True 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) firstrun = True 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) skip = False 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) origsize = os.path.getsize(file) 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (running and not found and not skip and 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (firstrun or 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ((time.time() - start_time) < self.LOG_COMPLETION_TIMEOUT))): 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) firstrun = False 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) f.seek(0) 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if pid: 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # Make sure the process is still running so we don't wait for 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # 3 minutes if it was killed. See http://crbug.com/17453 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ps_out = subprocess.Popen("ps p %s" % pid, shell=True, 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stdout=subprocess.PIPE).stdout 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if len(ps_out.readlines()) < 2: 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) running = False 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else: 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) skip = True 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) running = False 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) found = log_is_finished(f, False) 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if not running and not found: 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) logging.warn("Valgrind process PID = %s is not running but its " 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "XML log has not been finished correctly.\n" 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Make it up by adding some closing tags manually." % pid) 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) found = log_is_finished(f, not running) 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if running and not found: 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) time.sleep(1) 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) f.close() 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if not found: 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) badfiles.add(file) 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else: 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) newsize = os.path.getsize(file) 5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if origsize > newsize+1: 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) logging.warn(str(origsize - newsize) + 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) " bytes of junk were after </valgrindoutput> in %s!" % 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) file) 5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) try: 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) parsed_file = parse(file); 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) except ExpatError, e: 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) parse_failed = True 5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) logging.warn("could not parse %s: %s" % (file, e)) 5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) lineno = e.lineno - 1 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) context_lines = 5 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) context_start = max(0, lineno - context_lines) 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) context_end = lineno + context_lines + 1 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) context_file = open(file, "r") 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for i in range(0, context_start): 5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) context_file.readline() 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for i in range(context_start, context_end): 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) context_data = context_file.readline().rstrip() 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if i != lineno: 5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) logging.warn(" %s" % context_data) 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else: 5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) logging.warn("> %s" % context_data) 5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) context_file.close() 5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if TheAddressTable != None: 5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) load_objs = parsed_file.getElementsByTagName("load_obj") 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for load_obj in load_objs: 5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) obj = getTextOf(load_obj, "obj") 5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ip = getTextOf(load_obj, "ip") 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TheAddressTable.AddBinaryAt(obj, ip) 5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) commandline = None 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) preamble = parsed_file.getElementsByTagName("preamble")[0]; 5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for node in preamble.getElementsByTagName("line"): 5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if node.localName == "line": 5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for x in node.childNodes: 5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if x.nodeType == node.TEXT_NODE and "Command" in x.data: 5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) commandline = x.data 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) raw_errors = parsed_file.getElementsByTagName("error") 5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for raw_error in raw_errors: 5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # Ignore "possible" leaks for now by default. 5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (self._show_all_leaks or 5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) getTextOf(raw_error, "kind") != "Leak_PossiblyLost"): 5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error = ValgrindError(self._source_dir, 5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) raw_error, commandline, testcase) 5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if error not in cur_report_errors: 5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # We haven't seen such errors doing this report yet... 5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if error in self._errors: 5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # ... but we saw it in earlier reports, e.g. previous UI test 5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cur_report_errors.add("This error was already printed in " 5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "some other test, see 'hash=#%016X#'" % \ 5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error.ErrorHash()) 5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else: 5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # ... and we haven't seen it in other tests as well 5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self._errors.add(error) 5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cur_report_errors.add(error) 5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) suppcountlist = parsed_file.getElementsByTagName("suppcounts") 5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if len(suppcountlist) > 0: 5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) suppcountlist = suppcountlist[0] 5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for node in suppcountlist.getElementsByTagName("pair"): 5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) count = getTextOf(node, "count"); 5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) name = getTextOf(node, "name"); 5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) suppcounts[name] += int(count) 5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if len(badfiles) > 0: 5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) logging.warn("valgrind didn't finish writing %d files?!" % len(badfiles)) 5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for file in badfiles: 5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) logging.warn("Last 20 lines of %s :" % file) 5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) os.system("tail -n 20 '%s' 1>&2" % file) 5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if parse_failed: 5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) logging.error("FAIL! Couldn't parse Valgrind output file") 5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -2 5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) common.PrintUsedSuppressionsList(suppcounts) 5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) retcode = 0 5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if cur_report_errors: 5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) logging.error("FAIL! There were %s errors: " % len(cur_report_errors)) 5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if TheAddressTable != None: 5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TheAddressTable.ResolveAll() 5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for error in cur_report_errors: 5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) logging.error(error) 5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) retcode = -1 5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # Report tool's insanity even if there were errors. 5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if check_sanity: 5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) remaining_sanity_supp = MemcheckAnalyzer.SANITY_TEST_SUPPRESSIONS 5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (name, count) in suppcounts.iteritems(): 6005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) # Workaround for http://crbug.com/334074 6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (name in remaining_sanity_supp and 6025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) remaining_sanity_supp[name] <= count): 6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) del remaining_sanity_supp[name] 6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if remaining_sanity_supp: 6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) logging.error("FAIL! Sanity check failed!") 6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) logging.info("The following test errors were not handled: ") 6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (name, count) in remaining_sanity_supp.iteritems(): 6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) logging.info(" * %dx %s" % (count, name)) 6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) retcode = -3 6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if retcode != 0: 6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return retcode 6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) logging.info("PASS! No errors found!") 6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0 6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def _main(): 6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) '''For testing only. The MemcheckAnalyzer class should be imported instead.''' 6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) parser = optparse.OptionParser("usage: %prog [options] <files to analyze>") 6214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) parser.add_option("", "--source-dir", 6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) help="path to top of source tree for this build" 6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "(used to normalize source paths in baseline)") 6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (options, args) = parser.parse_args() 6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if len(args) == 0: 6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) parser.error("no filename specified") 6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) filenames = args 6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) analyzer = MemcheckAnalyzer(options.source_dir, use_gdb=True) 6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return analyzer.Report(filenames, None) 6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)if __name__ == "__main__": 6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sys.exit(_main()) 636