home *** CD-ROM | disk | FTP | other *** search
/ PC World 2005 June / PCWorld_2005-06_cd.bin / software / vyzkuste / firewally / firewally.exe / framework-2.3.exe / dis.py < prev    next >
Text File  |  2003-12-30  |  7KB  |  228 lines

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