PageRenderTime 61ms CodeModel.GetById 14ms RepoModel.GetById 14ms app.codeStats 0ms

/pydbgr/lib/disassemble.py

http://pydbgr.googlecode.com/
Python | 203 lines | 179 code | 2 blank | 22 comment | 11 complexity | a629af2b2c4cf548ea230fe3a4ab5a79 MD5 | raw file
Possible License(s): GPL-3.0
  1. # -*- coding: utf-8 -*-
  2. # Copyright (C) 2009 Rocky Bernstein
  3. # This program is free software: you can redistribute it and/or modify
  4. # it under the terms of the GNU General Public License as published by
  5. # the Free Software Foundation, either version 3 of the License, or
  6. # (at your option) any later version.
  7. #
  8. # This program is distributed in the hope that it will be useful,
  9. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. # GNU General Public License for more details.
  12. #
  13. # You should have received a copy of the GNU General Public License
  14. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  15. '''Disassembly Routines'''
  16. import inspect, sys, types
  17. from dis import distb, findlabels, findlinestarts
  18. from opcode import cmp_op, hasconst, hascompare, hasfree, hasname, hasjrel, \
  19. haslocal, opname, EXTENDED_ARG, HAVE_ARGUMENT
  20. # Modified from dis. Changed output to use msg and msg_nocr.
  21. # Added first_line and last_line parameters
  22. def dis(msg, msg_nocr, errmsg, x=None, start_line=-1, end_line=None,
  23. relative_pos = False):
  24. """Disassemble classes, methods, functions, or code.
  25. With no argument, disassemble the last traceback.
  26. """
  27. lasti = -1
  28. if x is None:
  29. distb()
  30. return
  31. if type(x) is types.InstanceType:
  32. x = x.__class__
  33. if hasattr(x, 'im_func'):
  34. msg("Disassembly of %s: " % x)
  35. x = x.im_func
  36. if hasattr(x, 'func_code'):
  37. msg("Disassembly of %s: " % x)
  38. x = x.func_code
  39. elif hasattr(x, 'f_code'):
  40. print "++++ 1"
  41. msg("Disassembly of %s: " % x)
  42. if hasattr(x, 'f_lasti'):
  43. print "++++ 2"
  44. lasti = x.f_lasti
  45. pass
  46. x = x.f_code
  47. pass
  48. elif inspect.iscode(x):
  49. pass
  50. if hasattr(x, '__dict__'):
  51. items = x.__dict__.items()
  52. items.sort()
  53. for name, x1 in items:
  54. if type(x1) in (types.MethodType,
  55. types.FunctionType,
  56. types.CodeType,
  57. types.ClassType):
  58. try:
  59. dis(msg, msg_nocr, errmsg, x1,
  60. start_line=start_line, end_line=end_line,
  61. relative_pos = relative_pos)
  62. msg("")
  63. except TypeError, msg:
  64. errmsg("Sorry:", msg)
  65. elif hasattr(x, 'co_code'):
  66. disassemble(msg, msg_nocr, x, lasti=lasti,
  67. start_line=start_line, end_line=end_line,
  68. relative_pos = relative_pos)
  69. elif isinstance(x, str):
  70. disassemble_string(msg, msg_nocr, x,)
  71. else:
  72. errmsg("Don't know how to disassemble %s objects." %
  73. type(x).__name__)
  74. return
  75. def disassemble(msg, msg_nocr, co, lasti=-1, start_line=-1, end_line=None,
  76. relative_pos=False):
  77. """Disassemble a code object."""
  78. disassemble_string(msg, msg_nocr, co.co_code, lasti, co.co_firstlineno,
  79. start_line, end_line, relative_pos,
  80. co.co_varnames, co.co_names, co.co_consts,
  81. co.co_cellvars, co.co_freevars,
  82. dict(findlinestarts(co)))
  83. return
  84. def disassemble_string(orig_msg, orig_msg_nocr, code, lasti=-1, cur_line=0,
  85. start_line=-1, end_line=None, relative_pos=False,
  86. varnames=(), names=(), consts=(), cellvars=(),
  87. freevars=(), linestarts={}):
  88. """Disassemble byte string of code. If end_line is negative
  89. it counts the number of statement linestarts to use."""
  90. statement_count = 10000
  91. if end_line is None:
  92. end_line = 10000
  93. elif relative_pos:
  94. end_line += start_line -1
  95. pass
  96. labels = findlabels(code)
  97. n = len(code)
  98. i = 0
  99. extended_arg = 0
  100. free = None
  101. null_print = lambda x: None
  102. if start_line > cur_line:
  103. msg_nocr = null_print
  104. msg = null_print
  105. else:
  106. msg_nocr = orig_msg_nocr
  107. msg = orig_msg
  108. pass
  109. while i < n and statement_count >= 0:
  110. c = code[i]
  111. op = ord(c)
  112. if i in linestarts:
  113. if i > 0:
  114. msg("")
  115. cur_line = linestarts[i]
  116. if start_line and start_line > cur_line:
  117. msg_nocr = null_print
  118. msg = null_print
  119. else:
  120. statement_count -= 1
  121. msg_nocr = orig_msg_nocr
  122. msg = orig_msg
  123. pass
  124. if cur_line > end_line: break
  125. msg_nocr("%3d" % cur_line)
  126. else:
  127. msg_nocr(' ')
  128. if i == lasti: msg_nocr('-->')
  129. else: msg_nocr(' ')
  130. if i in labels: msg_nocr('>>')
  131. else: msg_nocr(' ')
  132. msg_nocr(repr(i).rjust(4))
  133. msg_nocr(' ')
  134. msg_nocr(opname[op].ljust(20))
  135. i += 1
  136. if op >= HAVE_ARGUMENT:
  137. oparg = ord(code[i]) + ord(code[i+1])*256 + extended_arg
  138. extended_arg = 0
  139. i += 2
  140. if op == EXTENDED_ARG:
  141. extended_arg = oparg*65536L
  142. msg_nocr(repr(oparg).rjust(5))
  143. msg_nocr(' ')
  144. if op in hasconst:
  145. msg_nocr('(' + repr(consts[oparg]) + ')')
  146. elif op in hasname:
  147. msg_nocr('(' + names[oparg] + ')')
  148. elif op in hasjrel:
  149. msg_nocr('(to ' + repr(i + oparg) + ')')
  150. elif op in haslocal:
  151. msg_nocr('(' + varnames[oparg] + ')')
  152. elif op in hascompare:
  153. msg_nocr('(' + cmp_op[oparg] + ')')
  154. elif op in hasfree:
  155. if free is None:
  156. free = cellvars + freevars
  157. msg_nocr('(' + free[oparg] + ')')
  158. pass
  159. pass
  160. msg("")
  161. return
  162. import marshal, struct, time
  163. # Inspired by show_file from:
  164. # http://nedbatchelder.com/blog/200804/the_structure_of_pyc_files.html
  165. def pyc2code(fname):
  166. '''Return a code object from a Python compiled file'''
  167. f = open(fname, "rb")
  168. magic = f.read(4)
  169. moddate = f.read(4)
  170. modtime = time.localtime(struct.unpack('L', moddate)[0])
  171. code = marshal.load(f)
  172. f.close()
  173. return magic, moddate, modtime, code
  174. # Demo it
  175. if __name__ == '__main__':
  176. def msg(msg_str):
  177. print msg_str
  178. return
  179. def msg_nocr(msg_str):
  180. sys.stdout.write(msg_str)
  181. return
  182. def errmsg(msg_str):
  183. msg('*** ' + msg_str)
  184. return
  185. curframe = inspect.currentframe()
  186. dis(msg, msg_nocr, errmsg, curframe,
  187. start_line=10, end_line=40)
  188. print '-' * 40
  189. dis(msg, msg_nocr, errmsg, disassemble)
  190. print '-' * 40
  191. magic, moddate, modtime, co = pyc2code(sys.modules['types'].__file__)
  192. disassemble(msg, msg_nocr, co, -1, 1, 70)
  193. pass