def test_readable(self): self.assertFalse(Mfile.readable('fdafdsa')) for mode, can_read in [(stat.S_IRUSR, True), (stat.S_IWUSR, False)]: f = tempfile.NamedTemporaryFile() os.chmod(f.name, mode) self.assertEqual(can_read, Mfile.readable(f.name)) f.close() pass return
def test_readable(self): self.assertFalse(Mfile.readable("fdafdsa")) for mode, can_read in [(stat.S_IRUSR, True), (stat.S_IWUSR, False)]: f = tempfile.NamedTemporaryFile() os.chmod(f.name, mode) self.assertEqual(can_read, Mfile.readable(f.name)) f.close() pass return
def add_startup_file(dbg_initfiles): """ Read debugger startup file(s): both python code and debugger profile to dbg_initfiles.""" startup_python_file = default_configfile('profile.py') if Mfile.readable(startup_python_file): with codecs.open(startup_python_file, 'r', encoding='utf8') as fp: exec(fp.read()) startup_trepan_file = default_configfile('profile') if Mfile.readable(startup_trepan_file): dbg_initfiles.append(startup_trepan_file) pass return
def run(self, args): parms = args[1:-1] opts = {} for arg in parms: if arg == "-v": opts["verbose"] = True elif arg == "-Y": opts["confirm_val"] = True elif arg == "-N": opts["confirm_val"] = False elif arg == "-c": opts["abort_on_error"] = False pass filename = args[-1] expanded_file = osp.expanduser(filename) if not readable(expanded_file): self.errmsg("Debugger command file '%s' is not a readable file" % filename) return False # Push a new interface. script_intf = ScriptInterface(expanded_file, opts=opts, out=self.debugger.intf[-1].output) self.debugger.intf.append(script_intf) return False
def add_startup_file(dbg_initfiles): """Read debugger startup file(s): both python code and debugger profile to dbg_initfiles.""" startup_python_file = default_configfile("profile.py") if Mfile.readable(startup_python_file): with codecs.open(startup_python_file, "r", encoding="utf8") as fp: exec(fp.read()) startup_trepan_file = default_configfile("profile") if Mfile.readable(startup_trepan_file): if startup_trepan_file not in dbg_initfiles: dbg_initfiles.append(startup_trepan_file) pass return
def open(self, pid, opts=None): # Not in/out are reversed from server side d = tempfile.gettempdir() self.out_name = os.path.join(d, ('trepan-%s.in' % pid)) self.in_name = os.path.join(d, ('trepan-%s.out' % pid)) is_readable = Mfile.readable(self.out_name) if not is_readable: if is_readable is None: raise IOError("output FIFO %s doesn't exist" % self.out_name) else: raise IOError("output FIFO %s is not readable" % self.out_name) pass is_readable = Mfile.readable(self.in_name) if not is_readable: if is_readable is None: raise IOError("input FIFO %s doesn't exist" % self.in_name) else: raise IOError("output FIFO %s is not readable" % self.out_name) self.state = 'active' pass return
def queue_startfile(self, cmdfile): '''Arrange for file of debugger commands to get read in the process-command loop.''' expanded_cmdfile = os.path.expanduser(cmdfile) is_readable = Mfile.readable(expanded_cmdfile) if is_readable: self.cmd_queue.append('source ' + expanded_cmdfile) elif is_readable is None: self.errmsg("source file '%s' doesn't exist" % expanded_cmdfile) else: self.errmsg("source file '%s' is not readable" % expanded_cmdfile) pass return
def open(self, pid, opts=None): # Not in/out are reversed from server side d = tempfile.gettempdir() self.out_name = os.path.join(d, ("trepan-%s.in" % pid)) self.in_name = os.path.join(d, ("trepan-%s.out" % pid)) is_readable = Mfile.readable(self.out_name) if not is_readable: if is_readable is None: raise IOError("output FIFO %s doesn't exist" % self.out_name) else: raise IOError("output FIFO %s is not readable" % self.out_name) pass is_readable = Mfile.readable(self.in_name) if not is_readable: if is_readable is None: raise IOError("input FIFO %s doesn't exist" % self.in_name) else: raise IOError("output FIFO %s is not readable" % self.out_name) self.state = "active" pass self.closed = False return
def run(self, args): parms = args[1:-1] opts = {} for arg in parms: if arg == '-v': opts['verbose'] = True elif arg == '-Y': opts['confirm_val'] = True elif arg == '-N': opts['confirm_val'] = False elif arg == '-c': opts['abort_on_error'] = False pass filename = args[-1] expanded_file = os.path.expanduser(filename) if not Mfile.readable(expanded_file): self.errmsg("Debugger command file '%s' is not a readable file" % filename) return False # Push a new interface. script_intf = \ Mscript.ScriptInterface(expanded_file, opts=opts, out=self.debugger.intf[-1].output) self.debugger.intf.append(script_intf) return False
def run(self, args): proc = self.proc dbg_obj = self.core.debugger # We'll use a rough estimate of 4 bytes per instruction and # go off listsize listsize = dbg_obj.settings['listsize'] * 4 curframe = proc.curframe opts = {'highlight': self.settings['highlight'], 'start_line': 1, 'end_line': None, 'start_offset': None, 'end_offset': None, 'relative_pos': False, } do_parse = True if len(args) == 2: try: obj=self.proc.eval(args[1]) opts['start_offset'] = 0 is_offset = True start = 0 last = dbg_obj.settings['listsize'] * 4 last_is_offset = False if (inspect.ismethod(obj) or inspect.isfunction(obj) or inspect.isgeneratorfunction(obj) or inspect.isgenerator(obj) or inspect.isframe(obj) or inspect.iscode(obj)): do_parse = False except: pass if do_parse: (bytecode_file, start, is_offset, last, last_is_offset, obj) = parse_addr_list_cmd(proc, args, listsize) if bytecode_file is None: return if is_offset: opts['start_offset'] = start else: opts['start_line'] = start if last_is_offset: opts['end_offset'] = last else: opts['end_line'] = last if not (obj or bytecode_file.endswith('.pyo') or bytecode_file.endswith('pyc')): bytecode_file = cache_from_source(bytecode_file) if bytecode_file and Mfile.readable(bytecode_file): self.msg("Reading %s ..." % bytecode_file) (version, timestamp, magic_int, obj, is_pypy, source_size) = load_module(bytecode_file) elif not curframe: self.errmsg("No frame selected.") return else: try: obj=self.proc.eval(args[1]) opts['start_line'] = -1 except: self.errmsg(("Object '%s' is not something we can" + " disassemble.") % args[1]) return # We now have all information. Do the listing. (self.object, proc.list_offset) = Mdis.dis(self.msg, self.msg_nocr, self.section, self.errmsg, obj, **opts) return False
def process_options(debugger_name, pkg_version, sys_argv, option_list=None): """Handle debugger options. Set `option_list' if you are writing another main program and want to extend the existing set of debugger options. The options dicionary from opt_parser is return. sys_argv is also updated.""" usage_str="""%prog [debugger-options] [python-script [script-options...]] Runs the extended python debugger""" # serverChoices = ('TCP','FIFO', None) optparser = OptionParser(usage=usage_str, option_list=option_list, version="%%prog version %s" % pkg_version) optparser.add_option("-X", "--trace", dest="linetrace", action="store_true", default=False, help="Show lines before executing them. " + "This option also sets --batch") optparser.add_option("-F", "--fntrace", dest="fntrace", action="store_true", default=False, help="Show functions before executing them. " + "This option also sets --batch") optparser.add_option("--basename", dest="basename", action="store_true", default=False, help="Filenames strip off basename, " + "(e.g. for regression tests)" ) # optparser.add_option("--batch", dest="noninteractive", # action="store_true", default=False, # help="Don't run interactive commands shell on "+ # "stops.") optparser.add_option("--client", dest="client", action='store_true', help="Connect to an existing debugger process " + "started with the --server option. " + "See options for client.") optparser.add_option("-x", "--command", dest="command", action="store", type='string', metavar='FILE', help="Execute commands from FILE.") optparser.add_option("--cd", dest="cd", action="store", type='string', metavar='DIR', help="Change current directory to DIR.") optparser.add_option("--confirm", dest="confirm", action="store_true", default=True, help="Confirm potentially dangerous operations") optparser.add_option("--dbg_trepan", dest="dbg_trepan", action="store_true", default=False, help="Debug the debugger") optparser.add_option("--different", dest="different", action="store_true", default=True, help="Consecutive stops should have " "different positions") # optparser.add_option("--error", dest="errors", metavar='FILE', # action="store", type='string', # help="Write debugger's error output " # + "(stderr) to FILE") optparser.add_option("-e", "--exec", dest="execute", type="string", help="list of debugger commands to " + "execute. Separate the commands with ;;") optparser.add_option("-H", "--host", dest="host", default='127.0.0.1', action="store", type='string', metavar='IP-OR-HOST', help="connect IP or host name. " "Only valid if --client option given.") optparser.add_option("--highlight", dest="highlight", action="store", type='string', metavar='{light|dark|plain}', default='light', help="Use syntax and terminal highlight output. " "'plain' is no highlight") optparser.add_option("--private", dest="private", action='store_true', default=False, help="Don't register this as a global debugger") optparser.add_option("--post-mortem", dest="post_mortem", action='store_true', default=True, help="Enter debugger on an uncaught (fatal) " "exception") optparser.add_option("--no-post-mortem", dest="post_mortem", action='store_false', default=True, help="Don't enter debugger on an uncaught (fatal) " "exception") optparser.add_option("-n", "--nx", dest="noexecute", action="store_true", default=False, help="Don't execute commands found in any " + "initialization files") optparser.add_option("-o", "--output", dest="output", metavar='FILE', action="store", type='string', help="Write debugger's output (stdout) " + "to FILE") optparser.add_option("-P", "--port", dest="port", default=1027, action="store", type='int', help="Use TCP port number NUMBER for " "out-of-process connections.") optparser.add_option("--server", dest="server", action='store_true', help="Out-of-process server connection mode") optparser.add_option("--sigcheck", dest="sigcheck", action="store_true", default=False, help="Set to watch for signal handler changes") optparser.add_option("-t", "--target", dest="target", help="Specify a target to connect to. Arguments" + " should be of form, 'protocol address'."), optparser.add_option("--from_ipython", dest='from_ipython', action='store_true', default=False, help="Called from inside ipython") # annotate option produces annotations, used in trepan.el for a # better emacs integration. Annotations are similar in purpose to # those of GDB (see that manual for a description), although the # syntax is different. they have the following format: # # ^Z^Zannotation-name # <arbitrary text> # ^Z^Z # # where ^Z is the ctrl-Z character, and "annotname" is the name of the # annotation. A line with only two ^Z ends the annotation (no nesting # allowed). See trepan.el for the usage optparser.add_option("--annotate", default=0, type="int", help="Use annotations to work inside emacs") # Set up to stop on the first non-option because that's the name # of the script to be debugged on arguments following that are # that scripts options that should be left untouched. We would # not want to interpret and option for the script, e.g. --help, as # one one of our own, e.g. --help. optparser.disable_interspersed_args() sys.argv = list(sys_argv) (opts, sys.argv) = optparser.parse_args() dbg_opts = {'from_ipython': opts.from_ipython} # Handle debugger startup command files: --nx (-n) and --command. dbg_initfiles = [] if not opts.noexecute: # Read debugger startup file(s), e.g. $HOME/.trepan2rc and ~/.trepan2rc startup_file = ".%src" % debugger_name if Mfile.readable(os.path.join('.' , startup_file)): dbg_initfiles.append(startup_file) else: startup_home_file = os.path.join(os.environ.get('HOME', '~'), startup_file) expanded_startup_home = \ Mclifns.path_expanduser_abs(startup_home_file) if Mfile.readable(expanded_startup_home): dbg_initfiles.append(startup_home_file) pass pass # As per gdb, first we execute user initialization files and then # we execute any file specified via --command. if opts.command: dbg_initfiles.append(opts.command) pass dbg_opts['proc_opts'] = {'initfile_list': dbg_initfiles} if opts.cd: os.chdir(opts.cd) pass if opts.output: try: dbg_opts['output'] = Moutput.DebuggerUserOutput(opts.output) except IOError: _, xxx_todo_changeme, _ = sys.exc_info() (errno, strerror) = xxx_todo_changeme.args print("I/O in opening debugger output file %s" % opts.output) print("error(%s): %s" % (errno, strerror)) except: print("Unexpected error in opening debugger output file %s" % opts.output) print(sys.exc_info()[0]) sys.exit(2) pass pass return opts, dbg_opts, sys.argv
def run(self, args): relative_pos = False opts = {'highlight': self.settings['highlight'], 'start_line': -1, 'end_line': None } if len(args) > 1: start, opts['relative_pos'], is_offset = self.parse_arg(args[1]) if start is None: # First argument should be an evaluatable object # or a filename bytecode_file = args[1] have_code = False if not (bytecode_file.endswith('.pyo') or bytecode_file.endswith('pyc')): bytecode_file = cache_from_source(bytecode_file) if bytecode_file and Mfile.readable(bytecode_file): print("Reading %s ..." % bytecode_file) version, timestamp, magic_int, obj = uncompyle6.load.load_module(bytecode_file) have_code = True elif not self.proc.curframe: self.errmsg("No frame selected.") return else: try: obj=self.proc.eval(args[1]) opts['start_line'] = -1 except: self.errmsg(("Object '%s' is not something we can" + " disassemble.") % args[1]) return pass if len(args) > 2: start, opts['relative_pos'], is_offset = self.parse_arg(args[2]) if start is None: ilk = 'line' if is_offset else 'offset' self.errmsg = ('Start %s should be a number. Got %s.' % (ilk, args[2])) return else: opts['start_offset' if is_offset else 'start_line'] = start if len(args) == 4: finish, relative_pos, is_offset = self.parse_arg(args[3]) if finish is None: self.errmsg = ('End %s should be a number. ' + ' Got %s.' % (ilk, args[3])) return else: opts['end_offset' if is_offset else 'end_line'] = finish pass elif len(args) > 4: self.errmsg("Expecting 0-3 parameters. Got %d" % len(args)-1) return pass elif not have_code: try: obj=Mcmdfns.get_val(self.proc.curframe, self.errmsg, args[1]) except: return pass Mdis.dis(self.msg, self.msg_nocr, self.section, self.errmsg, obj, **opts) return False else: opts['start_offset' if is_offset else 'start_line'] = start if len(args) == 3: finish, not_used, is_offset = self.parse_arg(args[2]) if finish is None: self.errmsg = ('End line should be a number. ' + ' Got %s.' % args[2]) return else: opts['end_offset' if is_offset else 'end_line'] = finish pass elif len(args) > 3: self.errmsg("Expecting 1-2 line parameters. Got %d." % len(args)-1) return False pass pass elif not self.proc.curframe: self.errmsg("No frame selected.") return Mdis.dis(self.msg, self.msg_nocr, self.section, self.errmsg, self.proc.curframe, **opts) return False
def run(self, args): proc = self.proc # FIXME: add a setting for assembler list size listsize = 4 opts = { "highlight": self.settings["highlight"], "start_line": 1, "end_line": None, "start_offset": None, "end_offset": None, "relative_pos": False, "asm_format": self.settings["asmfmt"], } curframe = proc.curframe if curframe: line_no = inspect.getlineno(curframe) opts["start_line"] = line_no - 1 opts["end_line"] = line_no + 1 do_parse = True if len(args) == 2: if args[1].endswith("()"): eval_args = args[1][:-2] else: eval_args = args[1] try: obj = self.proc.eval(eval_args, show_error=False) except: obj = None else: if (inspect.ismethod(obj) or inspect.isfunction(obj) or inspect.isgeneratorfunction(obj) or inspect.isgenerator(obj) or inspect.isframe(obj) or inspect.iscode(obj)): opts["start_offset"] = 0 last_is_offset = is_offset = True start = 0 opts["start_line"] = 0 opts["end_line"] = last = None do_parse = False bytecode_file = None if do_parse: ( bytecode_file, start, is_offset, last, last_is_offset, obj, ) = parse_addr_list_cmd(proc, args, listsize) if bytecode_file is None: return if is_offset: opts["start_offset"] = start else: opts["start_line"] = start if last_is_offset: opts["end_offset"] = last else: opts["end_line"] = last if not obj and (bytecode_file and (not bytecode_file.endswith(".pyo") or bytecode_file.endswith("pyc"))): # bytecode_file may be a source file. Try to tun it into a bytecode file for diassembly. bytecode_file = cache_from_source(bytecode_file) if bytecode_file and Mfile.readable(bytecode_file): self.msg("Reading %s ..." % bytecode_file) ( version, timestamp, magic_int, obj, is_pypy, source_size, sip_hash, ) = load_module(bytecode_file) elif not curframe: self.errmsg("No frame selected.") return else: try: obj = self.proc.eval(args[1]) opts["start_line"] = -1 except: self.errmsg(("Object '%s' is not something we can" + " disassemble.") % args[1]) return # We now have all information. Do the listing. (obj, proc.list_offset) = dis(self.msg, self.msg_nocr, self.section, self.errmsg, obj, **opts) return False
def main(dbg=None, sys_argv=list(sys.argv)): """Routine which gets run if we were invoked directly""" # Save the original just for use in the restart that works via exec. orig_sys_argv = list(sys_argv) opts, dbg_opts, sys_argv = Moptions.process_options(__title__, __version__, sys_argv) if opts.server: connection_opts={'IO': 'TCP', 'PORT': opts.port} intf = Mserver.ServerInterface(connection_opts=connection_opts) dbg_opts['interface'] = intf if 'FIFO' == intf.server_type: print('Starting FIFO server for process %s.' % os.getpid()) elif 'TCP' == intf.server_type: print('Starting TCP server listening on port %s.' % intf.inout.PORT) pass elif opts.client: Mclient.main(opts, sys_argv) return dbg_opts['orig_sys_argv'] = orig_sys_argv if dbg is None: dbg = Mdebugger.Debugger(dbg_opts) dbg.core.add_ignore(main) pass Moptions._postprocess_options(dbg, opts) # process_options has munged sys.argv to remove any options that # options that belong to this debugger. The original options to # invoke the debugger and script are in global sys_argv if len(sys_argv) == 0: # No program given to debug. Set to go into a command loop # anyway mainpyfile = None else: mainpyfile = sys_argv[0] # Get script filename. if not os.path.isfile(mainpyfile): mainpyfile=Mclifns.whence_file(mainpyfile) is_readable = Mfile.readable(mainpyfile) if is_readable is None: print("%s: Python script file '%s' does not exist" % (__title__, mainpyfile,), file=sys.stderr) sys.exit(1) elif not is_readable: print("%s: Can't read Python script file '%s'" % (__title__, mainpyfile, ), file=sys.stderr) sys.exit(1) return if Mfile.is_compiled_py(mainpyfile): try: from uncompyle6 import uncompyle_file except ImportError: print("%s: Compiled python file '%s', but uncompyle6 not found" % (__title__, mainpyfile), file=sys.stderr) sys.exit(1) short_name = os.path.basename(mainpyfile).strip('.pyc') fd = tempfile.NamedTemporaryFile(suffix='.py', prefix=short_name + "_", delete=False) try: uncompyle_file(mainpyfile, fd) except: print("%s: error uncompyling '%s'" % (__title__, mainpyfile), file=sys.stderr) sys.exit(1) mainpyfile = fd.name fd.close() # If mainpyfile is an optimized Python script try to find and # use non-optimized alternative. mainpyfile_noopt = pyficache.pyc2py(mainpyfile) if mainpyfile != mainpyfile_noopt \ and Mfile.readable(mainpyfile_noopt): print("%s: Compiled Python script given and we can't use that." % __title__, file=sys.stderr) print("%s: Substituting non-compiled name: %s" % ( __title__, mainpyfile_noopt,), file=sys.stderr) mainpyfile = mainpyfile_noopt pass # Replace trepan's dir with script's dir in front of # module search path. sys.path[0] = dbg.main_dirname = os.path.dirname(mainpyfile) # XXX If a signal has been received we continue in the loop, otherwise # the loop exits for some reason. dbg.sig_received = False # if not mainpyfile: # print('For now, you need to specify a Python script name!') # sys.exit(2) # pass while True: # Run the debugged script over and over again until we get it # right. try: if dbg.program_sys_argv and mainpyfile: normal_termination = dbg.run_script(mainpyfile) if not normal_termination: break else: dbg.core.execution_status = 'No program' dbg.core.processor.process_commands() pass dbg.core.execution_status = 'Terminated' dbg.intf[-1].msg("The program finished - quit or restart") dbg.core.processor.process_commands() except Mexcept.DebuggerQuit: break except Mexcept.DebuggerRestart: dbg.core.execution_status = 'Restart requested' if dbg.program_sys_argv: sys.argv = list(dbg.program_sys_argv) part1 = ('Restarting %s with arguments:' % dbg.core.filename(mainpyfile)) args = ' '.join(dbg.program_sys_argv[1:]) dbg.intf[-1].msg(Mmisc.wrapped_lines(part1, args, dbg.settings['width'])) else: break except SystemExit: # In most cases SystemExit does not warrant a post-mortem session. break except: # FIXME: Should be handled above without this mess exception_name = str(sys.exc_info()[0]) if exception_name == str(Mexcept.DebuggerQuit): break elif exception_name == str(Mexcept.DebuggerRestart): dbg.core.execution_status = 'Restart requested' if dbg.program_sys_argv: sys.argv = list(dbg.program_sys_argv) part1 = ('Restarting %s with arguments:' % dbg.core.filename(mainpyfile)) args = ' '.join(dbg.program_sys_argv[1:]) dbg.intf[-1].msg( Mmisc.wrapped_lines(part1, args, dbg.settings['width'])) pass else: raise pass # Restore old sys.argv sys.argv = orig_sys_argv return
def main(dbg=None, sys_argv=list(sys.argv)): """Routine which gets run if we were invoked directly""" # Save the original just for use in the restart that works via exec. orig_sys_argv = list(sys_argv) opts, dbg_opts, sys_argv = Moptions.process_options(__title__, __version__, sys_argv) if opts.server: connection_opts={'IO': 'TCP', 'PORT': opts.port} intf = Mserver.ServerInterface(connection_opts=connection_opts) dbg_opts['interface'] = intf if 'FIFO' == intf.server_type: print('Starting FIFO server for process %s.' % os.getpid()) elif 'TCP' == intf.server_type: print('Starting TCP server listening on port %s.' % intf.inout.PORT) pass elif opts.client: Mclient.main(opts, sys_argv) return dbg_opts['orig_sys_argv'] = orig_sys_argv if dbg is None: dbg = Mdebugger.Debugger(dbg_opts) dbg.core.add_ignore(main) pass Moptions._postprocess_options(dbg, opts) # process_options has munged sys.argv to remove any options that # options that belong to this debugger. The original options to # invoke the debugger and script are in global sys_argv if len(sys_argv) == 0: # No program given to debug. Set to go into a command loop # anyway mainpyfile = None else: mainpyfile = sys_argv[0] # Get script filename. if not os.path.isfile(mainpyfile): mainpyfile=Mclifns.whence_file(mainpyfile) is_readable = Mfile.readable(mainpyfile) if is_readable is None: print("%s: Python script file '%s' does not exist" % (__title__, mainpyfile,), file=sys.stderr) sys.exit(1) elif not is_readable: print("%s: Can't read Python script file '%s'" % (__title__, mainpyfile, ), file=sys.stderr) sys.exit(1) return if Mfile.is_compiled_py(mainpyfile): try: from uncompyle2 import uncompyle_file except ImportError: print("%s: Compiled python file '%s', but uncompyle2 not found" % (__title__, mainpyfile), file=sys.stderr) sys.exit(1) short_name = os.path.basename(mainpyfile).strip('.pyc') fd = tempfile.NamedTemporaryFile(suffix='.py', prefix=short_name + "_", delete=False) try: uncompyle_file(mainpyfile, fd) except: print("%s: error uncompyling '%s'" % (__title__, mainpyfile), file=sys.stderr) sys.exit(1) mainpyfile = fd.name fd.close() # If mainpyfile is an optimized Python script try to find and # use non-optimized alternative. mainpyfile_noopt = Mfile.file_pyc2py(mainpyfile) if mainpyfile != mainpyfile_noopt \ and Mfile.readable(mainpyfile_noopt): print("%s: Compiled Python script given and we can't use that." % __title__, file=sys.stderr) print("%s: Substituting non-compiled name: %s" % ( __title__, mainpyfile_noopt,), file=sys.stderr) mainpyfile = mainpyfile_noopt pass # Replace trepan's dir with script's dir in front of # module search path. sys.path[0] = dbg.main_dirname = os.path.dirname(mainpyfile) # XXX If a signal has been received we continue in the loop, otherwise # the loop exits for some reason. dbg.sig_received = False # if not mainpyfile: # print('For now, you need to specify a Python script name!') # sys.exit(2) # pass while True: # Run the debugged script over and over again until we get it # right. try: if dbg.program_sys_argv and mainpyfile: normal_termination = dbg.run_script(mainpyfile) if not normal_termination: break else: dbg.core.execution_status = 'No program' dbg.core.processor.process_commands() pass dbg.core.execution_status = 'Terminated' dbg.intf[-1].msg("The program finished - quit or restart") dbg.core.processor.process_commands() except Mexcept.DebuggerQuit: break except Mexcept.DebuggerRestart: dbg.core.execution_status = 'Restart requested' if dbg.program_sys_argv: sys.argv = list(dbg.program_sys_argv) part1 = ('Restarting %s with arguments:' % dbg.core.filename(mainpyfile)) args = ' '.join(dbg.program_sys_argv[1:]) dbg.intf[-1].msg(Mmisc.wrapped_lines(part1, args, dbg.settings['width'])) else: break except SystemExit: # In most cases SystemExit does not warrant a post-mortem session. break except: # FIXME: Should be handled above without this mess exception_name = str(sys.exc_info()[0]) if exception_name == str(Mexcept.DebuggerQuit): break elif exception_name == str(Mexcept.DebuggerRestart): dbg.core.execution_status = 'Restart requested' if dbg.program_sys_argv: sys.argv = list(dbg.program_sys_argv) part1 = ('Restarting %s with arguments:' % dbg.core.filename(mainpyfile)) args = ' '.join(dbg.program_sys_argv[1:]) dbg.intf[-1].msg( Mmisc.wrapped_lines(part1, args, dbg.settings['width'])) pass else: raise pass # Restore old sys.argv sys.argv = orig_sys_argv return
def run(self, args): proc = self.proc dbg_obj = self.core.debugger # We'll use a rough estimate of 4 bytes per instruction and # go off listsize listsize = dbg_obj.settings['listsize'] * 4 curframe = proc.curframe opts = { 'highlight': self.settings['highlight'], 'start_line': 1, 'end_line': None, 'start_offset': None, 'end_offset': None, 'relative_pos': False, } do_parse = True if len(args) == 2: try: obj = self.proc.eval(args[1]) opts['start_offset'] = 0 is_offset = True start = 0 last = dbg_obj.settings['listsize'] * 4 last_is_offset = False if (inspect.ismethod(obj) or inspect.isfunction(obj) or inspect.isgeneratorfunction(obj) or inspect.isgenerator(obj) or inspect.isframe(obj) or inspect.iscode(obj)): do_parse = False except: pass if do_parse: (bytecode_file, start, is_offset, last, last_is_offset, obj) = parse_addr_list_cmd(proc, args, listsize) if bytecode_file is None: return if is_offset: opts['start_offset'] = start else: opts['start_line'] = start if last_is_offset: opts['end_offset'] = last else: opts['end_line'] = last if not (obj or bytecode_file.endswith('.pyo') or bytecode_file.endswith('pyc')): bytecode_file = cache_from_source(bytecode_file) if bytecode_file and Mfile.readable(bytecode_file): self.msg("Reading %s ..." % bytecode_file) (version, timestamp, magic_int, obj, is_pypy, source_size) = load_module(bytecode_file) elif not curframe: self.errmsg("No frame selected.") return else: try: obj = self.proc.eval(args[1]) opts['start_line'] = -1 except: self.errmsg(("Object '%s' is not something we can" + " disassemble.") % args[1]) return # We now have all information. Do the listing. (self.object, proc.list_offset) = Mdis.dis(self.msg, self.msg_nocr, self.section, self.errmsg, obj, **opts) return False
def main(dbg=None, sys_argv=list(sys.argv)): """Routine which gets run if we were invoked directly""" global __title__ # Save the original just for use in the restart that works via exec. orig_sys_argv = list(sys_argv) opts, dbg_opts, sys_argv = Moptions.process_options( __title__, VERSION, sys_argv) if opts.server is not None: if opts.server == 'tcp': connection_opts = {'IO': 'TCP', 'PORT': opts.port} else: connection_opts = {'IO': 'FIFO'} intf = Mserver.ServerInterface(connection_opts=connection_opts) dbg_opts['interface'] = intf if 'FIFO' == intf.server_type: print('Starting FIFO server for process %s.' % os.getpid()) elif 'TCP' == intf.server_type: print('Starting TCP server listening on port %s.' % intf.inout.PORT) pass elif opts.client: Mclient.main(opts, sys_argv) return dbg_opts['orig_sys_argv'] = orig_sys_argv if dbg is None: dbg = Mdebugger.Trepan(dbg_opts) dbg.core.add_ignore(main) pass Moptions._postprocess_options(dbg, opts) # process_options has munged sys.argv to remove any options that # options that belong to this debugger. The original options to # invoke the debugger and script are in global sys_argv if len(sys_argv) == 0: # No program given to debug. Set to go into a command loop # anyway mainpyfile = None else: mainpyfile = sys_argv[0] # Get script filename. if not osp.isfile(mainpyfile): mainpyfile = Mclifns.whence_file(mainpyfile) is_readable = Mfile.readable(mainpyfile) if is_readable is None: print("%s: Python script file '%s' does not exist" % ( __title__, mainpyfile, )) sys.exit(1) elif not is_readable: print("%s: Can't read Python script file '%s'" % ( __title__, mainpyfile, )) sys.exit(1) return if Mfile.is_compiled_py(mainpyfile): try: from xdis import load_module, PYTHON_VERSION, IS_PYPY (python_version, timestamp, magic_int, co, is_pypy, source_size) = load_module(mainpyfile, code_objects=None, fast_load=True) assert is_pypy == IS_PYPY assert python_version == PYTHON_VERSION, \ "bytecode is for version %s but we are version %s" % ( python_version, PYTHON_VERSION) # We should we check version magic_int py_file = co.co_filename if osp.isabs(py_file): try_file = py_file else: mainpydir = osp.dirname(mainpyfile) tag = sys.implementation.cache_tag dirnames = [ osp.join(mainpydir, tag), mainpydir ] + os.environ['PATH'].split(osp.pathsep) + ['.'] try_file = Mclifns.whence_file(py_file, dirnames) if osp.isfile(try_file): mainpyfile = try_file pass else: # Move onto the except branch raise IOError( "Python file name embedded in code %s not found" % try_file) except IOError: try: from uncompyle6 import decompile_file except ImportError: print( "%s: Compiled python file '%s', but uncompyle6 not found" % (__title__, mainpyfile), file=sys.stderr) sys.exit(1) return short_name = osp.basename(mainpyfile).strip('.pyc') fd = tempfile.NamedTemporaryFile(suffix='.py', prefix=short_name + "_", delete=False) old_write = fd.file.write def write_wrapper(*args, **kwargs): if isinstance(args[0], str): new_args = list(args) new_args[0] = args[0].encode('utf-8') old_write(*new_args, **kwargs) else: old_write(*args, **kwargs) fd.file.write = write_wrapper # from io import StringIO # linemap_io = StringIO() try: decompile_file(mainpyfile, fd.file, mapstream=fd) except: print("%s: error decompiling '%s'" % (__title__, mainpyfile), file=sys.stderr) sys.exit(1) return # # Get the line associations between the original and # # decompiled program # mapline = linemap_io.getvalue() # fd.write(mapline + "\n\n") # linemap = eval(mapline[3:]) mainpyfile = fd.name fd.close() # Since we are actually running the recreated source, # there is little no need to remap line numbers. # The mapping is given at the end of the file. # However we should consider adding this information # and original file name. print( "%s: couldn't find Python source so we recreated it at '%s'" % (__title__, mainpyfile), file=sys.stderr) pass # If mainpyfile is an optimized Python script try to find and # use non-optimized alternative. mainpyfile_noopt = pyficache.pyc2py(mainpyfile) if mainpyfile != mainpyfile_noopt \ and Mfile.readable(mainpyfile_noopt): print("%s: Compiled Python script given and we can't use that." % __title__) print("%s: Substituting non-compiled name: %s" % ( __title__, mainpyfile_noopt, )) mainpyfile = mainpyfile_noopt pass # Replace trepan's dir with script's dir in front of # module search path. sys.path[0] = dbg.main_dirname = osp.dirname(mainpyfile) # XXX If a signal has been received we continue in the loop, otherwise # the loop exits for some reason. dbg.sig_received = False # if not mainpyfile: # print('For now, you need to specify a Python script name!') # sys.exit(2) # pass while True: # Run the debugged script over and over again until we get it # right. try: if dbg.program_sys_argv and mainpyfile: normal_termination = dbg.run_script(mainpyfile) if not normal_termination: break else: dbg.core.execution_status = 'No program' dbg.core.processor.process_commands() pass dbg.core.execution_status = 'Terminated' dbg.intf[-1].msg("The program finished - quit or restart") dbg.core.processor.process_commands() except Mexcept.DebuggerQuit: break except Mexcept.DebuggerRestart: dbg.core.execution_status = 'Restart requested' if dbg.program_sys_argv: sys.argv = list(dbg.program_sys_argv) part1 = ('Restarting %s with arguments:' % dbg.core.filename(mainpyfile)) args = ' '.join(dbg.program_sys_argv[1:]) dbg.intf[-1].msg( Mmisc.wrapped_lines(part1, args, dbg.settings['width'])) else: break except SystemExit: # In most cases SystemExit does not warrant a post-mortem session. break pass # Restore old sys.argv sys.argv = orig_sys_argv return
def main(dbg=None, sys_argv=list(sys.argv)): """Routine which gets run if we were invoked directly""" # Save the original just for use in the restart that works via exec. orig_sys_argv = list(sys_argv) opts, dbg_opts, sys_argv = Moptions.process_options( __title__, __version__, sys_argv) if opts.server: connection_opts = {"IO": "TCP", "PORT": opts.port} intf = Mserver.ServerInterface(connection_opts=connection_opts) dbg_opts["interface"] = intf if "FIFO" == intf.server_type: print("Starting FIFO server for process %s." % os.getpid()) elif "TCP" == intf.server_type: print("Starting TCP server listening on port %s." % intf.inout.PORT) pass elif opts.client: Mclient.main(opts, sys_argv) return dbg_opts["orig_sys_argv"] = orig_sys_argv if dbg is None: dbg = Mdebugger.Debugger(dbg_opts) dbg.core.add_ignore(main) pass Moptions._postprocess_options(dbg, opts) # process_options has munged sys.argv to remove any options that # options that belong to this debugger. The original options to # invoke the debugger and script are in global sys_argv if len(sys_argv) == 0: # No program given to debug. Set to go into a command loop # anyway mainpyfile = None else: mainpyfile = sys_argv[0] # Get script filename. if not osp.isfile(mainpyfile): mainpyfile = Mclifns.whence_file(mainpyfile) is_readable = Mfile.readable(mainpyfile) if is_readable is None: sys.stderr.write( "%s: Python script file '%s' does not exist\n" % (__title__, mainpyfile)) sys.exit(1) elif not is_readable: sys.stderr.write("%s: Can't read Python script file '%s'\n" % ( __title__, mainpyfile, )) sys.exit(1) return if Mfile.is_compiled_py(mainpyfile): try: from xdis import load_module from xdis_version import load_module, PYTHON_VERSION_TRIPLE, IS_PYPY, version_tuple_to_str ( python_version, timestamp, magic_int, co, is_pypy, source_size, ) = load_module(mainpyfile, code_objects=None, fast_load=True) assert is_pypy == IS_PYPY assert ( python_version == PYTHON_VERSION_TRIPLE ), "bytecode is for version %s but we are version %s" % ( python_version, version_tuple_to_str(), ) # We should we check version magic_int py_file = co.co_filename if osp.isabs(py_file): try_file = py_file else: mainpydir = osp.dirname(mainpyfile) dirnames = ([mainpydir] + os.environ["PATH"].split(os.pathsep) + ["."]) try_file = Mclifns.whence_file(py_file, dirnames) if osp.isfile(try_file): mainpyfile = try_file pass else: # Move onto the except branch raise IOError( "Python file name embedded in code %s not found" % try_file) except: try: from uncompyle6 import decompile_file except ImportError: sys.stderr.write( "%s: Compiled python file '%s', but uncompyle6 not found\n" % (__title__, mainpyfile)) sys.exit(1) return short_name = osp.basename(mainpyfile).strip(".pyc") fd = tempfile.NamedTemporaryFile( suffix=".py", prefix=short_name + "_", dir=dbg.settings["tempdir"], delete=False, ) try: decompile_file(mainpyfile, outstream=fd) mainpyfile = fd.name fd.close() except: sys.stderr.write("%s: error uncompyling '%s'\n" % (__title__, mainpyfile)) sys.exit(1) pass # If mainpyfile is an optimized Python script try to find and # use non-optimized alternative. mainpyfile_noopt = pyficache.resolve_name_to_path(mainpyfile) if mainpyfile != mainpyfile_noopt \ and Mfile.readable(mainpyfile_noopt): sys.stderr.write( "%s: Compiled Python script given and we can't use that.\n" % __title__) sys.stderr.write("%s: Substituting non-compiled name: %s\n" % (__title__, mainpyfile_noopt)) mainpyfile = mainpyfile_noopt pass # Replace trepan's dir with script's dir in front of # module search path. sys.path[0] = dbg.main_dirname = osp.dirname(mainpyfile) # XXX If a signal has been received we continue in the loop, otherwise # the loop exits for some reason. dbg.sig_received = False # if not mainpyfile: # print('For now, you need to specify a Python script name!') # sys.exit(2) # pass while True: # Run the debugged script over and over again until we get it # right. try: if dbg.program_sys_argv and mainpyfile: normal_termination = dbg.run_script(mainpyfile) if not normal_termination: break else: dbg.core.execution_status = "No program" dbg.core.processor.process_commands() pass dbg.core.execution_status = "Terminated" dbg.intf[-1].msg("The program finished - quit or restart") dbg.core.processor.process_commands() except Mexcept.DebuggerQuit: break except Mexcept.DebuggerRestart: dbg.core.execution_status = "Restart requested" if dbg.program_sys_argv: sys.argv = list(dbg.program_sys_argv) part1 = "Restarting %s with arguments:" % dbg.core.filename( mainpyfile) args = " ".join(dbg.program_sys_argv[1:]) dbg.intf[-1].msg( Mmisc.wrapped_lines(part1, args, dbg.settings["width"])) else: break except SystemExit: # In most cases SystemExit does not warrant a post-mortem session. break except: # FIXME: Should be handled above without this mess exception_name = str(sys.exc_info()[0]) if exception_name == str(Mexcept.DebuggerQuit): break elif exception_name == str(Mexcept.DebuggerRestart): dbg.core.execution_status = "Restart requested" if dbg.program_sys_argv: sys.argv = list(dbg.program_sys_argv) part1 = "Restarting %s with arguments:" % dbg.core.filename( mainpyfile) args = " ".join(dbg.program_sys_argv[1:]) dbg.intf[-1].msg( Mmisc.wrapped_lines(part1, args, dbg.settings["width"])) pass else: raise pass # Restore old sys.argv sys.argv = orig_sys_argv return
def run(self, args): relative_pos = False opts = { 'highlight': self.settings['highlight'], 'start_line': -1, 'end_line': None } if len(args) > 1: start, opts['relative_pos'], is_offset = self.parse_arg(args[1]) if start is None: # First argument should be an evaluatable object # or a filename bytecode_file = args[1] have_code = False if not (bytecode_file.endswith('.pyo') or bytecode_file.endswith('pyc')): bytecode_file = cache_from_source(bytecode_file) if bytecode_file and Mfile.readable(bytecode_file): print("Reading %s ..." % bytecode_file) version, timestamp, magic_int, obj = uncompyle6.load.load_module( bytecode_file) have_code = True elif not self.proc.curframe: self.errmsg("No frame selected.") return else: try: obj = self.proc.eval(args[1]) opts['start_line'] = -1 except: self.errmsg(("Object '%s' is not something we can" + " disassemble.") % args[1]) return pass if len(args) > 2: start, opts['relative_pos'], is_offset = self.parse_arg( args[2]) if start is None: ilk = 'line' if is_offset else 'offset' self.errmsg = ('Start %s should be a number. Got %s.' % (ilk, args[2])) return else: opts['start_offset' if is_offset else 'start_line'] = start if len(args) == 4: finish, relative_pos, is_offset = self.parse_arg( args[3]) if finish is None: self.errmsg = ('End %s should be a number. ' + ' Got %s.' % (ilk, args[3])) return else: opts['end_offset' if is_offset else 'end_line'] = finish pass elif len(args) > 4: self.errmsg("Expecting 0-3 parameters. Got %d" % len(args) - 1) return pass elif not have_code: try: obj = Mcmdfns.get_val(self.proc.curframe, self.errmsg, args[1]) except: return pass Mdis.dis(self.msg, self.msg_nocr, self.section, self.errmsg, obj, **opts) return False else: opts['start_offset' if is_offset else 'start_line'] = start if len(args) == 3: finish, not_used, is_offset = self.parse_arg(args[2]) if finish is None: self.errmsg = ('End line should be a number. ' + ' Got %s.' % args[2]) return else: opts[ 'end_offset' if is_offset else 'end_line'] = finish pass elif len(args) > 3: self.errmsg("Expecting 1-2 line parameters. Got %d." % len(args) - 1) return False pass pass elif not self.proc.curframe: self.errmsg("No frame selected.") return Mdis.dis(self.msg, self.msg_nocr, self.section, self.errmsg, self.proc.curframe, **opts) return False
def run(self, args): start_line = -1 end_line = None relative_pos = False if len(args) > 1: start_line, relative_pos = self.parse_arg(args[1]) if start_line is None: # First argument should be an evaluatable object # or a filename if args[1].endswith('.pyc') and Mfile.readable(args[1]): magic, moddate, modtime, obj = Mdis.pyc2code(args[1]) elif not self.proc.curframe: self.errmsg("No frame selected.") return else: try: obj=self.proc.eval(args[1]) start_line = -1 except: self.errmsg(("Object '%s' is not something we can" + " disassemble.") % args[1]) return pass if len(args) > 2: start_line, relative_pos = self.parse_arg(args[2]) if start_line is None: self.errmsg = ('Start line should be a number. Got %s.' % args[2]) return if len(args) == 4: end_line, relative_pos = self.parse_arg(args[3]) if end_line is None: self.errmsg = ('End line should be a number. ' + ' Got %s.' % args[3]) return pass elif len(args) > 4: self.errmsg("Expecting 0-3 parameters. Got %d" % len(args)-1) return pass else: try: obj=Mcmdfns.get_val(self.proc.curframe, self.errmsg, args[1]) except: return pass Mdis.dis(self.msg, self.msg_nocr, self.section, self.errmsg, obj, start_line=start_line, end_line=end_line, relative_pos=relative_pos) return False else: if len(args) == 3: end_line, not_used = self.parse_arg(args[2]) if end_line is None: self.errmsg = ('End line should be a number. ' + ' Got %s.' % args[2]) return pass elif len(args) > 3: self.errmsg("Expecting 1-2 line parameters. Got %d." % len(args)-1) return False pass pass elif not self.proc.curframe: self.errmsg("No frame selected.") return Mdis.dis(self.msg, self.msg_nocr, self.section, self.errmsg, self.proc.curframe, start_line=start_line, end_line=end_line, relative_pos=relative_pos) return False
def run(self, args): relative_pos = False opts = {'highlight': self.settings['highlight'], 'start_line': -1, 'end_line': None } if len(args) > 1: start, opts['relative_pos'], is_offset = self.parse_arg(args[1]) if start is None: # First argument should be an evaluatable object # or a filename if args[1].endswith('.pyc') and Mfile.readable(args[1]): magic, moddate, modtime, obj = Mdis.pyc2code(args[1]) elif not self.proc.curframe: self.errmsg("No frame selected.") return else: try: obj=self.proc.eval(args[1]) opts['start_line'] = -1 except: self.errmsg(("Object '%s' is not something we can" + " disassemble.") % args[1]) return pass if len(args) > 2: start, opts['relative_pos'], is_offset = self.parse_arg(args[2]) if start is None: ilk = 'line' if is_offset else 'offset' self.errmsg = ('Start %s should be a number. Got %s.' % (ilk, args[2])) return else: opts['start_offset' if is_offset else 'start_line'] = start if len(args) == 4: finish, relative_pos, is_offset = self.parse_arg(args[3]) if finish is None: self.errmsg = ('End %s should be a number. ' + ' Got %s.' % (ilk, args[3])) return else: opts['end_offset' if is_offset else 'end_line'] = finish pass elif len(args) > 4: self.errmsg("Expecting 0-3 parameters. Got %d" % len(args)-1) return pass else: try: obj=Mcmdfns.get_val(self.proc.curframe, self.errmsg, args[1]) except: return pass Mdis.dis(self.msg, self.msg_nocr, self.section, self.errmsg, obj, **opts) return False else: opts['start_offset' if is_offset else 'start_line'] = start if len(args) == 3: finish, not_used, is_offset = self.parse_arg(args[2]) if finish is None: self.errmsg = ('End line should be a number. ' + ' Got %s.' % args[2]) return else: opts['end_offset' if is_offset else 'end_line'] = finish pass elif len(args) > 3: self.errmsg("Expecting 1-2 line parameters. Got %d." % len(args)-1) return False pass pass elif not self.proc.curframe: self.errmsg("No frame selected.") return Mdis.dis(self.msg, self.msg_nocr, self.section, self.errmsg, self.proc.curframe, **opts) return False
def main(dbg=None, sys_argv=list(sys.argv)): """Routine which gets run if we were invoked directly""" global __title__ # Save the original just for use in the restart that works via exec. orig_sys_argv = list(sys_argv) opts, dbg_opts, sys_argv = process_options(__title__, __version__, sys_argv) dbg_opts["orig_sys_argv"] = sys_argv dbg_opts["interface"] = BWInterface() dbg_opts["processor"] = "bullwinkle" if dbg is None: dbg = Mdebugger.Trepan(dbg_opts) dbg.core.add_ignore(main) pass _postprocess_options(dbg, opts) # process_options has munged sys.argv to remove any options that # options that belong to this debugger. The original options to # invoke the debugger and script are in global sys_argv if len(sys_argv) == 0: # No program given to debug. Set to go into a command loop # anyway mainpyfile = None else: mainpyfile = sys_argv[0] # Get script filename. if not osp.isfile(mainpyfile): mainpyfile = Mclifns.whence_file(mainpyfile) is_readable = readable(mainpyfile) if is_readable is None: print( "%s: Python script file '%s' does not exist" % ( __title__, mainpyfile, ) ) sys.exit(1) elif not is_readable: print( "%s: Can't read Python script file '%s'" % ( __title__, mainpyfile, ) ) sys.exit(1) return # If mainpyfile is an optimized Python script try to find and # use non-optimized alternative. mainpyfile_noopt = pyficache.resolve_name_to_file(mainpyfile) if mainpyfile != mainpyfile_noopt and readable(mainpyfile_noopt): print("%s: Compiled Python script given and we can't use that." % __title__) print( "%s: Substituting non-compiled name: %s" % ( __title__, mainpyfile_noopt, ) ) mainpyfile = mainpyfile_noopt pass # Replace trepan's dir with script's dir in front of # module search path. sys.path[0] = dbg.main_dirname = osp.dirname(mainpyfile) # XXX If a signal has been received we continue in the loop, otherwise # the loop exits for some reason. dbg.sig_received = False # if not mainpyfile: # print('For now, you need to specify a Python script name!') # sys.exit(2) # pass while True: # Run the debugged script over and over again until we get it # right. try: if dbg.program_sys_argv and mainpyfile: normal_termination = dbg.run_script(mainpyfile) if not normal_termination: break else: dbg.core.execution_status = "No program" dbg.core.processor.process_commands() pass dbg.core.execution_status = "Terminated" dbg.intf[-1].msg("The program finished - quit or restart") dbg.core.processor.process_commands() except Mexcept.DebuggerQuit: break except Mexcept.DebuggerRestart: dbg.core.execution_status = "Restart requested" if dbg.program_sys_argv: sys.argv = list(dbg.program_sys_argv) part1 = "Restarting %s with arguments:" % dbg.core.filename(mainpyfile) args = " ".join(dbg.program_sys_argv[1:]) dbg.intf[-1].msg( Mmisc.wrapped_lines(part1, args, dbg.settings["width"]) ) else: break except SystemExit: # In most cases SystemExit does not warrant a post-mortem session. break pass # Restore old sys.argv sys.argv = orig_sys_argv return