You've already forked python-uncompyle6
mirror of
https://github.com/rocky/python-uncompyle6.git
synced 2025-08-03 16:59:52 +08:00
Merge branch 'master' of github.com:rocky/python-uncompyle6
Conflicts: uncompyle6/parsers/parse26.py
This commit is contained in:
14
HISTORY.md
14
HISTORY.md
@@ -93,8 +93,18 @@ so. Then hamled made a few commits earler on, while Eike Siewertsen
|
|||||||
made a few commits later on. But mostly wibiti, and Guenther
|
made a few commits later on. But mostly wibiti, and Guenther
|
||||||
Starnberger got the code to where uncompyle2 was around 2012.
|
Starnberger got the code to where uncompyle2 was around 2012.
|
||||||
|
|
||||||
This project, uncompyle6, however owes its existence to the fork of
|
In uncompyle2 decompilation of python bytecode 2.5 & 2.6 is done by
|
||||||
uncompyle2 by Myst herie (Mysterie) whose first commit picks up at
|
transforming the byte code into a a pseudo 2.7 python bytecode and is
|
||||||
|
based on code from Eloi Vanderbeken.
|
||||||
|
|
||||||
|
This project, uncompyle6, abandons that approach for various
|
||||||
|
reasons. However the main reason is that we need offsets in fragment
|
||||||
|
deparsing to be exactly the same, and the transformation process can
|
||||||
|
remove instructions. Adding instructions with psuedo_offsets is
|
||||||
|
however okay.
|
||||||
|
|
||||||
|
Uncompyle6, however owes its existence to the fork of uncompyle2 by
|
||||||
|
Myst herie (Mysterie) whose first commit picks up at
|
||||||
2012. I chose this since it seemed to have been at that time the most
|
2012. I chose this since it seemed to have been at that time the most
|
||||||
actively, if briefly, worked on. Also starting around 2012 is Dark
|
actively, if briefly, worked on. Also starting around 2012 is Dark
|
||||||
Fenx's uncompyle3 which I used for inspiration for Python3 support.
|
Fenx's uncompyle3 which I used for inspiration for Python3 support.
|
||||||
|
@@ -86,11 +86,12 @@ Known Bugs/Restrictions
|
|||||||
|
|
||||||
Python 2 deparsing decompiles each and all the Python 2.7.10 and
|
Python 2 deparsing decompiles each and all the Python 2.7.10 and
|
||||||
2.7.11 installed packages I have on my system, more than 90% verify
|
2.7.11 installed packages I have on my system, more than 90% verify
|
||||||
ok. Some of these failures may be bugs in the verification process. So
|
ok. Some of these failures may be bugs in the verification process.
|
||||||
as such, it is probably a little better than uncompyle2. Other Python
|
So as such, it is probably a little better than uncompyle2. Python 2.6
|
||||||
2 versions do worse.
|
is catching up the versions of uncompyle2 that support 2.6 but is
|
||||||
|
currently worse. Even less good is Python 2.5 bytecodes.
|
||||||
|
|
||||||
All of the Python 3.2-3.5.4 Python standard lib packages that I have
|
All of the Python 3.2-3.5 Python standard lib packages that I have
|
||||||
installed on my system deparse. Each Python version has about 200
|
installed on my system deparse. Each Python version has about 200
|
||||||
bytecode files. I'm not sure how well these verify though.
|
bytecode files. I'm not sure how well these verify though.
|
||||||
|
|
||||||
|
@@ -199,13 +199,7 @@ class PythonParser(GenericASTBuilder):
|
|||||||
_jump ::= JUMP_FORWARD
|
_jump ::= JUMP_FORWARD
|
||||||
_jump ::= JUMP_BACK
|
_jump ::= JUMP_BACK
|
||||||
|
|
||||||
# Note: Python < 2.7 doesn't have POP_JUMP_IF ...
|
# Zero or more COME_FROMs
|
||||||
# FIXME: segregate 2.7+
|
|
||||||
|
|
||||||
jmp_false ::= POP_JUMP_IF_FALSE
|
|
||||||
jmp_true ::= POP_JUMP_IF_TRUE
|
|
||||||
|
|
||||||
# Zero or more COME_FROM
|
|
||||||
# loops can have this
|
# loops can have this
|
||||||
_come_from ::= _come_from COME_FROM
|
_come_from ::= _come_from COME_FROM
|
||||||
_come_from ::=
|
_come_from ::=
|
||||||
|
@@ -69,8 +69,6 @@ class Python26Parser(Python2Parser):
|
|||||||
# after one of these jumps
|
# after one of these jumps
|
||||||
def p_jumps26(self, args):
|
def p_jumps26(self, args):
|
||||||
"""
|
"""
|
||||||
jmp_false ::= JUMP_IF_FALSE
|
|
||||||
jmp_true ::= JUMP_IF_TRUE
|
|
||||||
jmp_true ::= JUMP_IF_TRUE POP_TOP
|
jmp_true ::= JUMP_IF_TRUE POP_TOP
|
||||||
jmp_false ::= JUMP_IF_FALSE POP_TOP
|
jmp_false ::= JUMP_IF_FALSE POP_TOP
|
||||||
jf_pop ::= JUMP_FORWARD come_from_pop
|
jf_pop ::= JUMP_FORWARD come_from_pop
|
||||||
@@ -84,7 +82,8 @@ class Python26Parser(Python2Parser):
|
|||||||
ja_cf_pop ::= JUMP_ABSOLUTE come_from_pop
|
ja_cf_pop ::= JUMP_ABSOLUTE come_from_pop
|
||||||
jf_cf_pop ::= JUMP_FORWARD come_froms POP_TOP
|
jf_cf_pop ::= JUMP_FORWARD come_froms POP_TOP
|
||||||
|
|
||||||
jb_bp_come_from ::= JUMP_BACK POP_BLOCK COME_FROM
|
bp_come_from ::= POP_BLOCK COME_FROM
|
||||||
|
jb_bp_come_from ::= JUMP_BACK bp_come_from
|
||||||
|
|
||||||
_ifstmts_jump ::= c_stmts_opt jf_pop COME_FROM
|
_ifstmts_jump ::= c_stmts_opt jf_pop COME_FROM
|
||||||
_ifstmts_jump ::= c_stmts_opt JUMP_FORWARD COME_FROM come_from_pop
|
_ifstmts_jump ::= c_stmts_opt JUMP_FORWARD COME_FROM come_from_pop
|
||||||
@@ -94,6 +93,7 @@ class Python26Parser(Python2Parser):
|
|||||||
# we start a new block. For reasons I don't fully
|
# we start a new block. For reasons I don't fully
|
||||||
# understand, there is also a value on the top of the stack
|
# understand, there is also a value on the top of the stack
|
||||||
come_from_pop ::= COME_FROM POP_TOP
|
come_from_pop ::= COME_FROM POP_TOP
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def p_stmt26(self, args):
|
def p_stmt26(self, args):
|
||||||
@@ -134,11 +134,10 @@ class Python26Parser(Python2Parser):
|
|||||||
SETUP_FINALLY LOAD_FAST DELETE_FAST
|
SETUP_FINALLY LOAD_FAST DELETE_FAST
|
||||||
|
|
||||||
whilestmt ::= SETUP_LOOP testexpr l_stmts_opt jb_pop POP_BLOCK _come_from
|
whilestmt ::= SETUP_LOOP testexpr l_stmts_opt jb_pop POP_BLOCK _come_from
|
||||||
|
whilestmt ::= SETUP_LOOP testexpr l_stmts_opt jb_cf_pop bp_come_from
|
||||||
|
whilestmt ::= SETUP_LOOP testexpr return_stmts come_froms POP_TOP bp_come_from
|
||||||
|
|
||||||
whilestmt ::= SETUP_LOOP testexpr l_stmts_opt jb_cf_pop POP_BLOCK COME_FROM
|
while1stmt ::= SETUP_LOOP return_stmts bp_come_from
|
||||||
whilestmt ::= SETUP_LOOP testexpr return_stmts come_froms POP_TOP POP_BLOCK COME_FROM
|
|
||||||
|
|
||||||
while1stmt ::= SETUP_LOOP return_stmts POP_BLOCK COME_FROM
|
|
||||||
|
|
||||||
return_stmt ::= ret_expr RETURN_END_IF come_from_pop
|
return_stmt ::= ret_expr RETURN_END_IF come_from_pop
|
||||||
return_stmt ::= ret_expr RETURN_VALUE come_from_pop
|
return_stmt ::= ret_expr RETURN_VALUE come_from_pop
|
||||||
|
@@ -30,9 +30,11 @@ class Python27Parser(Python2Parser):
|
|||||||
jmp_false POP_TOP designator POP_TOP
|
jmp_false POP_TOP designator POP_TOP
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def p_misc27(self, args):
|
def p_jump27(self, args):
|
||||||
"""
|
"""
|
||||||
_ifstmts_jump ::= c_stmts_opt JUMP_FORWARD COME_FROM
|
_ifstmts_jump ::= c_stmts_opt JUMP_FORWARD COME_FROM
|
||||||
|
jmp_false ::= POP_JUMP_IF_FALSE
|
||||||
|
jmp_true ::= POP_JUMP_IF_TRUE
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
@@ -247,6 +247,8 @@ class Python3Parser(PythonParser):
|
|||||||
"""
|
"""
|
||||||
come_froms ::= come_froms COME_FROM
|
come_froms ::= come_froms COME_FROM
|
||||||
come_froms ::= COME_FROM
|
come_froms ::= COME_FROM
|
||||||
|
jmp_false ::= POP_JUMP_IF_FALSE
|
||||||
|
jmp_true ::= POP_JUMP_IF_TRUE
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def p_stmt3(self, args):
|
def p_stmt3(self, args):
|
||||||
|
@@ -557,6 +557,8 @@ class Scanner2(scan.Scanner):
|
|||||||
# not myself? If so, it's part of a larger conditional.
|
# not myself? If so, it's part of a larger conditional.
|
||||||
# rocky: if we have a conditional jump to the next instruction, then
|
# rocky: if we have a conditional jump to the next instruction, then
|
||||||
# possibly I am "skipping over" a "pass" or null statement.
|
# possibly I am "skipping over" a "pass" or null statement.
|
||||||
|
|
||||||
|
## FIXME: need to handle <2.7 which has this as two instructions.
|
||||||
if ( code[pre[target]] in
|
if ( code[pre[target]] in
|
||||||
(self.pop_jump_if_or_pop | self.pop_jump_if)
|
(self.pop_jump_if_or_pop | self.pop_jump_if)
|
||||||
and (target > pos) ):
|
and (target > pos) ):
|
||||||
|
@@ -272,6 +272,8 @@ class Scanner26(scan.Scanner2):
|
|||||||
if offset in self.load_asserts:
|
if offset in self.load_asserts:
|
||||||
op_name = 'LOAD_ASSERT'
|
op_name = 'LOAD_ASSERT'
|
||||||
elif op == self.opc.RETURN_VALUE:
|
elif op == self.opc.RETURN_VALUE:
|
||||||
|
# FIXME: return_end_ifs calculation is off.
|
||||||
|
# not taking into account "and" expressions
|
||||||
if offset in self.return_end_ifs:
|
if offset in self.return_end_ifs:
|
||||||
op_name = 'RETURN_END_IF'
|
op_name = 'RETURN_END_IF'
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user