home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / pyos2bin.zip / Lib / dis.py < prev    next >
Text File  |  1997-11-18  |  6KB  |  259 lines

  1. """Disassembler of Python byte code into mnemonics."""
  2.  
  3. import sys
  4. import string
  5. import types
  6.  
  7. def dis(x=None):
  8.     """Disassemble classes, methods, functions, or code.
  9.  
  10.     With no argument, disassemble the last traceback.
  11.  
  12.     """
  13.     if not x:
  14.         distb()
  15.         return
  16.     if type(x) is types.InstanceType:
  17.         x = x.__class__
  18.     if hasattr(x, '__dict__'):
  19.         items = x.__dict__.items()
  20.         items.sort()
  21.         for name, x1 in items:
  22.             if type(x1) in (types.MethodType,
  23.                     types.FunctionType,
  24.                     types.CodeType):
  25.                 print "Disassembly of %s:" % name
  26.                 try:
  27.                     dis(x1)
  28.                 except TypeError, msg:
  29.                     print "Sorry:", msg
  30.                 print
  31.     else:
  32.         if hasattr(x, 'im_func'):
  33.             x = x.im_func
  34.         if hasattr(x, 'func_code'):
  35.             x = x.func_code
  36.         if hasattr(x, 'co_code'):
  37.             disassemble(x)
  38.         else:
  39.             raise TypeError, \
  40.                   "don't know how to disassemble %s objects" % \
  41.                   type(x).__name__
  42.  
  43. def distb(tb=None):
  44.     """Disassemble a traceback (default: last traceback)."""
  45.     if not tb:
  46.         try:
  47.             tb = sys.last_traceback
  48.         except AttributeError:
  49.             raise RuntimeError, "no last traceback to disassemble"
  50.         while tb.tb_next: tb = tb.tb_next
  51.     disassemble(tb.tb_frame.f_code, tb.tb_lasti)
  52.  
  53. def disassemble(co, lasti=-1):
  54.     """Disassemble a code object."""
  55.     code = co.co_code
  56.     labels = findlabels(code)
  57.     n = len(code)
  58.     i = 0
  59.     while i < n:
  60.         c = code[i]
  61.         op = ord(c)
  62.         if op == SET_LINENO and i > 0: print # Extra blank line
  63.         if i == lasti: print '-->',
  64.         else: print '   ',
  65.         if i in labels: print '>>',
  66.         else: print '  ',
  67.         print string.rjust(`i`, 4),
  68.         print string.ljust(opname[op], 15),
  69.         i = i+1
  70.         if op >= HAVE_ARGUMENT:
  71.             oparg = ord(code[i]) + ord(code[i+1])*256
  72.             i = i+2
  73.             print string.rjust(`oparg`, 5),
  74.             if op in hasconst:
  75.                 print '(' + `co.co_consts[oparg]` + ')',
  76.             elif op in hasname:
  77.                 print '(' + co.co_names[oparg] + ')',
  78.             elif op in hasjrel:
  79.                 print '(to ' + `i + oparg` + ')',
  80.             elif op in haslocal:
  81.                 print '(' + co.co_varnames[oparg] + ')',
  82.             elif op in hascompare:
  83.                 print '(' + cmp_op[oparg] + ')',
  84.         print
  85.  
  86. disco = disassemble
  87.  
  88. def findlabels(code):
  89.     """Detect all offsets in a byte code which are jump targets.
  90.  
  91.     Return the list of offsets.
  92.  
  93.     """
  94.     labels = []
  95.     n = len(code)
  96.     i = 0
  97.     while i < n:
  98.         c = code[i]
  99.         op = ord(c)
  100.         i = i+1
  101.         if op >= HAVE_ARGUMENT:
  102.             oparg = ord(code[i]) + ord(code[i+1])*256
  103.             i = i+2
  104.             label = -1
  105.             if op in hasjrel:
  106.                 label = i+oparg
  107.             elif op in hasjabs:
  108.                 label = oparg
  109.             if label >= 0:
  110.                 if label not in labels:
  111.                     labels.append(label)
  112.     return labels
  113.  
  114. cmp_op = ('<', '<=', '==', '!=', '>', '>=', 'in', 'not in', 'is',
  115.         'is not', 'exception match', 'BAD')
  116.  
  117. hasconst = []
  118. hasname = []
  119. hasjrel = []
  120. hasjabs = []
  121. haslocal = []
  122. hascompare = []
  123.  
  124. opname = [''] * 256
  125. for op in range(256): opname[op] = '<' + `op` + '>'
  126.  
  127. def def_op(name, op):
  128.     opname[op] = name
  129.  
  130. def name_op(name, op):
  131.     opname[op] = name
  132.     hasname.append(op)
  133.  
  134. def jrel_op(name, op):
  135.     opname[op] = name
  136.     hasjrel.append(op)
  137.  
  138. def jabs_op(name, op):
  139.     opname[op] = name
  140.     hasjabs.append(op)
  141.  
  142. # Instruction opcodes for compiled code
  143.  
  144. def_op('STOP_CODE', 0)
  145. def_op('POP_TOP', 1)
  146. def_op('ROT_TWO', 2)
  147. def_op('ROT_THREE', 3)
  148. def_op('DUP_TOP', 4)
  149.  
  150. def_op('UNARY_POSITIVE', 10)
  151. def_op('UNARY_NEGATIVE', 11)
  152. def_op('UNARY_NOT', 12)
  153. def_op('UNARY_CONVERT', 13)
  154.  
  155. def_op('UNARY_INVERT', 15)
  156.  
  157. def_op('BINARY_POWER', 19)
  158.  
  159. def_op('BINARY_MULTIPLY', 20)
  160. def_op('BINARY_DIVIDE', 21)
  161. def_op('BINARY_MODULO', 22)
  162. def_op('BINARY_ADD', 23)
  163. def_op('BINARY_SUBTRACT', 24)
  164. def_op('BINARY_SUBSCR', 25)
  165.  
  166. def_op('SLICE+0', 30)
  167. def_op('SLICE+1', 31)
  168. def_op('SLICE+2', 32)
  169. def_op('SLICE+3', 33)
  170.  
  171. def_op('STORE_SLICE+0', 40)
  172. def_op('STORE_SLICE+1', 41)
  173. def_op('STORE_SLICE+2', 42)
  174. def_op('STORE_SLICE+3', 43)
  175.  
  176. def_op('DELETE_SLICE+0', 50)
  177. def_op('DELETE_SLICE+1', 51)
  178. def_op('DELETE_SLICE+2', 52)
  179. def_op('DELETE_SLICE+3', 53)
  180.  
  181. def_op('STORE_SUBSCR', 60)
  182. def_op('DELETE_SUBSCR', 61)
  183.  
  184. def_op('BINARY_LSHIFT', 62)
  185. def_op('BINARY_RSHIFT', 63)
  186. def_op('BINARY_AND', 64)
  187. def_op('BINARY_XOR', 65)
  188. def_op('BINARY_OR', 66)
  189.  
  190. def_op('PRINT_EXPR', 70)
  191. def_op('PRINT_ITEM', 71)
  192. def_op('PRINT_NEWLINE', 72)
  193.  
  194. def_op('BREAK_LOOP', 80)
  195.  
  196. def_op('LOAD_LOCALS', 82)
  197. def_op('RETURN_VALUE', 83)
  198.  
  199. def_op('EXEC_STMT', 85)
  200.  
  201. def_op('POP_BLOCK', 87)
  202. def_op('END_FINALLY', 88)
  203. def_op('BUILD_CLASS', 89)
  204.  
  205. HAVE_ARGUMENT = 90        # Opcodes from here have an argument: 
  206.  
  207. name_op('STORE_NAME', 90)    # Index in name list 
  208. name_op('DELETE_NAME', 91)    # "" 
  209. def_op('UNPACK_TUPLE', 92)    # Number of tuple items 
  210. def_op('UNPACK_LIST', 93)    # Number of list items 
  211. def_op('UNPACK_ARG', 94)    # Number of arguments expected
  212. name_op('STORE_ATTR', 95)    # Index in name list 
  213. name_op('DELETE_ATTR', 96)    # ""
  214. name_op('STORE_GLOBAL', 97)    # ""
  215. name_op('DELETE_GLOBAL', 98)    # ""
  216. name_op('UNPACK_VARARG', 99)    # Minimal number of arguments
  217.  
  218. def_op('LOAD_CONST', 100)    # Index in const list 
  219. hasconst.append(100)
  220. name_op('LOAD_NAME', 101)    # Index in name list 
  221. def_op('BUILD_TUPLE', 102)    # Number of tuple items 
  222. def_op('BUILD_LIST', 103)    # Number of list items 
  223. def_op('BUILD_MAP', 104)    # Always zero for now 
  224. name_op('LOAD_ATTR', 105)    # Index in name list 
  225. def_op('COMPARE_OP', 106)    # Comparison operator 
  226. hascompare.append(106)
  227. name_op('IMPORT_NAME', 107)    # Index in name list 
  228. name_op('IMPORT_FROM', 108)    # Index in name list 
  229.  
  230. jrel_op('JUMP_FORWARD', 110)    # Number of bytes to skip 
  231. jrel_op('JUMP_IF_FALSE', 111)    # "" 
  232. jrel_op('JUMP_IF_TRUE', 112)    # "" 
  233. jabs_op('JUMP_ABSOLUTE', 113)    # Target byte offset from beginning of code 
  234. jrel_op('FOR_LOOP', 114)    # Number of bytes to skip 
  235.  
  236. name_op('LOAD_LOCAL', 115)    # Index in name list
  237. name_op('LOAD_GLOBAL', 116)    # Index in name list
  238.  
  239. def_op('SET_FUNC_ARGS', 117)    # Argcount
  240.  
  241. jrel_op('SETUP_LOOP', 120)    # Distance to target address
  242. jrel_op('SETUP_EXCEPT', 121)    # ""
  243. jrel_op('SETUP_FINALLY', 122)    # ""
  244.  
  245. def_op('LOAD_FAST', 124)    # Local variable number
  246. haslocal.append(124)
  247. def_op('STORE_FAST', 125)    # Local variable number
  248. haslocal.append(125)
  249. def_op('DELETE_FAST', 126)    # Local variable number
  250. haslocal.append(126)
  251.  
  252. def_op('SET_LINENO', 127)    # Current line number
  253. SET_LINENO = 127
  254.  
  255. def_op('RAISE_VARARGS', 130)
  256. def_op('CALL_FUNCTION', 131)
  257. def_op('MAKE_FUNCTION', 132)
  258. def_op('BUILD_SLICE', 133)
  259.