Commit 9508c3e7 authored by Henrik Kjellander's avatar Henrik Kjellander Committed by Commit Bot

Fix Valgrind by restoring scripts deleted in Chroium.

Copy Valgrind scripts that was deleted from Chromium's tools/ to fix the Memcheck bot:
    valgrind/chrome_tests.bat
    valgrind/chrome_tests.py
    valgrind/chrome_tests.sh
    valgrind/common.py
    valgrind/gdb_helper.py
    valgrind/locate_valgrind.sh
    valgrind/memcheck_analyze.py
    valgrind/valgrind.gni
    valgrind/valgrind.sh
    valgrind/valgrind_test.py

valgrind_test.py was stripped of its Mac and Dr Memory specific parts, which
we don't use. There's still more cleanup to do, tracked in bugs.webrc.org/7849.

This is similar to changes in https://codereview.webrtc.org/2945753002.

BUG=libyuv:714
NOTRY=True

Change-Id: Ia6ba9bd3d3fca6f2ebe0e4f30e1eb39bb1a66813
Reviewed-on: https://chromium-review.googlesource.com/615162Reviewed-by: 's avatarHenrik Kjellander <kjellander@chromium.org>
Commit-Queue: Henrik Kjellander <kjellander@chromium.org>
parent 9079966f
@echo off
:: Copyright (c) 2011 The Chromium Authors. All rights reserved.
:: Use of this source code is governed by a BSD-style license that can be
:: found in the LICENSE file.
setlocal
set THISDIR=%~dp0
set TOOL_NAME="unknown"
:: Get the tool name and put it into TOOL_NAME {{{1
:: NB: SHIFT command doesn't modify %*
:PARSE_ARGS_LOOP
if %1 == () GOTO:TOOLNAME_NOT_FOUND
if %1 == --tool GOTO:TOOLNAME_FOUND
SHIFT
goto :PARSE_ARGS_LOOP
:TOOLNAME_NOT_FOUND
echo "Please specify a tool (e.g. drmemory) by using --tool flag"
exit /B 1
:TOOLNAME_FOUND
SHIFT
set TOOL_NAME=%1
:: }}}
if "%TOOL_NAME%" == "drmemory" GOTO :SETUP_DRMEMORY
if "%TOOL_NAME%" == "drmemory_light" GOTO :SETUP_DRMEMORY
if "%TOOL_NAME%" == "drmemory_full" GOTO :SETUP_DRMEMORY
if "%TOOL_NAME%" == "drmemory_pattern" GOTO :SETUP_DRMEMORY
echo "Unknown tool: `%TOOL_NAME%`! Only drmemory is supported right now"
exit /B 1
:SETUP_DRMEMORY
:: Set up DRMEMORY_COMMAND to invoke Dr. Memory {{{1
set DRMEMORY_PATH=%THISDIR%..\..\third_party\drmemory
set DRMEMORY_SFX=%DRMEMORY_PATH%\drmemory-windows-sfx.exe
if EXIST %DRMEMORY_SFX% GOTO DRMEMORY_BINARY_OK
echo "Can't find Dr. Memory executables."
echo "See http://www.chromium.org/developers/how-tos/using-valgrind/dr-memory"
echo "for the instructions on how to get them."
exit /B 1
:DRMEMORY_BINARY_OK
%DRMEMORY_SFX% -o%DRMEMORY_PATH%\unpacked -y
set DRMEMORY_COMMAND=%DRMEMORY_PATH%\unpacked\bin\drmemory.exe
:: }}}
goto :RUN_TESTS
:RUN_TESTS
set PYTHONPATH=%THISDIR%../python/google
set RUNNING_ON_VALGRIND=yes
python %THISDIR%/chrome_tests.py %*
This diff is collapsed.
#!/bin/bash
# Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
#
# Use of this source code is governed by a BSD-style license
# that can be found in the LICENSE file in the root of the source
# tree. An additional intellectual property rights grant can be found
# in the file PATENTS. All contributing project authors may
# be found in the AUTHORS file in the root of the source tree.
# Set up some paths and re-direct the arguments to chrome_tests.py
export THISDIR=`dirname $0`
ARGV_COPY="$@"
# We need to set CHROME_VALGRIND iff using Memcheck:
# tools/valgrind/chrome_tests.sh --tool memcheck
# or
# tools/valgrind/chrome_tests.sh --tool=memcheck
tool="memcheck" # Default to memcheck.
while (( "$#" ))
do
if [[ "$1" == "--tool" ]]
then
tool="$2"
shift
elif [[ "$1" =~ --tool=(.*) ]]
then
tool="${BASH_REMATCH[1]}"
fi
shift
done
NEEDS_VALGRIND=0
NEEDS_DRMEMORY=0
case "$tool" in
"memcheck")
NEEDS_VALGRIND=1
;;
"drmemory" | "drmemory_light" | "drmemory_full" | "drmemory_pattern")
NEEDS_DRMEMORY=1
;;
esac
if [ "$NEEDS_VALGRIND" == "1" ]
then
export CHROME_VALGRIND=`sh $THISDIR/locate_valgrind.sh`
if [ "$CHROME_VALGRIND" = "" ]
then
# locate_valgrind.sh failed
exit 1
fi
echo "Using valgrind binaries from ${CHROME_VALGRIND}"
PATH="${CHROME_VALGRIND}/bin:$PATH"
# We need to set these variables to override default lib paths hard-coded into
# Valgrind binary.
export VALGRIND_LIB="$CHROME_VALGRIND/lib/valgrind"
export VALGRIND_LIB_INNER="$CHROME_VALGRIND/lib/valgrind"
# Clean up some /tmp directories that might be stale due to interrupted
# chrome_tests.py execution.
# FYI:
# -mtime +1 <- only print files modified more than 24h ago,
# -print0/-0 are needed to handle possible newlines in the filenames.
echo "Cleanup /tmp from Valgrind stuff"
find /tmp -maxdepth 1 \(\
-name "vgdb-pipe-*" -or -name "vg_logs_*" -or -name "valgrind.*" \
\) -mtime +1 -print0 | xargs -0 rm -rf
fi
if [ "$NEEDS_DRMEMORY" == "1" ]
then
if [ -z "$DRMEMORY_COMMAND" ]
then
DRMEMORY_PATH="$THISDIR/../../third_party/drmemory"
DRMEMORY_SFX="$DRMEMORY_PATH/drmemory-windows-sfx.exe"
if [ ! -f "$DRMEMORY_SFX" ]
then
echo "Can't find Dr. Memory executables."
echo "See http://www.chromium.org/developers/how-tos/using-valgrind/dr-memory"
echo "for the instructions on how to get them."
exit 1
fi
chmod +x "$DRMEMORY_SFX" # Cygwin won't run it without +x.
"$DRMEMORY_SFX" -o"$DRMEMORY_PATH/unpacked" -y
export DRMEMORY_COMMAND="$DRMEMORY_PATH/unpacked/bin/drmemory.exe"
fi
fi
PYTHONPATH=$THISDIR/../python/google python \
"$THISDIR/chrome_tests.py" $ARGV_COPY
# Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
#
# Use of this source code is governed by a BSD-style license
# that can be found in the LICENSE file in the root of the source
# tree. An additional intellectual property rights grant can be found
# in the file PATENTS. All contributing project authors may
# be found in the AUTHORS file in the root of the source tree.
import logging
import platform
import os
import signal
import subprocess
import sys
import time
class NotImplementedError(Exception):
pass
class TimeoutError(Exception):
pass
def RunSubprocessInBackground(proc):
"""Runs a subprocess in the background. Returns a handle to the process."""
logging.info("running %s in the background" % " ".join(proc))
return subprocess.Popen(proc)
def RunSubprocess(proc, timeout=0):
""" Runs a subprocess, until it finishes or |timeout| is exceeded and the
process is killed with taskkill. A |timeout| <= 0 means no timeout.
Args:
proc: list of process components (exe + args)
timeout: how long to wait before killing, <= 0 means wait forever
"""
logging.info("running %s, timeout %d sec" % (" ".join(proc), timeout))
sys.stdout.flush()
sys.stderr.flush()
# Manually read and print out stdout and stderr.
# By default, the subprocess is supposed to inherit these from its parent,
# however when run under buildbot, it seems unable to read data from a
# grandchild process, so we have to read the child and print the data as if
# it came from us for buildbot to read it. We're not sure why this is
# necessary.
# TODO(erikkay): should we buffer stderr and stdout separately?
p = subprocess.Popen(proc, universal_newlines=True,
bufsize=0, # unbuffered
stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
logging.info("started subprocess")
did_timeout = False
if timeout > 0:
wait_until = time.time() + timeout
while p.poll() is None and not did_timeout:
# Have to use readline rather than readlines() or "for line in p.stdout:",
# otherwise we get buffered even with bufsize=0.
line = p.stdout.readline()
while line and not did_timeout:
sys.stdout.write(line)
sys.stdout.flush()
line = p.stdout.readline()
if timeout > 0:
did_timeout = time.time() > wait_until
if did_timeout:
logging.info("process timed out")
else:
logging.info("process ended, did not time out")
if did_timeout:
if IsWindows():
subprocess.call(["taskkill", "/T", "/F", "/PID", str(p.pid)])
else:
# Does this kill all children, too?
os.kill(p.pid, signal.SIGINT)
logging.error("KILLED %d" % p.pid)
# Give the process a chance to actually die before continuing
# so that cleanup can happen safely.
time.sleep(1.0)
logging.error("TIMEOUT waiting for %s" % proc[0])
raise TimeoutError(proc[0])
else:
for line in p.stdout:
sys.stdout.write(line)
if not IsMac(): # stdout flush fails on Mac
logging.info("flushing stdout")
sys.stdout.flush()
logging.info("collecting result code")
result = p.poll()
if result:
logging.error("%s exited with non-zero result code %d" % (proc[0], result))
return result
def IsLinux():
return sys.platform.startswith('linux')
def IsMac():
return sys.platform.startswith('darwin')
def IsWindows():
return sys.platform == 'cygwin' or sys.platform.startswith('win')
def WindowsVersionName():
"""Returns the name of the Windows version if it is known, or None.
Possible return values are: xp, vista, 7, 8, or None
"""
if sys.platform == 'cygwin':
# Windows version number is hiding in system name. Looks like:
# CYGWIN_NT-6.1-WOW64
try:
version_str = platform.uname()[0].split('-')[1]
except:
return None
elif sys.platform.startswith('win'):
# Normal Windows version string. Mine: 6.1.7601
version_str = platform.version()
else:
return None
parts = version_str.split('.')
try:
major = int(parts[0])
minor = int(parts[1])
except:
return None # Can't parse, unknown version.
if major == 5:
return 'xp'
elif major == 6 and minor == 0:
return 'vista'
elif major == 6 and minor == 1:
return '7'
elif major == 6 and minor == 2:
return '8' # Future proof. ;)
return None
def PlatformNames():
"""Return an array of string to be used in paths for the platform
(e.g. suppressions, gtest filters, ignore files etc.)
The first element of the array describes the 'main' platform
"""
if IsLinux():
return ['linux']
if IsMac():
return ['mac']
if IsWindows():
names = ['win32']
version_name = WindowsVersionName()
if version_name is not None:
names.append('win-%s' % version_name)
return names
raise NotImplementedError('Unknown platform "%s".' % sys.platform)
def PutEnvAndLog(env_name, env_value):
os.putenv(env_name, env_value)
logging.info('export %s=%s', env_name, env_value)
def BoringCallers(mangled, use_re_wildcards):
"""Return a list of 'boring' function names (optinally mangled)
with */? wildcards (optionally .*/.).
Boring = we drop off the bottom of stack traces below such functions.
"""
need_mangling = [
# Don't show our testing framework:
("testing::Test::Run", "_ZN7testing4Test3RunEv"),
("testing::TestInfo::Run", "_ZN7testing8TestInfo3RunEv"),
("testing::internal::Handle*ExceptionsInMethodIfSupported*",
"_ZN7testing8internal3?Handle*ExceptionsInMethodIfSupported*"),
# Depend on scheduling:
("MessageLoop::Run", "_ZN11MessageLoop3RunEv"),
("MessageLoop::RunTask", "_ZN11MessageLoop7RunTask*"),
("RunnableMethod*", "_ZN14RunnableMethod*"),
("DispatchToMethod*", "_Z*16DispatchToMethod*"),
("base::internal::Invoker*::DoInvoke*",
"_ZN4base8internal8Invoker*DoInvoke*"), # Invoker{1,2,3}
("base::internal::RunnableAdapter*::Run*",
"_ZN4base8internal15RunnableAdapter*Run*"),
]
ret = []
for pair in need_mangling:
ret.append(pair[1 if mangled else 0])
ret += [
# Also don't show the internals of libc/pthread.
"start_thread",
"main",
"BaseThreadInitThunk",
]
if use_re_wildcards:
for i in range(0, len(ret)):
ret[i] = ret[i].replace('*', '.*').replace('?', '.')
return ret
def NormalizeWindowsPath(path):
"""If we're using Cygwin Python, turn the path into a Windows path.
Don't turn forward slashes into backslashes for easier copy-pasting and
escaping.
TODO(rnk): If we ever want to cut out the subprocess invocation, we can use
_winreg to get the root Cygwin directory from the registry key:
HKEY_LOCAL_MACHINE\SOFTWARE\Cygwin\setup\rootdir.
"""
if sys.platform.startswith("cygwin"):
p = subprocess.Popen(["cygpath", "-m", path],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
(out, err) = p.communicate()
if err:
logging.warning("WARNING: cygpath error: %s", err)
return out.strip()
else:
return path
############################
# Common output format code
def PrintUsedSuppressionsList(suppcounts):
""" Prints out the list of used suppressions in a format common to all the
memory tools. If the list is empty, prints nothing and returns False,
otherwise True.
suppcounts: a dictionary of used suppression counts,
Key -> name, Value -> count.
"""
if not suppcounts:
return False
print "-----------------------------------------------------"
print "Suppressions used:"
print " count name"
for (name, count) in sorted(suppcounts.items(), key=lambda (k,v): (v,k)):
print "%7d %s" % (count, name)
print "-----------------------------------------------------"
sys.stdout.flush()
return True
# Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
#
# Use of this source code is governed by a BSD-style license
# that can be found in the LICENSE file in the root of the source
# tree. An additional intellectual property rights grant can be found
# in the file PATENTS. All contributing project authors may
# be found in the AUTHORS file in the root of the source tree.
''' A bunch of helper functions for querying gdb.'''
import logging
import os
import re
import tempfile
GDB_LINE_RE = re.compile(r'Line ([0-9]*) of "([^"]*)".*')
def _GdbOutputToFileLine(output_line):
''' Parse the gdb output line, return a pair (file, line num) '''
match = GDB_LINE_RE.match(output_line)
if match:
return match.groups()[1], match.groups()[0]
else:
return None
def ResolveAddressesWithinABinary(binary_name, load_address, address_list):
''' For each address, return a pair (file, line num) '''
commands = tempfile.NamedTemporaryFile()
commands.write('add-symbol-file "%s" %s\n' % (binary_name, load_address))
for addr in address_list:
commands.write('info line *%s\n' % addr)
commands.write('quit\n')
commands.flush()
gdb_commandline = 'gdb -batch -x %s 2>/dev/null' % commands.name
gdb_pipe = os.popen(gdb_commandline)
result = gdb_pipe.readlines()
address_count = 0
ret = {}
for line in result:
if line.startswith('Line'):
ret[address_list[address_count]] = _GdbOutputToFileLine(line)
address_count += 1
if line.startswith('No line'):
ret[address_list[address_count]] = (None, None)
address_count += 1
gdb_pipe.close()
commands.close()
return ret
class AddressTable(object):
''' Object to do batched line number lookup. '''
def __init__(self):
self._load_addresses = {}
self._binaries = {}
self._all_resolved = False
def AddBinaryAt(self, binary, load_address):
''' Register a new shared library or executable. '''
self._load_addresses[binary] = load_address
def Add(self, binary, address):
''' Register a lookup request. '''
if binary == '':
logging.warn('adding address %s in empty binary?' % address)
if binary in self._binaries:
self._binaries[binary].append(address)
else:
self._binaries[binary] = [address]
self._all_resolved = False
def ResolveAll(self):
''' Carry out all lookup requests. '''
self._translation = {}
for binary in self._binaries.keys():
if binary != '' and binary in self._load_addresses:
load_address = self._load_addresses[binary]
addr = ResolveAddressesWithinABinary(
binary, load_address, self._binaries[binary])
self._translation[binary] = addr
self._all_resolved = True
def GetFileLine(self, binary, addr):
''' Get the (filename, linenum) result of a previously-registered lookup
request.
'''
if self._all_resolved:
if binary in self._translation:
if addr in self._translation[binary]:
return self._translation[binary][addr]
return (None, None)
......@@ -54,7 +54,7 @@ CHROME_VALGRIND_SCRIPTS=$THISDIR/../../tools/valgrind
if [ "$NEEDS_VALGRIND" == "1" ]
then
CHROME_VALGRIND=`sh $CHROME_VALGRIND_SCRIPTS/locate_valgrind.sh`
CHROME_VALGRIND=`sh $THISDIR/locate_valgrind.sh`
if [ "$CHROME_VALGRIND" = "" ]
then
CHROME_VALGRIND=../../src/third_party/valgrind/linux_x64
......
#!/bin/bash
# Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
#
# Use of this source code is governed by a BSD-style license
# that can be found in the LICENSE file in the root of the source
# tree. An additional intellectual property rights grant can be found
# in the file PATENTS. All contributing project authors may
# be found in the AUTHORS file in the root of the source tree.
# Prints a path to Valgrind binaries to be used for Chromium.
# Select the valgrind from third_party/valgrind by default,
# but allow users to override this default without editing scripts and
# without specifying a commandline option
export THISDIR=`dirname $0`
# User may use their own valgrind by giving its path with CHROME_VALGRIND env.
if [ "$CHROME_VALGRIND" = "" ]
then
# Guess which binaries we should use by uname
case "$(uname -a)" in
*Linux*x86_64*)
PLATFORM="linux_x64"
;;
*Linux*86*)
PLATFORM="linux_x86"
;;
*Darwin*9.[678].[01]*i386*)
# Didn't test other kernels.
PLATFORM="mac"
;;
*Darwin*10.[0-9].[0-9]*i386*)
PLATFORM="mac_10.6"
;;
*Darwin*10.[0-9].[0-9]*x86_64*)
PLATFORM="mac_10.6"
;;
*Darwin*11.[0-9].[0-9]*x86_64*)
PLATFORM="mac_10.7"
;;
*)
(echo "Sorry, your platform is not supported:" &&
uname -a
echo
echo "If you're on Mac OS X, please see http://crbug.com/441425") >&2
exit 42
esac
# The binaries should be in third_party/valgrind
# (checked out from deps/third_party/valgrind/binaries).
CHROME_VALGRIND="$THISDIR/../../third_party/valgrind/$PLATFORM"
# TODO(timurrrr): readlink -f is not present on Mac...
if [ "$PLATFORM" != "mac" ] && \
[ "$PLATFORM" != "mac_10.6" ] && \
[ "$PLATFORM" != "mac_10.7" ]
then
# Get rid of all "../" dirs
CHROME_VALGRIND=$(readlink -f $CHROME_VALGRIND)
fi
fi
if ! test -x $CHROME_VALGRIND/bin/valgrind
then
echo "Oops, could not find Valgrind binaries in your checkout." >&2
echo "Please see" >&2
echo " http://dev.chromium.org/developers/how-tos/using-valgrind/get-valgrind" >&2
echo "for the instructions on how to download pre-built binaries." >&2
exit 1
fi
echo $CHROME_VALGRIND
This diff is collapsed.
#!/bin/bash
# Copyright (c) 2017 The LibYuv Project Authors. All rights reserved.
#
# Use of this source code is governed by a BSD-style license
# that can be found in the LICENSE file in the root of the source
# tree. An additional intellectual property rights grant can be found
# in the file PATENTS. All contributing project authors may
# be found in the AUTHORS file in the root of the source tree.
# This is a small script for manually launching valgrind, along with passing
# it the suppression file, and some helpful arguments (automatically attaching
# the debugger on failures, etc). Run it from your repo root, something like:
# $ sh ./tools/valgrind/valgrind.sh ./out/Debug/chrome
#
# This is mostly intended for running the chrome browser interactively.
# To run unit tests, you probably want to run chrome_tests.sh instead.
# That's the script used by the valgrind buildbot.
export THISDIR=`dirname $0`
setup_memcheck() {
RUN_COMMAND="valgrind"
# Prompt to attach gdb when there was an error detected.
DEFAULT_TOOL_FLAGS=("--db-command=gdb -nw %f %p" "--db-attach=yes" \
# Keep the registers in gdb in sync with the code.
"--vex-iropt-register-updates=allregs-at-mem-access" \
# Overwrite newly allocated or freed objects
# with 0x41 to catch inproper use.
"--malloc-fill=41" "--free-fill=41" \
# Increase the size of stacks being tracked.
"--num-callers=30")
}
setup_unknown() {
echo "Unknown tool \"$TOOL_NAME\" specified, the result is not guaranteed"
DEFAULT_TOOL_FLAGS=()
}
set -e
if [ $# -eq 0 ]; then
echo "usage: <command to run> <arguments ...>"
exit 1
fi
TOOL_NAME="memcheck"
declare -a DEFAULT_TOOL_FLAGS[0]
# Select a tool different from memcheck with --tool=TOOL as a first argument
TMP_STR=`echo $1 | sed 's/^\-\-tool=//'`
if [ "$TMP_STR" != "$1" ]; then
TOOL_NAME="$TMP_STR"
shift
fi
if echo "$@" | grep "\-\-tool" ; then
echo "--tool=TOOL must be the first argument" >&2
exit 1
fi
case $TOOL_NAME in
memcheck*) setup_memcheck "$1";;
*) setup_unknown;;
esac
SUPPRESSIONS="$THISDIR/$TOOL_NAME/suppressions.txt"
CHROME_VALGRIND=`sh $THISDIR/locate_valgrind.sh`
if [ "$CHROME_VALGRIND" = "" ]
then
# locate_valgrind.sh failed
exit 1
fi
echo "Using valgrind binaries from ${CHROME_VALGRIND}"
set -x
PATH="${CHROME_VALGRIND}/bin:$PATH"
# We need to set these variables to override default lib paths hard-coded into
# Valgrind binary.
export VALGRIND_LIB="$CHROME_VALGRIND/lib/valgrind"
export VALGRIND_LIB_INNER="$CHROME_VALGRIND/lib/valgrind"
# G_SLICE=always-malloc: make glib use system malloc
# NSS_DISABLE_UNLOAD=1: make nss skip dlclosing dynamically loaded modules,
# which would result in "obj:*" in backtraces.
# NSS_DISABLE_ARENA_FREE_LIST=1: make nss use system malloc
# G_DEBUG=fatal_warnings: make GTK abort on any critical or warning assertions.
# If it crashes on you in the Options menu, you hit bug 19751,
# comment out the G_DEBUG=fatal_warnings line.
#
# GTEST_DEATH_TEST_USE_FORK=1: make gtest death tests valgrind-friendly
#
# When everyone has the latest valgrind, we might want to add
# --show-possibly-lost=no
# to ignore possible but not definite leaks.
G_SLICE=always-malloc \
NSS_DISABLE_UNLOAD=1 \
NSS_DISABLE_ARENA_FREE_LIST=1 \
G_DEBUG=fatal_warnings \
GTEST_DEATH_TEST_USE_FORK=1 \
$RUN_COMMAND \
--trace-children=yes \
--leak-check=yes \
--suppressions="$SUPPRESSIONS" \
"${DEFAULT_TOOL_FLAGS[@]}" \
"$@"
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment