Start Python 2.1 bytecode decompile

This commit is contained in:
rocky
2016-10-07 22:42:30 -04:00
parent 2e1bd2dc13
commit 056f600da1
89 changed files with 128 additions and 31 deletions

View File

@@ -38,7 +38,7 @@ entry_points={
]}
ftp_url = None
install_requires = ['spark-parser >= 1.4.0',
'xdis >= 2.3.0']
'xdis >= 2.3.1']
license = 'MIT'
mailing_list = 'python-debugger@googlegroups.com'
modname = 'uncompyle6'

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
test/bytecode_2.1/exec.pyc Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
test/bytecode_2.1/misc.pyc Normal file

Binary file not shown.

Binary file not shown.

BIN
test/bytecode_2.1/print.pyc Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -78,7 +78,7 @@ for vers in (2.7, 3.4, 3.5, 3.6):
test_options[key] = (os.path.join(src_dir, pythonlib), PYOC, key, vers)
pass
for vers in (2.2, 2.3, 2.4, 2.5, 2.6, 2.7,
for vers in (2.1, 2.2, 2.3, 2.4, 2.5, 2.6, 2.7,
3.1, 3.2, 3.3,
3.4, 3.5, 3.6, 'pypy3.2', 'pypy2.7'):
bytecode = "bytecode_%s" % vers

View File

@@ -553,7 +553,13 @@ def get_python_parser(
# FIXME: there has to be a better way...
if version < 3.0:
if version == 2.2:
if version == 2.1:
import uncompyle6.parsers.parse21 as parse21
if compile_mode == 'exec':
p = parse21.Python21Parser(debug_parser)
else:
p = parse21.Python21ParserSingle(debug_parser)
elif version == 2.2:
import uncompyle6.parsers.parse22 as parse22
if compile_mode == 'exec':
p = parse22.Python22Parser(debug_parser)

View File

@@ -196,16 +196,18 @@ class Python2Parser(PythonParser):
genexpr ::= LOAD_GENEXPR MAKE_FUNCTION_0 expr GET_ITER CALL_FUNCTION_1
'''
# def p_import2(self, args):
# '''
# # These might be relevant for only Python 2.0 or so.
# importstar ::= LOAD_CONST LOAD_CONST IMPORT_NAME_CONT IMPORT_STAR
# importfrom ::= LOAD_CONST LOAD_CONST IMPORT_NAME_CONT importlist2 POP_TOP
# import_as_cont ::= IMPORT_NAME_CONT designator
# import_as_cont ::= IMPORT_NAME_CONT load_attrs designator
# '''
def p_import15(self, args):
'''
stmt ::= importstmt
stmt ::= importfrom
importstmt ::= IMPORT_NAME STORE_FAST
importstmt ::= IMPORT_NAME STORE_NAME
importfrom ::= IMPORT_NAME importlist
importlist ::= importlist IMPORT_FROM
importlist ::= IMPORT_FROM
'''
def p_expr2(self, args):
"""
expr ::= LOAD_LOCALS

View File

@@ -0,0 +1,57 @@
# Copyright (c) 2016 Rocky Bernstein
# Copyright (c) 2000-2002 by hartmut Goebel <hartmut@goebel.noris.de>
from spark_parser import DEFAULT_DEBUG as PARSER_DEFAULT_DEBUG
from uncompyle6.parser import PythonParserSingle
from uncompyle6.parsers.parse22 import Python22Parser
class Python21Parser(Python22Parser):
def __init__(self, debug_parser=PARSER_DEFAULT_DEBUG):
super(Python22Parser, self).__init__(debug_parser)
self.customized = {}
def p_forstmt21(self, args):
"""
_for ::= LOAD_CONST FOR_LOOP
forstmt ::= SETUP_LOOP expr _for designator
return_stmts
POP_BLOCK COME_FROM
forstmt ::= SETUP_LOOP expr _for designator
l_stmts_opt _jump_back
POP_BLOCK COME_FROM
"""
def p_import21(self, args):
'''
# These are be relevant for only Python 2.0 and 2.1
stmt ::= importstmt2
stmt ::= importfrom2
stmt ::= importstar
stmt ::= import_as_cont
stmt ::= import_as
importfrom2 ::= LOAD_CONST IMPORT_NAME importlist2 POP_TOP
importlist2 ::= importlist2 import_as
importstmt2 ::= LOAD_CONST IMPORT_NAME designator
importstmt2 ::= LOAD_CONST IMPORT_NAME IMPORT_FROM designator POP_TOP
importstar ::= LOAD_CONST LOAD_CONST IMPORT_NAME_CONT IMPORT_STAR
importfrom ::= LOAD_CONST LOAD_CONST IMPORT_NAME_CONT importlist2 POP_TOP
import_as ::= LOAD_CONST IMPORT_NAME LOAD_ATTR designator
import_as ::= LOAD_CONST IMPORT_NAME LOAD_ATTR LOAD_ATTR designator
import_as ::= LOAD_CONST IMPORT_NAME LOAD_ATTR LOAD_ATTR LOAD_ATTR designator
import_as ::= IMPORT_FROM designator
import_as_cont ::= LOAD_CONST IMPORT_NAME_CONT designator
import_as_cont ::= IMPORT_NAME_CONT load_attrs designator
'''
class Python21ParserSingle(Python22Parser, PythonParserSingle):
pass
if __name__ == '__main__':
# Check grammar
p = Python21Parser()
p.checkGrammar()
p.dumpGrammar()
# local variables:
# tab-width: 4

View File

@@ -18,7 +18,7 @@ from uncompyle6 import PYTHON3, IS_PYPY
from uncompyle6.scanners.tok import Token
# The byte code versions we support
PYTHON_VERSIONS = (2.2, 2.3, 2.4, 2.5, 2.6, 2.7,
PYTHON_VERSIONS = (2.1, 2.2, 2.3, 2.4, 2.5, 2.6, 2.7,
3.1, 3.2, 3.3, 3.4, 3.5, 3.6)
# FIXME: DRY

View File

@@ -0,0 +1,27 @@
# Copyright (c) 2016 by Rocky Bernstein
"""
Python 2.1 bytecode scanner/deparser
This massages tokenized 2.1 bytecode to make it more amenable for
grammar parsing.
"""
import uncompyle6.scanners.scanner22 as scan
# from uncompyle6.scanners.scanner26 import ingest as ingest26
# bytecode verification, verify(), uses JUMP_OPs from here
from xdis.opcodes import opcode_21
JUMP_OPs = opcode_21.JUMP_OPs
# We base this off of 2.2 instead of the other way around
# because we cleaned things up this way.
# The history is that 2.7 support is the cleanest,
# then from that we got 2.6 and so on.
class Scanner21(scan.Scanner22):
def __init__(self, show_asm=False):
scan.Scanner22.__init__(self, show_asm)
self.opc = opcode_21
self.opname = opcode_21.opname
self.version = 2.1
self.genexpr_name = '<generator expression>';
return

View File

@@ -1,10 +1,9 @@
# Copyright (c) 2016 by Rocky Bernstein
"""
Python 2.2 bytecode scanner/deparser
Python 2.2 bytecode ingester.
This overlaps Python's 2.2's dis module, but it can be run from
Python 3 and other versions of Python. Also, we save token
information for later use in deparsing.
This massages tokenized 2.2 bytecode to make it more amenable for
grammar parsing.
"""
import uncompyle6.scanners.scanner23 as scan

View File

@@ -1,10 +1,9 @@
# Copyright (c) 2015, 2016 by Rocky Bernstein
"""
Python 2.7 bytecode scanner/deparser
Python 2.7 bytecode ingester.
This overlaps Python's 2.7's dis module, but it can be run from
Python 3 and other versions of Python. Also, we save token information
for later use in deparsing.
This massages tokenized 2.7 bytecode to make it more amenable for
grammar parsing.
"""

View File

@@ -564,14 +564,18 @@ class SourceWalker(GenericASTTraversal, object):
TABLE_DIRECT.update({
'tryfinallystmt': ( '%|try:\n%+%c%-%|finally:\n%+%c%-\n\n', 1, 4 )
})
###########################
# Import style for 2.0-2.3
###########################
TABLE_DIRECT.update({
'importstmt20': ( '%|import %c\n', 1),
'importstar20': ( '%|from %[1]{pattr} import *\n', ),
'importfrom20': ( '%|from %[1]{pattr} import %c\n', 2 ),
'importlist20': ( '%C', (0, maxint, ', ') ),
if version == 2.1:
###########################
# Import style for 2.0-2.3
###########################
TABLE_DIRECT.update({
'importstmt2': ( '%|import %c\n', 1),
'import_as_cont': ( '%|import %c as %c\n', 1, 2),
'importstar2': ( '%|from %[1]{pattr} import *\n', ),
'importfrom2': ( '%|from %[1]{pattr} import %c\n', 2 ),
'importlist2': ( '%C', (0, maxint, ', ') ),
'IMPORT_NAME': ( '%{pattr}', ),
'IMPORT_NAME_CONT': ( '%{pattr}', ),
})
elif version >= 2.5:
@@ -1055,13 +1059,17 @@ class SourceWalker(GenericASTTraversal, object):
self.prune()
def n_import_as(self, node):
iname = node[0].pattr
if self.version == 2.1 and node == 'import_as_cont':
self.write("\n", self.indent, "import ")
iname = node[1].pattr if node[0] == 'LOAD_CONST' else node[0].pattr
assert node[-1][-1].type.startswith('STORE_')
sname = node[-1][-1].pattr # assume one of STORE_.... here
if iname == sname or iname.startswith(sname + '.'):
if iname and iname == sname or iname.startswith(sname + '.'):
self.write(iname)
else:
self.write(iname, ' as ', sname)
if self.version == 2.1 and node == 'import_as_cont':
self.write("\n")
self.prune() # stop recursing
n_import_as_cont = n_import_as
@@ -1794,7 +1802,6 @@ class SourceWalker(GenericASTTraversal, object):
"""
# self.println("----> ", startnode.type)
fmt = entry[0]
arg = 1
i = 0