import sys, re, cStringIO, os, dis, types
import xam
from SimpleHTTPServer import SimpleHTTPRequestHandler, test
#
# Adapted from SimpleHTTPServer.py.
#
def show_vinfos(array, d, co=None, path=[]):
text = "
"
for i in range(len(array)):
vi = array[i]
text += "- "
if hasattr(co, 'co_code') and path == []:
j = i - xam.LOC_LOCALS_PLUS
if 0 <= j < len(co.co_varnames):
text += "(%s):\t" % co.co_varnames[j]
#if name is not None:
# text += "%s " % name
if vi is None:
text += "[NULL]"
else:
text += "[%x] %s" % (vi.addr, vi.gettext())
if d.has_key(vi.addr):
text += " (already seen above)"
else:
d[vi.addr] = 1
if vi.array:
text += show_vinfos(vi.array, d, co, path+[i])
text += '
\n'
text += '
\n'
return text
re_codebuf = re.compile(r'[/]0x([0-9A-Fa-f]+)$')
re_proxy = re.compile(r'[/]proxy(\d+)$')
def cache_load(filename, cache={}):
try:
return cache[filename]
except KeyError:
data = {}
try:
f = execfile(filename, data)
except:
data = None
cache[filename] = data
return data
class CodeBufHTTPHandler(SimpleHTTPRequestHandler):
def symhtml(self, sym, addr, inbuf=None):
text = xam.symtext(sym, addr, inbuf)
if isinstance(sym, xam.CodeBuf):
if addr == sym.addr:
name = ''
else:
name = '#0x%x' % addr
text = "%s" % (sym.addr, name, text)
return text
def linehtml(self, line, addr):
return "%s" % (addr, line)
def proxyhtml(self, proxy):
return "(snapshot)\n" % codebufs.index(proxy)
def htmlpage(self, title, data):
return ('%s\n' % title
+ '%s
\n' % title
# + '
\n'
+ data
+ '
\n')
def bufferpage(self, codebuf):
rev = {}
for o, c in codebuf.reverse_lookup:
if c is not codebuf:
rev[c] = rev.get(c,0) + 1
if rev:
data = 'Other code buffers pointing to this one:
\n'
for c in codebufs: # display them in original load order
if rev.has_key(c):
if rev[c] == 1:
extra = ''
else:
extra = '\t(%d times)' % rev[c]
data += '- %s\t(%d bytes)%s
\n' % \
(self.symhtml(c, c.addr),
len(c.data),
extra)
data += '
\n'
else:
data = 'No other code buffer points to this one.
\n'
data += '
\n'
data += '%s
\n' % codebuf.disassemble(self.symhtml,
self.linehtml,
self.proxyhtml)
data += "
Back to the list of code objects\n"
if codebuf.co_name:
data = 'Code object %s from file %s, at position %s
%s' % (
codebuf.co_name, codebuf.co_filename, codebuf.get_next_instr(),
data)
return data
def send_head(self):
if self.path == '/':
title = 'List of all named code objects'
data = ''
for codebuf in codebufs:
if codebuf.data and codebuf.co_name:
data += '- %s:\t%s:\t%s:\t%s\t(%d bytes)
\n' % (
codebuf.co_filename, codebuf.co_name,
codebuf.get_next_instr(),
self.symhtml(codebuf, codebuf.addr),
len(codebuf.data))
data += '
\n'
else:
match = re_codebuf.match(self.path)
if match:
addr = long(match.group(1), 16)
codebuf = xam.codeat(addr)
if not codebuf:
self.send_error(404, "No code buffer at this address")
return None
title = '%s code buffer at 0x%x' % (codebuf.mode.capitalize(),
codebuf.addr)
data = self.bufferpage(codebuf)
else:
match = re_proxy.match(self.path)
if match:
title = 'Snapshot'
proxy = codebufs[int(match.group(1))]
filename = os.path.join(DIRECTORY, proxy.co_filename)
moduledata = cache_load(filename)
if moduledata is None:
co = None
else:
co = moduledata.get(proxy.co_name)
if hasattr(co, 'func_code'):
co = co.func_code
data = 'PsycoObject structure at this point:
\n'
data += show_vinfos(proxy.vlocals, {}, co)
data += '
Disassembly of %s:%s:%s:
\n' % (
proxy.co_filename, proxy.co_name, proxy.get_next_instr())
if moduledata is None:
txt = "(exception while loading the file '%s')\n" % (
filename)
else:
if not hasattr(co, 'co_code'):
txt = "(no function object '%s' in file '%s')\n" % (
proxy.co_name, filename)
else:
txt = cStringIO.StringIO()
oldstdout = sys.stdout
try:
sys.stdout = txt
dis.disassemble(co, proxy.get_next_instr())
finally:
sys.stdout = oldstdout
txt = txt.getvalue()
data += '%s
\n' % txt
data += "
Back\n" % proxy.addr
else:
self.send_error(404, "Invalid path")
return None
f = cStringIO.StringIO(self.htmlpage(title, data))
self.send_response(200)
self.send_header("Content-type", "text/html")
self.end_headers()
return f
if __name__ == '__main__':
if len(sys.argv) <= 1:
print "Usage: python httpxam.py "
print " psyco.dump and any .py files containing code objects"
print " are loaded from the ."
sys.exit(1)
DIRECTORY = sys.argv[1]
del sys.argv[1]
codebufs = xam.readdump(os.path.join(DIRECTORY, 'psyco.dump'))
test(CodeBufHTTPHandler)