diff --git a/uncompyle6/bin/pydisassemble.py b/uncompyle6/bin/pydisassemble.py index eb01d0b7..b2f5862e 100755 --- a/uncompyle6/bin/pydisassemble.py +++ b/uncompyle6/bin/pydisassemble.py @@ -34,7 +34,7 @@ def main(): Usage_short = """usage: %s FILE... Type -h for for full help.""" % program - use_uncompyle6_format = False + native = True if len(sys.argv) == 1: print("No file(s) given", file=sys.stderr) @@ -56,7 +56,7 @@ Type -h for for full help.""" % program print("%s %s" % (program, VERSION)) sys.exit(0) elif opt in ('-U', '--uncompyle6'): - use_uncompyle6_format = True + native = False else: print(opt) print(Usage_short, file=sys.stderr) @@ -65,7 +65,7 @@ Type -h for for full help.""" % program for file in files: if os.path.exists(files[0]): - disassemble_file(file, sys.stdout, use_uncompyle6_format) + disassemble_file(file, sys.stdout, native) else: print("Can't read %s - skipping" % files[0], file=sys.stderr) diff --git a/uncompyle6/disas.py b/uncompyle6/disas.py index 20a76cc2..02ba1a40 100644 --- a/uncompyle6/disas.py +++ b/uncompyle6/disas.py @@ -18,45 +18,52 @@ want to run on Python 2.7. from __future__ import print_function -import os, sys +import datetime, sys from collections import deque import uncompyle6 + +from xdis.main import disassemble_file as xdisassemble_file +from xdis.util import format_code_info from xdis.code import iscode from xdis.load import check_object_path, load_module +from uncompyle6 import PYTHON_VERSION from uncompyle6.scanner import get_scanner -def disco(version, co, out=None, use_uncompyle6_format=False): + +def disco(version, co, timestamp, out=None): """ diassembles and deparses a given code block 'co' """ assert iscode(co) + out.write('# Python bytecode %s (disassembled from Python %s)\n' % + (version, PYTHON_VERSION)) + if timestamp > 0: + value = datetime.datetime.fromtimestamp(timestamp) + out.write(value.strftime('# Timestamp in code: ' + '%Y-%m-%d %H:%M:%S\n')) + # store final output stream for case of error real_out = out or sys.stdout - print('# Python %s' % version, file=real_out) + if co.co_filename: print('# Embedded file name: %s' % co.co_filename, file=real_out) scanner = get_scanner(version) - disasm = scanner.disassemble_native \ - if (not use_uncompyle6_format) and hasattr(scanner, 'disassemble_native') \ - else scanner.disassemble - queue = deque([co]) - disco_loop(disasm, queue, real_out, use_uncompyle6_format) + disco_loop(scanner.disassemble, version, queue, real_out) -def disco_loop(disasm, queue, real_out, use_uncompyle6_format): +def disco_loop(disasm, version, queue, real_out): while len(queue) > 0: co = queue.popleft() - if co.co_name != '': - print('\n# %s line %d of %s' % - (co.co_name, co.co_firstlineno, co.co_filename), - file=real_out) + + print(format_code_info(co, version), file=real_out) + tokens, customize = disasm(co) for t in tokens: if iscode(t.pattr): @@ -74,88 +81,19 @@ def disassemble_file(filename, outstream=None, native=False): If given a Python source file (".py") file, we'll try to find the corresponding compiled object. """ + + if native: + xdisassemble_file(filename, outstream) + return filename = check_object_path(filename) version, timestamp, magic_int, co = load_module(filename) if type(co) == list: for con in co: disco(version, con, outstream, native) else: - disco(version, co, outstream, native) + disco(version, co, timestamp, outstream) co = None -def disassemble_files(in_base, out_base, files, outfile=None, - native=False): - """ - in_base base directory for input files - out_base base directory for output files (ignored when - files list of filenames to be uncompyled (relative to src_base) - outfile write output to this filename (overwrites out_base) - - For redirecting output to - - outfile= (out_base is ignored) - - files below out_base out_base=... - - stdout out_base=None, outfile=None - """ - def _get_outstream(outfile): - dir = os.path.dirname(outfile) - failed_file = outfile + '_failed' - if os.path.exists(failed_file): - os.remove(failed_file) - try: - os.makedirs(dir) - except OSError: - pass - return open(outfile, 'w') - - of = outfile - if outfile == '-': - outfile = None # use stdout - elif outfile and os.path.isdir(outfile): - out_base = outfile; outfile = None - elif outfile: - out_base = outfile; outfile = None - - for filename in files: - infile = os.path.join(in_base, filename) - # print (infile, file=sys.stderr) - - if of: # outfile was given as parameter - outstream = _get_outstream(outfile) - elif out_base is None: - outstream = sys.stdout - else: - outfile = os.path.join(out_base, filename) + '_dis' - outstream = _get_outstream(outfile) - # print(outfile, file=sys.stderr) - pass - - # try to disassemble the input file - try: - disassemble_file(infile, outstream, native) - except KeyboardInterrupt: - if outfile: - outstream.close() - os.remove(outfile) - raise - except: - if outfile: - outstream.close() - os.rename(outfile, outfile + '_failed') - else: - sys.stderr.write("\n# Can't disassemble %s\n" % infile) - import traceback - traceback.print_exc() - else: # uncompyle successfull - if outfile: - outstream.close() - if not outfile: print('\n# okay disassembling', infile) - sys.stdout.flush() - - if outfile: - sys.stdout.write("\n") - sys.stdout.flush() - return - def _test(): """Simple test program to disassemble a file.""" argc = len(sys.argv)