aboutsummaryrefslogtreecommitdiffstats
path: root/python/mozdebug/mozdebug.py
diff options
context:
space:
mode:
authorMatthew Rasmus <mattr@zzntd.com>2014-11-23 21:02:37 -0800
committerMatthew Rasmus <mattr@zzntd.com>2014-11-23 23:21:28 -0800
commitf0d5083557f37c695ff4fbdff45ff48833e3f222 (patch)
tree8826f2bbcb0157b16838b5b929d954b1f692339c /python/mozdebug/mozdebug.py
parent4a257bc27152bef98068cfdc1433549aab05c5de (diff)
downloadservo-f0d5083557f37c695ff4fbdff45ff48833e3f222.tar.gz
servo-f0d5083557f37c695ff4fbdff45ff48833e3f222.zip
mozilla-central modules for debugger detection
Borrows two python modules from mozilla-central to give mach the ability to detect and pass arguments to a system's preferred debugger. Links to borrowed files: http://hg.mozilla.org/mozilla-central/file/c9cfa9b91dea/testing/mozbase/mozinfo/mozinfo/mozinfo.py http://hg.mozilla.org/mozilla-central/file/c9cfa9b91dea/testing/mozbase/mozdebug/mozdebug/mozdebug.py
Diffstat (limited to 'python/mozdebug/mozdebug.py')
-rw-r--r--python/mozdebug/mozdebug.py168
1 files changed, 168 insertions, 0 deletions
diff --git a/python/mozdebug/mozdebug.py b/python/mozdebug/mozdebug.py
new file mode 100644
index 00000000000..3f3a54d6be4
--- /dev/null
+++ b/python/mozdebug/mozdebug.py
@@ -0,0 +1,168 @@
+#!/usr/bin/env python
+
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this file,
+# You can obtain one at http://mozilla.org/MPL/2.0/.
+
+import os
+import mozinfo
+from collections import namedtuple
+from distutils.spawn import find_executable
+
+__all__ = ['get_debugger_info',
+ 'get_default_debugger_name',
+ 'DebuggerSearch']
+
+'''
+Map of debugging programs to information about them, like default arguments
+and whether or not they are interactive.
+
+To add support for a new debugger, simply add the relative entry in
+_DEBUGGER_INFO and optionally update the _DEBUGGER_PRIORITIES.
+'''
+_DEBUGGER_INFO = {
+ # gdb requires that you supply the '--args' flag in order to pass arguments
+ # after the executable name to the executable.
+ 'gdb': {
+ 'interactive': True,
+ 'args': ['-q', '--args']
+ },
+
+ 'cgdb': {
+ 'interactive': True,
+ 'args': ['-q', '--args']
+ },
+
+ 'lldb': {
+ 'interactive': True,
+ 'args': ['--'],
+ 'requiresEscapedArgs': True
+ },
+
+ # Visual Studio Debugger Support.
+ 'devenv.exe': {
+ 'interactive': True,
+ 'args': ['-debugexe']
+ },
+
+ # Visual C++ Express Debugger Support.
+ 'wdexpress.exe': {
+ 'interactive': True,
+ 'args': ['-debugexe']
+ },
+
+ # valgrind doesn't explain much about leaks unless you set the
+ # '--leak-check=full' flag. But there are a lot of objects that are
+ # semi-deliberately leaked, so we set '--show-possibly-lost=no' to avoid
+ # uninteresting output from those objects. We set '--smc-check==all-non-file'
+ # and '--vex-iropt-register-updates=allregs-at-mem-access' so that valgrind
+ # deals properly with JIT'd JavaScript code.
+ 'valgrind': {
+ 'interactive': False,
+ 'args': ['--leak-check=full',
+ '--show-possibly-lost=no',
+ '--smc-check=all-non-file',
+ '--vex-iropt-register-updates=allregs-at-mem-access']
+ }
+}
+
+# Maps each OS platform to the preferred debugger programs found in _DEBUGGER_INFO.
+_DEBUGGER_PRIORITIES = {
+ 'win': ['devenv.exe', 'wdexpress.exe'],
+ 'linux': ['gdb', 'cgdb', 'lldb'],
+ 'mac': ['lldb', 'gdb'],
+ 'unknown': ['gdb']
+}
+
+def get_debugger_info(debugger, debuggerArgs = None, debuggerInteractive = False):
+ '''
+ Get the information about the requested debugger.
+
+ Returns a dictionary containing the |path| of the debugger executable,
+ if it will run in |interactive| mode, its arguments and whether it needs
+ to escape arguments it passes to the debugged program (|requiresEscapedArgs|).
+ If the debugger cannot be found in the system, returns |None|.
+
+ :param debugger: The name of the debugger.
+ :param debuggerArgs: If specified, it's the arguments to pass to the debugger,
+ as a string. Any debugger-specific separator arguments are appended after these
+ arguments.
+ :param debuggerInteractive: If specified, forces the debugger to be interactive.
+ '''
+
+ debuggerPath = None
+
+ if debugger:
+ # Append '.exe' to the debugger on Windows if it's not present,
+ # so things like '--debugger=devenv' work.
+ if (os.name == 'nt'
+ and not debugger.lower().endswith('.exe')):
+ debugger += '.exe'
+
+ debuggerPath = find_executable(debugger)
+
+ if not debuggerPath:
+ print 'Error: Could not find debugger %s.' % debugger
+ return None
+
+ debuggerName = os.path.basename(debuggerPath).lower()
+
+ def get_debugger_info(type, default):
+ if debuggerName in _DEBUGGER_INFO and type in _DEBUGGER_INFO[debuggerName]:
+ return _DEBUGGER_INFO[debuggerName][type]
+ return default
+
+ # Define a namedtuple to access the debugger information from the outside world.
+ DebuggerInfo = namedtuple(
+ 'DebuggerInfo',
+ ['path', 'interactive', 'args', 'requiresEscapedArgs']
+ )
+
+ debugger_arguments = []
+
+ if debuggerArgs:
+ # Append the provided debugger arguments at the end of the arguments list.
+ debugger_arguments += debuggerArgs.split()
+
+ debugger_arguments += get_debugger_info('args', [])
+
+ # Override the default debugger interactive mode if needed.
+ debugger_interactive = get_debugger_info('interactive', False)
+ if debuggerInteractive:
+ debugger_interactive = debuggerInteractive
+
+ d = DebuggerInfo(
+ debuggerPath,
+ debugger_interactive,
+ debugger_arguments,
+ get_debugger_info('requiresEscapedArgs', False)
+ )
+
+ return d
+
+# Defines the search policies to use in get_default_debugger_name.
+class DebuggerSearch:
+ OnlyFirst = 1
+ KeepLooking = 2
+
+def get_default_debugger_name(search=DebuggerSearch.OnlyFirst):
+ '''
+ Get the debugger name for the default debugger on current platform.
+
+ :param search: If specified, stops looking for the debugger if the
+ default one is not found (|DebuggerSearch.OnlyFirst|) or keeps
+ looking for other compatible debuggers (|DebuggerSearch.KeepLooking|).
+ '''
+
+ # Find out which debuggers are preferred for use on this platform.
+ debuggerPriorities = _DEBUGGER_PRIORITIES[mozinfo.os if mozinfo.os in _DEBUGGER_PRIORITIES else 'unknown']
+
+ # Finally get the debugger information.
+ for debuggerName in debuggerPriorities:
+ debuggerPath = find_executable(debuggerName)
+ if debuggerPath:
+ return debuggerName
+ elif not search == DebuggerSearch.KeepLooking:
+ return None
+
+ return None