python 源码分析之字节码工具
分析 python 字节码有一个趁手的工具非常重要,找了好久,看来分析 python 源码的博主远远不如 java 的多。 仅仅适用于 python 3。用法python parse.py test.py非常简单直观。#!/usr/bin/env python# encoding: utf-8# parse.pyimport dis, marshal, struct, sy...
·
分析 python 字节码有一个趁手的工具非常重要,找了好久,看来分析 python 源码的博主远远不如 java 的多。 仅仅适用于 python 3。
用法
python parse.py test.py
非常简单直观。
#!/usr/bin/env python
# encoding: utf-8
# parse.py
import dis, marshal, struct, sys, time, types, binascii
import py_compile
def generate(filename):
if not filename.endswith("py"):
raise ValueError("filename must be xxx.py")
py_compile.compile(filename, cfile=filename + "c")
def show_file(fname):
generate(fname)
fname += "c"
f = open(fname, "rb")
magic = f.read(4)
moddate = f.read(4)
filesz = f.read(4)
modtime = time.asctime(time.localtime(struct.unpack('=L', moddate)[0]))
filesz = struct.unpack('=L', filesz)
print ("magic %s" % (binascii.hexlify(magic)))
print ("moddate %s (%s)" % (binascii.hexlify(moddate), modtime))
print ("files sz %d" % filesz)
code = marshal.load(f)
show_code(code)
def show_code(code, indent=''):
print ("%scode" % indent)
indent += ' '
print ("%sargcount %d" % (indent, code.co_argcount))
print ("%snlocals %d" % (indent, code.co_nlocals))
print ("%sstacksize %d" % (indent, code.co_stacksize))
print ("%sflags %04x" % (indent, code.co_flags))
show_hex("code", code.co_code, indent=indent)
dis.disassemble(code)
print ("%sconsts" % indent)
for const in code.co_consts:
if type(const) == types.CodeType:
show_code(const, indent+' ')
else:
print (" %s%r" % (indent, const))
print ("%snames %r" % (indent, code.co_names))
print ("%svarnames %r" % (indent, code.co_varnames))
print ("%sfreevars %r" % (indent, code.co_freevars))
print ("%scellvars %r" % (indent, code.co_cellvars))
print ("%sfilename %r" % (indent, code.co_filename))
print ("%sname %r" % (indent, code.co_name))
print ("%sfirstlineno %d" % (indent, code.co_firstlineno))
show_hex("lnotab", code.co_lnotab, indent=indent)
def show_hex(label, h, indent):
h = binascii.hexlify(h)
if len(h) < 60:
print ("%s%s %s" % (indent, label, h))
else:
print ("%s%s" % (indent, label))
for i in range(0, len(h), 60):
print ("%s %s" % (indent, h[i:i+60]))
if __name__ == "__main__":
show_file(sys.argv[1])
更多推荐
已为社区贡献3条内容
所有评论(0)