1a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#!/usr/bin/env python
2a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)# Copyright 2013 The Chromium Authors. All rights reserved.
3a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)# Use of this source code is governed by a BSD-style license that can be
4a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)# found in the LICENSE file.
5a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
6a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)"""Wrapper around chrome.
7a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
8a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)Replaces all the child processes (renderer, GPU, plugins and utility) with the
9a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)IPC fuzzer. The fuzzer will then play back a specified testcase.
10a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
11a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)Depends on ipc_fuzzer being available on the same directory as chrome.
12a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)"""
13a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)import argparse
15a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)import os
16a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)import platform
17a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)import subprocess
18a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)import sys
19a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
20a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)def main():
215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  desc = 'Wrapper to run chrome with child processes replaced by IPC fuzzers'
225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  parser = argparse.ArgumentParser(description=desc)
235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  parser.add_argument('--out-dir', dest='out_dir', default='out',
245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                      help='output directory under src/ directory')
255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  parser.add_argument('--build-type', dest='build_type', default='Release',
265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                      help='Debug vs. Release build')
275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  parser.add_argument('--gdb-browser', dest='gdb_browser', default=False,
285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                      action='store_true',
295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                      help='run browser process inside gdb')
305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  parser.add_argument('testcase',
315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                      help='IPC file to be replayed')
325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  parser.add_argument('chrome_args',
335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                      nargs=argparse.REMAINDER,
345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                      help='any additional arguments are passed to chrome')
355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  args = parser.parse_args()
36a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
37a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  chrome_binary = 'chrome'
385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  fuzzer_binary = 'ipc_fuzzer_replay'
39a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  script_path = os.path.realpath(__file__)
415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ipc_fuzzer_dir = os.path.dirname(script_path)
425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  src_dir = os.path.abspath(os.path.join(ipc_fuzzer_dir, os.pardir, os.pardir))
435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  out_dir =  os.path.join(src_dir, args.out_dir)
445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  build_dir = os.path.join(out_dir, args.build_type)
45a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  chrome_path = os.path.join(build_dir, chrome_binary)
475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if not os.path.exists(chrome_path):
485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    print 'chrome executable not found at ', chrome_path
49a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return 1
50a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  fuzzer_path = os.path.join(build_dir, fuzzer_binary)
52a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if not os.path.exists(fuzzer_path):
535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    print 'fuzzer executable not found at ', fuzzer_path
545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    print ('ensure GYP_DEFINES="enable_ipc_fuzzer=1" and build target ' +
555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)           fuzzer_binary + '.')
56a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return 1
57a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
58a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  prefixes = {
59a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    '--renderer-cmd-prefix',
60a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    '--gpu-launcher',
61a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    '--plugin-launcher',
62a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    '--ppapi-plugin-launcher',
63a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    '--utility-cmd-prefix',
64a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
65a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  chrome_command = [
67a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    chrome_path,
685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    '--ipc-fuzzer-testcase=' + args.testcase,
69a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    '--no-sandbox',
70a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    '--disable-kill-after-bad-ipc',
71a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  ]
72a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if args.gdb_browser:
745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    chrome_command = ['gdb', '--args'] + chrome_command
755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
76a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  launchers = {}
77a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  for prefix in prefixes:
78a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    launchers[prefix] = fuzzer_path
79a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for arg in args.chrome_args:
81a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    if arg.find('=') != -1:
82a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      switch, value = arg.split('=', 1)
83a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      if switch in prefixes:
84a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        launchers[switch] = value + ' ' + launchers[switch]
85a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        continue
865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    chrome_command.append(arg)
87a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
88a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  for switch, value in launchers.items():
895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    chrome_command.append(switch + '=' + value)
90a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  command_line = ' '.join(['\'' + arg + '\'' for arg in chrome_command])
925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  print 'Executing: ' + command_line
93a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return subprocess.call(chrome_command)
95a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
96a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
97a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)if __name__ == "__main__":
98a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  sys.exit(main())
99