Index: tools/valgrind/valgrind_test.py |
=================================================================== |
--- tools/valgrind/valgrind_test.py (revision 12673) |
+++ tools/valgrind/valgrind_test.py (working copy) |
@@ -14,6 +14,7 @@ |
import logging |
import optparse |
import os |
+import re |
import shutil |
import stat |
import sys |
@@ -100,6 +101,10 @@ |
def Setup(self): |
return self.ParseArgv() |
+ def PrepareForTest(self): |
+ """Perform necessary tasks prior to executing the test.""" |
+ pass |
+ |
def ValgrindCommand(self): |
"""Get the valgrind command to run.""" |
raise RuntimeError, "Never use Valgrind directly. Always subclass and " \ |
@@ -136,6 +141,8 @@ |
return True |
def RunTestsAndAnalyze(self): |
+ self.PrepareForTest() |
+ |
self.Execute() |
if self._generate_suppressions: |
logging.info("Skipping analysis to let you look at the raw output...") |
@@ -240,6 +247,62 @@ |
def __init__(self): |
Valgrind.__init__(self) |
+ def PrepareForTest(self): |
+ """Runs dsymutil if needed. |
+ |
+ Valgrind for Mac OS X requires that debugging information be in a .dSYM |
+ bundle generated by dsymutil. It is not currently able to chase DWARF |
+ data into .o files like gdb does, so executables without .dSYM bundles or |
+ with the Chromium-specific "fake_dsym" bundles generated by |
+ build/mac/strip_save_dsym won't give source file and line number |
+ information in valgrind. |
+ |
+ This function will run dsymutil if the .dSYM bundle is missing or if |
+ it looks like a fake_dsym. A non-fake dsym that already exists is assumed |
+ to be up-to-date. |
+ """ |
+ |
+ test_command = self._args[0] |
+ dsym_bundle = self._args[0] + '.dSYM' |
+ dsym_file = os.path.join(dsym_bundle, 'Contents', 'Resources', 'DWARF', |
+ os.path.basename(test_command)) |
+ dsym_info_plist = os.path.join(dsym_bundle, 'Contents', 'Info.plist') |
+ |
+ needs_dsymutil = True |
+ saved_test_command = None |
+ |
+ if os.path.exists(dsym_file) and os.path.exists(dsym_info_plist): |
+ # Look for the special fake_dsym tag in dsym_info_plist. |
+ dsym_info_plist_contents = open(dsym_info_plist).read() |
+ |
+ if not re.search('^\s*<key>fake_dsym</key>$', dsym_info_plist_contents, |
+ re.MULTILINE): |
+ # fake_dsym is not set, this is a real .dSYM bundle produced by |
+ # dsymutil. dsymutil does not need to be run again. |
+ needs_dsymutil = False |
+ else: |
+ # fake_dsym is set. dsym_file is a copy of the original test_command |
+ # before it was stripped. Copy it back to test_command so that |
+ # dsymutil has unstripped input to work with. Move the stripped |
+ # test_command out of the way, it will be restored when this is |
+ # done. |
+ saved_test_command = test_command + '.stripped' |
+ os.rename(test_command, saved_test_command) |
+ shutil.copyfile(dsym_file, test_command) |
+ |
+ if needs_dsymutil: |
+ # Remove the .dSYM bundle if it exists. |
+ shutil.rmtree(dsym_bundle, True) |
+ |
+ dsymutil_command = ['dsymutil', test_command] |
+ |
+ # dsymutil is crazy slow. Let it run for up to a half hour. I hope |
+ # that's enough. |
+ common.RunSubprocess(dsymutil_command, 30 * 60) |
+ |
+ if saved_test_command: |
+ os.rename(saved_test_command, test_command) |
TVL
2009/03/27 20:04:31
do you want an exception handler on any of this to
|
+ |
def ValgrindCommand(self): |
"""Get the valgrind command to run.""" |
proc = ["valgrind", "--smc-check=all", "--leak-check=full", |