예제 #1
0
def premain() -> None:
    # If isatty() is false, we might be redirecting to a file (or in another non-interactive context)
    # If we're not being run interactivly, we shouldn't use terminal color codes
    # If inside GDB, isatty() may return false but we stil want colors
    if check_gdb() or (hasattr(sys.stdout, 'isatty') and sys.stdout.isatty()):
        set_color_output(True)

    if check_gdb():
        out_stream, err_stream = gdb_plugin.plugin.output_streams()
    else:
        out_stream = stream.Std(sys.stdout)
        err_stream = stream.Std(sys.stderr)

    main(out_stream, err_stream, sys.argv, input)
예제 #2
0
def parse_args(args):
    '''
    Looks for the special -g and --gdb arguements
    Returns None if not found
    Returns an instance of Args if found, which can be passed to run_gdb()
    Returned Args has the arguments before and after the -g split
    '''

    # debugging infinitaly nested debuggers isn't fun
    if check_gdb():
        return None

    # Look for the -d or --gdb arguments, and split the argument list based on where they are
    for i in range(len(args)):
        if args[i] == '-g' or args[i] == '--gdb':
            return Args(args[:i], args[i + 1:])
        elif len(args[i]) > 2 and args[i][0] == '-' and args[i][1] != '-':
            # look for a g at the end of a list of single char args
            if 'g' in args[i][:-1]:
                raise RuntimeError(
                    repr(args[i]) +
                    ' invalid, -g option must be last in a list of single-character options'
                )
            if args[i][-1] == 'g':
                return Args(args[:i] + [args[i][:-1]], args[i + 1:])

    return None
예제 #3
0
'''
This backend runs wayland-debug as a GDB plugin
This allows detection of multiple Wyland connections and GDB breakpoints on Wayland messages
Note that when running as a GDB plugin, two instances of wayland-debug will be running
- The instance started by the user, which runs GDB (the runner instance)
- The instance insided GDB (the plugin instance)
This module holds logic for both
'''
from core.util import check_gdb

from . import runner

if check_gdb():
    from .plugin import Plugin
    from .plugin import output_streams
else:
    from .runner import run_gdb
예제 #4
0
def main(out_stream: stream.Base, err_stream: stream.Base, argv: List[str],
         input_func: Callable[[str], str]) -> None:
    '''
    Parse arguments and run wayland-debug
    out_stream: An instance of stream.Base to use for output
    err_stream: An instance of stream.Base to use for logging and errors
    argv: A list of str arguments (should include the program name like sys.argv)
    input_func: the input builtin, or a mock function that behaves the same
    '''

    # If we want to run inside GDB, the rest of main does not get called in this instance of the script
    # Instead GDB is run, an instance of wayland-debug is run inside it and main() is run in that
    # gdb_plugin.runner.parse_args() will check if this needs to happen, and gdb_plugin.run_gdb() will do it
    gdb_runner_args = gdb_plugin.runner.parse_args(argv)
    if gdb_runner_args:
        gdb_plugin.run_gdb(gdb_runner_args, False)
        return

    import argparse
    parser = argparse.ArgumentParser(
        description=
        'Debug Wayland protocol messages, see https://github.com/wmww/wayland-debug for additional info'
    )
    parser.add_argument('--matcher-help',
                        action='store_true',
                        help='show how to write matchers and exit')
    parser.add_argument(
        '-v',
        '--verbose',
        action='store_true',
        help='verbose output, mostly used for debugging this program')
    parser.add_argument('-l',
                        '--load',
                        dest='path',
                        type=str,
                        help='load WAYLAND_DEBUG=1 messages from a file')
    parser.add_argument(
        '-p',
        '--pipe',
        action='store_true',
        help=
        'receive WAYLAND_DEBUG=1 messages from stdin (note: messages are printed to stderr so you may want to redirect using 2>&1 before piping)'
    )
    parser.add_argument('-s',
                        '--supress',
                        action='store_true',
                        help='supress non-wayland output of the program')
    parser.add_argument(
        '-c',
        '--color',
        action='store_true',
        help='force color output (default for interactive sessions)')
    parser.add_argument(
        '-C',
        '--no-color',
        action='store_true',
        help='disable color output (default for non-interactive sessions)')
    parser.add_argument(
        '-f',
        '--filter',
        dest='f',
        type=str,
        help='only show these objects/messages (see --matcher-help for syntax)'
    )
    parser.add_argument(
        '-b',
        '--break',
        dest='b',
        type=str,
        help='stop on these objects/messages (see --matcher-help for syntax)')
    parser.add_argument(
        '-g',
        '--gdb',
        action='store_true',
        help=
        'run inside gdb, all subsequent arguments are sent to gdb, when inside gdb start commands with \'wl\''
    )
    # NOTE: -g/--gdb is here only for the help text, it is processed without argparse in gdb_runner.main()

    args = parser.parse_args(
        args=argv[1:])  # chop off the first argument (program name)

    assert not args.gdb, 'GDB argument should have been intercepted by gdb_plugin.runner.parse_args()'

    if args.no_color:
        set_color_output(False)
    elif args.color:
        set_color_output(True)

    verbose = bool(args.verbose)
    unprocessed_output = not bool(args.supress)
    output = Output(verbose, unprocessed_output, out_stream, err_stream)

    if verbose:
        set_verbose(True)
        logger.info('Verbose output enabled')

    if args.no_color:
        if args.color:
            output.warn(
                'Ignoring --color, since --no-color was also specified')
        logger.info('Color output disabled')
    elif args.color:
        # Print message in rainbow colors
        s = ''
        for i, c in enumerate('Color output enabled'):
            s += color('1;' + str(i % 6 + 31), c)
        logger.info(s)

    if unprocessed_output:
        logger.info('Showing unparsable output')

    if args.matcher_help:
        matcher.show_help(output)
        return

    filter_matcher = matcher.always
    if args.f:
        try:
            filter_matcher = matcher.parse(args.f).simplify()
            logger.info('Filter matcher: ' + str(filter_matcher))
        except RuntimeError as e:
            output.error(e)

    stop_matcher = matcher.never
    if args.b:
        try:
            stop_matcher = matcher.parse(args.b).simplify()
            logger.info('Break matcher: ' + str(stop_matcher))
        except RuntimeError as e:
            output.error(e)

    protocol.load_all(output)

    connection_list = ConnectionManager()
    ui_controller = Controller(output, connection_list, filter_matcher,
                               stop_matcher)

    file_path = args.path
    input_from_pipe = args.pipe

    if check_gdb():
        try:
            if file_path is not None or input_from_pipe:
                output.warn(
                    'Ignoring load/pipe argument because we\'re inside GDB')
            gdb_plugin.plugin.Plugin(output, connection_list, ui_controller,
                                     ui_controller)
        except:
            import traceback
            traceback.print_exc()
    elif file_path is not None:
        if input_from_pipe:
            output.warn('Ignoring piped input because load file is specified')
        file_input_main(file_path, output, connection_list, ui_controller,
                        ui_controller, input_func)
    elif input_from_pipe:
        if args.b:
            output.warn(
                'Ignoring stop matcher when stdin is used for messages')
        piped_input_main(output, connection_list)
    else:
        output.warn('No action specified')
        parser.print_help()
예제 #5
0
                output.warn('Ignoring load file because we\'re inside GDB')
            gdb_plugin.plugin.Plugin(output, connection_list, ui_controller,
                                     ui_controller)
        except:
            import traceback
            traceback.print_exc()
    elif file_path:
        file_input_main(file_path, output, connection_list, ui_controller,
                        ui_controller, input_func)
    else:
        if args.b:
            output.warn(
                'Ignoring stop matcher when stdin is used for messages')
        piped_input_main(output, connection_list)


if __name__ == '__main__':
    # If isatty() is false, we might be redirecting to a file (or in another non-interactive context)
    # If we're not being run interactivly, we shouldn't use terminal color codes
    # If inside GDB, isatty() may return false but we stil want colors
    if check_gdb() or (hasattr(sys.stdout, 'isatty') and sys.stdout.isatty()):
        set_color_output(True)

    if check_gdb():
        out_stream, err_stream = gdb_plugin.plugin.output_streams()
    else:
        out_stream = stream.Std(sys.stdout)
        err_stream = stream.Std(sys.stderr)

    main(out_stream, err_stream, sys.argv, input)