def deparse_and_cache(co, errmsg_fn): # co = proc_obj.curframe.f_code out = StringIO() try: float_version = sysinfo2float() except: errmsg_fn(str(sys.exc_info()[0])) errmsg_fn("error in deparsing code") return None, None text = out.getvalue() deparsed = deparse_code_with_map(float_version, co, is_pypy=IS_PYPY) linemap = [(line_no, deparsed.source_linemap[line_no]) for line_no in sorted(deparsed.source_linemap.keys())] # FIXME: DRY code with version in cmdproc.py print_location name_for_code = sha1(co.co_code).hexdigest()[:6] prefix='deparsed-' fd = tempfile.NamedTemporaryFile(suffix='.py', prefix=prefix) fd.write(text.encode('utf-8')) map_line = "\n\n# %s" % linemap fd.write(map_line.encode('utf-8')) remapped_file = fd.name # FIXME remap filename to a short name. pyficache.remap_file_lines(name_for_code, remapped_file, linemap) return remapped_file, name_for_code
def uncompyle_test(): frame = inspect.currentframe() try: co = frame.f_code decompile(sysinfo2float(), co, sys.stdout, 1, 1) print() finally: del frame
def run(self, args): co = self.proc.curframe.f_code name = co.co_name try: opts, args = getopt(args[1:], "hpPAto:O", [ "help", "parent", "pretty", "AST", 'tree', "offset=", "offsets" ]) except GetoptError as err: # print help information and exit: print(str( err)) # will print something like "option -a not recognized" return show_parent = False show_ast = False offset = None show_offsets = False for o, a in opts: if o in ("-h", "--help"): self.proc.commands['help'].run(['help', 'deparse']) return elif o in ("-O", "--offsets"): show_offsets = True elif o in ("-p", "--parent"): show_parent = True elif o in ("-A", "--tree", '--AST'): show_ast = True elif o in ("-o", '--offset'): offset = a else: self.errmsg("unhandled option '%s'" % o) pass pass nodeInfo = None try: float_version = sysinfo2float() except: self.errmsg(sys.exc_info()[1]) return if len(args) >= 1 and args[0] == '.': temp_filename, name_for_code = deparse_and_cache(co, self.errmsg) if not temp_filename: return self.print_text(''.join(getlines(temp_filename))) return elif show_offsets: deparsed = deparse_code(float_version, co, is_pypy=IS_PYPY) self.section("Offsets known:") m = self.columnize_commands( list(sorted(deparsed.offsets.keys(), key=lambda x: str(x[0])))) self.msg_nocr(m) return elif offset is not None: mess = ("The 'deparse' command when given an argument requires an" " instruction offset. Got: '%s'" % offset) last_i = self.proc.get_an_int(offset, mess) if last_i is None: return else: last_i = self.proc.curframe.f_lasti if last_i == -1: last_i = 0 try: deparsed = deparse_code(float_version, co, is_pypy=IS_PYPY) nodeInfo = deparsed_find((name, last_i), deparsed, co) if not nodeInfo: self.errmsg( "Can't find exact offset %d; giving inexact results" % last_i) deparsed = deparse_code_around_offset(co.co_name, last_i, float_version, co, is_pypy=IS_PYPY) except: self.errmsg(sys.exc_info()[1]) self.errmsg("error in deparsing code at offset %d" % last_i) return if not nodeInfo: nodeInfo = deparsed_find((name, last_i), deparsed, co) if nodeInfo: extractInfo = deparsed.extract_node_info(nodeInfo) parentInfo = None # print extractInfo if show_ast: p = deparsed.ast if show_parent: parentInfo, p = deparsed.extract_parent_info(nodeInfo.node) self.msg(p) if extractInfo: self.rst_msg("*instruction:* %s" % (nodeInfo.node)) self.print_text(extractInfo.selectedLine) self.msg(extractInfo.markerLine) if show_parent: if not parentInfo: parentInfo, p = deparsed.extract_parent_info( nodeInfo.node) if parentInfo: self.section("Contained in...") self.rst_msg("\t*Grammar Symbol:* %s" % p.kind) self.print_text(parentInfo.selectedLine) self.msg(parentInfo.markerLine) pass pass pass elif last_i == -1: if name: self.msg("At beginning of %s " % name) elif self.core.filename(None): self.msg("At beginning of program %s" % self.core.filename(None)) else: self.msg("At beginning") else: self.errmsg( "haven't recorded info for offset %d. Offsets I know are:" % last_i) m = self.columnize_commands( list(sorted(deparsed.offsets.keys(), key=lambda x: str(x[0])))) self.msg_nocr(m) return
def decompile(bytecode_version, co, out=None, showasm=None, showast=False, timestamp=None, showgrammar=False, code_objects={}, source_size=None, is_pypy=None, magic_int=None, mapstream=None, do_fragments=False): """ ingests and deparses a given code block 'co' if `bytecode_version` is None, use the current Python intepreter version. Caller is responsible for closing `out` and `mapstream` """ if bytecode_version is None: bytecode_version = sysinfo2float() # store final output stream for case of error real_out = out or sys.stdout def write(s): s += '\n' real_out.write(s) assert iscode(co) co_pypy_str = 'PyPy ' if is_pypy else '' run_pypy_str = 'PyPy ' if IS_PYPY else '' sys_version_lines = sys.version.split('\n') write('# decompyle3 version %s\n' '# %sPython bytecode %s%s\n# Decompiled from: %sPython %s' % (VERSION, co_pypy_str, bytecode_version, " (%s)" % str(magic_int) if magic_int else "", run_pypy_str, '\n# '.join(sys_version_lines))) if co.co_filename: write('# Embedded file name: %s' % co.co_filename, ) if timestamp: write('# Compiled at: %s' % datetime.datetime.fromtimestamp(timestamp)) if source_size: write('# Size of source mod 2**32: %d bytes' % source_size) debug_opts = {'asm': showasm, 'ast': showast, 'grammar': showgrammar} try: if mapstream: if isinstance(mapstream, str): mapstream = _get_outstream(mapstream) deparsed = deparse_code_with_map( bytecode_version, co, out, showasm, showast, showgrammar, code_objects=code_objects, is_pypy=is_pypy, ) header_count = 3 + len(sys_version_lines) linemap = [(line_no, deparsed.source_linemap[line_no] + header_count) for line_no in sorted(deparsed.source_linemap.keys())] mapstream.write("\n\n# %s\n" % linemap) else: if do_fragments: deparse_fn = code_deparse_fragments else: deparse_fn = code_deparse deparsed = deparse_fn(co, out, bytecode_version, debug_opts=debug_opts, is_pypy=is_pypy) pass return deparsed except pysource.SourceWalkerError as e: # deparsing failed raise pysource.SourceWalkerError(str(e))
def decompile( bytecode_version, co, out=None, showasm=None, showast={}, timestamp=None, showgrammar=False, source_encoding=None, code_objects={}, source_size=None, is_pypy=None, magic_int=None, mapstream=None, do_fragments=False, ): """ ingests and deparses a given code block 'co' if `bytecode_version` is None, use the current Python intepreter version. Caller is responsible for closing `out` and `mapstream` """ if bytecode_version is None: bytecode_version = sysinfo2float() # store final output stream for case of error real_out = out or sys.stdout def write(s): s += "\n" real_out.write(s) assert iscode(co) co_pypy_str = "PyPy " if is_pypy else "" run_pypy_str = "PyPy " if IS_PYPY else "" sys_version_lines = sys.version.split("\n") if source_encoding: write("# -*- coding: %s -*-" % source_encoding) write("# uncompyle6 version %s\n" "# %sPython bytecode %s%s\n# Decompiled from: %sPython %s" % ( VERSION, co_pypy_str, bytecode_version, " (%s)" % str(magic_int) if magic_int else "", run_pypy_str, "\n# ".join(sys_version_lines), )) if PYTHON_VERSION < 3.0 and bytecode_version >= 3.0: write( '# Warning: this version has problems handling the Python 3 "byte" type in constants properly.\n' ) if co.co_filename: write("# Embedded file name: %s" % co.co_filename, ) if timestamp: write("# Compiled at: %s" % datetime.datetime.fromtimestamp(timestamp)) if source_size: write("# Size of source mod 2**32: %d bytes" % source_size) debug_opts = {"asm": showasm, "ast": showast, "grammar": showgrammar} try: if mapstream: if isinstance(mapstream, str): mapstream = _get_outstream(mapstream) deparsed = deparse_code_with_map( bytecode_version, co, out, showasm, showast, showgrammar, code_objects=code_objects, is_pypy=is_pypy, ) header_count = 3 + len(sys_version_lines) linemap = [(line_no, deparsed.source_linemap[line_no] + header_count) for line_no in sorted(deparsed.source_linemap.keys())] mapstream.write("\n\n# %s\n" % linemap) else: if do_fragments: deparse_fn = code_deparse_fragments else: deparse_fn = code_deparse deparsed = deparse_fn(co, out, bytecode_version, debug_opts=debug_opts, is_pypy=is_pypy) pass return deparsed except pysource.SourceWalkerError as e: # deparsing failed raise pysource.SourceWalkerError(str(e))