1
0
mirror of https://bitbucket.org/librepilot/librepilot.git synced 2024-11-30 08:24:11 +01:00
LibrePilot/flight/libraries/PyMite/tools/dismantle.py
2013-04-25 13:13:36 +03:00

171 lines
4.4 KiB
Python

#!/usr/bin/env python
# This file is Copyright 2003, 2006, 2007, 2009, 2010 Dean Hall.
#
# This file is part of the Python-on-a-Chip program.
# Python-on-a-Chip is free software: you can redistribute it and/or modify
# it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE Version 2.1.
#
# Python-on-a-Chip is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# A copy of the GNU LESSER GENERAL PUBLIC LICENSE Version 2.1
# is seen in the file COPYING in this directory.
"""
Dismantles a .py file by compiling it
into a code object and recursively dismantling
and disassembling the code object.
"""
__usage__ = """Usage:
dismantle.py sourcefilename.py
"""
## @file
# @copybrief dismantle
## @package dismantle
# @brief Dismantles a .py file by compiling it
# into a code object and recursively dismantling
# and disassembling the code object.
STRINGTOOLONG = 32
import dis, sys, types, py_compile, time
def dismantle_file(fn):
"""Dismantles the .py file, fn. Returns the root code object.
"""
#create a code object
f = open(fn)
source = f.read()
f.close()
return dismantle(source, fn)
def dismantle(source, fn=""):
# If no filename given, just dismantle source, skip magic and ignore
if fn == "":
magic = 0
ignore = 0
fn = "fn"
pyc = ""
else:
# Compile to .pyc and open
py_compile.compile(fn)
f = open(fn + 'c','rb')
pyc = f.read()
f.close()
# Check for magic number
magic = int((ord(pyc[0]) ) | (ord(pyc[1]) << 8) |
(ord(pyc[2]) << 16) | (ord(pyc[3]) << 24))
# Grab the next 4 bytes (don't know what they do)
ignore = int((ord(pyc[4]) ) | (ord(pyc[5]) << 8) |
(ord(pyc[6]) << 16) | (ord(pyc[7]) << 24))
code = compile(source, fn, "exec")
# Print header
print "BEGIN DISMANTLE"
print "date: \t", time.ctime(time.time())
print "src file: \t", fn
print "src file size: \t", len(source), "bytes"
print "pyc file size: \t", len(pyc), "bytes"
print
print "magic: \t0x%08x" % magic
print "ignore: \t0x%08x" % ignore
print
# Recurse into the code object
rdismantle(code)
print "END DISMANTLE"
return code
def rdismantle(co, parent = None):
"""Dismantles the code object, co. Prints the co_* field values and
the co_code disassembly for each code object in the file and recurses
into any code objects in the constant pool.
"""
# Create full name
if parent:
fullname = parent + "." + co.co_name
else:
fullname = co.co_name
# Print object fields and values
print "fullname: \t", fullname
print " co_name: \t", co.co_name
print " co_filename: \t", co.co_filename
print " co_firstlineno:\t", co.co_firstlineno
print " co_flags: \t0x%04x" % co.co_flags
print " co_stacksize: \t", co.co_stacksize
print " co_lnotab[%3d]:\t%s" % \
(len(co.co_lnotab), repr(co.co_lnotab[:8]))
print " co_argcount: \t", co.co_argcount
print " co_nlocals: \t", co.co_nlocals
print " co_freevars: \t", co.co_freevars
print " co_cellvars: \t", co.co_cellvars
# Print vital compound components
tabspacing = "\t\t"
print " co_varnames:"
i = 0
for item in co.co_varnames:
print tabspacing, i, ":\t", item
i += 1
print " co_names: "
i = 0
for item in co.co_names:
print tabspacing, i, ":\t", item
i += 1
print " co_consts: "
i = 0
for item in co.co_consts:
if type(item) == types.StringType and \
len(item) > STRINGTOOLONG:
print tabspacing, i, ":\t", repr(item[:STRINGTOOLONG]), "..."
else:
print tabspacing, i, ":\t", repr(item)
i += 1
# Print disassembly
print " co_code:"
dis.dis(co)
print "\n"
# Dismantle code objects in constant pool
for obj in co.co_consts:
if type(obj) == types.CodeType:
rdismantle(obj, fullname)
return
def main():
"""Dismantles the source file given as an arg.
"""
if len(sys.argv) == 2:
return dismantle_file(sys.argv[1])
else:
print __usage__
if __name__ == "__main__":
main()