dis.py (6052B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\carbon\common\stdlib\dis.py 2 import sys 3 import types 4 from opcode import * 5 from opcode import __all__ as _opcodes_all 6 __all__ = ['dis', 7 'disassemble', 8 'distb', 9 'disco', 10 'findlinestarts', 11 'findlabels'] + _opcodes_all 12 del _opcodes_all 13 _have_code = (types.MethodType, 14 types.FunctionType, 15 types.CodeType, 16 types.ClassType, 17 type) 18 19 def dis(x = None): 20 if x is None: 21 distb() 22 return 23 if isinstance(x, types.InstanceType): 24 x = x.__class__ 25 if hasattr(x, 'im_func'): 26 x = x.im_func 27 if hasattr(x, 'func_code'): 28 x = x.func_code 29 if hasattr(x, '__dict__'): 30 items = x.__dict__.items() 31 items.sort() 32 for name, x1 in items: 33 if isinstance(x1, _have_code): 34 print 'Disassembly of %s:' % name 35 try: 36 dis(x1) 37 except TypeError as msg: 38 print 'Sorry:', msg 39 40 print 41 42 elif hasattr(x, 'co_code'): 43 disassemble(x) 44 elif isinstance(x, str): 45 disassemble_string(x) 46 else: 47 raise TypeError, "don't know how to disassemble %s objects" % type(x).__name__ 48 49 50 def distb(tb = None): 51 if tb is None: 52 try: 53 tb = sys.last_traceback 54 except AttributeError: 55 raise RuntimeError, 'no last traceback to disassemble' 56 57 while tb.tb_next: 58 tb = tb.tb_next 59 60 disassemble(tb.tb_frame.f_code, tb.tb_lasti) 61 62 63 def disassemble(co, lasti = -1): 64 code = co.co_code 65 labels = findlabels(code) 66 linestarts = dict(findlinestarts(co)) 67 n = len(code) 68 i = 0 69 extended_arg = 0 70 free = None 71 while i < n: 72 c = code[i] 73 op = ord(c) 74 if i in linestarts: 75 if i > 0: 76 print 77 print '%3d' % linestarts[i], 78 else: 79 print ' ', 80 if i == lasti: 81 print '-->', 82 else: 83 print ' ', 84 if i in labels: 85 print '>>', 86 else: 87 print ' ', 88 print repr(i).rjust(4), 89 print opname[op].ljust(20), 90 i = i + 1 91 if op >= HAVE_ARGUMENT: 92 oparg = ord(code[i]) + ord(code[i + 1]) * 256 + extended_arg 93 extended_arg = 0 94 i = i + 2 95 if op == EXTENDED_ARG: 96 extended_arg = oparg * 65536L 97 print repr(oparg).rjust(5), 98 if op in hasconst: 99 print '(' + repr(co.co_consts[oparg]) + ')', 100 elif op in hasname: 101 print '(' + co.co_names[oparg] + ')', 102 elif op in hasjrel: 103 print '(to ' + repr(i + oparg) + ')', 104 elif op in haslocal: 105 print '(' + co.co_varnames[oparg] + ')', 106 elif op in hascompare: 107 print '(' + cmp_op[oparg] + ')', 108 elif op in hasfree: 109 if free is None: 110 free = co.co_cellvars + co.co_freevars 111 print '(' + free[oparg] + ')', 112 print 113 114 115 def disassemble_string(code, lasti = -1, varnames = None, names = None, constants = None): 116 labels = findlabels(code) 117 n = len(code) 118 i = 0 119 while i < n: 120 c = code[i] 121 op = ord(c) 122 if i == lasti: 123 print '-->', 124 else: 125 print ' ', 126 if i in labels: 127 print '>>', 128 else: 129 print ' ', 130 print repr(i).rjust(4), 131 print opname[op].ljust(15), 132 i = i + 1 133 if op >= HAVE_ARGUMENT: 134 oparg = ord(code[i]) + ord(code[i + 1]) * 256 135 i = i + 2 136 print repr(oparg).rjust(5), 137 if op in hasconst: 138 if constants: 139 print '(' + repr(constants[oparg]) + ')', 140 else: 141 print '(%d)' % oparg, 142 elif op in hasname: 143 if names is not None: 144 print '(' + names[oparg] + ')', 145 else: 146 print '(%d)' % oparg, 147 elif op in hasjrel: 148 print '(to ' + repr(i + oparg) + ')', 149 elif op in haslocal: 150 if varnames: 151 print '(' + varnames[oparg] + ')', 152 else: 153 print '(%d)' % oparg, 154 elif op in hascompare: 155 print '(' + cmp_op[oparg] + ')', 156 print 157 158 159 disco = disassemble 160 161 def findlabels(code): 162 labels = [] 163 n = len(code) 164 i = 0 165 while i < n: 166 c = code[i] 167 op = ord(c) 168 i = i + 1 169 if op >= HAVE_ARGUMENT: 170 oparg = ord(code[i]) + ord(code[i + 1]) * 256 171 i = i + 2 172 label = -1 173 if op in hasjrel: 174 label = i + oparg 175 elif op in hasjabs: 176 label = oparg 177 if label >= 0: 178 if label not in labels: 179 labels.append(label) 180 181 return labels 182 183 184 def findlinestarts(code): 185 byte_increments = [ ord(c) for c in code.co_lnotab[0::2] ] 186 line_increments = [ ord(c) for c in code.co_lnotab[1::2] ] 187 lastlineno = None 188 lineno = code.co_firstlineno 189 addr = 0 190 for byte_incr, line_incr in zip(byte_increments, line_increments): 191 if byte_incr: 192 if lineno != lastlineno: 193 yield (addr, lineno) 194 lastlineno = lineno 195 addr += byte_incr 196 lineno += line_incr 197 198 if lineno != lastlineno: 199 yield (addr, lineno) 200 201 202 def _test(): 203 if sys.argv[1:]: 204 if sys.argv[2:]: 205 sys.stderr.write('usage: python dis.py [-|file]\n') 206 sys.exit(2) 207 fn = sys.argv[1] 208 if not fn or fn == '-': 209 fn = None 210 else: 211 fn = None 212 if fn is None: 213 f = sys.stdin 214 else: 215 f = open(fn) 216 source = f.read() 217 if fn is not None: 218 f.close() 219 else: 220 fn = '<stdin>' 221 code = compile(source, fn, 'exec') 222 dis(code) 223 224 225 if __name__ == '__main__': 226 _test()