| # Disassembler |
| |
| import sys |
| import string |
| |
| def dis(): |
| tb= sys.last_traceback |
| while tb.tb_next: tb= tb.tb_next |
| distb(tb) |
| |
| def distb(tb): |
| disassemble(tb.tb_frame.f_code, tb.tb_lasti) |
| |
| def disco(co): |
| disassemble(co,-1) |
| |
| def disassemble(co, lasti): |
| code= co.co_code |
| labels= findlabels(code) |
| n= len(code) |
| i=0 |
| while i< n: |
| c= code[i] |
| op= ord(c) |
| if op== SET_LINENOand i>0:print# Extra blank line |
| if i== lasti:print'-->', |
| else:print' ', |
| if iin labels:print'>>', |
| else:print' ', |
| print string.rjust(`i`,4), |
| print string.ljust(opname[op],15), |
| i= i+1 |
| if op>= HAVE_ARGUMENT: |
| oparg= ord(code[i])+ ord(code[i+1])*256 |
| i= i+2 |
| print string.rjust(`oparg`,5), |
| if opin hasconst: |
| print'('+`co.co_consts[oparg]`+')', |
| elif opin hasname: |
| print'('+ co.co_names[oparg]+')', |
| elif opin hasjrel: |
| print'(to '+`i+ oparg`+')', |
| print |
| |
| def findlabels(code): |
| labels=[] |
| n= len(code) |
| i=0 |
| while i< n: |
| c= code[i] |
| op= ord(c) |
| i= i+1 |
| if op>= HAVE_ARGUMENT: |
| oparg= ord(code[i])+ ord(code[i+1])*256 |
| i= i+2 |
| label=-1 |
| if opin hasjrel: |
| label= i+oparg |
| elif opin hasjabs: |
| label= oparg |
| if label>=0: |
| if labelnotin labels: |
| labels.append(label) |
| return labels |
| |
| hasconst=[] |
| hasname=[] |
| hasjrel=[] |
| hasjabs=[] |
| |
| opname=['']*256 |
| for opin range(256): opname[op]='<'+`op`+'>' |
| |
| def def_op(name, op): |
| opname[op]= name |
| |
| def name_op(name, op): |
| opname[op]= name |
| hasname.append(op) |
| |
| def jrel_op(name, op): |
| opname[op]= name |
| hasjrel.append(op) |
| |
| def jabs_op(name, op): |
| opname[op]= name |
| hasjabs.append(op) |
| |
| # Instruction opcodes for compiled code |
| |
| def_op('STOP_CODE',0) |
| def_op('POP_TOP',1) |
| def_op('ROT_TWO',2) |
| def_op('ROT_THREE',3) |
| def_op('DUP_TOP',4) |
| |
| def_op('UNARY_POSITIVE',10) |
| def_op('UNARY_NEGATIVE',11) |
| def_op('UNARY_NOT',12) |
| def_op('UNARY_CONVERT',13) |
| def_op('UNARY_CALL',14) |
| def_op('UNARY_INVERT',15) |
| |
| def_op('BINARY_MULTIPLY',20) |
| def_op('BINARY_DIVIDE',21) |
| def_op('BINARY_MODULO',22) |
| def_op('BINARY_ADD',23) |
| def_op('BINARY_SUBTRACT',24) |
| def_op('BINARY_SUBSCR',25) |
| def_op('BINARY_CALL',26) |
| |
| def_op('SLICE+0',30) |
| def_op('SLICE+1',31) |
| def_op('SLICE+2',32) |
| def_op('SLICE+3',33) |
| |
| def_op('STORE_SLICE+0',40) |
| def_op('STORE_SLICE+1',41) |
| def_op('STORE_SLICE+2',42) |
| def_op('STORE_SLICE+3',43) |
| |
| def_op('DELETE_SLICE+0',50) |
| def_op('DELETE_SLICE+1',51) |
| def_op('DELETE_SLICE+2',52) |
| def_op('DELETE_SLICE+3',53) |
| |
| def_op('STORE_SUBSCR',60) |
| def_op('DELETE_SUBSCR',61) |
| |
| def_op('PRINT_EXPR',70) |
| def_op('PRINT_ITEM',71) |
| def_op('PRINT_NEWLINE',72) |
| |
| def_op('BREAK_LOOP',80) |
| def_op('RAISE_EXCEPTION',81) |
| def_op('LOAD_LOCALS',82) |
| def_op('RETURN_VALUE',83) |
| |
| def_op('BUILD_FUNCTION',86) |
| def_op('POP_BLOCK',87) |
| def_op('END_FINALLY',88) |
| def_op('BUILD_CLASS',89) |
| |
| HAVE_ARGUMENT=90# Opcodes from here have an argument: |
| |
| name_op('STORE_NAME',90)# Index in name list |
| name_op('DELETE_NAME',91)# "" |
| def_op('UNPACK_TUPLE',92)# Number of tuple items |
| def_op('UNPACK_LIST',93)# Number of list items |
| def_op('UNPACK_ARG',94)# Number of arguments expected |
| name_op('STORE_ATTR',95)# Index in name list |
| name_op('DELETE_ATTR',96)# "" |
| name_op('STORE_GLOBAL',97)# "" |
| name_op('DELETE_GLOBAL',98)# "" |
| name_op('UNPACK_VARARG',99)# Minimal number of arguments |
| |
| def_op('LOAD_CONST',100)# Index in const list |
| hasconst.append(100) |
| name_op('LOAD_NAME',101)# Index in name list |
| def_op('BUILD_TUPLE',102)# Number of tuple items |
| def_op('BUILD_LIST',103)# Number of list items |
| def_op('BUILD_MAP',104)# Always zero for now |
| name_op('LOAD_ATTR',105)# Index in name list |
| def_op('COMPARE_OP',106)# Comparison operator |
| name_op('IMPORT_NAME',107)# Index in name list |
| name_op('IMPORT_FROM',108)# Index in name list |
| |
| jrel_op('JUMP_FORWARD',110)# Number of bytes to skip |
| jrel_op('JUMP_IF_FALSE',111)# "" |
| jrel_op('JUMP_IF_TRUE',112)# "" |
| jabs_op('JUMP_ABSOLUTE',113)# Target byte offset from beginning of code |
| jrel_op('FOR_LOOP',114)# Number of bytes to skip |
| |
| name_op('LOAD_LOCAL',115)# Index in name list |
| name_op('LOAD_GLOBAL',116)# Index in name list |
| |
| jrel_op('SETUP_LOOP',120)# Distance to target address |
| jrel_op('SETUP_EXCEPT',121)# "" |
| jrel_op('SETUP_FINALLY',122)# "" |
| |
| def_op('RESERVE_FAST',123)# Number of local variables |
| hasconst.append(123) |
| def_op('LOAD_FAST',124)# Local variable number |
| def_op('STORE_FAST',125)# Local variable number |
| def_op('DELETE_FAST',126)# Local variable number |
| |
| def_op('SET_LINENO',127)# Current line number |
| SET_LINENO=127 |