You've already forked python-uncompyle6
mirror of
https://github.com/rocky/python-uncompyle6.git
synced 2025-08-03 16:59:52 +08:00
Make use of xdis routines in disassembly
This commit is contained in:
@@ -34,7 +34,7 @@ def main():
|
|||||||
Usage_short = """usage: %s FILE...
|
Usage_short = """usage: %s FILE...
|
||||||
Type -h for for full help.""" % program
|
Type -h for for full help.""" % program
|
||||||
|
|
||||||
use_uncompyle6_format = False
|
native = True
|
||||||
|
|
||||||
if len(sys.argv) == 1:
|
if len(sys.argv) == 1:
|
||||||
print("No file(s) given", file=sys.stderr)
|
print("No file(s) given", file=sys.stderr)
|
||||||
@@ -56,7 +56,7 @@ Type -h for for full help.""" % program
|
|||||||
print("%s %s" % (program, VERSION))
|
print("%s %s" % (program, VERSION))
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
elif opt in ('-U', '--uncompyle6'):
|
elif opt in ('-U', '--uncompyle6'):
|
||||||
use_uncompyle6_format = True
|
native = False
|
||||||
else:
|
else:
|
||||||
print(opt)
|
print(opt)
|
||||||
print(Usage_short, file=sys.stderr)
|
print(Usage_short, file=sys.stderr)
|
||||||
@@ -65,7 +65,7 @@ Type -h for for full help.""" % program
|
|||||||
|
|
||||||
for file in files:
|
for file in files:
|
||||||
if os.path.exists(files[0]):
|
if os.path.exists(files[0]):
|
||||||
disassemble_file(file, sys.stdout, use_uncompyle6_format)
|
disassemble_file(file, sys.stdout, native)
|
||||||
else:
|
else:
|
||||||
print("Can't read %s - skipping" % files[0],
|
print("Can't read %s - skipping" % files[0],
|
||||||
file=sys.stderr)
|
file=sys.stderr)
|
||||||
|
@@ -18,45 +18,52 @@ want to run on Python 2.7.
|
|||||||
|
|
||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
|
|
||||||
import os, sys
|
import datetime, sys
|
||||||
from collections import deque
|
from collections import deque
|
||||||
|
|
||||||
import uncompyle6
|
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.code import iscode
|
||||||
from xdis.load import check_object_path, load_module
|
from xdis.load import check_object_path, load_module
|
||||||
|
from uncompyle6 import PYTHON_VERSION
|
||||||
from uncompyle6.scanner import get_scanner
|
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'
|
diassembles and deparses a given code block 'co'
|
||||||
"""
|
"""
|
||||||
|
|
||||||
assert iscode(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
|
# store final output stream for case of error
|
||||||
real_out = out or sys.stdout
|
real_out = out or sys.stdout
|
||||||
print('# Python %s' % version, file=real_out)
|
|
||||||
if co.co_filename:
|
if co.co_filename:
|
||||||
print('# Embedded file name: %s' % co.co_filename,
|
print('# Embedded file name: %s' % co.co_filename,
|
||||||
file=real_out)
|
file=real_out)
|
||||||
|
|
||||||
scanner = get_scanner(version)
|
scanner = get_scanner(version)
|
||||||
|
|
||||||
disasm = scanner.disassemble_native \
|
|
||||||
if (not use_uncompyle6_format) and hasattr(scanner, 'disassemble_native') \
|
|
||||||
else scanner.disassemble
|
|
||||||
|
|
||||||
queue = deque([co])
|
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:
|
while len(queue) > 0:
|
||||||
co = queue.popleft()
|
co = queue.popleft()
|
||||||
if co.co_name != '<module>':
|
|
||||||
print('\n# %s line %d of %s' %
|
print(format_code_info(co, version), file=real_out)
|
||||||
(co.co_name, co.co_firstlineno, co.co_filename),
|
|
||||||
file=real_out)
|
|
||||||
tokens, customize = disasm(co)
|
tokens, customize = disasm(co)
|
||||||
for t in tokens:
|
for t in tokens:
|
||||||
if iscode(t.pattr):
|
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
|
If given a Python source file (".py") file, we'll
|
||||||
try to find the corresponding compiled object.
|
try to find the corresponding compiled object.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
if native:
|
||||||
|
xdisassemble_file(filename, outstream)
|
||||||
|
return
|
||||||
filename = check_object_path(filename)
|
filename = check_object_path(filename)
|
||||||
version, timestamp, magic_int, co = load_module(filename)
|
version, timestamp, magic_int, co = load_module(filename)
|
||||||
if type(co) == list:
|
if type(co) == list:
|
||||||
for con in co:
|
for con in co:
|
||||||
disco(version, con, outstream, native)
|
disco(version, con, outstream, native)
|
||||||
else:
|
else:
|
||||||
disco(version, co, outstream, native)
|
disco(version, co, timestamp, outstream)
|
||||||
co = None
|
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
|
|
||||||
- <filename> outfile=<filename> (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():
|
def _test():
|
||||||
"""Simple test program to disassemble a file."""
|
"""Simple test program to disassemble a file."""
|
||||||
argc = len(sys.argv)
|
argc = len(sys.argv)
|
||||||
|
Reference in New Issue
Block a user