From 3956a5a709ab468c1753de2d6b58ad31beb28cc1 Mon Sep 17 00:00:00 2001 From: Mysterie Date: Fri, 14 Dec 2012 17:22:59 +0100 Subject: [PATCH] modification of LIST_APPEND opcode handling --- uncompyle2/opcode/opcode_25.py | 7 +- uncompyle2/opcode/opcode_26.py | 7 +- uncompyle2/opcode/opcode_27.py | 2 + uncompyle2/scanner.py | 9 +- uncompyle2/scanner25.py | 236 ++++++++++++++++++++------------- uncompyle2/scanner26.py | 218 +++++++++++++++++++----------- uncompyle2/scanner27.py | 6 + 7 files changed, 308 insertions(+), 177 deletions(-) diff --git a/uncompyle2/opcode/opcode_25.py b/uncompyle2/opcode/opcode_25.py index 94a668a7..e75e50f9 100755 --- a/uncompyle2/opcode/opcode_25.py +++ b/uncompyle2/opcode/opcode_25.py @@ -13,6 +13,7 @@ hasjabs = [] haslocal = [] hascompare = [] hasfree = [] +hasArgumentExtended = [] PJIF = PJIT = JA = JF = 0 opmap = {} @@ -37,6 +38,10 @@ def jabs_op(name, op): def_op(name, op) hasjabs.append(op) +def def_extArg(name, op): + def_op(name, op) + hasArgumentExtended.append(op) + def updateGlobal(): globals().update({'PJIF': opmap['JUMP_IF_FALSE']}) globals().update({'PJIT': opmap['JUMP_IF_TRUE']}) @@ -63,7 +68,7 @@ def_op('UNARY_CONVERT', 13) # 25 def_op('UNARY_INVERT', 15) # 34 -def_op('LIST_APPEND', 18) # 68 +def_extArg('LIST_APPEND', 18) # 68 def_op('BINARY_POWER', 19) # 28 def_op('BINARY_MULTIPLY', 20) # 36 def_op('BINARY_DIVIDE', 21) # 12 diff --git a/uncompyle2/opcode/opcode_26.py b/uncompyle2/opcode/opcode_26.py index 250f8eda..29ed55ab 100755 --- a/uncompyle2/opcode/opcode_26.py +++ b/uncompyle2/opcode/opcode_26.py @@ -13,6 +13,7 @@ hasjabs = [] haslocal = [] hascompare = [] hasfree = [] +hasArgumentExtended = [] PJIF = PJIT = JA = JF = 0 opmap = {} @@ -37,6 +38,10 @@ def jabs_op(name, op): def_op(name, op) hasjabs.append(op) +def def_extArg(name, op): + def_op(name, op) + hasArgumentExtended.append(op) + def updateGlobal(): globals().update({'PJIF': opmap['JUMP_IF_FALSE']}) globals().update({'PJIT': opmap['JUMP_IF_TRUE']}) @@ -63,7 +68,7 @@ def_op('UNARY_CONVERT', 13) def_op('UNARY_INVERT', 15) -def_op('LIST_APPEND', 18) +def_extArg('LIST_APPEND', 18) def_op('BINARY_POWER', 19) def_op('BINARY_MULTIPLY', 20) def_op('BINARY_DIVIDE', 21) diff --git a/uncompyle2/opcode/opcode_27.py b/uncompyle2/opcode/opcode_27.py index 05b655b2..c1d17a21 100755 --- a/uncompyle2/opcode/opcode_27.py +++ b/uncompyle2/opcode/opcode_27.py @@ -13,6 +13,7 @@ hasjabs = [] haslocal = [] hascompare = [] hasfree = [] +hasArgumentExtended = [] PJIF = PJIT = JA = JF = 0 opmap = {} @@ -133,6 +134,7 @@ name_op('DELETE_NAME', 91) # "" def_op('UNPACK_SEQUENCE', 92) # Number of tuple items jrel_op('FOR_ITER', 93) def_op('LIST_APPEND', 94) + name_op('STORE_ATTR', 95) # Index in name list name_op('DELETE_ATTR', 96) # "" name_op('STORE_GLOBAL', 97) # "" diff --git a/uncompyle2/scanner.py b/uncompyle2/scanner.py index 6caf3401..13dcedd8 100755 --- a/uncompyle2/scanner.py +++ b/uncompyle2/scanner.py @@ -206,13 +206,16 @@ class Scanner(object): elif t == target: result.append(i) return result - + def op_size(self, op): - if op < self.opc.HAVE_ARGUMENT: + if op < self.opc.HAVE_ARGUMENT and op not in self.opc.hasArgumentExtended: return 1 else: return 3 - + + def op_hasArgument(self, op): + return self.op_size(op) > 1 + def op_range(self, start, end): while start < end: yield start diff --git a/uncompyle2/scanner25.py b/uncompyle2/scanner25.py index bb4d52af..baf103d9 100755 --- a/uncompyle2/scanner25.py +++ b/uncompyle2/scanner25.py @@ -31,13 +31,10 @@ class Scanner25(scan.Scanner): customize = {} Token = self.Token # shortcut self.code = array('B', co.co_code) - n = len(self.code) # linestarts contains bloc code adresse (addr,block) self.linestarts = list(dis.findlinestarts(co)) self.prev = [0] - # change jump struct - self.restructRelativeJump() - + # class and names if classname: classname = '_' + classname.lstrip('_') + '__' @@ -54,40 +51,18 @@ class Scanner25(scan.Scanner): names = co.co_names varnames = co.co_varnames self.names = names - # add instruction to remonde in "toDel" list - toDel = [] - # add instruction to change in "toChange" list + + # list of instruction to remove/add or change to match with bytecode 2.7 self.toChange = [] - for i in self.op_range(0, n): - op = self.code[i] - ret = self.getOpcodeToDel(i) - if ret != None: - toDel += ret - - #self.print_bytecode() - - if toDel: - toDel = sorted(list(set(toDel))) - delta = 0 - self.restructCode(toDel) - for x in toDel: - if self.code[x-delta] >= HAVE_ARGUMENT: - self.code.pop(x-delta) - self.code.pop(x-delta) - self.code.pop(x-delta) - delta += 3 - else: - self.code.pop(x-delta) - delta += 1 - + self.restructBytecode() + codelen = len(self.code) # mapping adresses of prev instru - n = len(self.code) - for i in self.op_range(0, n): + for i in self.op_range(0, codelen): op = self.code[i] self.prev.append(i) - if op >= HAVE_ARGUMENT: - self.prev.append(i) + if self.op_hasArgument(op): self.prev.append(i) + self.prev.append(i) j = 0 linestarts = self.linestarts self.lines = [] @@ -100,17 +75,16 @@ class Scanner25(scan.Scanner): j += 1 last_op = self.code[self.prev[start_byte]] (prev_start_byte, prev_line_no) = (start_byte, line_no) - while j < n: - self.lines.append(linetuple(prev_line_no, n)) + while j < codelen: + self.lines.append(linetuple(prev_line_no, codelen)) j+=1 # self.lines contains (block,addrLastInstr) cf = self.find_jump_targets(self.code) # contains (code, [addrRefToCode]) - last_stmt = self.next_stmt[0] i = self.next_stmt[last_stmt] replace = {} - while i < n-1: + while i < codelen-1: if self.lines[last_stmt].next > i: if self.code[last_stmt] == PRINT_ITEM: if self.code[i] == PRINT_ITEM: @@ -120,7 +94,7 @@ class Scanner25(scan.Scanner): last_stmt = i i = self.next_stmt[i] - imports = self.all_instr(0, n, (IMPORT_NAME, IMPORT_FROM, IMPORT_STAR)) + imports = self.all_instr(0, codelen, (IMPORT_NAME, IMPORT_FROM, IMPORT_STAR)) if len(imports) > 1: last_import = imports[0] for i in imports[1:]: @@ -130,7 +104,7 @@ class Scanner25(scan.Scanner): last_import = i extended_arg = 0 - for offset in self.op_range(0, n): + for offset in self.op_range(0, codelen): op = self.code[offset] op_name = opname[op] oparg = None; pattr = None @@ -141,7 +115,7 @@ class Scanner25(scan.Scanner): rv.append(Token('COME_FROM', None, repr(j), offset="%s_%d" % (offset, k) )) k += 1 - if op >= HAVE_ARGUMENT: + if self.op_hasArgument(op): oparg = self.get_argument(offset) + extended_arg extended_arg = 0 if op == EXTENDED_ARG: @@ -238,6 +212,10 @@ class Scanner25(scan.Scanner): ''' opcode = self.code[i] opsize = self.op_size(opcode) + + if i+opsize >= len(self.code): + return None + if opcode == EXTENDED_ARG: raise 'TODO' # del POP_TOP @@ -288,7 +266,7 @@ class Scanner25(scan.Scanner): end += self.op_size(LOAD_FAST) # log JA/POP_TOP to del and update PJIF while start < end: - start = self.first_instr(start, len(self.code), (PJIF,PJIT)) + start = self.first_instr(start, end, (PJIF,PJIT)) # end = len(self.code) if start == None: break target = self.get_target(start) if self.code[target] == POP_TOP and self.code[target-3] == JA: @@ -357,65 +335,144 @@ class Scanner25(scan.Scanner): return toDel return None - def restructRelativeJump(self): - ''' - change relative JUMP_IF_FALSE/TRUE to absolut jump - and remap the target of PJIF/PJIT - ''' - - for i in self.op_range(0, len(self.code)): - if(self.code[i] in (PJIF,PJIT)): - target = self.get_argument(i) - target += i + 3 - self.restructJump(i, target) - - for i in self.op_range(0, len(self.code)): - if(self.code[i] in (PJIF,PJIT)): - target = self.get_target(i) - if self.code[target] == JA: - target = self.get_target(target) - self.restructJump(i, target) - - def restructCode(self, listDel): - ''' - restruct linestarts and jump destination after removing bad opcode - ''' + def getOpcodeToExp(self): + # we handle listExp, if opcode have to be resized + listExp = [] + i=0 + while i < len(self.code): # we can't use op_range for the moment + op = self.code[i] + if op in self.opc.hasArgumentExtended: + listExp += [i] + elif self.op_hasArgument(op): + i+=2 + i+=1 + return listExp + def restructCode(self, listDel, listExp): + ''' + restruct linestarts and jump destination + ''' + # restruct linestarts with deleted / modificated opcode result = list() for block in self.linestarts: startBlock = 0 for toDel in listDel: if toDel < block[0]: startBlock -= self.op_size(self.code[toDel]) - else: - break + for toExp in listExp: + if toExp < block[0]: + startBlock += 2 result.append((block[0]+startBlock, block[1])) self.linestarts = result - + # handle opcodeToChange deplacement for index in xrange(len(self.toChange)): change = self.toChange[index] delta = 0 for toDel in listDel: if change > toDel: - delta += self.op_size(self.code[toDel]) - else: - break - self.toChange[index] -= delta + delta -= self.op_size(self.code[toDel]) + for toExp in listExp: + if change > toExp: + delta += 2 + self.toChange[index] += delta + # restruct jmp opcode + if listDel: + for jmp in self.op_range(0, len(self.code)): + op = self.code[jmp] + if op in hasjrel+hasjabs: + offset = 0 + jmpTarget = self.get_target(jmp) + for toDel in listDel: + if toDel < jmpTarget: + if op in hasjabs or jmp < toDel: + offset-=self.op_size(self.code[toDel]) + self.restructJump(jmp, jmpTarget+offset) + if listExp: + jmp = 0 + while jmp < len(self.code): # we can't use op_range for the moment + op = self.code[jmp] + if op in hasjrel+hasjabs: + offset = 0 + jmpTarget = self.get_target(jmp) + for toExp in listExp: + if toExp < jmpTarget: + if op in hasjabs or jmp < toExp: + offset+=2 + self.restructJump(jmp, jmpTarget+offset) + if self.op_hasArgument(op) and op not in self.opc.hasArgumentExtended: + jmp += 3 + else: jmp += 1 + + def restructBytecode(self): + ''' + add/change/delete bytecode for suiting bytecode 2.7 + ''' + # we can't use op_range for the moment + # convert jump opcode to 2.7 + self.restructRelativeJump() - for jmp in self.op_range(0, len(self.code)): - op = self.code[jmp] - if op in hasjrel+hasjabs: # jmp - offset = 0 - jmpTarget = self.get_target(jmp) - for toDel in listDel: - if toDel < jmpTarget: - if op in hasjabs: - offset-=self.op_size(self.code[toDel]) - elif jmp < toDel: - offset-=self.op_size(self.code[toDel]) - else: - break - self.restructJump(jmp, self.get_target(jmp)+offset) + listExp = self.getOpcodeToExp() + # change code structure + if listExp: + listExp = sorted(list(set(listExp))) + self.restructCode([], listExp) + # we add arg to expended opcode + offset=0 + for toExp in listExp: + self.code.insert(toExp+offset+1, 0) + self.code.insert(toExp+offset+1, 0) + offset+=2 + # op_range is now ok :) + # add instruction to change in "toChange" list + MAJ toDel + listDel = [] + for i in self.op_range(0, len(self.code)): + ret = self.getOpcodeToDel(i) + if ret != None: + listDel += ret + + # change code structure after deleting byte + if listDel: + listDel = sorted(list(set(listDel))) + self.restructCode(listDel, []) + # finaly we delete useless opcode + delta = 0 + for x in listDel: + if self.op_hasArgument(self.code[x-delta]): + self.code.pop(x-delta) + self.code.pop(x-delta) + self.code.pop(x-delta) + delta += 3 + else: + self.code.pop(x-delta) + delta += 1 + + def restructRelativeJump(self): + ''' + change relative JUMP_IF_FALSE/TRUE to absolut jump + and remap the target of PJIF/PJIT + ''' + i=0 + while i < len(self.code): # we can't use op_range for the moment + op = self.code[i] + if(op in (PJIF,PJIT)): + target = self.get_argument(i) + target += i + 3 + self.restructJump(i, target) + if self.op_hasArgument(op) and op not in self.opc.hasArgumentExtended: + i += 3 + else: i += 1 + + i=0 + while i < len(self.code): # we can't use op_range for the moment + op = self.code[i] + if(op in (PJIF,PJIT)): + target = self.get_target(i) + if self.code[target] == JA: + target = self.get_target(target) + self.restructJump(i, target) + if self.op_hasArgument(op) and op not in self.opc.hasArgumentExtended: + i += 3 + else: i += 1 def restructJump(self, pos, newTarget): if not (self.code[pos] in hasjabs+hasjrel): @@ -428,7 +485,7 @@ class Scanner25(scan.Scanner): raise 'TODO' self.code[pos+2] = (target >> 8) & 0xFF self.code[pos+1] = target & 0xFF - + def build_stmt_indices(self): code = self.code start = 0; @@ -442,7 +499,7 @@ class Scanner25(scan.Scanner): STORE_ATTR, DELETE_ATTR, STORE_SUBSCR, DELETE_SUBSCR, RETURN_VALUE, RAISE_VARARGS, POP_TOP, PRINT_EXPR, PRINT_ITEM, PRINT_NEWLINE, PRINT_ITEM_TO, PRINT_NEWLINE_TO, - JUMP_ABSOLUTE, EXEC_STMT, + JUMP_ABSOLUTE, EXEC_STMT } stmt_opcode_seqs = [(PJIF, JF), (PJIF, JA), (PJIT, JF), (PJIT, JA)] @@ -539,8 +596,6 @@ class Scanner25(scan.Scanner): in python2.3+ ''' - # TODO: check the struct boundaries more precisely -Dan - code = self.code # Ev remove this test and make op a mandatory argument -Dan if op is None: @@ -630,7 +685,6 @@ class Scanner25(scan.Scanner): end = self.restrict_to_parent(target, parent) if target != end: self.fixed_jumps[pos] = end - #print target, end, parent ## Add the try block self.structs.append({'type': 'try', 'start': start, @@ -808,7 +862,7 @@ class Scanner25(scan.Scanner): ## Determine structures and fix jumps for 2.3+ self.detect_structure(i, op) - if op >= HAVE_ARGUMENT: + if self.op_hasArgument(op): label = self.fixed_jumps.get(i) oparg = self.get_argument(i) if label is None: diff --git a/uncompyle2/scanner26.py b/uncompyle2/scanner26.py index 73e7c75a..7f093e19 100755 --- a/uncompyle2/scanner26.py +++ b/uncompyle2/scanner26.py @@ -32,12 +32,9 @@ class Scanner26(scan.Scanner): customize = {} Token = self.Token # shortcut self.code = array('B', co.co_code) - n = len(self.code) # linestarts contains bloc code adresse (addr,block) self.linestarts = list(dis.findlinestarts(co)) self.prev = [0] - # change jump struct - self.restructRelativeJump() # class and names if classname: classname = '_' + classname.lstrip('_') + '__' @@ -55,41 +52,19 @@ class Scanner26(scan.Scanner): varnames = co.co_varnames self.names = names - # add instruction to remonde in "toDel" list - toDel = [] - # add instruction to change in "toChange" list + # list of instruction to remove/add or change to match with bytecode 2.7 self.toChange = [] - for i in self.op_range(0, n): - op = self.code[i] - ret = self.getOpcodeToDel(i) - if ret != None: - toDel += ret - if toDel: - toDel = sorted(list(set(toDel))) - delta = 0 - self.restructCode(toDel) - for x in toDel: - if self.code[x-delta] >= HAVE_ARGUMENT: - self.code.pop(x-delta) - self.code.pop(x-delta) - self.code.pop(x-delta) - delta += 3 - else: - self.code.pop(x-delta) - delta += 1 - - # mapping adresses of prev instru - n = len(self.code) - for i in self.op_range(0, n): + self.restructBytecode() + codelen = len(self.code) + # mapping adresses of prev instru + for i in self.op_range(0, codelen): op = self.code[i] self.prev.append(i) - if op >= HAVE_ARGUMENT: + if self.op_hasArgument(op): self.prev.append(i) self.prev.append(i) - j = 0 linestarts = self.linestarts - self.lines = [] linetuple = namedtuple('linetuple', ['l_no', 'next']) linestartoffsets = {a for (a, _) in linestarts} @@ -100,8 +75,8 @@ class Scanner26(scan.Scanner): j += 1 last_op = self.code[self.prev[start_byte]] (prev_start_byte, prev_line_no) = (start_byte, line_no) - while j < n: - self.lines.append(linetuple(prev_line_no, n)) + while j < codelen: + self.lines.append(linetuple(prev_line_no, codelen)) j+=1 # self.lines contains (block,addrLastInstr) cf = self.find_jump_targets(self.code) @@ -110,7 +85,7 @@ class Scanner26(scan.Scanner): last_stmt = self.next_stmt[0] i = self.next_stmt[last_stmt] replace = {} - while i < n-1: + while i < codelen-1: if self.lines[last_stmt].next > i: if self.code[last_stmt] == PRINT_ITEM: if self.code[i] == PRINT_ITEM: @@ -120,7 +95,7 @@ class Scanner26(scan.Scanner): last_stmt = i i = self.next_stmt[i] - imports = self.all_instr(0, n, (IMPORT_NAME, IMPORT_FROM, IMPORT_STAR)) + imports = self.all_instr(0, codelen, (IMPORT_NAME, IMPORT_FROM, IMPORT_STAR)) if len(imports) > 1: last_import = imports[0] for i in imports[1:]: @@ -130,7 +105,7 @@ class Scanner26(scan.Scanner): last_import = i extended_arg = 0 - for offset in self.op_range(0, n): + for offset in self.op_range(0, codelen): op = self.code[offset] op_name = opname[op] oparg = None; pattr = None @@ -141,7 +116,7 @@ class Scanner26(scan.Scanner): rv.append(Token('COME_FROM', None, repr(j), offset="%s_%d" % (offset, k) )) k += 1 - if op >= HAVE_ARGUMENT: + if self.op_hasArgument(op): oparg = self.get_argument(offset) + extended_arg extended_arg = 0 if op == EXTENDED_ARG: @@ -296,7 +271,7 @@ class Scanner26(scan.Scanner): end += self.op_size(LOAD_FAST) # log JA/POP_TOP to del and update PJIF while start < end: - start = self.first_instr(start, len(self.code), (PJIF,PJIT)) + start = self.first_instr(start, end, (PJIF,PJIT)) if start == None: break target = self.get_target(start) if self.code[target] == POP_TOP and self.code[target-3] == JA: @@ -356,64 +331,145 @@ class Scanner26(scan.Scanner): return toDel return None - def restructRelativeJump(self): - ''' - change relative JUMP_IF_FALSE/TRUE to absolut jump - and remap the target of PJIF/PJIT - ''' - for i in self.op_range(0, len(self.code)): - if(self.code[i] in (PJIF,PJIT)): - target = self.get_argument(i) - target += i + 3 - self.restructJump(i, target) + def getOpcodeToExp(self): + # we handle listExp, if opcode have to be resized + listExp = [] + i=0 + while i < len(self.code): # we can't use op_range for the moment + op = self.code[i] + if op in self.opc.hasArgumentExtended: + listExp += [i] + elif self.op_hasArgument(op): + i+=2 + i+=1 + return listExp - for i in self.op_range(0, len(self.code)): - if(self.code[i] in (PJIF,PJIT)): - target = self.get_target(i) - if self.code[target] == JA: - target = self.get_target(target) - self.restructJump(i, target) - - def restructCode(self, listDel): + def restructCode(self, listDel, listExp): ''' - restruct linestarts and jump destination after removing a POP_TOP + restruct linestarts and jump destination after converting bytecode ''' + # restruct linestarts with deleted / modificated opcode result = list() for block in self.linestarts: startBlock = 0 for toDel in listDel: if toDel < block[0]: startBlock -= self.op_size(self.code[toDel]) - else: - break + for toExp in listExp: + if toExp < block[0]: + startBlock += 2 result.append((block[0]+startBlock, block[1])) self.linestarts = result - + # handle opcodeToChange deplacement for index in xrange(len(self.toChange)): change = self.toChange[index] delta = 0 for toDel in listDel: if change > toDel: - delta += self.op_size(self.code[toDel]) - else: - break - self.toChange[index] -= delta + delta -= self.op_size(self.code[toDel]) + for toExp in listExp: + if change > toExp: + delta += 2 + self.toChange[index] += delta + # restruct jmp opcode + if listDel: + for jmp in self.op_range(0, len(self.code)): + op = self.code[jmp] + if op in hasjrel+hasjabs: + offset = 0 + jmpTarget = self.get_target(jmp) + for toDel in listDel: + if toDel < jmpTarget: + if op in hasjabs or jmp < toDel: + offset-=self.op_size(self.code[toDel]) + self.restructJump(jmp, jmpTarget+offset) + if listExp: + jmp = 0 + while jmp < len(self.code): # we can't use op_range for the moment + op = self.code[jmp] + if op in hasjrel+hasjabs: + offset = 0 + jmpTarget = self.get_target(jmp) + for toExp in listExp: + if toExp < jmpTarget: + if op in hasjabs or jmp < toExp: + offset+=2 + self.restructJump(jmp, jmpTarget+offset) + if self.op_hasArgument(op) and op not in self.opc.hasArgumentExtended: + jmp += 3 + else: jmp += 1 + + def restructBytecode(self): + ''' + add/change/delete bytecode for suiting bytecode 2.7 + ''' + # we can't use op_range for the moment + # convert jump opcode to 2.7 + self.restructRelativeJump() - for jmp in self.op_range(0, len(self.code)): - op = self.code[jmp] - if op in hasjrel+hasjabs: # jmp - offset = 0 - jmpTarget = self.get_target(jmp) - for toDel in listDel: - if toDel < jmpTarget: - if op in hasjabs: - offset-=self.op_size(self.code[toDel]) - elif jmp < toDel: - offset-=self.op_size(self.code[toDel]) - else: - break - self.restructJump(jmp, self.get_target(jmp)+offset) - + listExp = self.getOpcodeToExp() + # change code structure + if listExp: + listExp = sorted(list(set(listExp))) + self.restructCode([], listExp) + # we add arg to expended opcode + offset=0 + for toExp in listExp: + self.code.insert(toExp+offset+1, 0) + self.code.insert(toExp+offset+1, 0) + offset+=2 + # op_range is now ok :) + # add instruction to change in "toChange" list + MAJ toDel + listDel = [] + for i in self.op_range(0, len(self.code)): + ret = self.getOpcodeToDel(i) + if ret != None: + listDel += ret + + # change code structure after deleting byte + if listDel: + listDel = sorted(list(set(listDel))) + self.restructCode(listDel, []) + # finaly we delete useless opcode + delta = 0 + for x in listDel: + if self.op_hasArgument(self.code[x-delta]): + self.code.pop(x-delta) + self.code.pop(x-delta) + self.code.pop(x-delta) + delta += 3 + else: + self.code.pop(x-delta) + delta += 1 + + def restructRelativeJump(self): + ''' + change relative JUMP_IF_FALSE/TRUE to absolut jump + and remap the target of PJIF/PJIT + ''' + i=0 + while i < len(self.code): # we can't use op_range for the moment + op = self.code[i] + if(op in (PJIF,PJIT)): + target = self.get_argument(i) + target += i + 3 + self.restructJump(i, target) + if self.op_hasArgument(op) and op not in self.opc.hasArgumentExtended: + i += 3 + else: i += 1 + + i=0 + while i < len(self.code): # we can't use op_range for the moment + op = self.code[i] + if(op in (PJIF,PJIT)): + target = self.get_target(i) + if self.code[target] == JA: + target = self.get_target(target) + self.restructJump(i, target) + if self.op_hasArgument(op) and op not in self.opc.hasArgumentExtended: + i += 3 + else: i += 1 + def restructJump(self, pos, newTarget): if not (self.code[pos] in hasjabs+hasjrel): raise 'Can t change this argument. Opcode is not a jump' @@ -425,7 +481,7 @@ class Scanner26(scan.Scanner): raise 'TODO' self.code[pos+2] = (target >> 8) & 0xFF self.code[pos+1] = target & 0xFF - + def build_stmt_indices(self): code = self.code start = 0; @@ -805,7 +861,7 @@ class Scanner26(scan.Scanner): ## Determine structures and fix jumps for 2.3+ self.detect_structure(i, op) - if op >= HAVE_ARGUMENT: + if self.op_hasArgument(op): label = self.fixed_jumps.get(i) oparg = self.get_argument(i) if label is None: diff --git a/uncompyle2/scanner27.py b/uncompyle2/scanner27.py index 154aeba2..48fee726 100755 --- a/uncompyle2/scanner27.py +++ b/uncompyle2/scanner27.py @@ -194,6 +194,12 @@ class Scanner27(scan.Scanner): print >>out return rv, customize + def op_size(self, op): + if op < self.opc.HAVE_ARGUMENT: + return 1 + else: + return 3 + def build_stmt_indices(self): code = self.code start = 0;