mirror of
https://bitbucket.org/librepilot/librepilot.git
synced 2024-12-05 13:24:11 +01:00
171 lines
4.4 KiB
Python
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()
|
||
|
|