mirror of https://github.com/svaarala/duktape.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
131 lines
3.9 KiB
131 lines
3.9 KiB
8 years ago
|
#!/usr/bin/env python2
|
||
|
#
|
||
|
# Utility to dump bytecode into a human readable form.
|
||
|
#
|
||
|
|
||
|
import os
|
||
|
import sys
|
||
|
import struct
|
||
|
import optparse
|
||
|
|
||
|
def decode_string(buf, off):
|
||
|
strlen, = struct.unpack('>L', buf[off:off+4])
|
||
|
off += 4
|
||
|
strdata = buf[off:off+strlen]
|
||
|
off += strlen
|
||
|
|
||
|
return off, strdata
|
||
|
|
||
|
def sanitize_string(val):
|
||
|
# Don't try to UTF-8 decode, just escape non-printable ASCII.
|
||
|
def f(c):
|
||
|
if ord(c) < 0x20 or ord(c) > 0x7e or c in '\'"':
|
||
|
return '\\x%02x' % ord(c)
|
||
|
else:
|
||
|
return c
|
||
|
return "'" + ''.join(map(f, val)) + "'"
|
||
|
|
||
|
def decode_sanitize_string(buf, off):
|
||
|
off, val = decode_string(buf, off)
|
||
|
return off, sanitize_string(val)
|
||
|
|
||
|
def dump_function(buf, off, ind):
|
||
|
count_inst, count_const, count_funcs = struct.unpack('>LLL', buf[off:off+12])
|
||
|
off += 12
|
||
|
print '%sInstructions: %d' % (ind, count_inst)
|
||
|
print '%sConstants: %d' % (ind, count_const)
|
||
|
print '%sInner functions: %d' % (ind, count_funcs)
|
||
|
|
||
|
nregs, nargs, start_line, end_line = struct.unpack('>HHLL', buf[off:off+12])
|
||
|
off += 12
|
||
|
print '%sNregs: %d' % (ind, nregs)
|
||
|
print '%sNargs: %d' % (ind, nargs)
|
||
|
print '%sStart line number: %d' % (ind, start_line)
|
||
|
print '%sEnd line number: %d' % (ind, end_line)
|
||
|
|
||
|
compfunc_flags, = struct.unpack('>L', buf[off:off+4])
|
||
|
off += 4
|
||
|
print '%sduk_hcompiledfunction flags: 0x%08x' % (ind, compfunc_flags)
|
||
|
|
||
|
for i in xrange(count_inst):
|
||
|
ins, = struct.unpack('>L', buf[off:off+4])
|
||
|
off += 4
|
||
|
print '%s %06d: %08lx' % (ind, i, ins)
|
||
|
|
||
|
print '%sConstants:' % ind
|
||
|
for i in xrange(count_const):
|
||
|
const_type, = struct.unpack('B', buf[off:off+1])
|
||
|
off += 1
|
||
|
|
||
|
if const_type == 0x00:
|
||
|
off, strdata = decode_sanitize_string(buf, off)
|
||
|
print '%s %06d: %s' % (ind, i, strdata)
|
||
|
elif const_type == 0x01:
|
||
|
num, = struct.unpack('>d', buf[off:off+8])
|
||
|
off += 8
|
||
|
print '%s %06d: %f' % (ind, i, num)
|
||
|
else:
|
||
|
raise Exception('invalid constant type: %d' % const_type)
|
||
|
|
||
|
for i in xrange(count_funcs):
|
||
|
print '%sInner function %d:' % (ind, i)
|
||
|
off = dump_function(buf, off, ind + ' ')
|
||
|
|
||
|
val, = struct.unpack('>L', buf[off:off+4])
|
||
|
off += 4
|
||
|
print '%s.length: %d' % (ind, val)
|
||
|
off, val = decode_sanitize_string(buf, off)
|
||
|
print '%s.name: %s' % (ind, val)
|
||
|
off, val = decode_sanitize_string(buf, off)
|
||
|
print '%s.fileName: %s' % (ind, val)
|
||
|
off, val = decode_string(buf, off) # actually a buffer
|
||
|
print '%s._Pc2line: %s' % (ind, val.encode('hex'))
|
||
|
|
||
|
while True:
|
||
|
off, name = decode_string(buf, off)
|
||
|
if name == '':
|
||
|
break
|
||
|
name = sanitize_string(name)
|
||
|
val, = struct.unpack('>L', buf[off:off+4])
|
||
|
off += 4
|
||
|
print '%s_Varmap[%s] = %d' % (ind, name, val)
|
||
|
|
||
|
idx = 0
|
||
|
while True:
|
||
|
off, name = decode_string(buf, off)
|
||
|
if name == '':
|
||
|
break
|
||
|
name = sanitize_string(name)
|
||
|
print '%s_Formals[%d] = %s' % (ind, idx, name)
|
||
|
idx += 1
|
||
|
|
||
|
return off
|
||
|
|
||
|
def dump_bytecode(buf, off, ind):
|
||
|
sig, ver = struct.unpack('BB', buf[off:off+2])
|
||
|
off += 2
|
||
|
if sig != 0xff:
|
||
|
raise Exception('invalid signature byte: %d' % sig)
|
||
|
if ver != 0x00:
|
||
|
raise Exception('unsupported bytecode version: %d' % ver)
|
||
|
print '%sBytecode version: 0x%02x' % (ind, ver)
|
||
|
|
||
|
off = dump_function(buf, off, ind + ' ')
|
||
|
|
||
|
return off
|
||
|
|
||
|
def main():
|
||
|
parser = optparse.OptionParser()
|
||
|
parser.add_option('--hex-decode', dest='hex_decode', default=False, action='store_true', help='Input file is ASCII hex encoded, decode before dump')
|
||
|
(opts, args) = parser.parse_args()
|
||
|
|
||
|
with open(args[0], 'rb') as f:
|
||
|
d = f.read()
|
||
|
if opts.hex_decode:
|
||
|
d = d.strip()
|
||
|
d = d.decode('hex')
|
||
|
dump_bytecode(d, 0, '')
|
||
|
|
||
|
if __name__ == '__main__':
|
||
|
main()
|