aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--README.md0
-rwxr-xr-xdwasm.py33
-rw-r--r--execute.py1056
-rw-r--r--init.py415
-rw-r--r--linker.py2
-rw-r--r--opcodes.py332
-rwxr-xr-xparse.py1031
-rwxr-xr-xrun.sh3
-rw-r--r--section_structs.py301
-rw-r--r--test/injected.wasmbin0 -> 1313 bytes
-rw-r--r--test/linker/.depend2
-rw-r--r--test/linker/file0.c20
-rw-r--r--test/linker/file1.c25
-rw-r--r--test/linker/makefile44
-rw-r--r--utils.py425
15 files changed, 3689 insertions, 0 deletions
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/README.md
diff --git a/dwasm.py b/dwasm.py
new file mode 100755
index 0000000..e404dca
--- /dev/null
+++ b/dwasm.py
@@ -0,0 +1,33 @@
+#!/usr/bin/python3
+
+import argparse
+import code
+import readline
+import signal
+import sys
+from parse import Argparser, premain, SigHandler_SIGINT,PythonInterpreter
+from utils import ParseFlags
+
+def getWASMModule():
+ module_path = sys.argv[1]
+ interpreter = PythonInterpreter()
+ module = interpreter.parse(module_path)
+
+def main():
+ signal.signal(signal.SIGINT, SigHandler_SIGINT)
+ argparser = Argparser()
+ if argparser.args.dbg:
+ try:
+ premain(argparser)
+ except Exception as e:
+ print(e.__doc__)
+ if e.message: print(e.message)
+ variables = globals().copy()
+ variables.update(locals())
+ shell = code.InteractiveConsole(variables)
+ shell.interact(banner="DEVIWASM REPL")
+ else:
+ premain(argparser)
+
+if __name__ == "__main__":
+ main()
diff --git a/execute.py b/execute.py
new file mode 100644
index 0000000..40b9042
--- /dev/null
+++ b/execute.py
@@ -0,0 +1,1056 @@
+from opcodes import *
+from utils import Colors, ror, rol
+import numpy as np
+import math
+
+
+class Label():
+ def __init__(self, arity, name):
+ self.arity = arity
+ self.name = name
+
+
+class Frame():
+ def __init__(self, arity, local_indices, self_ref):
+ self.arity = arity
+ self.local_indices = local_indices
+ self.self_ref = self_ref
+
+
+# takes the machinestate, opcode and operand to run. updates the machinestate
+class Execute(): # pragma: no cover
+ def __init__(self, machinestate):
+ self.machinestate = machinestate
+ self.opcodeint = ''
+ self.immediates = []
+ self.op_gas = int()
+ self.stack_top = []
+
+ def getOPGas(self):
+ return self.op_gas
+
+ def chargeGasMem(self, mem_size_page):
+ factor = 64
+ self.op_gas += 64 * mem_size_page
+
+ def chargeGas(self, opcodeint):
+ if opcodeint != 64:
+ self.op_gas += 1
+ else:
+ chargeGasMem()
+ pass
+
+ def getInstruction(self, opcodeint, immediates):
+ self.opcodeint = opcodeint
+ dummy = []
+ #FIXME-why is it being cast to int?
+ for i in immediates:
+ dummy.append(int(i))
+ self.immediates = dummy
+
+ def callExecuteMethod(self):
+ runmethod = self.instructionUnwinder(self.opcodeint, self.immediates, self.machinestate)
+ #print (repr(hex(self.opcodeint)) + ' ' + repr(self.immediates))
+ try:
+ runmethod(self.opcodeint, self.immediates)
+ except IndexError:
+ # trap
+ print(Colors.red + 'bad stack access.' + Colors.ENDC)
+ val2 = self.machinestate.Stack_Omni.pop()
+
+
+ def instructionUnwinder(self, opcodeint, immediates, machinestate):
+ self.chargeGas(opcodeint)
+
+ if opcodeint == 0:
+ return(self.run_unreachable)
+ elif opcodeint == 1:
+ return(self.run_nop)
+ elif opcodeint == 2:
+ return(self.run_block)
+ elif opcodeint == 3:
+ return(self.run_loop)
+ elif opcodeint == 4:
+ return(self.run_if)
+ elif opcodeint == 5:
+ return(self.run_else)
+ elif opcodeint == 11:
+ return(self.run_end)
+ elif opcodeint == 12:
+ return(self.run_br)
+ elif opcodeint == 13:
+ return(self.run_br_if)
+ elif opcodeint == 14:
+ return(self.run_br_table)
+ elif opcodeint == 15:
+ return(self.run_return)
+ elif opcodeint == 16:
+ return(self.run_call)
+ elif opcodeint == 17:
+ return(self.run_call_indirect)
+ elif opcodeint == 26:
+ return(self.run_drop)
+ elif opcodeint == 27:
+ return(self.run_select)
+ elif opcodeint == 32:
+ return(self.run_getlocal)
+ elif opcodeint == 33:
+ return(self.run_setlocal)
+ elif opcodeint == 34:
+ return(self.run_teelocal)
+ elif opcodeint == 35:
+ return(self.run_getglobal)
+ elif opcodeint == 36:
+ return(self.run_setglobal)
+ elif opcodeint >= 40 and opcodeint <= 53:
+ return(self.run_load)
+ elif opcodeint >= 54 and opcodeint <= 62:
+ return(self.run_store)
+ elif opcodeint == 63:
+ return(self.run_current_memory)
+ elif opcodeint == 64:
+ self.chargeGasMem(immediates[0])
+ return(self.run_grow_memory)
+ elif opcodeint >= 65 and opcodeint <= 68:
+ return(self.run_const)
+ elif opcodeint == 69 or opcodeint == 80:
+ return(self.run_eqz)
+ elif opcodeint == 70 or opcodeint == 81 or opcodeint == 91 or opcodeint == 97:
+ return(self.run_eq)
+ elif opcodeint == 71 or opcodeint == 82 or opcodeint == 92 or opcodeint == 98:
+ return(self.run_ne)
+ elif opcodeint == 72 or opcodeint == 83:
+ return(self.run_lt_s)
+ elif opcodeint == 73 or opcodeint == 84:
+ return(self.run_lt_u)
+ elif opcodeint == 74 or opcodeint == 85:
+ return(self.run_gt_s)
+ elif opcodeint == 75 or opcodeint == 86:
+ return(self.run_gt_u)
+ elif opcodeint == 76 or opcodeint == 87:
+ return(self.run_le_s)
+ elif opcodeint == 77 or opcodeint == 88:
+ return(self.run_le_u)
+ elif opcodeint == 78 or opcodeint == 89:
+ return(self.run_ge_s)
+ elif opcodeint == 79 or opcodeint == 90:
+ return(self.run_ge_u)
+ elif opcodeint == 93 or opcodeint == 99:
+ return(self.run_lt)
+ elif opcodeint == 94 or opcodeint == 100:
+ return(self.run_gt)
+ elif opcodeint == 95 or opcodeint == 101:
+ return(self.run_le)
+ elif opcodeint == 96 or opcodeint == 102:
+ return(self.run_ge)
+ elif opcodeint == 103 or opcodeint == 121:
+ return(self.run_clz)
+ elif opcodeint == 104 or opcodeint == 122:
+ return(self.run_ctz)
+ elif opcodeint == 105 or opcodeint == 123:
+ return(self.run_popcnt)
+ elif opcodeint == 106 or opcodeint == 124 or opcodeint == 146 or opcodeint == 160:
+ return(self.run_add)
+ elif opcodeint == 107 or opcodeint == 125 or opcodeint == 147 or opcodeint == 161:
+ return(self.run_sub)
+ elif opcodeint == 108 or opcodeint == 126 or opcodeint == 148 or opcodeint == 162:
+ return(self.run_mul)
+ elif opcodeint == 109 or opcodeint == 127:
+ return(self.run_div_s)
+ elif opcodeint == 110 or opcodeint == 128:
+ return(self.run_div_u)
+ elif opcodeint == 111 or opcodeint == 129:
+ return(self.run_rem_s)
+ elif opcodeint == 112 or opcodeint == 130:
+ return(self.run_rem_u)
+ elif opcodeint == 113 or opcodeint == 131:
+ return(self.run_and)
+ elif opcodeint == 114 or opcodeint == 132:
+ return(self.run_or)
+ elif opcodeint == 115 or opcodeint == 133:
+ return(self.run_xor)
+ elif opcodeint == 116 or opcodeint == 134:
+ return(self.run_shl)
+ elif opcodeint == 117 or opcodeint == 135:
+ return(self.run_shr_s)
+ elif opcodeint == 118 or opcodeint == 136:
+ return(self.run_shr_u)
+ elif opcodeint == 119 or opcodeint == 137:
+ return(self.run_rotl)
+ elif opcodeint == 120 or opcodeint == 138:
+ return(self.run_rotr)
+ elif opcodeint == 139 or opcodeint == 153:
+ return(self.run_abs)
+ elif opcodeint == 140 or opcodeint == 154:
+ return(self.run_neg)
+ elif opcodeint == 141 or opcodeint == 155:
+ return(self.run_ceil)
+ elif opcodeint == 142 or opcodeint == 156:
+ return(self.run_floor)
+ elif opcodeint == 143 or opcodeint == 157:
+ return(self.run_trunc)
+ elif opcodeint == 144 or opcodeint == 158:
+ return(self.run_nearest)
+ elif opcodeint == 145 or opcodeint == 159:
+ return(self.run_sqrt)
+ elif opcodeint == 149 or opcodeint == 163:
+ return(self.run_div)
+ elif opcodeint == 150 or opcodeint == 164:
+ return(self.run_min)
+ elif opcodeint == 151 or opcodeint == 165:
+ return(self.run_max)
+ elif opcodeint == 152 or opcodeint == 166:
+ return(self.run_copysign)
+ elif opcodeint == 167:
+ return(self.run_i32wrapi64)
+ elif opcodeint == 168:
+ return(self.run_i32trunc_sf32)
+ elif opcodeint == 169:
+ return(self.run_i32trunc_uf32)
+ elif opcodeint == 170:
+ return(self.run_i32trunc_sf64)
+ elif opcodeint == 171:
+ return(self.run_i32trunc_uf64)
+ elif opcodeint == 172:
+ return(self.run_i64extend_si32)
+ elif opcodeint == 173:
+ return(self.run_i64extend_ui3o)
+ elif opcodeint == 174:
+ return(self.run_i64trunc_sf32)
+ elif opcodeint == 175:
+ return(self.run_i64trunc_uf32)
+ elif opcodeint == 176:
+ return(self.run_i64trunc_sf64)
+ elif opcodeint == 177:
+ return(self.run_i64trunc_uf64)
+ elif opcodeint == 178:
+ return(self.run_f32convert_si32)
+ elif opcodeint == 179:
+ return(self.run_f32convert_ui32)
+ elif opcodeint == 180:
+ return(self.run_f32convert_si64)
+ elif opcodeint == 181:
+ return(self.run_f32convert_ui64)
+ elif opcodeint == 182:
+ return(self.run_f32demotef64)
+ elif opcodeint == 183:
+ return(self.run_f64convert_si32)
+ elif opcodeint == 184:
+ return(self.run_f64convert_ui32)
+ elif opcodeint == 185:
+ return(self.run_f64convert_si64)
+ elif opcodeint == 186:
+ return(self.run_f64convert_ui64)
+ elif opcodeint == 187:
+ return(self.run_f64promotef32)
+ elif opcodeint == 188:
+ return(self.run_i32reinterpretf32)
+ elif opcodeint == 189:
+ return(self.run_i64reinterpretf64)
+ elif opcodeint == 190:
+ return(self.run_f32reinterpreti32)
+ elif opcodeint == 191:
+ return(self.run_f64reinterpreti64)
+ else:
+ raise Exception(Colors.red + 'unknown opcode' + Colors.ENDC)
+
+ def run_unreachable(self, opcodeint, immediates):
+ # trap
+ raise Exception(Colors.red + "trapped." + Colors.ENDC)
+
+ def run_nop(self, opcodeint, immediates):
+ # literally do nothing
+ pass
+
+ def run_block(self, opcodeint, immediates):
+ self.machinestate.Stack_Label.append(self.machinestate.Stack_Label_Height)
+ self.machinestate.Stack_Label_Height += 1
+
+ def run_loop(self, opcodeint, immediates):
+ # assertion
+ if not self.machinestate.Stack_Omni:
+ print(Colors.red + "entered a loop. stack is empty." + Colors.ENDC)
+ # exit 1
+ self.machinestate.Stack_Label.append(self.machinestate.Stack_Label_Height)
+ self.machinestate.Stack_Label_Height += 1
+ val = self.machinestate.Stack_Omni.pop()
+ if val != 0:
+ pass
+ else:
+ pass
+
+ def run_if(self, opcodeint, immediates):
+ pass
+
+ def run_else(self, opcodeint, immediates):
+ pass
+
+ def run_end(self, opcodeint, immediates):
+ #self.machinestate.Stack_Label.pop()
+ pass
+
+ def run_br(self, opcodeint, immediates):
+ if self.machinestate.Stack_Label_Height >= immediates[0] + 1:
+ print(Colors.red + "label stack does not have enough labels." + Colors.ENDC)
+ # exit 1
+ if len(self.machinestate.Stack_Omni) < 1:
+ print(Colors.red + "the value stack does not have enough values." + Colors.ENDC)
+ # exit 1
+ val = self.machinestate.Stack_Omni.pop()
+ label = self.machinestate.Stack_Label.pop()
+
+ def run_br_if(self, opcodeint, immediates):
+ val = self.machinestate.Stack_Omni.pop()
+ if val:
+ pass
+ else:
+ self.run_br(dummy, immediates[0])
+
+ def run_br_table(self, opcodeint, immediates):
+ pass
+
+ def run_return(self, opcodeint, immediates):
+ pass
+
+ def run_call(self, opcodeint, immediates):
+ pass
+
+ def run_call_indirect(self, opcodeint, immediates):
+ pass
+
+ def run_drop(self, opcodeint, immediates):
+ self.machinestate.Stack_Omni.pop()
+
+ def run_select(self, opcodeint, immediates):
+ pass
+
+ def run_getlocal(self, opcodeint, immediates):
+ local = self.machinestate.Index_Space_Locals[int(immediates[0])]
+ self.machinestate.Stack_Omni.append(local)
+
+ def run_setlocal(self, opcodeint, immediates):
+ self.machinestate.Index_Space_Locals[int(immediates[0])] = self.machinestate.Stack_Omni.pop()
+
+ def run_teelocal(self, dummy, immediates):
+ # @DEVI-we dont pop and push
+ self.machinestate.Index_Space_Locals[int(immediates[0])] = self.machinestate.Stack_Omni[-1]
+
+ def run_getglobal(self, opcodeint, immediates):
+ val = self.machinestate.Index_Space_Global[immediates[0]]
+ self.machinestate.Stack_Omni.append(val)
+
+ def run_setglobal(self, opcodeint, immediates):
+ val = self.machinestate.Stack_Omni.pop()
+ self.machinestate.Index_Space_Global = val
+
+ # currently only one linear memory is allowed so thats the default.
+ def run_load(self, opcodeint, immediates):
+ if opcodeint == 40:
+ bytes = self.machinestate.Linear_Memory[0][int(immediates[1]):int(immediates) + 4]
+ self.machinestate.Stack_Omni.append(np.int32(bytes))
+ elif opcodeint == 41:
+ bytes = self.machinestate.Linear_Memory[0][int(immediates[1]):int(immediates) + 8]
+ self.machinestate.Stack_Omni.append(np.int64(bytes))
+ elif opcodeint == 42:
+ bytes = self.machinestate.Linear_Memory[0][int(immediates[1]):int(immediates) + 4]
+ self.machinestate.Stack_Omni.append(np.float32(bytes))
+ elif opcodeint == 43:
+ bytes = self.machinestate.Linear_Memory[0][int(immediates[1]):int(immediates) + 8]
+ self.machinestate.Stack_Omni.append(np.float64(bytes))
+ elif opcodeint == 44:
+ temp = np.int8(self.machinestate.Linear_Memory[0][int(immediates[1])])
+ temp2 = (temp & 0x0000007f) | ((temp & 0x80) << 24)
+ self.machinestate.append(np.int32(tmep2))
+ elif opcodeint == 45:
+ temp = np.int8(self.machinestate.Linear_Memory[0][int(immediates[1])])
+ temp2 = temp & 0x000000ff
+ self.machinestate.append(np.uint32(tmep2))
+ elif opcodeint == 46:
+ temp = np.int8(self.machinestate.Linear_Memory[0][int(immediates[1]):int(immediates[1] + 2)])
+ temp2 = (temp & 0x00007fff) | ((temp & 0x8000) << 16)
+ self.machinestate.append(np.int32(tmep2))
+ elif opcodeint == 47:
+ temp = np.int8(self.machinestate.Linear_Memory[0][int(immediates[1]):int(immediates[1] + 2)])
+ temp2 = temp & 0x0000ffff
+ self.machinestate.append(np.uint32(tmep2))
+ elif opcodeint == 48:
+ temp = np.int8(self.machinestate.Linear_Memory[0][int(immediates[1])])
+ temp2 = (temp & 0x000000000000007f) | ((temp & 0x80) << 56)
+ self.machinestate.append(np.int64(tmep2))
+ elif opcodeint == 49:
+ temp = np.uint8(self.machinestate.Linear_Memory[0][int(immediates[1])])
+ self.machinestate.append(np.uint64(tmep))
+ elif opcodeint == 50:
+ temp = np.int8(self.machinestate.Linear_Memory[0][int(immediates[1]):int(immediates[1] + 2)])
+ temp2 = (temp & 0x0000000000007fff) | ((temp & 0x8000) << 48)
+ self.machinestate.append(np.int64(tmep2))
+ elif opcodeint == 51:
+ temp = np.uint8(self.machinestate.Linear_Memory[0][int(immediates[1]):int(immediates[1] + 2)])
+ self.machinestate.append(np.uint64(tmep))
+ elif opcodeint == 52:
+ temp = np.int8(self.machinestate.Linear_Memory[0][int(immediates[1]):int(immediates[1] + 4)])
+ temp2 = (temp & 0x000000007fffffff) | ((temp & 0x80000000) << 32)
+ self.machinestate.append(np.int64(tmep2))
+ elif opcodeint == 53:
+ temp = np.uint8(self.machinestate.Linear_Memory[0][int(immediates[1]):int(immediates[1] + 4)])
+ self.machinestate.append(np.uint64(tmep))
+ else:
+ raise Exception(Colors.red + 'invalid load instruction.' + Colors.ENDC)
+
+ # currently only one linear memory is allowed so thats the default.
+ def run_store(self, opcodeint, immediates):
+ if opcodeint == 54:
+ val = self.machinestate.Stack_Omni.pop()
+ self.machinestate.Linear_Memory[0][int(immediates[1]) + 0] = val & 0x000000ff
+ self.machinestate.Linear_Memory[0][int(immediates[1]) + 1] = val & 0x0000ff00 >> 8
+ self.machinestate.Linear_Memory[0][int(immediates[1]) + 2] = val & 0x00ff0000 >> 16
+ self.machinestate.Linear_Memory[0][int(immediates[1]) + 3] = val & 0xff000000 >> 24
+ elif opcodeint == 55:
+ val = self.machinestate.Stack_Omni.pop()
+ self.machinestate.Linear_Memory[0][int(immediates[1]) + 0] = val & 0x00000000000000ff
+ self.machinestate.Linear_Memory[0][int(immediates[1]) + 1] = val & 0x000000000000ff00 >> 8
+ self.machinestate.Linear_Memory[0][int(immediates[1]) + 2] = val & 0x0000000000ff0000 >> 16
+ self.machinestate.Linear_Memory[0][int(immediates[1]) + 3] = val & 0x00000000ff000000 >> 24
+ self.machinestate.Linear_Memory[0][int(immediates[1]) + 4] = val & 0x000000ff00000000 >> 32
+ self.machinestate.Linear_Memory[0][int(immediates[1]) + 5] = val & 0x0000ff0000000000 >> 40
+ self.machinestate.Linear_Memory[0][int(immediates[1]) + 6] = val & 0x00ff000000000000 >> 48
+ self.machinestate.Linear_Memory[0][int(immediates[1]) + 7] = val & 0xff00000000000000 >> 56
+ # @DEVI-FIXME-needs reinterpret cast
+ elif opcodeint == 56:
+ pass
+ # @DEVI-FIXME-needs reinterpret cast
+ elif opcodeint == 57:
+ pass
+ elif opcodeint == 58:
+ val = self.machinestate.Stack_Omni.pop()
+ self.machinestate.Linear_Memory[0][int(immediates[1])] = np.in8(val & 0x000000ff)
+ elif opcodeint == 59:
+ val = self.machinestate.Stack_Omni.pop()
+ self.machinestate.Linear_Memory[0][int(immediates[1]) + 0] = np.in8(val & 0x000000ff)
+ self.machinestate.Linear_Memory[0][int(immediates[1]) + 1] = np.in8(val & 0x0000ff00 >> 8)
+ elif opcodeint == 60:
+ val = self.machinestate.Stack_Omni.pop()
+ self.machinestate.Linear_Memory[0][int(immediates[1])] = np.in8(val & 0x00000000000000ff)
+ elif opcodeint == 61:
+ val = self.machinestate.Stack_Omni.pop()
+ self.machinestate.Linear_Memory[0][int(immediates[1]) + 0] = np.in8(val & 0x00000000000000ff)
+ self.machinestate.Linear_Memory[0][int(immediates[1]) + 1] = np.in8(val & 0x000000000000ff00 >> 8)
+ elif opcodeint == 62:
+ val = self.machinestate.Stack_Omni.pop()
+ self.machinestate.Linear_Memory[0][int(immediates[1]) + 0] = np.in8(val & 0x00000000000000ff)
+ self.machinestate.Linear_Memory[0][int(immediates[1]) + 1] = np.in8(val & 0x000000000000ff00 >> 8)
+ self.machinestate.Linear_Memory[0][int(immediates[1]) + 2] = np.in8(val & 0x0000000000ff0000 >> 16)
+ self.machinestate.Linear_Memory[0][int(immediates[1]) + 3] = np.in8(val & 0x00000000ff000000 >> 24)
+ else:
+ raise Exception(Colors.red + 'invalid store instruction' + Colors.ENDC)
+
+ def run_current_memory(self, opcodeint, immediates):
+ pass
+
+ def run_grow_memory(self, opcodeint, immediates):
+ pass
+
+ def run_const(self, opcodeint, immediates):
+ if opcodeint == 65:
+ self.machinestate.Stack_Omni.append(immediates[0])
+ elif opcodeint == 66:
+ self.machinestate.Stack_Omni.append(immediates[0])
+ elif opcodeint == 67:
+ self.machinestate.Stack_Omni.append(immediates[0])
+ elif opcodeint == 68:
+ self.machinestate.Stack_Omni.append(immediates[0])
+ else:
+ raise Exception(Colors.red + 'invalid const instruction' + Colors.ENDC)
+
+ def run_eqz(self, opcodeint, immediates):
+ if opcodeint == 69 or opcodeint == 80:
+ val = self.machinestate.Stack_Omni.pop()
+ if val == 0:
+ self.machinestate.Stack_Omni.append(1)
+ else:
+ self.machinestate.Stack_Omni.append(0)
+ else:
+ raise Exception(Colors.red + 'invalid eqz instruction' + Colors.ENDC)
+
+ def run_eq(self, opcodeint, immediates):
+ if opcodeint == 70 or opcodeint == 81 or opcodeint == 91 or opcodeint == 97:
+ val2 = self.machinestate.Stack_Omni.pop()
+ val1 = self.machinestate.Stack_Omni.pop()
+ if val1 == val2:
+ self.machinestate.Stack_Omni.append(1)
+ else:
+ self.machinestate.Stack_Omni.append(0)
+ else:
+ raise Exception(Colors.red + 'invalid eq instruction' + Colors.ENDC)
+
+ def run_ne(self, opcodeint, immediates):
+ if opcodeint == 71 or opcodeint == 82 or opcodeint == 92 or opcodeint == 98:
+ val2 = self.machinestate.Stack_Omni.pop()
+ val1 = self.machinestate.Stack_Omni.pop()
+ if val1 != val2:
+ self.machinestate.Stack_Omni.append(1)
+ else:
+ self.machinestate.Stack_Omni.append(0)
+ else:
+ raise Exception(Colors.red + 'invalid ne instruction' + Colors.ENDC)
+
+ def run_lt_s(self, opcodeint, immediates):
+ val2 = self.machinestate.Stack_Omni.pop()
+ val1 = self.machinestate.Stack_Omni.pop()
+ if opcodeint == 72:
+ if np.int32(val1) < np.int32(val2):
+ self.machinestate.Stack_Omni.append(1)
+ else:
+ self.machinestate.Stack_Omni.append(0)
+ elif opcodeint == 83:
+ if np.int64(val1) < np.int64(val2):
+ self.machinestate.Stack_Omni.append(1)
+ else:
+ self.machinestate.Stack_Omni.append(0)
+ else:
+ raise Exception(Colors.red + 'invalid lt_s instruction' + Colors.ENDC)
+
+ def run_lt_u(self, opcodeint, immediates):
+ val2 = self.machinestate.Stack_Omni.pop()
+ val1 = self.machinestate.Stack_Omni.pop()
+ if opcodeint == 73:
+ if np.uint32(val1) < np.uint32(val2):
+ self.machinestate.Stack_Omni.append(1)
+ else:
+ self.machinestate.Stack_Omni.append(0)
+ elif opcodeint == 84:
+ if np.uint64(val1) < np.uint64(val2):
+ self.machinestate.Stack_Omni.append(1)
+ else:
+ self.machinestate.Stack_Omni.append(0)
+ else:
+ raise Exception(Colors.red + 'invalid lt_u instruction' + Colors.ENDC)
+
+ def run_gt_s(self, opcodeint, immediates):
+ val2 = self.machinestate.Stack_Omni.pop()
+ val1 = self.machinestate.Stack_Omni.pop()
+ if opcodeint == 74:
+ if np.int32(val1) > np.int32(val2):
+ self.machinestate.Stack_Omni.append(1)
+ else:
+ self.machinestate.Stack_Omni.append(0)
+ elif opcodeint == 85:
+ if np.int64(val1) > np.int64(val2):
+ self.machinestate.Stack_Omni.append(1)
+ else:
+ self.machinestate.Stack_Omni.append(0)
+ else:
+ raise Exception(Colors.red + 'invalid gt_s instruction' + Colors.ENDC)
+
+ def run_gt_u(self, opcodeint, immediates):
+ val2 = self.machinestate.Stack_Omni.pop()
+ val1 = self.machinestate.Stack_Omni.pop()
+ if opcodeint == 75:
+ if np.uint32(val1) > np.uint32(val2):
+ self.machinestate.Stack_Omni.append(1)
+ else:
+ self.machinestate.Stack_Omni.append(0)
+ elif opcodeint == 86:
+ if np.uint64(val1) > np.uint64(val2):
+ self.machinestate.Stack_Omni.append(1)
+ else:
+ self.machinestate.Stack_Omni.append(0)
+ else:
+ raise Exception(Colors.red + 'invalid gt_u instruction' + Colors.ENDC)
+
+ def run_le_s(self, opcodeint, immediates):
+ val2 = self.machinestate.Stack_Omni.pop()
+ val1 = self.machinestate.Stack_Omni.pop()
+ if opcodeint == 76:
+ if np.int32(val1) <= np.int32(val2):
+ self.machinestate.Stack_Omni.append(1)
+ else:
+ self.machinestate.Stack_Omni.append(0)
+ elif opcodeint == 87:
+ if np.int64(val1) <= np.int64(val2):
+ self.machinestate.Stack_Omni.append(1)
+ else:
+ self.machinestate.Stack_Omni.append(0)
+ else:
+ raise Exception(Colors.red + 'invalid le_s instruction' + Colors.ENDC)
+
+ def run_le_u(self, opcodeint, immediates):
+ val2 = self.machinestate.Stack_Omni.pop()
+ val1 = self.machinestate.Stack_Omni.pop()
+ if opcodeint == 77:
+ if np.uint32(val1) <= np.uint32(val2):
+ self.machinestate.Stack_Omni.append(1)
+ else:
+ self.machinestate.Stack_Omni.append(0)
+ elif opcodeint == 88:
+ if np.uint64(val1) <= np.uint64(val2):
+ self.machinestate.Stack_Omni.append(1)
+ else:
+ self.machinestate.Stack_Omni.append(0)
+ else:
+ raise Exception(Colors.red + 'invalid le_u instruction' + Colors.ENDC)
+
+ def run_ge_s(self, opcodeint, immediates):
+ val2 = self.machinestate.Stack_Omni.pop()
+ val1 = self.machinestate.Stack_Omni.pop()
+ if opcodeint == 78:
+ if np.int32(val1) >= np.int32(val2):
+ self.machinestate.Stack_Omni.append(1)
+ else:
+ self.machinestate.Stack_Omni.append(0)
+ elif opcodeint == 89:
+ if np.int64(val1) >= np.int64(val2):
+ self.machinestate.Stack_Omni.append(1)
+ else:
+ self.machinestate.Stack_Omni.append(0)
+ else:
+ raise Exception(Colors.red + 'invalid ge_s instruction' + Colors.ENDC)
+
+ def run_ge_u(self, opcodeint, immediates):
+ val2 = self.machinestate.Stack_Omni.pop()
+ val1 = self.machinestate.Stack_Omni.pop()
+ if opcodeint == 79:
+ if np.uint32(val1) >= np.uint32(val2):
+ self.machinestate.Stack_Omni.append(1)
+ else:
+ self.machinestate.Stack_Omni.append(0)
+ elif opcodeint == 90:
+ if np.uint64(val1) >= np.uint64(val2):
+ self.machinestate.Stack_Omni.append(1)
+ else:
+ self.machinestate.Stack_Omni.append(0)
+ else:
+ raise Exception(Colors.red + 'invalid ge_u instruction' + Colors.ENDC)
+
+ def run_lt(self, opcodeint, immediates):
+ val2 = self.machinestate.Stack_Omni.pop()
+ val1 = self.machinestate.Stack_Omni.pop()
+ if opcodeint == 93:
+ if np.float32(v1) < np.float32(v2):
+ self.machinestate.Stack_Omni.append(1)
+ else:
+ self.machinestate.Stack_Omni.append(0)
+ elif opcodeint == 99:
+ if np.float64(v1) < np.float64(v2):
+ self.machinestate.Stack_Omni.append(1)
+ else:
+ self.machinestate.Stack_Omni.append(0)
+ else:
+ raise Exception(Colors.red + 'invalid lt instruction' + Colors.ENDC)
+
+ def run_gt(self, opcodeint, immediates):
+ val2 = self.machinestate.Stack_Omni.pop()
+ val1 = self.machinestate.Stack_Omni.pop()
+ if opcodeint == 94:
+ if np.float32(v1) > np.float32(v2):
+ self.machinestate.Stack_Omni.append(1)
+ else:
+ self.machinestate.Stack_Omni.append(0)
+ elif opcodeint == 100:
+ if np.float64(v1) > np.float64(v2):
+ self.machinestate.Stack_Omni.append(1)
+ else:
+ self.machinestate.Stack_Omni.append(0)
+ else:
+ raise Exception(Colors.red + 'invalid gt instruction' + Colors.ENDC)
+
+ def run_le(self, opcodeint, immediates):
+ val2 = self.machinestate.Stack_Omni.pop()
+ val1 = self.machinestate.Stack_Omni.pop()
+ if opcodeint == 95:
+ if np.float32(v1) <= np.float32(v2):
+ self.machinestate.Stack_Omni.append(1)
+ else:
+ self.machinestate.Stack_Omni.append(0)
+ elif opcodeint == 101:
+ if np.float64(v1) <= np.float64(v2):
+ self.machinestate.Stack_Omni.append(1)
+ else:
+ self.machinestate.Stack_Omni.append(0)
+ else:
+ raise Exception(Colors.red + 'invalid le instruction' + Colors.ENDC)
+
+ def run_ge(self, opcodeint, immediates):
+ val2 = self.machinestate.Stack_Omni.pop()
+ val1 = self.machinestate.Stack_Omni.pop()
+ if opcodeint == 96:
+ if np.float32(v1) >= np.float32(v2):
+ self.machinestate.Stack_Omni.append(1)
+ else:
+ self.machinestate.Stack_Omni.append(0)
+ elif opcodeint == 102:
+ if np.float64(v1) >= np.float64(v2):
+ self.machinestate.Stack_Omni.append(1)
+ else:
+ self.machinestate.Stack_Omni.append(0)
+ else:
+ raise Exception(Colors.red + 'invalid ge instruction' + Colors.ENDC)
+
+ def run_clz(self, opcodeint, immediates):
+ val1 = self.machinestate.Stack_Omni.pop()
+ if opcodeint == 103:
+ self.machinestate.Stack_Omni.append(clz(val, 'uint32'))
+ elif opcodeint == 121:
+ self.machinestate.Stack_Omni.append(clz(val, 'uint64'))
+ else:
+ raise Exception(Colors.red + 'invalid clz instruction' + Colors.ENDC)
+
+ def run_ctz(self, opcodeint, immediates):
+ val1 = self.machinestate.Stack_Omni.pop()
+ if opcodeint == 104:
+ self.machinestate.Stack_Omni.append(ctz(val, 'uint32'))
+ elif opcodeint == 122:
+ self.machinestate.Stack_Omni.append(ctz(val, 'uint64'))
+ else:
+ raise Exception(Colors.red + 'invalid ctz instruction' + Colors.ENDC)
+
+ def run_popcnt(self, opcodeint, immediates):
+ val1 = self.machinestate.Stack_Omni.pop()
+ if opcodeint == 105:
+ self.machinestate.Stack_Omni.append(pop_cnt(val, 'uint32'))
+ elif opcodeint == 123:
+ self.machinestate.Stack_Omni.append(pop_cnt(val, 'uint64'))
+ else:
+ raise Exception(Colors.red + 'invalid popcnt instruction' + Colors.ENDC)
+
+ def run_add(self, opcodeint, immediates):
+ val2 = self.machinestate.Stack_Omni.pop()
+ val1 = self.machinestate.Stack_Omni.pop()
+ if opcodeint == 106:
+ self.machinestate.Stack_Omni.append(np.uint32(val1 + val2))
+ elif opcodeint == 124:
+ self.machinestate.Stack_Omni.append(np.uint64(val1 + val2))
+ elif opcodeint == 146:
+ self.machinestate.Stack_Omni.append(np.float32(val1 + val2))
+ elif opcodeint == 160:
+ self.machinestate.Stack_Omni.append(np.float64(val1 + val2))
+ else:
+ raise Exception(Colors.red + 'invalid add instruction' + Colors.ENDC)
+
+ def run_sub(self, opcodeint, immediates):
+ val2 = self.machinestate.Stack_Omni.pop()
+ val1 = self.machinestate.Stack_Omni.pop()
+ if opcodeint == 107:
+ self.machinestate.Stack_Omni.append(np.uint32(val1 - val2))
+ elif opcodeint == 125:
+ self.machinestate.Stack_Omni.append(np.uint64(val1 - val2))
+ elif opcodeint == 147:
+ self.machinestate.Stack_Omni.append(np.float32(val1 - val2))
+ elif opcodeint == 161:
+ self.machinestate.Stack_Omni.append(np.float64(val1 - val2))
+ else:
+ raise Exception(Colors.red + 'invalid sub instruction' + Colors.ENDC)
+
+ def run_mul(self, opcodeint, immediates):
+ val2 = self.machinestate.Stack_Omni.pop()
+ val1 = self.machinestate.Stack_Omni.pop()
+ if opcodeint == 108:
+ self.machinestate.Stack_Omni.append(np.uint32(val1 * val2))
+ elif opcodeint == 126:
+ self.machinestate.Stack_Omni.append(np.uint64(val1 * val2))
+ elif opcodeint == 148:
+ self.machinestate.Stack_Omni.append(np.float32(val1 * val2))
+ elif opcodeint == 162:
+ self.machinestate.Stack_Omni.append(np.float64(val1 * val2))
+ else:
+ raise Exception(Colors.red + 'invalid mul instruction' + Colors.ENDC)
+
+ def run_div_s(self, opcodeint, immediates):
+ val2 = self.machinestate.Stack_Omni.pop()
+ val1 = self.machinestate.Stack_Omni.pop()
+ if opcodeint == 109:
+ self.machinestate.Stack_Omni.append(np.int32(np.int32(val1) / np.int32(val2)))
+ elif opcodeint == 127:
+ self.machinestate.Stack_Omni.append(np.int64(np.int64(val1) / np.int64(val2)))
+ else:
+ raise Exception(Colors.red + 'invalid div_s instruction' + Colors.ENDC)
+
+ def run_div_u(self, opcodeint, immediates):
+ val2 = self.machinestate.Stack_Omni.pop()
+ val1 = self.machinestate.Stack_Omni.pop()
+ if opcodeint == 110:
+ self.machinestate.Stack_Omni.append(np.uint32(np.uint32(val1) / np.uint32(val2)))
+ elif opcodeint == 128:
+ self.machinestate.Stack_Omni.append(np.uint64(np.uint64(val1) / np.uint64(val2)))
+ else:
+ raise Exception(Colors.red + 'invalid div_u instruction' + Colors.ENDC)
+
+ def run_rem_s(self, opcodeint, immediates):
+ val2 = self.machinestate.Stack_Omni.pop()
+ val1 = self.machinestate.Stack_Omni.pop()
+ if opcodeint == 111:
+ self.machinestate.Stack_Omni.append(np.int32(np.int32(val1) % np.int32(val2)))
+ elif opcodeint == 129:
+ self.machinestate.Stack_Omni.append(np.int64(np.int64(val1) % np.int64(val2)))
+ else:
+ raise Exception(Colors.red + 'invalid rem_s instruction' + Colors.ENDC)
+
+ def run_rem_u(self, opcodeint, immediates):
+ val2 = self.machinestate.Stack_Omni.pop()
+ val1 = self.machinestate.Stack_Omni.pop()
+ if opcodeint == 112:
+ self.machinestate.Stack_Omni.append(np.uint32(np.uint32(val1) % np.uint32(val2)))
+ elif opcodeint == 130:
+ self.machinestate.Stack_Omni.append(np.uint64(np.uint64(val1) % np.uint64(val2)))
+ else:
+ raise Exception(Colors.red + 'invalid rem_u instruction' + Colors.ENDC)
+
+ def run_and(self, opcodeint, immediates):
+ val2 = self.machinestate.Stack_Omni.pop()
+ val1 = self.machinestate.Stack_Omni.pop()
+ if opcodeint == 113:
+ self.machinestate.Stack_Omni.append(np.uint32(np.uint32(val1) & np.uint32(val2)))
+ elif opcodeint == 131:
+ self.machinestate.Stack_Omni.append(np.uint64(np.uint64(val1) & np.uint64(val2)))
+ else:
+ raise Exception(Colors.red + 'invalid and instruction' + Colors.ENDC)
+
+ def run_or(self, opcodeint, immediates):
+ val2 = self.machinestate.Stack_Omni.pop()
+ val1 = self.machinestate.Stack_Omni.pop()
+ if opcodeint == 114:
+ self.machinestate.Stack_Omni.append(np.uint32(np.uint32(val1) | np.uint32(val2)))
+ elif opcodeint == 132:
+ self.machinestate.Stack_Omni.append(np.uint64(np.uint64(val1) | np.uint64(val2)))
+ else:
+ raise Exception(Colors.red + 'invalid or instruction' + Colors.ENDC)
+
+ def run_xor(self, opcodeint, immediates):
+ val2 = self.machinestate.Stack_Omni.pop()
+ val1 = self.machinestate.Stack_Omni.pop()
+ if opcodeint == 115:
+ self.machinestate.Stack_Omni.append(np.uint32(np.uint32(val1) ^ np.uint32(val2)))
+ elif opcodeint == 133:
+ self.machinestate.Stack_Omni.append(np.uint64(np.uint64(val1) ^ np.uint64(val2)))
+ else:
+ raise Exception(Colors.red + 'invalid xor instruction' + Colors.ENDC)
+
+ def run_shl(self, opcodeint, immediates):
+ val2 = self.machinestate.Stack_Omni.pop()
+ val1 = self.machinestate.Stack_Omni.pop()
+ if opcodeint == 116:
+ self.machinestate.Stack_Omni.append(np.uint32(np.uint32(val1) << (np.uint32(val2))))
+ elif opcodeint == 134:
+ self.machinestate.Stack_Omni.append(np.uint64(np.uint64(val1) << (np.uint64(val2))))
+ else:
+ raise Exception(Colors.red + 'invalid shl instruction' + Colors.ENDC)
+
+ def run_shr_s(self, opcodeint, immediates):
+ val2 = self.machinestate.Stack_Omni.pop()
+ val1 = self.machinestate.Stack_Omni.pop()
+ if opcodeint == 117:
+ self.machinestate.Stack_Omni.append(np.int32(np.int32(val1) >> (np.int32(val2))))
+ elif opcodeint == 135:
+ self.machinestate.Stack_Omni.append(np.int64(np.int64(val1) >> (np.int64(val2))))
+ else:
+ raise Exception(Colors.red + 'invalid shr_s instruction' + Colors.ENDC)
+
+ def run_shr_u(self, opcodeint, immediates):
+ val2 = self.machinestate.Stack_Omni.pop()
+ val1 = self.machinestate.Stack_Omni.pop()
+ if opcodeint == 118:
+ self.machinestate.Stack_Omni.append(np.uint32(np.uint32(val1) >> (np.uint32(val2))))
+ elif opcodeint == 136:
+ self.machinestate.Stack_Omni.append(np.uint64(np.uint64(val1) >> (np.uint64(val2))))
+ else:
+ raise Exception(Colors.red + 'invalid shr_u instruction' + Colors.ENDC)
+
+ def run_rotl(self, opcodeint, immediates):
+ val2 = self.machinestate.Stack_Omni.pop()
+ val1 = self.machinestate.Stack_Omni.pop()
+ if opcodeint == 119:
+ self.machinestate.Stack_Omni.append(rol(val1, 32, val2))
+ elif opcodeint == 137:
+ self.machinestate.Stack_Omni.append(rol(val1, 64, val2))
+ else:
+ raise Exception(Colors.red + 'invalid rotl instruction' + Colors.ENDC)
+
+ def run_rotr(self, opcodeint, immediates):
+ val2 = self.machinestate.Stack_Omni.pop()
+ val1 = self.machinestate.Stack_Omni.pop()
+ if opcodeint == 120:
+ self.machinestate.Stack_Omni.append(ror(val1, 32, val2))
+ elif opcodeint == 138:
+ self.machinestate.Stack_Omni.append(ror(val1, 32, val2))
+ else:
+ raise Exception(Colors.red + 'invalid rotl instruction' + Colors.ENDC)
+
+ def run_abs(self, opcodeint, immediates):
+ val1 = self.machinestate.Stack_Omni.pop()
+ if opcodeint == 139 or opcodeint == 153:
+ self.machinestate.Stack_Omni.append(abs(val1))
+ else:
+ raise Exception(Colors.red + 'invalid abs instruction' + Colors.ENDC)
+
+ def run_neg(self, opcodeint, immediates):
+ val1 = self.machinestate.Stack_Omni.pop()
+ if opcodeint == 140 or opcodeint == 154:
+ self.machinestate.Stack_Omni.append(-val1)
+ else:
+ raise Exception(Colors.red + 'invalid neg instruction' + Colors.ENDC)
+
+ def run_ceil(self, opcodeint, immediates):
+ val1 = self.machinestate.Stack_Omni.pop()
+ if opcodeint == 141 or opcodeint == 155:
+ self.machinestate.Stack_Omni.append(math.ceil(val1))
+ else:
+ raise Exception(Colors.red + 'invalid ceil instruction' + Colors.ENDC)
+
+ def run_floor(self, opcodeint, immediates):
+ if opcodeint == 142 or opcodeint == 156:
+ self.machinestate.Stack_Omni.append(math.floor(val1))
+ else:
+ raise Exception(Colors.red + 'invalid floor instruction' + Colors.ENDC)
+
+ def run_trunc(self, opcodeint, immediates):
+ val1 = self.machinestate.Stack_Omni.pop()
+ if opcodeint == 143 or opcodeint == 157:
+ self.machinestate.Stack_Omni.append(math.trunc(val1))
+ else:
+ raise Exception(Colors.red + 'invalid trunc instruction' + Colors.ENDC)
+
+ def run_nearest(self, opcodeint, immediates):
+ val1 = self.machinestate.Stack_Omni.pop()
+ if opcodeint == 144 or opcodeint == 158:
+ self.machinestate.Stack_Omni.append(round(val1))
+ else:
+ raise Exception(Colors.red + 'invalid nearest instruction' + Colors.ENDC)
+
+ def run_sqrt(self, opcodeint, immediates):
+ val1 = self.machinestate.Stack_Omni.pop()
+ if opcodeint == 145 or opcodeint == 159:
+ self.machinestate.Stack_Omni.append(math.sqrt(val1))
+ else:
+ raise Exception(Colors.red + 'invalid sqrt instruction' + Colors.ENDC)
+
+ def run_div(self, opcodeint, immediates):
+ val2 = self.machinestate.Stack_Omni.pop()
+ val1 = self.machinestate.Stack_Omni.pop()
+ if opcodeint == 149:
+ self.machinestate.Stack_Omni.append(v1 / v2)
+ else:
+ raise Exception(Colors.red + 'invalid float div instruction' + Colors.ENDC)
+
+ def run_min(self, opcodeint, immediates):
+ val2 = self.machinestate.Stack_Omni.pop()
+ val1 = self.machinestate.Stack_Omni.pop()
+ if opcodeint == 150 or opcodeint == 164:
+ self.machinestate.Stack_Omni.append(min(val1, val2))
+ else:
+ raise Exception(Colors.red + 'invalid min instruction' + Colors.ENDC)
+
+ def run_max(self, opcodeint, immediates):
+ val2 = self.machinestate.Stack_Omni.pop()
+ val1 = self.machinestate.Stack_Omni.pop()
+ if opcodeint == 151 or opcodeint == 165:
+ self.machinestate.Stack_Omni.append(max(val1, val2))
+ else:
+ raise Exception(Colors.red + 'invalid max instruction' + Colors.ENDC)
+
+ def run_copysign(self, opcodeint, immediates):
+ val2 = self.machinestate.Stack_Omni.pop()
+ val1 = self.machinestate.Stack_Omni.pop()
+ if opcodeint == 152 or opcodeint == 166:
+ self.machinestate.Stack_Omni.append(math.copysign(val1, val2))
+ else:
+ raise Exception(Colors.red + 'invalid max instruction' + Colors.ENDC)
+
+ def run_i32wrapi64(self, opcodeint, immediates):
+ val1 = self.machinestate.Stack_Omni.pop()
+ self.machinestate.Stack_Omni.append(np.int32(np.float64(val1)))
+
+ def run_i32trunc_sf32(self, opcodeint, immediates):
+ val1 = self.machinestate.Stack_Omni.pop()
+ self.machinestate.Stack_Omni.append(np.int32(np.float32(val1)))
+
+ def run_i32trunc_uf32(self, opcodeint, immediates):
+ val1 = self.machinestate.Stack_Omni.pop()
+ self.machinestate.Stack_Omni.append(np.uint32(np.float32(val1)))
+
+ def run_i32trunc_sf64(self, opcodeint, immediates):
+ val1 = self.machinestate.Stack_Omni.pop()
+ self.machinestate.Stack_Omni.append(np.int32(np.float64(val1)))
+
+ def run_i32trunc_uf64(self, opcodeint, immediates):
+ val1 = self.machinestate.Stack_Omni.pop()
+ self.machinestate.Stack_Omni.append(np.int32(np.float64(val1)))
+
+ def run_i64extend_si32(self, opcodeint, immediates):
+ val1 = self.machinestate.Stack_Omni.pop()
+ self.machinestate.Stack_Omni.append(np.float64(np.int32(val1)))
+
+ def run_i64extend_ui32(self, opcodeint, immediates):
+ val1 = self.machinestate.Stack_Omni.pop()
+ self.machinestate.Stack_Omni.append(np.float64(np.uint32(val1)))
+
+ def run_i64trunc_sf32(self, opcodeint, immediates):
+ val1 = self.machinestate.Stack_Omni.pop()
+ self.machinestate.Stack_Omni.append(np.int64(np.float32(val1)))
+
+ def run_i64trunc_uf32(self, opcodeint, immediates):
+ val1 = self.machinestate.Stack_Omni.pop()
+ self.machinestate.Stack_Omni.append(np.uint64(np.float32(val1)))
+
+ def run_i64trunc_sf64(self, opcodeint, immediates):
+ val1 = self.machinestate.Stack_Omni.pop()
+ self.machinestate.Stack_Omni.append(np.int64(np.float64(val1)))
+
+ def run_i64trunc_uf64(self, opcodeint, immediates):
+ val1 = self.machinestate.Stack_Omni.pop()
+ self.machinestate.Stack_Omni.append(np.uint64(np.float64(val1)))
+
+ def run_f32convert_si32(self, opcodeint, immediates):
+ val1 = self.machinestate.Stack_Omni.pop()
+ self.machinestate.Stack_Omni.append(np.float32(np.uint32(val1)))
+
+ def run_f32convert_ui32(self, opcodeint, immediates):
+ val1 = self.machinestate.Stack_Omni.pop()
+ self.machinestate.Stack_Omni.append(np.float32(np.int32(val1)))
+
+ def run_f32convert_si64(self, opcodeint, immediates):
+ val1 = self.machinestate.Stack_Omni.pop()
+ self.machinestate.Stack_Omni.append(np.float32(np.int64(val1)))
+
+ def run_f32convert_ui64(self, opcodeint, immediates):
+ val1 = self.machinestate.Stack_Omni.pop()
+ self.machinestate.Stack_Omni.append(np.float32(np.uint64(val1)))
+
+ def run_f32demotef64(self, opcodeint, immediates):
+ val1 = self.machinestate.Stack_Omni.pop()
+ self.machinestate.Stack_Omni.append(np.float32(np.float64(val1)))
+
+ def run_f64convert_si32(self, opcodeint, immediates):
+ val1 = self.machinestate.Stack_Omni.pop()
+ self.machinestate.Stack_Omni.append(np.float64(np.int32(val1)))
+
+ def run_f64convert_ui32(self, opcodeint, immediates):
+ val1 = self.machinestate.Stack_Omni.pop()
+ self.machinestate.Stack_Omni.append(np.float64(np.uint32(val1)))
+
+ def run_f64convert_si64(self, opcodeint, immediates):
+ val1 = self.machinestate.Stack_Omni.pop()
+ self.machinestate.Stack_Omni.append(np.float64(np.int64(val1)))
+
+ def run_f64convert_ui64(self, opcodeint, immediates):
+ val1 = self.machinestate.Stack_Omni.pop()
+ self.machinestate.Stack_Omni.append(np.float64(np.uint64(val1)))
+
+ def run_f64promotef32(self, opcodeint, immediates):
+ val1 = self.machinestate.Stack_Omni.pop()
+ self.machinestate.Stack_Omni.append(np.float64(np.float32(val1)))
+
+ def run_i32reinterpretf32(self, opcodeint, immediates):
+ val1 = self.machinestate.Stack_Omni.pop()
+ sel.machinestate.Stack_Omni.append(reinterpretf32toi32(val1))
+
+ def run_i64reinterpretf64(self, opcodeint, immediates):
+ val1 = self.machinestate.Stack_Omni.pop()
+ sel.machinestate.Stack_Omni.append(reinterpretf64toi64(val1))
+
+ def run_f32reinterpreti32(self, opcodeint, immediates):
+ val1 = self.machinestate.Stack_Omni.pop()
+ sel.machinestate.Stack_Omni.append(reinterpreti32tof32(val1))
+
+ def run_f64reinterpreti64(self, opcodeint, immediates):
+ val1 = self.machinestate.Stack_Omni.pop()
+ sel.machinestate.Stack_Omni.append(reinterpreti64tof64(val1))
diff --git a/init.py b/init.py
new file mode 100644
index 0000000..f3ac986
--- /dev/null
+++ b/init.py
@@ -0,0 +1,415 @@
+from utils import Colors, init_interpret, ParseFlags
+from opcodes import WASM_OP_Code
+from section_structs import Code_Section, Func_Body, WASM_Ins, Resizable_Limits, Memory_Section
+from execute import *
+import datetime as dti
+import os
+import sys
+import signal
+
+
+# McCabe cyclomatic complexity metric
+class Metric():
+ def __init__(self, code_section):
+ self.code_section = code_section
+ self.metric = []
+ self.soc = []
+
+ def mccabe(self):
+ soc = 0
+ Edges = 1
+ Nodes = 1
+ for funcs in self.code_section.func_bodies:
+ for ins in funcs.code:
+ soc += 1
+ #print(repr(ins.opcodeint))
+ if ins.opcodeint == 4 or ins.opcodeint == 5 or ins.opcodeint == 12 \
+ or ins.opcodeint == 13 or ins.opcodeint == 14:
+ Nodes += 2
+ Edges += 4
+ elif ins.opcode == 3:
+ Nodes += 2
+ Edges += 3
+ else:
+ pass
+
+ self.metric.append(Edges - Nodes + 1)
+ self.soc.append(soc)
+ soc = 0
+ Edges = 1
+ Nodes = 1
+
+ def getMcCabe(self):
+ return self.metric
+
+ def getSOC(self):
+ return self.soc
+
+
+# handles the debug option --memdump. dumps the contents of linear memories.
+def DumpLinearMems(linear_memories, threshold):
+ count = int()
+ strrep = []
+ linmem_cnt = int()
+ for lin_mem in linear_memories:
+ print('-----------------------------------------')
+ print(Colors.blue + Colors.BOLD + 'Linear Memory '+ repr(linmem_cnt)+ ' :' + Colors.ENDC)
+ for byte in lin_mem:
+ if count >= threshold:
+ break
+ if count%16 == 0:
+ for ch in strrep:
+ # @DEVI-line feed messes the pretty format up
+ if ord(ch) != 10:
+ print(Colors.green + ' ' + ch + Colors.ENDC, end = '')
+ else:
+ pass
+ print()
+ strrep = []
+ print(Colors.cyan + hex(count), ':\t' + Colors.ENDC, end='')
+ strrep.append(str(chr(byte)))
+ print(Colors.blue + format(byte, '02x') + ' ' + Colors.ENDC, end='')
+ else:
+ strrep += str(chr(byte))
+ print(Colors.blue + format(byte, '02x') + ' ' + Colors.ENDC, end='')
+ count += 1
+ count = 0
+ print()
+
+
+# handles the debug options --idxspc. dumps the index spaces.
+def DumpIndexSpaces(machinestate):
+ print('-----------------------------------------')
+ print(Colors.green + 'Function Index Space: ' + Colors.ENDC)
+ for iter in machinestate.Index_Space_Function:
+ print(Colors.blue + repr(iter) + Colors.ENDC)
+
+ print('-----------------------------------------')
+ print(Colors.green + 'Globa Index Space: ' + Colors.ENDC)
+ for iter in machinestate.Index_Space_Global:
+ print(Colors.blue + repr(iter) + Colors.ENDC)
+
+ print('-----------------------------------------')
+ print(Colors.green + 'Linear Memory Index Space: ' + Colors.ENDC)
+ for iter in machinestate.Index_Space_Linear:
+ print(Colors.blue + repr(iter) + Colors.ENDC)
+
+ print('-----------------------------------------')
+ print(Colors.green + 'Table Index Space: ' + Colors.ENDC)
+ for iter in machinestate.Index_Space_Table:
+ print(Colors.blue + repr(iter) + Colors.ENDC)
+ print('-----------------------------------------')
+
+
+# WIP-the Truebit Machine class
+class TBMachine():
+ def __init__(self):
+ # bytearray of size PAGE_SIZE
+ self.Linear_Memory = []
+ self.Stack_Label = list()
+ self.Stack_Label_Height = int()
+ self.Stack_Control_Flow = list()
+ self.Stack_Call = list()
+ self.Stack_Value = list()
+ self.Stack_Omni = list()
+ self.Vector_Globals = list()
+ self.Index_Space_Function = list()
+ self.Index_Space_Global = list()
+ self.Index_Space_Linear = list()
+ self.Index_Space_Table = list()
+ self.Index_Space_Locals = list()
+ self.Index_Space_Label = list()
+
+
+# handles the initialization of the WASM machine
+class TBInit():
+ def __init__(self, module, machinestate):
+ self.module = module
+ self.machinestate = machinestate
+
+ # a convenience function that runs the methods of the class. all methods
+ # can be called separately manually as well.
+ def run(self):
+ self.InitFuncIndexSpace()
+ self.InitGlobalIndexSpace()
+ self.InitLinearMemoryIndexSpace()
+ self.InitTableIndexSpace()
+ self.InitializeLinearMemory()
+
+ def InitFuncIndexSpace(self):
+ if self.module.import_section is not None:
+ for iter in self.module.import_section.import_entry:
+ if iter.kind == 0:
+ name = str()
+ for i in iter.field_str:
+ name += str(chr(i))
+ self.machinestate.Index_Space_Function.append(name)
+
+ if self.module.function_section is not None:
+ for iter in self.module.function_section.type_section_index:
+ self.machinestate.Index_Space_Function.append(iter)
+
+ def InitGlobalIndexSpace(self):
+ if self.module.import_section is not None:
+ for iter in self.module.import_section.import_entry:
+ if iter.kind == 3:
+ name = str()
+ for i in iter.field_str:
+ name += str(chr(i))
+ self.machinestate.Index_Space_Global.append(name)
+
+ if self.module.global_section is not None:
+ for iter in self.module.global_section.global_variables:
+ self.machinestate.Index_Space_Global.append(iter.init_expr)
+
+ def InitLinearMemoryIndexSpace(self):
+ if self.module.import_section is not None:
+ for iter in self.module.import_section.import_entry:
+ if iter.kind == 2:
+ name = str()
+ for i in iter.field_str:
+ name += str(chr(i))
+ self.machinestate.Index_Space_Linear.append(name)
+
+ if self.module.memory_section is not None:
+ for iter in self.module.memory_section.memory_types:
+ self.machinestate.Index_Space_Linear.append(iter.initial)
+
+ def InitTableIndexSpace(self):
+ if self.module.import_section is not None:
+ for iter in self.module.import_section.import_entry:
+ if iter.kind == 1:
+ name = str()
+ for i in iter.field_str:
+ name += str(chr(i))
+ self.machinestate.Index_Space_Table.append(name)
+
+ if self.module.table_section is not None:
+ for iter in self.module.table_section.table_types:
+ self.machinestate.Index_Space_Table.append(iter.element_type)
+
+ def InitializeLinearMemory(self):
+ # @DEVI-we could try to pack the data in the linear memory ourselve to
+ # decrease the machinestate size
+ if self.module.memory_section is None:
+ rsz_limits = Resizable_Limits()
+ self.module.memory_section = Memory_Section()
+ self.module.memory_section.memory_types = [rsz_limits]
+ self.module.memory_section.count = 1
+ for iter in self.module.memory_section.memory_types:
+ self.machinestate.Linear_Memory.append(bytearray(
+ WASM_OP_Code.PAGE_SIZE))
+ if self.module.data_section is not None:
+ for iter in self.module.data_section.data_segments:
+ count = int()
+ for byte in iter.data:
+ self.machinestate.Linear_Memory[iter.index][init_interpret(iter.offset) + count] = byte
+ count += 1
+
+ # returns the machinestate
+ def getInits(self):
+ return(self.machinestate)
+
+
+# WIP-holds the run-rime data structures for a wasm machine
+class RTE():
+ def __init__(self):
+ Stack_Control_Flow = list()
+ Stack_Value = list()
+ Vector_Locals = list()
+ Current_Position = int()
+ Local_Stacks = list()
+
+ def genFuncLocalStack(func_body):
+ pass
+
+
+# palceholder for the class that holds the validation functions
+class ModuleValidation():
+ def __init__(self, module):
+ self.module = module
+
+ def TypeSection(self):
+ pass
+
+ def ImportSection(self):
+ pass
+
+ def FunctionSection(self):
+ pass
+
+ def TableSection(self):
+ pass
+
+ def MemorySection(self):
+ pass
+
+ def GlobalSection(self):
+ pass
+
+ def ExportSection(self):
+ pass
+
+ def StartSection(self):
+ pass
+
+ def ElementSection(self):
+ pass
+
+ def CodeSection(self):
+ pass
+
+ def DataSection(self):
+ pass
+
+ def TBCustom(self):
+ pass
+
+ def ValidateAll(self):
+ self.TypeSection()
+ self.ImportSection()
+ self.FunctionSection()
+ self.TableSection()
+ self.MemorySection()
+ self.GlobalSection()
+ self.ExportSection()
+ self.StartSection()
+ self.ElementSection()
+ self.CodeSection()
+ self.DataSection()
+ self.TBCustom()
+
+ return(True)
+
+
+# a convinience class that handles the initialization of the wasm machine and
+# interpretation of the code.
+class VM():
+ def __init__(self, modules):
+ self.modules = modules
+ self.machinestate = TBMachine()
+ # @DEVI-FIXME- the first implementation is single-module only
+ self.init = TBInit(self.modules[0], self.machinestate)
+ self.init.run()
+ self.machinestate = self.init.getInits()
+ self.start_function = Func_Body()
+ self.ins_cache = WASM_Ins()
+ self.executewasm = Execute(self.machinestate)
+ self.totGas = int()
+ self.metric = Metric(modules[0].code_section)
+ self.parseflags = None
+
+ def setFlags(self, parseflags):
+ self.parseflags = parseflags
+
+ def getState(self):
+ return(self.machinestate)
+
+ def initLocalIndexSpace(self, local_count):
+ for i in range(0, local_count):
+ self.machinestate.Index_Space_Locals.append(0)
+
+ def getStartFunctionIndex(self):
+ if self.modules[0].start_section is None:
+ if self.parseflags.entry is None:
+ raise Exception(Colors.red + "module does not have a start section. no function index was provided with the --entry option.quitting..." + Colors.ENDC)
+ else:
+ start_index = int(self.parseflags.entry)
+ else:
+ print(Colors.green + "found start section: " + Colors.ENDC, end = '')
+ start_index = self.modules[0].start_section.function_section_index
+
+ print(Colors.blue + Colors.BOLD + "running function at index " + repr(start_index) + Colors.ENDC)
+ if (start_index > len(self.modules[0].code_section.func_bodies) - 1):
+ raise Exception(Colors.red + "invalid function index: the function index does not exist." + Colors.ENDC)
+ return(start_index)
+
+ def getStartFunctionBody(self):
+ start_index = self.getStartFunctionIndex()
+ if isinstance(start_index, int):
+ self.start_function = self.modules[0].code_section.func_bodies[start_index]
+ elif isinstance(start_index, str):
+ # we have to import the function from another module/library. we
+ # assume sys calls are not present.:w
+ pass
+ else:
+ raise Exception(Colors.red + "invalid entry for start function index" + Colors.ENDC)
+
+ def execute(self):
+ print(Colors.blue + Colors.BOLD + 'running module with code: ' + Colors.ENDC)
+ for ins in self.start_function.code:
+ print(Colors.purple + repr(ins.opcode) + ' ' + repr(ins.operands) + Colors.ENDC)
+ for ins in self.start_function.code:
+ self.executewasm.getInstruction(ins.opcodeint, ins.operands)
+ self.executewasm.callExecuteMethod()
+ self.getState()
+
+ # pre-execution hook
+ def startHook(self):
+ if self.parseflags.metric:
+ for mem in self.modules[0].memory_section.memory_types:
+ self.executewasm.chargeGasMem(mem.initial)
+
+ self.metric.mccabe()
+ print(Colors.red + "mccabe: " + repr(self.metric.getMcCabe()) + Colors.ENDC)
+ print(Colors.red + "soc: " + repr(self.metric.getSOC()) + Colors.ENDC)
+
+ # post-execution hook
+ def endHook(self):
+ if self.parseflags.gas:
+ self.totGas = self.executewasm.getOPGas()
+ print(Colors.red + "total gas cost: " + repr(self.totGas) + Colors.ENDC)
+ if self.machinestate.Stack_Omni:
+ print(Colors.green + "stack top: " + repr(self.machinestate.Stack_Omni.pop()) + Colors.ENDC)
+
+ # a convinience method
+ def run(self):
+ self.startHook()
+ self.getStartFunctionBody()
+ self.initLocalIndexSpace(self.start_function.local_count)
+ self.execute()
+ self.endHook()
+
+
+# a wrapper class for VM. it timeouts instructions that take too long to
+# execute.
+class Judicator():
+ def __int__(self, op_time_table, module):
+ self.op_time_table = op_time_table
+ self.vm = VM(modules)
+ self.vm.getStartFunctionBody()
+
+ def overseer():
+ # @DEVI- forking introduces a new source of non-determinism
+ pid = os.fork()
+ # child process
+ if pid == 0:
+ sys.stdout = open('./jstdout', 'w')
+ sys.stderr = open('./jstderr', 'w')
+ self.vm.execute()
+ sys.exit()
+ # parent process
+ if pid > 0:
+ cpid, status = os.waitpid(pid, 0)
+ if status == 0:
+ print('overseer child exited successfully.')
+ else:
+ print('overseer child exited with non-zero.')
+ # pid < 0
+ else:
+ raise Exception(Colors.red + 'could not fork judicator overseer.' + Colors.ENDC)
+
+ def setup(self):
+ signal.signal(signal.SIGALRM, self.to_sighandler)
+
+ def set_alarm(t):
+ signal.alaram(t)
+
+ def to_sighandler(signum, frame):
+ print(Colors.red + "execution time out..." + Colors.ENDC)
+ raise Exception(Colors.red + "execution time out" + Colors.ENDC)
+
+ def run(self):
+ self.setup()
+ self.set_alaram(10)
+ self.overseer()
diff --git a/linker.py b/linker.py
new file mode 100644
index 0000000..7cf804b
--- /dev/null
+++ b/linker.py
@@ -0,0 +1,2 @@
+import section_structs
+import utils
diff --git a/opcodes.py b/opcodes.py
new file mode 100644
index 0000000..f7c9a1b
--- /dev/null
+++ b/opcodes.py
@@ -0,0 +1,332 @@
+from enum import Enum
+
+SectionID = {0:"custom", 1:"type", 2:"import", 3:"function", 4:"table", 5:"memory", 6:"global", 7:"export", 8:"start", 9:"element", 10:"code", 11:"data", 63:"unknown"}
+
+class RelocType(Enum):
+ R_WEBASSEMBLY_FUNCTION_INDEX_LEB = 0
+ R_WEBASSEMBLY_TABLE_INDEX_SLEB = 1
+ R_WEBASSEMBLY_TABLE_INDEX_I32 = 2
+ R_WEBASSEMBLY_MEMORY_ADDR_LEB = 3
+ R_WEBASSEMBLY_MEMORY_ADDR_SLEB = 4
+ R_WEBASSEMBLY_MEMORY_ADDR_I32 = 5
+ R_WEBASSEMBLY_TYPE_INDEX_LEB = 6
+ R_WEBASSEMBLY_GLOBAL_INDEX_LEB = 7
+ R_WEBASSEMPLY_FUNCTION_OFFSET_I32 = 8
+ R_WEBASSEMBLY_SECTION_OFFSET_I32 = 9
+
+class LinkingSubsection(Enum):
+ WASM_SEGMENT_INFO = 5
+ WASM_INIT_FUNCS = 6
+ WASM_COMDAT_INFO = 7
+ WASM_SYMBOL_TABLE = 8
+
+class TypeType(Enum):
+ none = 1
+ lebu = 2
+ lebs = 3
+ flot = 4
+ dobl = 5
+
+class Syminfo_Kind():
+ SYMTAB_FUNCTION = 0
+ SYMTAB_DATA = 1
+ SYMTAB_GLOBAL = 2
+ SYMTAB_SECTION = 3
+
+TypeKS = [['uint8', 8, TypeType.none], ['uint16', 16, TypeType.none],
+ ['uint32', 32, TypeType.none], ['uint64', 64, TypeType.none],
+ ['varuint1', 1, TypeType.lebu], ['varuint7', 7, TypeType.lebu],
+ ['varuint32', 32, TypeType.lebu], ['varuint64', 64, TypeType.lebu],
+ ['varint1', 1, TypeType.lebs], ['varint7', 7, TypeType.lebs],
+ ['varint32', 32, TypeType.lebs], ['varint64', 64, TypeType.lebs]]
+
+TypeDic = {'uint8': 1, 'uint16': 2, 'uint32': 4, 'uint64': 8,
+ 'varuint1': 1, 'varuint7': 1, 'varuint32': 4, 'varuint64': 8,
+ 'varint1': 1, 'varint7': 1, 'varint32': 4, 'varint64': 8}
+
+# holds the version 1.0 wasm opcodes and immediates
+class WASM_OP_Code:
+ version_number = 0x01
+ magic_number = 0x6d736100
+ PAGE_SIZE = 65536
+ uint8 = 1
+ uint16 = 2
+ uint32 = 4
+ uint64 = 8
+ varuint1 = 1
+ varuint7 = 1
+ varuint32 = 4
+ varuint64 = 8
+ varint1 = 1
+ varint7 = 1
+ varint32 = 4
+ varint64 = 8
+ floatt = 4
+ doublet = 8
+
+ all_ops = [('i32', '7f', False), ('i64', '7e', False), ('f32', '7d', False),
+ ('f64', '7c', False), ('anyfunc', '7b', False),
+ ('func', '60', False), ('empty_block_type', '40', False),
+ ('unreachable', '00', False), ('nop', '01', False),
+ ('block', '02', True, ('varuint7')),
+ ('loop', '03', True, ('varuint7')),
+ ('if', '04', True, ('varuint7')), ('else', '05', False),
+ ('end', '0b', False), ('br', '0c', True, ('varuint32')),
+ ('br_if', '0d', True, ('varuint32')),
+ ('br_table', '0e', True, ('varuint32', 'varuint32', 'varuint32')),
+ ('return', '0f', False), ('call', '10', True, ('varuint32')),
+ ('call_indirect', '11', True, ('varuint32', 'varuint1')),
+ ('drop', '1a', False), ('select', '1b', False),
+ ('get_local', '20', True, ('varuint32')),
+ ('set_local', '21', True, ('varuint32')),
+ ('tee_local', '22', True, ('varuint32')),
+ ('get_global', '23', True, ('varuint32')),
+ ('set_global', '24', True, ('varuint32')),
+ ('i32.load', '28', True, ('varuint32', 'varuint32')),
+ ('i64.load', '29', True, ('varuint32', 'varuint32')),
+ ('f32.load', '2a', True, ('varuint32', 'varuint32')),
+ ('f64.load', '2b', True, ('varuint32', 'varuint32')),
+ ('i32.load8_s', '2c', True, ('varuint32', 'varuint32')),
+ ('i32.load8_u', '2d', True, ('varuint32', 'varuint32')),
+ ('i32.load16_s', '2e', True, ('varuint32', 'varuint32')),
+ ('i32.load16_u', '2f', True, ('varuint32', 'varuint32')),
+ ('i64.load8_s', '30', True, ('varuint32', 'varuint32')),
+ ('i64.load8_u', '31', True, ('varuint32', 'varuint32')),
+ ('i64.load16_s', '32', True, ('varuint32', 'varuint32')),
+ ('i64.load16_u', '33', True, ('varuint32', 'varuint32')),
+ ('i64.load32_s', '34', True, ('varuint32', 'varuint32')),
+ ('i64.load32_u', '35', True, ('varuint32', 'varuint32')),
+ ('i32.store', '36', True, ('varuint32', 'varuint32')),
+ ('i64.store', '37', True, ('varuint32', 'varuint32')),
+ ('f32.store', '38', True, ('varuint32', 'varuint32')),
+ ('f64.store', '39', True, ('varuint32', 'varuint32')),
+ ('i32.store8', '3a', True, ('varuint32', 'varuint32')),
+ ('i32.store16', '3b', True, ('varuint32', 'varuint32')),
+ ('i64.store8', '3c', True, ('varuint32', 'varuint32')),
+ ('i64.store16', '3d', True, ('varuint32', 'varuint32')),
+ ('i64.store32', '3e', True, ('varuint32', 'varuint32')),
+ ('current_memory', '3f', True, ('varuint1')),
+ ('grow_memory', '40', True, ('varuint1')),
+ ('i32.const', '41', True, ('varint32')),
+ ('i64.const', '42', True, ('varint64')),
+ ('f32.const', '43', True, ('uint32')),
+ ('f64.const', '44', True, ('uint64')),
+ ('i32.eqz', '45', False), ('i32.eq', '46', False),
+ ('i32.ne', '47', False), ('i32.lt_s', '48', False),
+ ('i32.lt_u', '49', False), ('i32.gt_s', '4a', False),
+ ('i32.gt_u', '4b', False), ('i32.le_s', '4c', False),
+ ('i32.le_u', '4d', False), ('i32.ge_s', '4e', False),
+ ('i32.ge_u', '4f', False), ('i64.eqz', '50', False),
+ ('i64.eq', '51', False), ('i64.ne', '52', False),
+ ('i64.lt_s', '53', False), ('i64.lt_u', '54', False),
+ ('i64.gt_s', '55', False), ('i64.gt_u', '56', False),
+ ('i64.le_s', '57', False), ('i64.le_u', '58', False),
+ ('i64.ge_s', '59', False), ('i64.ge_u', '5a', False),
+ ('f32.eq', '5b', False), ('f32.ne', '5c', False),
+ ('f32.lt', '5d', False), ('f32.gt', '5e', False),
+ ('f32.le', '5f', False), ('f32.ge', '60', False),
+ ('f64.eq', '61', False), ('f64.ne', '62', False),
+ ('f64.lt', '63', False), ('f64.gt', '64', False),
+ ('f64.le', '65', False), ('f64.ge', '66', False),
+ ('i32.clz', '67', False), ('i32.ctz', '68', False),
+ ('i32.popcnt', '69', False), ('i32.add', '6a', False),
+ ('i32.sub', '6b', False), ('i32.mul', '6c', False),
+ ('i32.div_s', '6d', False), ('i32.div_u', '6e', False),
+ ('i32.rem_s', '6f', False), ('i32.rem_u', '70', False),
+ ('i32.and', '71', False), ('i32.or', '72', False),
+ ('i32.xor', '73', False), ('i32.shl', '74', False),
+ ('i32.shr_s', '75', False), ('i32.shr_u', '76', False),
+ ('i32.rotl', '77', False), ('i32.rotr', '78', False),
+ ('i64.clz', '79', False), ('i64.ctz', '7a', False),
+ ('i64.popcnt', '7b', False), ('i64.add', '7c', False),
+ ('i64.sub', '7d', False), ('i64.mul', '7e', False),
+ ('i64.div_s', '7f', False), ('i64.div_u', '80', False),
+ ('i64.rem_s', '81', False), ('i64.rem_u', '82', False),
+ ('i64.and', '83', False), ('i64.or', '84', False),
+ ('i64.xor', '85', False), ('i64.shl', '86', False),
+ ('i64.shr_s', '87', False), ('i64.shr_u', '88', False),
+ ('i64.rotl', '89', False), ('i63.rotr', '8a', False),
+ ('f32.abs', '8b', False), ('f32.neg', '8c', False),
+ ('f32.ceil', '8d', False), ('f32.floor', '8e', False),
+ ('f32.trunc', '8f', False), ('f32.nearest', '90', False),
+ ('f32.sqrt', '91', False), ('f32.add', '92', False),
+ ('f32.sub', '93', False), ('f32.mul', '94', False),
+ ('f32.div', '95', False), ('f32.min', '96', False),
+ ('f32.max', '97', False), ('f32.copysign', '98', False),
+ ('f64.abs', '99', False), ('f64.neg', '9a', False),
+ ('f64.ceil', '9b', False), ('f64.floor', '9c', False),
+ ('f64.trunc', '9d', False), ('f64.nearest', '9e', False),
+ ('f64.sqrt', '9f', False), ('f64.add', 'a0', False),
+ ('f64.sub', 'a1', False), ('f64.mul', 'a2', False),
+ ('f64.div', 'a3', False), ('f64.min', 'a4', False),
+ ('f64.max', 'a5', False), ('f64.copysign', 'a6', False),
+ ('i32.wrap/i64', 'a7', False), ('i32.trunc_s/f32', 'a8', False),
+ ('i32.trunc_u/f32', 'a9', False),
+ ('i32.trunc_s/f64', 'aa', False),
+ ('i32.trunc_u/f64', 'ab', False),
+ ('i64.extend_s/i32', 'ac', False),
+ ('i64.extend_u/i32', 'ad', False),
+ ('i64.trunc_s/f32', 'ae', False),
+ ('i64.trunc_u/f32', 'af', False),
+ ('i64.trunc_s/f64', 'b0', False),
+ ('i64.trunc_u/f64', 'b1', False),
+ ('f32.convert_s/i32', 'b2', False),
+ ('f32.convert_u/i32', 'b3', False),
+ ('f32.convert_s/i64', 'b4', False),
+ ('f32.convert_u/i64', 'b5', False),
+ ('f32.demote/f64', 'b6', False),
+ ('f64.convert_s/i32', 'b7', False),
+ ('f64.convert_u/i32', 'b8', False),
+ ('f64.convert_s/i64', 'b9', False),
+ ('f64.convert_u/i64', 'ba', False),
+ ('f64.promote/f32', 'bb', False),
+ ('i32.reinterpret/f32', 'bc', False),
+ ('i64.reinterpret/f64', 'bd', False),
+ ('f32.reinterpret/i32', 'be', False),
+ ('f64.reinterpret/i64', 'bf', False)]
+
+ type_ops = [('i32', '7f'), ('i64', '7e'), ('f32', '7d'),
+ ('f64', '7c'), ('anyfunc', '7b'), ('func', '60'),
+ ('empty_block_type', '40')]
+ type_ops_dict = dict(type_ops)
+ type_ops_dict_rev = {v: k for k, v in type_ops_dict.items()}
+
+ control_flow_ops = [('unreachable', '00'), ('nop', '01'),
+ ('block', '02'), ('loop', '03'),
+ ('if', '04'), ('else', '05'),
+ ('end', '0b'), ('br', '0c'),
+ ('br_if', '0d'), ('br_table', '0e'),
+ ('return', '0f')]
+ control_flow_ops_dict = dict(control_flow_ops)
+ control_flow_ops_dict_rev = {v: k for k, v in control_flow_ops_dict.items()}
+
+ call_ops = [('call', '10'), ('call_indirect', '11')]
+ call_ops_dict = dict(call_ops)
+ call_ops_dict_rev = {v: k for k, v in call_ops_dict.items()}
+
+ param_ops = [('drop', '1a'), ('select', '1b')]
+ param_ops_dict = dict(param_ops)
+ param_ops_dict_rev = {v: k for k, v in param_ops_dict.items()}
+
+ var_access = [('get_local', '20'), ('set_local', '21'),
+ ('tee_local', '22'), ('get_global', '23'),
+ ('set_global', '24')]
+ var_access_dict = dict(var_access)
+ var_access_dict_rev = {v: k for k, v in var_access_dict.items()}
+
+ mem_ops = [('i32.load', '28'), ('i64.load', '29'),
+ ('f32.load', '2a'), ('f64.load', '2b'),
+ ('i32.load8_s', '2c'), ('i32.load8_u', '2d'),
+ ('i32.load16_s', '2e'), ('i32.load16_u', '2f'),
+ ('i64.load8_s', '30'), ('i64.load8_u', '31'),
+ ('i64.load16_s', '32'), ('i64.load16_u', '33'),
+ ('i64.load32_s', '34'), ('i64.load32_u', '35'),
+ ('i32.store', '36'), ('i64.store', '37'),
+ ('f32.store', '38'), ('f64.store', '39'),
+ ('i32.store8', '3a'), ('i32.store16', '3b'),
+ ('i64.store8', '3c'), ('i64.store16', '3d'),
+ ('i64.store32', '3e'), ('current_memory', '3f'),
+ ('grow_memory', '40')]
+ mem_ops_dict = dict(mem_ops)
+ mem_ops_dict_rev = {v: k for k, v in mem_ops_dict.items()}
+
+ consts = [('i32.const', '41'), ('i64.const', '42'),
+ ('f32.const', '43'), ('f64', '44')]
+ consts_dict = dict(consts)
+ consts_dict_rev = {v: k for k, v in consts_dict.items()}
+
+ comp_ops = [('i32.eqz', '45'), ('i32.eq', '46'), ('i32.ne', '47'),
+ ('i32.lt_s', '48'), ('i32.lt_u', '49'),
+ ('i32.gt_s', '4a'), ('i32.gt_u', '4b'),
+ ('i32.le_s', '4c'), ('i32.le_u', '4d'),
+ ('i32.ge_s', '4e'), ('i32.ge_u', '4f'),
+ ('i64.eqz', '50'), ('i64.eq', '51'),
+ ('i64.ne', '52'), ('i64.lt_s', '53'),
+ ('i64.lt_u', '54'), ('i64.gt_s', '55'),
+ ('i64.gt_u', '56'), ('i64.le_s', '57'),
+ ('i64.le_u', '58'), ('i64.ge_s', '59'),
+ ('i64.ge_u', '5a'), ('f32.eq', '5b'),
+ ('f32.ne', '5c'), ('f32.lt', '5d'),
+ ('f32.gt', '5e'), ('f32.le', '5f'),
+ ('f32.ge', '60'), ('f64.eq', '61'),
+ ('f64.ne', '62'), ('f64.lt', '63'),
+ ('f64.gt', '64'), ('f64.le', '65'),
+ ('f64.ge', '66')]
+ comp_ops_dict = dict(comp_ops)
+ comp_ops_dict_rev = {v: k for k, v in comp_ops_dict.items()}
+
+ num_ops = [('i32.clz', '67'), ('i32.ctz', '68'),
+ ('i32.popcnt', '69'), ('i32.add', '6a'),
+ ('i32.sub', '6b'), ('i32.mul', '6c'),
+ ('i32.div_s', '6d'), ('i32.div_u', '6e'),
+ ('i32.rem_s', '6e'), ('i32.rem_u', '70'),
+ ('i32.and', '71'), ('i32.or', '72'),
+ ('i32.xor', '73'), ('i32.shl', '74'),
+ ('i32.shr_s', '75'), ('i32.shr_u', '76'),
+ ('i32.rotl', '77'), ('i32.rotr', '78'),
+ ('i64.clz', '79'), ('i64.ctz', '7a'),
+ ('i64.popcnt', '7b'), ('i64.add', '7c'),
+ ('i64.sub', '7d'), ('i64.mul', '7e'),
+ ('i64.div_s', '7f'), ('i64.div_u', '80'),
+ ('i64.rem_s', '81'), ('i64.rem_u', '82'),
+ ('i64.and', '83'), ('i64.or', '84'),
+ ('i64.xor', '85'), ('i64.shl', '86'),
+ ('i64.shr_s', '87'), ('i64.shr_u', '88'),
+ ('i64.rotl', '89'), ('i63.rotr', '8a'),
+ ('f32.abs', '8b'), ('f32.neg', '8c'),
+ ('f32.ceil', '8d'), ('f32.floor', '8e'),
+ ('f32.trunc', '8f'), ('f32.nearest', '90'),
+ ('f32.sqrt', '91'), ('f32.add', '92'),
+ ('f32.sub', '93'), ('f32.mul', '94'),
+ ('f32.div', '95'), ('f32.min', '96'),
+ ('f32.max', '97'), ('f32.copysign', '98'),
+ ('f64.abs', '99'), ('f64.neg', '9a'),
+ ('f64.ceil', '9b'), ('f64.floor', '9c'),
+ ('f64.trunc', '9d'), ('f64.nearest', '9e'),
+ ('f64.sqrt', '9f'), ('f64.add', 'a0'),
+ ('f64.sub', 'a1'), ('f64.mul', 'a2'),
+ ('f64.div', 'a3'), ('f64.min', 'a4'),
+ ('f64.max', 'a5'), ('f64.copysign', 'a6')]
+ num_ops_dict = dict(num_ops)
+ num_ops_dict_rev = {v: k for k, v in num_ops_dict.items()}
+
+ conversion = [('i32.wrap/i64', 'a7'),
+ ('i32.trunc_s/f32', 'a8'),
+ ('i32.trunc_u/f32', 'a9'),
+ ('i32.trunc_s/f64', 'aa'),
+ ('i32.trunc_u/f64', 'ab'),
+ ('i64.extend_s/i32', 'ac'),
+ ('i64.extend_u/i32', 'ad'),
+ ('i64.trunc_s/f32', 'ae'),
+ ('i64.trunc_u/f32', 'af'),
+ ('i64.trunc_s/f64', 'b0'),
+ ('i64.trunc_u/f64', 'b1'),
+ ('f32.convert_s/i32', 'b2'),
+ ('f32.convert_u/i32', 'b3'),
+ ('f32.convert_s/i64', 'b4'),
+ ('f32.convert_u/i64', 'b5'),
+ ('f32.demote/f64', 'b6'),
+ ('f64.convert_s/i32', 'b7'),
+ ('f64.convert_u/i32', 'b8'),
+ ('f64.convert_s/i64', 'b9'),
+ ('f64.convert_u/i64', 'ba'),
+ ('f64.promote/f32', 'bb')]
+ conversion_dict = dict(conversion)
+ conversion_dict_rev = {v: k for k, v in conversion_dict.items()}
+
+ reinterpretations = [('i32.reinterpret/f32', 'bc'),
+ ('i64.reinterpret/f64', 'bd'),
+ ('f32.reinterpret/i32', 'be'),
+ ('f64.reinterpret/i64', 'bf')]
+ reinterpretations_dict = dict(reinterpretations)
+ reinterpretations_dict_rev = {v: k for k,
+ v in reinterpretations_dict.items()}
+
+ section_code = [('type', '01'), ('import', '02'),
+ ('function', '03'), ('table', '04'),
+ ('memory', '05'), ('global', '06'),
+ ('export', '07'), ('start', '08'),
+ ('element', '09'), ('code', '0a'),
+ ('data', '0b'), ('custom', '00')]
+ section_code_dict = dict(section_code)
+ section_code_dict_rev = {v: k for k, v in section_code_dict.items()}
diff --git a/parse.py b/parse.py
new file mode 100755
index 0000000..ff28b8a
--- /dev/null
+++ b/parse.py
@@ -0,0 +1,1031 @@
+#!/bin/python3
+
+from __future__ import print_function
+import argparse
+import sys
+import re
+from section_structs import *
+from utils import *
+from opcodes import *
+from copy import deepcopy
+from init import *
+import readline
+import code
+import signal
+
+_DBG_ = True
+
+def SigHandler_SIGINT(signum, frame):
+ print()
+ sys.exit(0)
+
+# we first read the object file and put all the sections in this class
+class ParsedStruct:
+ def __init__(self):
+ self.version_number = int()
+ self.section_list = []
+
+
+# like the above. currently unused
+class ParsedStructV2:
+ def __init__(self, version_number, section_list):
+ self.version_number = version_number
+ self.section_list = section_list
+
+
+# @DEVI-Deprecated-convert a bytearray to int
+def Conver2Int(little_endian, size, bytelist):
+ modifier = size - 1
+ sum = 0
+
+ if little_endian:
+ for bit in reversed(bytelist):
+ if bit != 0x80:
+ sum += bit*(pow(16, modifier))
+ modifier -= 1
+ return(sum)
+ else:
+ for bit in reversed(bytelist):
+ if bit != 0x80:
+ sum += bit*(pow(16, modifier))
+ modifier -= 1
+ return(sum)
+
+# the argparser
+class Argparser(object):
+ def __init__(self):
+ parser = argparse.ArgumentParser()
+ parser.add_argument("--wast", type=str, help="path to the wasm text file")
+ parser.add_argument("--wasm", type=str, nargs='+', help="path to the wasm object file")
+ parser.add_argument("--asb", type=str, help="path to the wast file to assemble")
+ parser.add_argument("--dis", type=str, help="path to the wasm file to disassemble")
+ parser.add_argument("-o", type=str, help="the path to the output file")
+ parser.add_argument("--dbg", action='store_true', help="print debug info", default=False)
+ parser.add_argument("--unval", action='store_true', help="skips validation tests", default=False)
+ parser.add_argument("--memdump", type=int, help="dumps the linear memory")
+ parser.add_argument("--idxspc", action='store_true', help="print index space data", default=False)
+ parser.add_argument("--run", action='store_true', help="runs the start function", default=False)
+ parser.add_argument("--metric", action='store_true', help="print metrics", default=False)
+ parser.add_argument("--gas", action='store_true', help="print gas usage", default=False)
+ parser.add_argument("--entry", type=str, help="name of the function that will act as the entry point into execution")
+ parser.add_argument("--link", type=str, nargs="+", help="link the following wasm modules")
+ parser.add_argument("--sectiondump", type=str, help="dumps the section provided")
+ parser.add_argument("--hexdump", type=int, help="dumps all sections")
+ parser.add_argument("--dbgsection", type=str, help="dumps the parsed section provided", default="")
+ parser.add_argument("--interactive", action='store_true', help="open in cli mode", default=False)
+ parser.add_argument("--rawdump", type=int, nargs=2, help="dumps all sections")
+ self.args = parser.parse_args()
+ if self.args.wasm is not None and self.args.wast is not None:
+ raise Exception("the --wast option and the --wasm option cannot\
+ be set at the same time. you need to choose one.")
+
+ def getParseFlags(self):
+ return(ParseFlags(self.args.wast, self.args.wasm, self.args.asb, self.args.dis,
+ self.args.o, self.args.dbg, self.args.unval, self.args.memdump,
+ self.args.idxspc, self.args.run, self.args.metric, self.args.gas, self.args.entry))
+
+# reads a wasm-obj file, returns a parsedstruct that holds all the sections'
+# bytecode, their section type and their length
+def ReadWASM(file_path, endianness, is_extended_isa, dbg):
+ temp_obj_file = []
+ wasm_file = open(file_path, "rb")
+ parsedstruct = ParsedStruct()
+ # read the magic cookie
+ byte = wasm_file.read(WASM_OP_Code.uint32)
+ if byte != WASM_OP_Code.magic_number.to_bytes(WASM_OP_Code.uint32, byteorder=endianness, signed=False):
+ raise Exception("bad magic cookie")
+
+ # read the version number
+ byte = wasm_file.read(WASM_OP_Code.uint32)
+ if byte != WASM_OP_Code.version_number.to_bytes(WASM_OP_Code.uint32, byteorder=endianness, signed=False):
+ raise Exception("bad version number")
+ else:
+ parsedstruct.version_number = byte
+
+ while True:
+ byte = wasm_file.read(1)
+ if byte != b'':
+ temp_obj_file.append(int.from_bytes(byte, byteorder='big', signed=False))
+ else:
+ break
+
+ offset = 0
+ loop = True
+ while loop:
+ try:
+ # section_id, offset, dummy = Read(temp_obj_file, offset, 'varuint7')
+ section_id, offset, dummy = Read(temp_obj_file, offset, 'varuint32')
+ except IndexError:
+ break
+
+ payload_length, offset, dummy = Read(temp_obj_file, offset, 'varuint32')
+
+ if section_id == 0:
+ is_custom_section = True
+ name_len, offset, dummy = Read(temp_obj_file, offset, 'varuint32')
+ name = temp_obj_file[offset : offset + name_len]
+ offset += name_len
+ if name.find("reloc", 0, 5) == 0:
+ is_reloc_section = True
+ reloc_entry_count = Read(temp_obj_file, offset, 'varuint32')
+ for i in range(0, reloc_entry_count):
+ reloc_entry, offset, dummy = Read(tmp_obj, offset, 'varuint32')
+ reloc_entries.append(reloc_entry)
+ else:
+ is_custom_section = False
+ name_len = 0
+ name = ''
+ dummy = 0
+
+ payload_data = temp_obj_file[offset:offset + payload_length - name_len - dummy]
+ offset += payload_length - name_len - dummy
+
+ # @DEVI-the second field is for general use. it is unused right
+ # now so we are filling it with jojo.
+ parsedstruct.section_list.append([section_id, 'jojo', payload_length, is_custom_section, name_len, name, payload_data])
+
+ # prints out the sections in the wasm object
+ for section in parsedstruct.section_list:
+ pass
+ #print(section)
+ wasm_file.close()
+ return(parsedstruct)
+
+# Receives a parsedstruct returned from ReadWASM, parses all the sections and
+# fills up a module class. the parse method, then can return the module.
+# the returned class objects are all defined in section_structs.py.
+class ObjReader(object):
+ def __init__(self, parsedstruct):
+ self.parsedstruct = parsedstruct
+
+ # we use this method to read the operands of instructions. it's only
+ # called by ReadCodeSection
+ def Disassemble(self, section_byte, offset):
+ # @DEVI-FIXME- not sure why i was using instruction. its a string...
+ matched = False
+ read_bytes = 0
+ read_bytes_temp = 0
+ read_bytes_temp_iter = 0
+ instruction = str()
+ operands = []
+ temp_wasm_ins = WASM_Ins()
+
+ # @DEVI-FIXME-for v1.0 opcodes. needs to get fixed for extended
+ # op-codes. ideally the mosule should hold its version number so we can
+ # check it here.
+ byte = format(section_byte[6][offset], '02x')
+ offset += 1
+ read_bytes += 1
+
+ for op_code in WASM_OP_Code.all_ops:
+ if op_code[1] == byte:
+ matched = True
+
+ # br_table has special immediates
+ # @DEVI-FIXME-this is costing us quite dearly for every opcode
+ # we read(at least two ticks per opcode). I could have the
+ # br_table opcode done separately but kinda hurts the codes
+ # uniformity. anyways.
+ if op_code[1] == '0e':
+ matched = True
+ temp, offset, read_bytes_temp_iter = Read(section_byte[6], offset, op_code[3][0])
+ instruction += repr(temp) + ' '
+ operands.append(repr(temp))
+ read_bytes_temp += read_bytes_temp_iter
+ for target_table in range(0, temp):
+ temp, offset, read_bytes_temp_iter = Read(section_byte[6], offset, op_code[3][1])
+ read_bytes_temp += read_bytes_temp_iter
+ instruction += repr(temp) + ' '
+ operands.append(repr(temp))
+ temp, offset, read_bytes_temp_iter = Read(section_byte[6], offset, op_code[3][2])
+ instruction += repr(temp) + ' '
+ operands.append(repr(temp))
+ read_bytes_temp += read_bytes_temp_iter
+ elif op_code[2]:
+ if isinstance(op_code[3], tuple):
+ for i in range(0, len(op_code [3])):
+ temp, offset, read_bytes_temp_iter = Read(section_byte[6], offset, op_code[3][i])
+ read_bytes_temp += read_bytes_temp_iter
+ instruction += repr(temp) + ' '
+ operands.append(repr(temp))
+ else:
+ temp, offset, read_bytes_temp = Read(section_byte[6], offset, op_code[3])
+ instruction += repr(temp)
+ operands.append(repr(temp))
+
+ temp_wasm_ins.opcode = op_code[0]
+ temp_wasm_ins.opcodeint = int(byte, 16)
+ #temp_wasm_ins.operands = instruction
+ temp_wasm_ins.operands = operands
+ instruction = str()
+ operands = []
+ break
+
+ read_bytes += read_bytes_temp
+ return offset, matched, read_bytes, temp_wasm_ins
+
+ # parses the code section. returns a Code_Section class
+ def ReadCodeSection(self):
+ offset = 0
+ CS = Code_Section()
+ temp_func_bodies = Func_Body()
+ temp_local_entry = Local_Entry()
+ section_exists = False
+ for whatever in self.parsedstruct.section_list:
+ # 10 is the code section
+ if whatever[0] == 10:
+ code_section = whatever.copy()
+ section_exists = True
+
+ if not section_exists:
+ return None
+
+ fn_cn, offset, dummy = Read(code_section[6], offset, 'varuint32')
+ function_cnt = fn_cn
+ CS.count = function_cnt
+
+ while function_cnt > 0:
+ function_body_length, offset, dummy = Read(code_section[6], offset, 'varuint32')
+ temp_func_bodies.body_size = function_body_length
+
+ local_count, offset, dummy = Read(code_section[6], offset, 'varuint32')
+ temp_func_bodies.local_count = local_count
+
+ # local_count_size will eventually hold how many bytes we will read
+ # in total because of the local section
+ local_count_size = dummy
+ if local_count != 0:
+ for i in range(0, local_count):
+ partial_local_count, offset, dummy = Read(code_section[6], offset, 'varuint32')
+ local_count_size += dummy
+ partial_local_type, offset, dummy = Read(code_section[6], offset, 'uint8')
+ local_count_size += dummy
+ temp_local_entry.count = partial_local_count
+ temp_local_entry.type = partial_local_type
+ temp_func_bodies.locals.append(deepcopy(temp_local_entry))
+ local_count -= partial_local_count
+ else:
+ pass
+
+ read_bytes_so_far = local_count_size
+ for i in range(0, function_body_length - local_count_size):
+ offset, matched, read_bytes, temp_wasm_ins = self.Disassemble(code_section, offset)
+ temp_func_bodies.code.append(deepcopy(temp_wasm_ins))
+
+ if not matched:
+ print(Colors.red + 'did not match anything' + Colors.ENDC)
+ print(Colors.red + 'code section offset: ' + repr(offset) + Colors.ENDC)
+ print(Colors.red + 'read bytes: ' + repr(read_bytes) + Colors.ENDC)
+ print(Colors.red + 'wasm ins: ' + repr(temp_wasm_ins.opcode) + Colors.ENDC)
+
+ for iter in temp_func_bodies.code:
+ print(iter.opcode)
+ print(iter.operands)
+ sys.exit(1)
+ else:
+ pass
+ matched = False
+ read_bytes_so_far += read_bytes
+ if read_bytes_so_far == function_body_length:
+ break
+
+ CS.func_bodies.append(deepcopy(temp_func_bodies))
+ temp_func_bodies.locals = []
+ temp_func_bodies.code = []
+ function_cnt -= 1
+ return(CS)
+
+ # parsed the data section. returns a Data_Section class
+ def ReadDataSection(self):
+ loop = True
+ section_exists = False
+ offset = 0
+ DS = Data_Section()
+ temp_data_segment = Data_Segment()
+ init_expr = []
+ for whatever in self.parsedstruct.section_list:
+ if whatever[0] == 11:
+ data_section = whatever.copy()
+ section_exists = True
+
+ if not section_exists:
+ return None
+
+ data_entry_count, offset, dummy = Read(data_section[6], offset, 'varuint32')
+ DS.count = data_entry_count
+
+ while data_entry_count != 0:
+ linear_memory_index, offset, dummy = Read(data_section[6], offset, 'varuint32')
+ temp_data_segment.index = linear_memory_index
+
+ # reading in the init-expr
+ while loop:
+ # @DEVI-FIXME-this only works for none extended opcodes
+ if data_section[6][offset] == 0x0b:
+ loop = False
+ data_char, offset, dummy = Read(data_section[6], offset, 'uint8')
+ init_expr.append(data_char)
+
+ temp_data_segment.offset = init_expr
+
+ data_entry_length, offset, dummy = Read(data_section[6], offset, 'varuint32')
+ temp_data_segment.size = data_entry_length
+
+ data_itself = data_section[6][offset:offset + data_entry_length]
+ temp_data_segment.data = data_itself
+ offset += data_entry_length
+
+ DS.data_segments.append(deepcopy(temp_data_segment))
+
+ data_entry_count -= 1
+ init_expr = []
+ loop = True
+ return(DS)
+
+ # parses the import section. returns an Import_Section class
+ def ReadImportSection(self):
+ offset = 0
+ section_exists = False
+ module_name = []
+ field_name = []
+ IS = Import_Section()
+ temp_import_entry = Import_Entry()
+ for whatever in self.parsedstruct.section_list:
+ if whatever[0] == 2:
+ import_section = whatever.copy()
+ section_exists = True
+
+ if not section_exists:
+ return None
+
+ import_cnt, offset, dummy = Read(import_section[6], offset, 'varuint32')
+ IS.count = import_cnt
+
+ while import_cnt != 0:
+ module_length, offset, dummy = Read(import_section[6], offset, 'varuint32')
+ temp_import_entry.module_len = module_length
+
+ for i in range(0, module_length):
+ module_name.append(import_section[6][offset + i])
+ temp_import_entry.module_str = module_name
+ offset += module_length
+
+ field_length, offset, dummy = Read(import_section[6], offset, 'varuint32')
+ temp_import_entry.field_len = field_length
+ for i in range(0, field_length):
+ field_name.append(import_section[6][offset + i])
+ temp_import_entry.field_str = field_name
+ offset += field_length
+
+ kind, offset, dummy = Read(import_section[6], offset, 'uint8')
+ temp_import_entry.kind = kind
+
+ # function type
+ if kind == 0:
+ import_type, offset, dummy = Read(import_section[6], offset, 'varuint32')
+ temp_import_entry.type = import_type
+ # table type
+ elif kind == 1:
+ table_type = Table_Type()
+ table_type.elemet_type, offset, dummy = Read(import_section[6], offset, 'varint7')
+ rsz_limits = Resizable_Limits()
+ rsz_limits.flags, offset, dummy = Read(import_section[6], offset, 'varuint1')
+ rsz_limits.initial, offset, dummy = Read(import_section[6], offset, 'varuint32')
+ if rsz_limits.flags:
+ rsz_limits.maximum, offset, dummy = Read(import_section[6], offset, 'varuint32')
+ table_type.limit = rsz_limits
+ temp_import_entry.type = table_type
+ elif kind == 2:
+ memory_type = Memory_Type()
+ rsz_limits = Resizable_Limits()
+ rsz_limits.flags, offset, dummy = Read(import_section[6], offset, 'varuint1')
+ rsz_limits.initial, offset, dummy = Read(import_section[6], offset, 'varuint32')
+ if rsz_limits.flags:
+ rsz_limits.maximum, offset, dummy = Read(import_section[6], offset, 'varuint32')
+ memory_type.limits = rsz_limits
+ temp_import_entry.type = memory_type
+ elif kind == 3:
+ global_type = Global_Type()
+ global_type.content_type, offset, dummy = Read(import_section[6], offset, 'uint8')
+ global_type.mutability, offset, dummy = Read(import_section[6], offset, 'varuint1')
+ temp_import_entry.type = global_type
+
+ IS.import_entry.append(deepcopy(temp_import_entry))
+
+ import_cnt -= 1
+ module_name = []
+ field_name = []
+ return(IS)
+
+ # parses the export section, returns an Export_Section class
+ def ReadExportSection(self):
+ offset = 0
+ section_exists = False
+ field_name = []
+ ES = Export_Section()
+ temp_export_entry = Export_Entry()
+ for whatever in self.parsedstruct.section_list:
+ if whatever[0] == 7:
+ export_section = whatever.copy()
+ section_exists = True
+
+ if not section_exists:
+ return None
+
+ export_entry_cnt, offset, dummy = Read(export_section[6], offset, 'varuint32')
+ ES.count = export_entry_cnt
+
+ while export_entry_cnt != 0:
+ field_length, offset, dummy = Read(export_section[6], offset, 'varuint32')
+ temp_export_entry.field_len = field_length
+
+ for i in range(0, field_length):
+ field_name.append(export_section[6][offset + i])
+ temp_export_entry.fiels_str = field_name
+ offset += field_length
+
+ kind, offset, dummy = Read(export_section[6], offset, 'uint8')
+ temp_export_entry.kind = kind
+
+ index, offset, dummy = Read(export_section[6], offset, 'varuint32')
+ temp_export_entry.index = index
+
+ ES.export_entries.append(deepcopy(temp_export_entry))
+
+ export_entry_cnt -= 1
+ field_name = []
+ return(ES)
+
+ # parses the type section, returns a Type_Section class
+ def ReadTypeSection(self):
+ offset = 0
+ section_exists = False
+ param_list = []
+ return_list = []
+ TS = Type_Section()
+ temp_func_type = Func_Type()
+ for whatever in self.parsedstruct.section_list:
+ if whatever[0] == 1:
+ type_section = whatever.copy()
+ section_exists = True
+
+ if not section_exists:
+ return None
+
+ type_entry_count, offset, dummy = Read(type_section[6], offset, 'varuint32')
+ TS.count = type_entry_count
+
+ while type_entry_count != 0:
+ form, offset, dummy = Read(type_section[6], offset, 'varint7')
+ temp_func_type.form = form
+
+ param_count, offset, dummy = Read(type_section[6], offset, 'varuint32')
+ temp_func_type.param_cnt = param_count
+
+ for i in range(0, param_count):
+ param_list.append(type_section[6][offset + i])
+ temp_func_type.param_types = param_list
+ offset += param_count
+
+ # @DEVI-FIXME- only works for MVP || single return value
+ return_count, offset, dummy = Read(type_section[6], offset, 'varuint1')
+ temp_func_type.return_cnt = return_count
+
+ for i in range(0, return_count):
+ return_list.append(type_section[6][offset + i])
+ temp_func_type.return_type = return_list
+ offset += return_count
+
+ TS.func_types.append(deepcopy(temp_func_type))
+
+ type_entry_count -= 1
+ param_list = []
+ return_list = []
+ return(TS)
+
+ # parses the function section, returns a Function_section class
+ def ReadFunctionSection(self):
+ offset = 0
+ section_exists = False
+ index_to_type = []
+ FS = Function_Section()
+ for whatever in self.parsedstruct.section_list:
+ if whatever[0] == 3:
+ function_section = whatever.copy()
+ section_exists = True
+
+ if not section_exists:
+ return None
+
+ function_entry_count, offset, dummy = Read(function_section[6], offset, 'varuint32')
+ FS.count = function_entry_count
+
+ for i in range(0, function_entry_count):
+ index, offset, dummy = Read(function_section[6], offset, 'varuint32')
+ index_to_type.append(index)
+ FS.type_section_index = index_to_type
+ offset += function_entry_count
+ return(FS)
+
+ # parses the element secction, returns an Element_Section class
+ def ReadElementSection(self):
+ offset = 0
+ section_exists = False
+ init_expr = []
+ loop = True
+ function_indices = []
+ ES = Element_Section()
+ temp_elem_segment = Elem_Segment()
+
+ for whatever in self.parsedstruct.section_list:
+ if whatever[0] == 9:
+ element_section = whatever.copy()
+ section_exists = True
+
+ if not section_exists:
+ return None
+
+ element_entry_count, offset, dummy = Read(element_section[6], offset, 'varuint32')
+ ES.count = element_entry_count
+
+ while element_entry_count != 0:
+ table_index, offset, dummy = Read(element_section[6], offset, 'varuint32')
+ temp_elem_segment.index = table_index
+
+ # @DEVI-FIXME-only works for non-extneded opcodes
+ while loop:
+ if element_section[6][offset] == 0x0b:
+ loop = False
+ init_expr.append(element_section[6][offset])
+ offset += 1
+ temp_elem_segment.offset = init_expr
+
+ num_elements, offset, dummy = Read(element_section[6], offset, 'varuint32')
+ temp_elem_segment.num_elem = num_elements
+
+ for i in range(0, num_elements):
+ index, offset, dummy = Read(element_section[6], offset, 'varuint32')
+ function_indices.append(index)
+ temp_elem_segment.elems = function_indices
+ offset += num_elements
+
+ ES.elem_segments.append(deepcopy(temp_elem_segment))
+
+ loop = True
+ init_expr = []
+ function_indices = []
+ element_entry_count -= 1
+ return(ES)
+
+ # parses the memory section, returns a Memory_Section class
+ def ReadMemorySection(self):
+ offset = 0
+ section_exists = False
+ MS = Memory_Section()
+ temp_rsz_limits = Resizable_Limits()
+
+ for whatever in self.parsedstruct.section_list:
+ if whatever[0] == 5:
+ memory_section = whatever.copy()
+ section_exists = True
+
+ if not section_exists:
+ return None
+
+ num_linear_mems, offset, dummy = Read(memory_section[6], offset, 'varuint32')
+ MS.count = num_linear_mems
+
+ while num_linear_mems != 0:
+ flag, offset, dummy = Read(memory_section[6], offset, 'varuint1')
+ temp_rsz_limits.flags = flag
+
+ initial,offset, dummy = Read(memory_section[6], offset, 'varuint32')
+ temp_rsz_limits.initial = initial
+
+ if flag:
+ maximum, offset, dummy = Read(memory_section[6], offset, 'varuint32')
+ temp_rsz_limits.maximum = maximum
+
+ MS.memory_types.append(deepcopy(temp_rsz_limits))
+ num_linear_mems -= 1
+ return(MS)
+
+ # parses the table section, returns a Table_Section class
+ def ReadTableSection(self):
+ offset = 0
+ section_exists = False
+ TS = Table_Section()
+ temp_table_type = Table_Type()
+ temp_rsz_limits = Resizable_Limits()
+
+ for whatever in self.parsedstruct.section_list:
+ if whatever[0] == 4:
+ table_section = whatever.copy()
+ section_exists = True
+
+ if not section_exists:
+ return None
+
+ table_count, offset, dummy = Read(table_section[6], offset, 'varuint32')
+ TS.count = table_count
+
+ while table_count != 0:
+ element_type, offset, dummy = Read(table_section[6], offset, 'varint7')
+ temp_table_type.element_type = element_type
+
+ flag, offset, dummy = Read(table_section[6], offset, 'varuint1')
+ temp_rsz_limits.flags = flag
+
+ initial, offset, dummy = Read(table_section[6], offset, 'varuint32')
+ temp_rsz_limits.initial = initial
+
+ if flag:
+ maximum, offset, dummy = Read(table_section[6], offset, 'varuint32')
+ temp_rsz_limits.maximum = maximum
+
+ temp_table_type.limit = temp_rsz_limits
+ TS.table_types.append(deepcopy(temp_table_type))
+
+ table_count -= 1
+ return(TS)
+
+ # parses the global section, returns a Global_Section class
+ def ReadGlobalSection(self):
+ offset = 0
+ loop = True
+ section_exists = False
+ init_expr = []
+ GS = Global_Section()
+ temp_gl_var = Global_Variable()
+ temp_gl_type = Global_Type()
+
+ for whatever in self.parsedstruct.section_list:
+ if whatever[0] == 6:
+ global_section = whatever.copy()
+ section_exists = True
+
+ if not section_exists:
+ return None
+
+ count, offset, dummy = Read(global_section[6], offset, 'varuint32')
+ GS.count = count
+
+ while count != 0:
+ content_type, offset, dummy = Read(global_section[6], offset, 'uint8')
+ temp_gl_type.content_type = content_type
+
+ mutability, offset, dummy = Read(global_section[6], offset, 'varuint1')
+ temp_gl_type.mutability = mutability
+
+ # @DEVI-FIXME-only works for non-extended opcodes
+ while loop:
+ if global_section[6][offset] == 0x0b:
+ loop = False
+ init_expr.append(global_section[6][offset])
+ offset += 1
+ temp_gl_var.init_expr = init_expr
+
+ temp_gl_var.global_type = temp_gl_type
+ GS.global_variables.append(deepcopy(temp_gl_var))
+
+
+ count -= 1
+ loop = True
+ init_expr = []
+ return(GS)
+
+ # parses the start section, returns a Start_Section
+ def ReadStartSection(self):
+ offset = 0
+ section_exists = False
+ SS = Start_Section()
+
+ for whatever in self.parsedstruct.section_list:
+ if whatever[0] == 8:
+ start_section = whatever.copy()
+ section_exists = True
+ if not section_exists:
+ return None
+
+ function_index, offset, dummy = Read(start_section[6], offset, 'varuint32')
+ SS.function_section_index = function_index
+ return(SS)
+
+ def ReadRelocationSection(self):
+ offset = 0
+ section_exists = False
+ RS = Relocation_Section()
+ for whatever in self.parsedstruct.section_list:
+ if whatever[0] == 0 and whatever[1] == "reloc":
+ reloc_section = whatever.copy()
+ section_exists = True
+ if not section_exists:
+ return None
+ return(RS)
+
+ def ReadNameSection(self):
+ offset = 0
+ section_exists = False
+ NS = Name_Section()
+ for whatever in self.parsedstruct.section_list:
+ if whatever[0] == 0 and whatever[1] == "name":
+ name_section = whatever.copy()
+ section_exists = True
+ if not section_exists:
+ return None
+ return(NS)
+
+ def ReadLinkingSection(self):
+ pass
+
+ def ReadLinkingDotSections(self):
+ pass
+
+ # unused-returns the cursor location in the object file
+ def getCursorLocation(self):
+ return(self.wasm_file.tell())
+
+ # a convinience method-builds a module class and returns it
+ def parse(self):
+ return(Module(self.ReadTypeSection(), self.ReadImportSection(),
+ self.ReadFunctionSection(), self.ReadTableSection(),
+ self.ReadMemorySection(), self.ReadGlobalSection(),
+ self.ReadExportSection(), self.ReadStartSection(),
+ self.ReadElementSection(), self.ReadCodeSection(),
+ self.ReadDataSection()))
+
+
+# WIP-basically how the assembler is constructed
+class ParserV1(object):
+ def __init__(self, path):
+ self.path = path
+
+ def run(self):
+ wasmtobj = WASMText(self.path)
+ # wasmtobj.test_print()
+ wasmtobj.RegExSearch()
+ wasmtobj.PrintTypeDict()
+ wasmtobj.PrintImportDict()
+ wasmtobj.PrintTableDict()
+ wasmtobj.PrintElemDict()
+ wasmtobj.PrintMemoryDict()
+ wasmtobj.PrintDataDict()
+ wasmtobj.PrintExportDict()
+ wasmtobj.PrintFuncDict()
+ wasmtobj.PrintElemDict()
+ wasmtobj.FuncParser()
+ wasmtobj.FuncParserTest()
+
+ funcbodyparser = FuncBodyParser(wasmtobj.getFuncBodies())
+ headerparser = FuncBodyParser(wasmtobj.getTypeHeader())
+
+ expr_stack = funcbodyparser.ParseBodyV3(False)
+ header_stack = headerparser.ParseBodyV3(True)
+
+ wasm_codeemitter = WASM_CodeEmitter(expr_stack)
+ #wasm_codeemitter.Obj_Header_32()
+ #wasm_codeemitter.Dump_Obj_STDOUT()
+
+ #wasm_codeemitter.SetNewStack(header_stack)
+ #wasm_codeemitter.EmitTypeHeader()
+ #wasm_codeemitter.PrintTypeHeaderObj()
+
+
+# our interpreter class
+class PythonInterpreter(object):
+ def __init__(self):
+ self.modules = []
+ self.sections = []
+
+ # appends a module to the module list that PythonInterpreter has
+ def appendmodule(self, module):
+ self.modules.append(module)
+
+ # returns the list of modules that we have parsed so far
+ def getmodules(self):
+ return(self.modules)
+
+ def appendsection(self, section):
+ self.sections.append(section)
+
+ def getsections(self):
+ return self.sections
+
+ # convinience method.calls the ObjReader to parse a wasm obj file.
+ # returns a module class.
+ def parse(self, file_path):
+ section = ReadWASM(file_path, 'little', False, True)
+ self.appendsection(section)
+ parser = ObjReader(section)
+ return(parser.parse())
+
+ # dumps the object sections' info to stdout. pretty print.
+ def dump_sections(self, module, dbgsection):
+ all = False
+ if dbgsection == "":
+ all = True
+ print(Colors.blue + Colors.BOLD +
+ 'BEGENNING OF MODULE' + Colors.ENDC)
+
+ # type_section
+ if module.type_section is not None and (dbgsection == "type" or all):
+ print(Colors.blue + '------------------------------------------------------' + Colors.ENDC)
+ print(Colors.blue + Colors.BOLD + 'Type Section:' + Colors.ENDC)
+ print(Colors.blue + '------------------------------------------------------' + Colors.ENDC)
+ print('count: ' + repr(module.type_section.count))
+ for iter in module.type_section.func_types:
+ print(Colors.cyan + 'form: ' + repr(iter.form) + Colors.ENDC)
+ print(Colors.green + 'param count: ' + repr(iter.param_cnt) + Colors.ENDC)
+ print(Colors.red + 'param types: ' + repr(iter.param_types) + Colors.ENDC)
+ print(Colors.purple + 'return count: ' + repr(iter.return_cnt) + Colors.ENDC)
+ print(Colors.yellow + 'return type: ' + repr(iter.return_type) + Colors.ENDC)
+
+ # import_section
+ if module.import_section is not None and (dbgsection == "import" or all):
+ print(Colors.blue + '------------------------------------------------------' + Colors.ENDC)
+ print(Colors.blue + Colors.BOLD + 'Import Section:' + Colors.ENDC)
+ print(Colors.blue + '------------------------------------------------------' + Colors.ENDC)
+ print('count: ' + repr(module.import_section.count))
+ for iter in module.import_section.import_entry:
+ print(Colors.cyan + 'module length: ' + repr(iter.module_len) + Colors.ENDC)
+ print(Colors.green + 'module str: ' + repr(iter.module_str) + Colors.ENDC)
+ print(Colors.red + 'field length: ' + repr(iter.field_len) + Colors.ENDC)
+ print(Colors.purple + 'field str: ' + repr(iter.field_str) + Colors.ENDC)
+ print(Colors.yellow + 'kind: ' + repr(iter.kind) + Colors.ENDC)
+ print(Colors.grey + 'type: ' + repr(iter.type) + Colors.ENDC)
+
+ # function_section
+ if module.function_section is not None and (dbgsection == "function" or all):
+ print(Colors.blue + '------------------------------------------------------' + Colors.ENDC)
+ print(Colors.blue + Colors.BOLD + 'Function Section:' + Colors.ENDC)
+ print(Colors.blue + '------------------------------------------------------' + Colors.ENDC)
+ print('count: ' + repr(module.function_section.count))
+ for iter in module.function_section.type_section_index:
+ print(Colors.cyan + 'type section index: ' + repr(iter) + Colors.ENDC)
+
+ # table_section
+ if module.table_section is not None and (dbgsection == "table" or all):
+ print(Colors.blue + '------------------------------------------------------' + Colors.ENDC)
+ print(Colors.blue + Colors.BOLD + 'Table Section:' + Colors.ENDC)
+ print(Colors.blue + '------------------------------------------------------' + Colors.ENDC)
+ print('count: ' + repr(module.table_section.count))
+ for iter in module.table_section.table_types:
+ print(Colors.cyan + 'element type: ' + repr(iter.element_type) + Colors.ENDC)
+ print(Colors.green + 'Resizable_Limits:flags: ' + repr(iter.limit.flags) + Colors.ENDC)
+ print(Colors.red + 'Resizable_Limits:initial: ' + repr(iter.limit.initial) + Colors.ENDC)
+ print(Colors.purple + 'Resizable_Limits:maximum: ' + repr(iter.limit.maximum) + Colors.ENDC)
+
+ # memory_section
+ if module.memory_section is not None and (dbgsection == "memory" or all):
+ print(Colors.blue + '------------------------------------------------------' + Colors.ENDC)
+ print(Colors.blue + Colors.BOLD + 'Memory Section:' + Colors.ENDC)
+ print(Colors.blue + '------------------------------------------------------' + Colors.ENDC)
+ print('count: ' + repr(module.memory_section.count))
+ for iter in module.memory_section.memory_types:
+ print(Colors.green + 'Resizable_Limits:flags: ' + repr(iter.flags) + Colors.ENDC)
+ print(Colors.red + 'Resizable_Limits:initial: ' + repr(iter.initial) + Colors.ENDC)
+ print(Colors.purple + 'Resizable_Limits:maximum: ' + repr(iter.maximum) + Colors.ENDC)
+
+ # global_section
+ if module.global_section is not None and (dbgsection == "global" or all):
+ print(Colors.blue + '------------------------------------------------------' + Colors.ENDC)
+ print(Colors.blue + Colors.BOLD + 'Global Section:' + Colors.ENDC)
+ print(Colors.blue + '------------------------------------------------------' + Colors.ENDC)
+ print('count: ' + repr(module.global_section.count))
+ for iter in module.global_section.global_variables:
+ print(Colors.green + 'global type: ' + repr(iter.global_type) + Colors.ENDC)
+ print(Colors.red + 'init expr: ' + repr(iter.init_expr) + Colors.ENDC)
+
+ # export_section
+ if module.export_section is not None and (dbgsection == "export" or all):
+ print(Colors.blue + '------------------------------------------------------' + Colors.ENDC)
+ print(Colors.blue + Colors.BOLD + 'Export Section:' + Colors.ENDC)
+ print(Colors.blue + '------------------------------------------------------' + Colors.ENDC)
+ print('count: ' + repr(module.export_section.count))
+ for iter in module.export_section.export_entries:
+ print(Colors.green + 'field length: ' + repr(iter.field_len) + Colors.ENDC)
+ print(Colors.red + 'field str: ' + repr(iter.field_str) + Colors.ENDC)
+ print(Colors.purple + 'kind: ' + repr(iter.kind) + Colors.ENDC)
+ print(Colors.cyan + 'index: ' + repr(iter.index) + Colors.ENDC)
+
+ # start_section
+ if module.start_section is not None and (dbgsection == "start" or all):
+ print(Colors.blue + '------------------------------------------------------' + Colors.ENDC)
+ print(Colors.blue + Colors.BOLD + 'Start Section:' + Colors.ENDC)
+ print(Colors.blue + '------------------------------------------------------' + Colors.ENDC)
+ print('start function index: ' + repr(module.start_section.function_section_index))
+
+ # element_section
+ if module.element_section is not None and (dbgsection == "element" or all):
+ print(Colors.blue + '------------------------------------------------------' + Colors.ENDC)
+ print(Colors.blue + Colors.BOLD + 'Element Section:' + Colors.ENDC)
+ print(Colors.blue + '------------------------------------------------------' + Colors.ENDC)
+ print('count: ' + repr(module.element_section.count))
+ for iter in module.element_section.elem_segments:
+ print(Colors.green + 'index: ' + repr(iter.index) + Colors.ENDC)
+ print(Colors.red + 'offset: ' + repr(iter.offset) + Colors.ENDC)
+ print(Colors.purple + 'num_elem: ' + repr(iter.num_elem) + Colors.ENDC)
+ print(Colors.cyan + 'elemes:' + repr(iter.elems) + Colors.ENDC)
+
+ # code_section
+ if module.code_section is not None and (dbgsection == "code" or all):
+ print(Colors.blue + '------------------------------------------------------' + Colors.ENDC)
+ print(Colors.blue + Colors.BOLD + 'Code Section:' + Colors.ENDC)
+ print(Colors.blue + '------------------------------------------------------' + Colors.ENDC)
+ print('count: ' + repr(module.code_section.count))
+ for iter in module.code_section.func_bodies:
+ print(Colors.green + 'body size: ' + repr(iter.body_size) + Colors.ENDC)
+ print(Colors.red + 'local enrty count: ' + repr(iter.local_count) + Colors.ENDC)
+ for iterer in iter.locals:
+ print(Colors.blue + 'local count: ' + repr(iterer.count) + Colors.ENDC)
+ print(Colors.blue + 'local type: ' + repr(iterer.type) + Colors.ENDC)
+ for iterer in iter.code:
+ instruction = iterer.opcode + ' ' + repr(iterer.operands)
+ print(Colors.yellow + instruction + Colors.ENDC, end="")
+ print("\t", end="")
+ print(Colors.cyan + 'opcode: ' + repr(iterer.opcode) + Colors.ENDC, end="")
+ print("\t", end="")
+ print(Colors.grey + 'immediate: ' + repr(iterer.operands) + Colors.ENDC, end="")
+ print("\t", end="")
+ print(Colors.UNDERLINE + "num of operands: " + repr(len(iterer.operands)) + Colors.ENDC)
+
+ # data_section
+ if module.data_section is not None and (dbgsection == "data" or all):
+ print(Colors.blue + '------------------------------------------------------' + Colors.ENDC)
+ print(Colors.blue + Colors.BOLD + 'Data Section:' + Colors.ENDC)
+ print(Colors.blue + '------------------------------------------------------' + Colors.ENDC)
+ print('count: ' + repr(module.data_section.count))
+ for iter in module.data_section.data_segments:
+ print(Colors.green + 'index: ' + repr(iter.index) + Colors.ENDC)
+ print(Colors.red + 'offset: ' + repr(iter.offset) + Colors.ENDC)
+ print(Colors.purple + 'size: ' + repr(iter.size) + Colors.ENDC)
+ print(Colors.cyan + 'data:' + repr(iter.data) + Colors.ENDC)
+
+ # palceholder for the validation tests
+ def runValidations(self):
+ modulevalidation = ModuleValidation(self.modules[0])
+ return(modulevalidation.ValidateAll())
+
+def premain(argparser):
+ interpreter = PythonInterpreter()
+ if argparser.args.wasm:
+ for file_path in argparser.args.wasm:
+ module = interpreter.parse(file_path)
+ print(type(module))
+ interpreter.appendmodule(module)
+ if argparser.args.dbg or argparser.args.dbgsection:
+ interpreter.dump_sections(module, argparser.args.dbgsection)
+ if interpreter.runValidations():
+ print(Colors.red + "validations are not implemented yet" + Colors.ENDC)
+ pass
+ else:
+ print(Colors.red + 'failed validation tests' + Colors.ENDC)
+ vm = VM(interpreter.getmodules())
+ vm.setFlags(argparser.getParseFlags())
+ ms = vm.getState()
+ if argparser.args.idxspc:
+ DumpIndexSpaces(ms)
+ if argparser.args.memdump:
+ DumpLinearMems(ms.Linear_Memory, argparser.getMEMDUMP())
+ if argparser.args.run:
+ vm.run()
+ # merklizer = Merklizer(ms.Linear_Memory[0][0:512], module)
+ # treelength, hashtree = merklizer.run()
+
+ if argparser.args.interactive:
+ variables = globals().copy()
+ variables.update(locals())
+ shell = code.InteractiveConsole(variables)
+ shell.interact(banner="WASM python REPL")
+ if argparser.args.hexdump:
+ dumpprettysections(interpreter.getsections(), argparser.args.hexdump, "")
+ if argparser.args.sectiondump is not None:
+ dumpprettysections(interpreter.getsections(), 24, argparser.args.sectiondump)
+ if argparser.args.wast:
+ #print(argparser.getWASTPath())
+ parser = ParserV1(argparser.getWASTPath())
+ parser.run()
+ # WIP-the assmebler
+ if argparser.args.asb:
+ print("not implemented yet")
+ sys.exit(1)
+ # WIP-the disassmebler
+ if argparser.args.dis:
+ print("not implemented yet")
+ sys.exit(1)
+
+def main():
+ argparser = Argparser()
+ if argparser.args.dbg:
+ try:
+ premain(argparser)
+ except Exception:
+ variables = globals().copy()
+ variables.update(locals())
+ shell = code.InteractiveConsole(variables)
+ shell.interact(banner="DEVIWASM REPL")
+ else:
+ premain(argparser)
+
+if __name__ == "__main__":
+ main()
diff --git a/run.sh b/run.sh
new file mode 100755
index 0000000..bcccca1
--- /dev/null
+++ b/run.sh
@@ -0,0 +1,3 @@
+#!/usr/bin/bash
+
+"./dwasm.py" --wasm ./test/injected.wasm --section code
diff --git a/section_structs.py b/section_structs.py
new file mode 100644
index 0000000..219f7ea
--- /dev/null
+++ b/section_structs.py
@@ -0,0 +1,301 @@
+# contains the data classes we use to hold the information of a module
+class WASM_SECTION(object):
+ def __init__(self):
+ self.section_id = int()
+ self.string = str()
+ self.payload_length = int()
+ self.is_custom_section = bool()
+ self.name_len = int()
+ self.name = str()
+ self.payload_data = bytes()
+
+class WASM_SEGMENT_INFO():
+ def __int__(self):
+ self.count = int()
+ self.segments = []
+
+class WASM_SEGMENT_INFO_SEGMENT():
+ def __init__(self):
+ self.name_len = int()
+ self.name_data = str()
+ self.alignment = int()
+ self.flags = int()
+
+class WASM_COMDAT_INFO_SUB():
+ def __init__(self):
+ self.count = int()
+ self.comdats = []
+
+class COMDAT():
+ def __init(self):
+ self.name_len = int()
+ self.name_str = str()
+ self.flags = int()
+ self.count = int()
+ self.comdat_syms = []
+
+class COMDAT_SYM():
+ def __init(self):
+ self.kind = int()
+ self.index = int()
+
+class WASM_COMDAT_KIND():
+ WASM_COMDAT_DATA = 0
+ WASM_COMDAT_FUNCTION = 1
+ WASM_COMDAT_GLOBAL = 2
+
+class WASM_INIT_FUNCS():
+ def __init__(self):
+ self.count = int()
+ self.functions = []
+
+class WASM_SYMBOL_TABLE():
+ def __init__(self):
+ self.count = int()
+ self.syminfo = []
+
+class SYM_INFO():
+ def __init__(self):
+ self.kind = int()
+ self.flags = int()
+
+class SYM_INFO_FLAGS():
+ WASM_SYM_BINDING_WEAK = 1
+ WASM_SYM_BINDING_LOCAL = 2
+ WASM_SYM_VISIBILITY_HIDDEN = 4
+ WASM_SYM_UNDEFINED = 16
+
+
+class Rel_Entry():
+ def __int__(self):
+ self.type = int()
+ self.offset = int()
+ self.index = int()
+
+class RelA_Entry():
+ def __int__(self):
+ self.type = int()
+ self.offset = int()
+ self.index = int()
+ self.addend = int()
+
+class Relocation_Section():
+ def __int__(self):
+ self.section_id = int()
+ self.name_length = int()
+ self.name = str()
+ self.count = int()
+ self.entries = int()
+
+class Func_Type():
+ def __init__(self):
+ self.form = int()
+ self.param_cnt = int()
+ self.param_types = []
+ self.return_cnt = int()
+ self.return_type = []
+
+class Global_Type():
+ def __init__(self):
+ self.content_type = int()
+ self.mutability = int()
+
+class Resizable_Limits():
+ def __init__(self):
+ self.flags = int()
+ self.initial = int()
+ self.maximum = int()
+
+class Table_Type():
+ def __init__(self):
+ self.element_type = int()
+ self.limit = Resizable_Limits()
+
+class External_Kind():
+ def __init__(self):
+ self.Function = 0
+ self.Table = 1
+ self.Memory = 2
+ self.Global = 3
+
+class Memory_Type():
+ def __init__(self):
+ self.limits = [Resizable_Limits()]
+
+# @DEVI-FIXME-
+class Init_Expr():
+ pass
+
+class Type_Section():
+ def __init__(self):
+ self.count = []
+ self.func_types = []
+
+class Import_Entry():
+ def __init__(self):
+ self.module_len = int()
+ self.module_str = []
+ self.field_len = int()
+ self.field_str = []
+ self.kind = int()
+ self.type = int()
+
+class Import_Section():
+ def __init__(self):
+ self.count = []
+ self.import_entry = []
+
+class Function_Section():
+ def __init__(self):
+ self.count = []
+ self.type_section_index = [int()]
+
+class Table_Section():
+ def __init__(self):
+ self.count = []
+ self.table_types = []
+
+class Memory_Section():
+ def __init__(self):
+ self.count = []
+ # Resizable_Limits
+ self.memory_types = []
+
+class Global_Variable():
+ def __init__(self):
+ self.global_type = Global_Type()
+ self.init_expr = []
+
+class Global_Section():
+ def __init__(self):
+ self.count = []
+ # Global_Variable
+ self.global_variables = []
+
+class Export_Entry():
+ def __init__(self):
+ self.field_len = int()
+ self.field_str = []
+ self.kind = int()
+ self.index = int()
+
+class Export_Section():
+ def __init__(self):
+ self.count = []
+ # Export_Entry
+ self.export_entries = []
+
+class Start_Section():
+ def __init__(self):
+ self.function_section_index = []
+
+class Elem_Segment():
+ def __init__(self):
+ self.index = int()
+ self.offset = []
+ self.num_elem = int()
+ self.elems = []
+
+class Element_Section():
+ def __init__(self):
+ self.count = []
+ # Elem_Segment
+ self.elem_segments = []
+
+class Local_Entry():
+ def __init__(self):
+ self.count = int()
+ self.type = int()
+
+class WASM_Ins():
+ def __init__(self):
+ self.opcode = str()
+ self.opcodeint = int()
+ self.operands = []
+
+class Func_Body():
+ def __init__(self):
+ self.body_size = int()
+ self.local_count = int()
+ # Local_Entry
+ self.locals = []
+ # WASM_Ins
+ self.code = []
+ self.end = int()
+
+class Code_Section():
+ def __init__(self):
+ self.count = []
+ # Func_Body
+ self.func_bodies = []
+
+class Data_Segment():
+ def __init__(self):
+ self.index = int()
+ self.offset = []
+ self.size = int()
+ self.data = []
+
+class Data_Section():
+ def __init__(self):
+ self.count = []
+ # Data_Segment
+ self.data_segments = []
+
+class Name_Type():
+ Module = 0
+ Function = 1
+ Local = 2
+
+class Name_Section_Entry(object):
+ def __init__(self, name_type, name_payload_len, name_payload_data):
+ self.name_type = name_type
+ self.name_payload_len = name_payload_len
+ self.name_payload_data = name_payload_data
+
+class Name_Section(object):
+ def __init__(self, name_section_entry):
+ self.name_section_entry = []
+ self.name_section_entry = name_section_entry
+
+class Module_Name(object):
+ def __init__(self, name_len, name_str):
+ self.name_len = name_len
+ self.name_str = name_str
+
+class Naming(object):
+ def __init__(self, index, name_len, name_str):
+ self.index = index
+ self.name_len = name_len
+ self.name_str = name_str
+
+class Name_Map(object):
+ def __init__(self, count, naming):
+ self.count = count
+ self.naming = []
+ self.naming = naming
+
+# the module class
+class Module():
+ def __init__(self, type_section, import_section, function_section,
+ table_section, memory_section, global_section, export_section,
+ start_section, element_section, code_section, data_section):
+ self.type_section = type_section
+ self.import_section = import_section
+ self.function_section = function_section
+ self.table_section = table_section
+ self.memory_section = memory_section
+ self.global_section = global_section
+ self.export_section = export_section
+ self.start_section = start_section
+ self.element_section = element_section
+ self.code_section = code_section
+ self.data_section = data_section
+
+'''
+class RT_INS_CELL(object):
+ def __init__(self):
+ label : str
+ mnemonic : str
+ ops : list
+'''
diff --git a/test/injected.wasm b/test/injected.wasm
new file mode 100644
index 0000000..59f492c
--- /dev/null
+++ b/test/injected.wasm
Binary files differ
diff --git a/test/linker/.depend b/test/linker/.depend
new file mode 100644
index 0000000..9cb14ac
--- /dev/null
+++ b/test/linker/.depend
@@ -0,0 +1,2 @@
+file0.o: file0.c file1.c
+file1.o: file1.c
diff --git a/test/linker/file0.c b/test/linker/file0.c
new file mode 100644
index 0000000..5eb172b
--- /dev/null
+++ b/test/linker/file0.c
@@ -0,0 +1,20 @@
+#include <stdio.h>
+#include <inttypes.h>
+#include "file1.c"
+
+#define CODE_SECTION_0_0 "constant_0_0"
+#define CODE_SECTION_0_1 "constant_0_1"
+#define CODE_SECTION_0_2 "constant_0_2"
+#define CODE_SECTION_0_3 "constant_0_3"
+#define CODE_SECTION_0_4 "constant_0_4"
+
+int g_int_0_0 = 0;
+int g_int_0_1 = 1;
+
+int dummy_f_0_0(int n) {
+ return n*4;
+}
+
+int main (int argc, char** argv) {
+ return 123;
+}
diff --git a/test/linker/file1.c b/test/linker/file1.c
new file mode 100644
index 0000000..233eaad
--- /dev/null
+++ b/test/linker/file1.c
@@ -0,0 +1,25 @@
+#include <stdio.h>
+#include <inttypes.h>
+#if 1
+void print(void) {
+ printf("external symbol");
+}
+#endif
+
+#define CODE_SECTION_1_0 "constant_1_0"
+#define CODE_SECTION_1_1 "constant_1_1"
+#define CODE_SECTION_1_2 "constant_1_2"
+#define CODE_SECTION_1_3 "constant_1_3"
+#define CODE_SECTION_1_4 "constant_1_4"
+
+int g_int_1_0 = 10;
+int g_int_1_1 = 11;
+
+int dummy_f_1_0(int n) {
+ if (n >= 1) return dummy_f_1_0(n-1) * n;
+ else return 1;
+}
+
+int dymmy_f_1_1(int n) {
+ return n*2;
+}
diff --git a/test/linker/makefile b/test/linker/makefile
new file mode 100644
index 0000000..1cc9413
--- /dev/null
+++ b/test/linker/makefile
@@ -0,0 +1,44 @@
+TARGET=file0
+CC=clang
+CC?=clang
+CC_FLAGS=
+CC_EXTRA?=
+CC_FLAGS+=$(CC_EXTRA)
+
+SRCS=$(wildcard *.c)
+WASM=$(patsubst %.c, %.wasm, $(wildcard *.c))
+
+.DEFAULT:all
+
+.PHONY:all clean help
+
+all:$(TARGET) wasmforce
+
+depend:.depend
+
+.depend:$(SRCS)
+ rm -rf .depend
+ $(CC) -MM $(CC_FLAGS) $^ > ./.depend
+
+-include ./.depend
+
+%.wasm:%.c
+ llvm-wasm $<
+
+wasmforce:$(WASM)
+ @echo forcing generation of wasm and wast
+
+.c.o:
+ $(CC) $(CC_FLAGS) -c $< -o $@
+
+$(TARGET): $(TARGET).o
+ $(CC) $^ $(LD_FLAGS) -o $@
+
+clean:
+ rm -f *.s *.wasm *.wast *.bc *.o *~ $(TARGET)
+ rm .depend
+
+help:
+ @echo "all is the default target"
+ @echo "there is delete."
+ @echo "there is clean."
diff --git a/utils.py b/utils.py
new file mode 100644
index 0000000..69393b4
--- /dev/null
+++ b/utils.py
@@ -0,0 +1,425 @@
+from opcodes import *
+import numpy as np
+import struct as stc
+
+class ParseFlags:
+ def __init__(self, wast_path, wasm_path, as_path, disa_path, out_path, dbg, unval, memdump
+ , idxspc, run, metric, gas, entry):
+ self.wast_path = wast_path
+ self.wasm_path = wasm_path
+ self.as_path = as_path
+ self.disa_path = disa_path
+ self.out_path = out_path
+ self.dbg = dbg
+ self.unval = unval
+ self.memdump = memdump
+ self.idxspc = idxspc
+ self.run = run
+ self.metric = metric
+ self.gas = gas
+ self.entry = entry
+
+# pretty print
+class Colors:
+ purple = '\033[95m'
+ blue = '\033[94m'
+ green = '\033[92m'
+ yellow = '\033[93m'
+ red = '\033[91m'
+ grey = '\033[1;37m'
+ darkgrey = '\033[1;30m'
+ cyan = '\033[1;36m'
+ ENDC = '\033[0m'
+ BOLD = '\033[1m'
+ UNDERLINE = '\033[4m'
+
+def LEB128UnsignedDecode(bytelist):
+ result = 0
+ shift = 0
+ for byte in bytelist:
+ result |= (byte & 0x7f) << shift
+ if (byte & 0x80) == 0:
+ break
+ shift += 7
+ return(result)
+
+def LEB128SignedDecode(bytelist):
+ result = 0
+ shift = 0
+ for byte in bytelist:
+ result |= (byte & 0x7f) << shift
+ last_byte = byte
+ shift += 7
+ if (byte & 0x80) == 0:
+ break
+
+ if last_byte & 0x40:
+ result |= - (1 << shift)
+
+ return(result)
+
+def LEB128UnsignedEncode(int_val):
+ if int_val < 0:
+ raise Exception("value must not be negative")
+ elif int_val == 0:
+ return bytes([0])
+
+ byte_array = bytearray()
+ while int_val:
+ byte = int_val & 0x7f
+ byte_array.append(byte | 0x80)
+ int_val >>= 7
+
+ byte_array[-1] ^= 0x80
+
+ return(byte_array)
+
+
+def LEB128SignedEncode(int_val):
+ byte_array = bytearray()
+ while True:
+ byte = int_val & 0x7f
+ byte_array.append(byte | 0x80)
+ int_val >>= 7
+ if (int_val == 0 and byte&0x40 == 0) or (int_val == -1 and byte&0x40):
+ byte_array[-1] ^= 0x80
+ break
+
+ return(byte_array)
+
+# @DEVI-FIXME-MVP-only-we currently inly support consts and get_global
+# interprets the init-exprs
+def init_interpret(expr):
+ offset = 0
+ byte, offset, dummy = Read(expr, offset, 'uint8')
+ const = int()
+
+ if byte == 65:
+ # @DEVI-FIXME-the spec says varint32, obviously we are not doing that
+ # since it will return neg values which are meningless and break things
+ const, offset, dummy = Read(expr, offset, 'varuint32')
+ elif byte == 66:
+ const, offset, dummy = Read(expr, offset, 'varint64')
+ elif byte == 67:
+ const, offset, dummy = Read(expr, offset, 'uint32')
+ elif byte == 68:
+ const, offset, dummy = Read(expr, offset, 'uint64')
+ elif byte == 35:
+ pass
+ else:
+ raise Exception(Colors.red + "illegal opcode for an MVP init expr." + Colors.ENDC)
+
+ block_end, offset, dummy = Read(expr, offset, 'uint8')
+ if block_end != 11:
+ raise Exception(Colors.red + "init expr has no block end." + Colors.ENDC)
+
+ return(const)
+
+# reads different-typed values from a byte array, takes in the bytearray, the
+# current offset the read should be performed from and the kind of value that
+# should be read. returns the read value as a decimal number, the updated
+# offset and the number of bytes read
+def Read(section_byte, offset, kind):
+ operand = []
+ return_list = int()
+ read_bytes = 0
+
+ if kind == 'varuint1' or kind == 'varuint7' or kind == 'varuint32' or kind == 'varuint64':
+ while True:
+ byte = int(section_byte[offset])
+ read_bytes += 1
+ offset += 1
+
+ operand.append(byte)
+
+ if byte == 0x80:
+ pass
+ elif byte & 0x80 != 0:
+ pass
+ else:
+ # we have read the last byte of the operand
+ break
+
+ return_list = LEB128UnsignedDecode(operand)
+ operand = []
+ elif kind == 'uint8' or kind == 'uint16' or kind == 'uint32' or kind == 'uint64':
+ byte = section_byte[offset: offset + TypeDic[kind]]
+ read_bytes += TypeDic[kind]
+ offset += TypeDic[kind]
+ operand.append(byte)
+ return_list = int.from_bytes(operand[0], byteorder='little', signed=False)
+ operand = []
+ elif kind == 'varint1' or kind == 'varint7' or kind == 'varint32' or kind == 'varint64':
+ while True:
+ byte = int(section_byte[offset])
+ read_bytes += 1
+ offset += 1
+ operand.append(byte)
+ # @DEVI-what happens when we decode a 56-bit value?
+ if byte == 0x80 or byte == 0xff:
+ pass
+ elif byte & 0x80 != 0:
+ pass
+ else:
+ # we have read the lasy byte of the operand
+ break
+ return_list = LEB128SignedDecode(operand)
+ operand = []
+ return return_list, offset, read_bytes
+
+def ror(val, type_length, rot_size):
+ rot_size_rem = rot_size % type_length
+ return (((val >> rot_size_rem) & (2**type_length - 1)) | ((val & (2**rot_size_rem - 1)) << (type_length - rot_size_rem)))
+
+def rol(val, type_length, rot_size):
+ rot_size_rem = rot_size % type_length
+ return (((val << rot_size_rem) & (2**type_length - 1)) | ((val & ((2**type_length - 1) - (2**(type_length - rot_size_rem) - 1))) >> (type_length - rot_size_rem)))
+
+# @DEVI-these are here because i wanted to test them to make sure what i thik is
+# happening is really happening
+def reinterpretf32toi32(val):
+ return (stc.unpack("i", stc.pack("f" ,val))[0])
+
+def reinterpretf64toi64(val):
+ return (stc.unpack("Q", stc.pack("d", val))[0])
+
+def reinterpreti32tof32(val):
+ return (stc.unpack("f", stc.pack("i", val))[0])
+
+def reinterpreti64tof64(val):
+ return (stc.unpack("d", stc.pack("Q", val))[0])
+
+# @DEVI-FIXME
+def clz(val, _type):
+ cnt = int()
+ if _type == 'uint32':
+ bits = np.uint32(val)
+ power = 31
+ while power > -1:
+ if val & 2**power == 0:
+ cnt += 1
+ else:
+ break
+ power -= 1
+ elif _type == 'uint64':
+ bits = bin(np.uint64(val))
+ power = 63
+ while power > -1:
+ if val & 2**power == 0:
+ cnt += 1
+ else:
+ break
+ power -= 1
+ else:
+ raise Exception(Colors.red + "unsupported type passed to clz." + Colors.ENDC)
+ return cnt
+
+
+# @DEVI-FIXME
+def ctz(val, _type):
+ cnt = int()
+ power = int()
+ if _type == 'uint32':
+ bits = np.uint32(val)
+ while power < 32:
+ if val & 2**power == 0:
+ cnt += 1
+ else:
+ break
+ power += 1
+ elif _type == 'uint64':
+ bits = bin(np.uint64(val))
+ while power < 64:
+ if val & 2**power == 0:
+ cnt += 1
+ else:
+ break
+ power += 1
+ else:
+ raise Exception(Colors.red + "unsupported type passed to ctz." + Colors.ENDC)
+ return cnt
+
+# @DEVI-FIXME
+def pop_cnt(val, _type):
+ cnt = int()
+ power = int()
+ if _type == 'uint32':
+ bits = np.uint32(val)
+ while power < 32:
+ if val & 2**power != 0:
+ cnt += 1
+ power += 1
+ elif _type == 'uint64':
+ bits = bin(np.uint64(val))
+ while power < 64:
+ if val & 2**power != 0:
+ cnt += 1
+ power += 1
+ else:
+ raise Exception(Colors.red + "unsupported type passed to pop_cnt." + Colors.ENDC)
+ return cnt
+
+def gen_label(label_stack):
+ counter += 1
+ label_stack.append(counter)
+
+def dumpprettysections(sections_list, width, section_name):
+ line_counter = 0
+ str_list = []
+ module_counter = 0
+ section_offset = 0
+ for sections in sections_list:
+ print (Colors.cyan + Colors.BOLD + "module " + repr(module_counter) + Colors.ENDC)
+ for section in sections.section_list:
+ if section_name == "": pass
+ else:
+ if section_name != SectionID[section[0]]:
+ continue
+ print(Colors.green + Colors.BOLD + SectionID[section[0]] + " section" + Colors.ENDC)
+ #print(Colors.green + "length: " + Colors.blue + section[1] + Colors.ENDC)
+ print(Colors.green + "length: " + Colors.blue + repr(section[2]) + Colors.ENDC)
+ print(Colors.green + "is custom section: " + Colors.blue + repr(section[3]) + Colors.ENDC)
+ print(Colors.green + "name length: " + Colors.blue + repr(section[4]) + Colors.ENDC)
+ print(Colors.green + "name: " + Colors.blue + section[5] + Colors.ENDC)
+ print("\t", end="")
+ for offset in range(0, width):
+ if offset <= 15:
+ print(Colors.yellow + hex(offset) + " " + Colors.ENDC, end="")
+ else:
+ print(Colors.yellow + hex(offset) + " " + Colors.ENDC, end="")
+ print()
+ print(Colors.yellow + Colors.BOLD + hex(section_offset) + "\t" + Colors.ENDC, end="")
+ for byte in section[6]:
+ if line_counter == width:
+ section_offset += width
+ #print("\t\t", end="")
+ line_counter = 0
+ for char in str_list:
+ print(Colors.green + "|" + Colors.ENDC, end="")
+ if ord(char) < 32: print(" ", end="")
+ else: print(char, end="")
+ str_list = []
+ print()
+ print(Colors.yellow + Colors.BOLD + hex(section_offset) + "\t" + Colors.ENDC, end="")
+ print(format(byte, '02x') + " ", end="")
+ str_list.append(chr(byte))
+ line_counter += 1
+ #print(" ", end="")
+ for i in range(0, width - line_counter): print(" ", end="")
+ for char in str_list:
+ if ord(char) < 32: print(" ", end="")
+ else: print(char, end="")
+ print(Colors.green + "|" + Colors.ENDC, end="")
+ str_list = []
+ line_counter = 0
+ section_offset = 0
+ print()
+ str_list = []
+ line_counter = 0
+ module_counter += 1
+ section_offset = 0
+
+def popcnt32(r1):
+ temp = r1
+ temp = (temp & 0x55555555) + ((temp >> 1) & 0x55555555)
+ temp = (temp & 0x33333333) + ((temp >> 2) & 0x33333333)
+ temp = (temp & 0x0f0f0f0f) + ((temp >> 4) & 0x0f0f0f0f)
+ temp = (temp & 0x00ff00ff) + ((temp >> 8) & 0x00ff00ff)
+ temp = (temp & 0x0000ffff) + ((temp >> 16) & 0x0000ffff)
+ return temp
+
+def popcnt64(r1):
+ temp = r1
+ temp = (temp & 0x5555555555555555) + ((temp >> 1) & 0x5555555555555555)
+ temp = (temp & 0x3333333333333333) + ((temp >> 2) & 0x3333333333333333)
+ temp = (temp & 0x0f0f0f0f0f0f0f0f) + ((temp >> 4) & 0x0f0f0f0f0f0f0f0f)
+ temp = (temp & 0x00ff00ff00ff00ff) + ((temp >> 8) & 0x00ff00ff00ff00ff)
+ temp = (temp & 0x0000ffff0000ffff) + ((temp >> 16) & 0x0000ffff0000ffff)
+ temp = (temp & 0x00000000ffffffff) + ((temp >> 32) & 0x00000000ffffffff)
+ return temp
+
+def clz32(r1):
+ if r1 == 0: return 32
+ temp_r1 = r1
+ n = 0
+ if temp_r1 & 0xffff0000 == 0:
+ n += 16
+ temp_r1 = temp_r1 << 16
+ if temp_r1 & 0xff000000 == 0:
+ n += 8
+ temp_r1 = temp_r1 << 8
+ if temp_r1 & 0xf0000000 == 0:
+ n += 4
+ temp_r1 = temp_r1 << 4
+ if temp_r1 & 0xc0000000 == 0:
+ n += 2
+ temp_r1 = temp_r1 << 2
+ if temp_r1 & 0x8000000 == 0:
+ n += 1
+ return n
+
+def clz64(r1):
+ if r1 == 0: return 64
+ temp_r1 = r1
+ n = 0
+ if temp_r1 & 0xffffffff00000000 == 0:
+ n += 32
+ temp_r1 = temp_r1 << 32
+ if temp_r1 & 0xffff000000000000 == 0:
+ n += 16
+ temp_r1 == temp_r1 << 16
+ if temp_r1 & 0xff00000000000000 == 0:
+ n+= 8
+ temp_r1 = temp_r1 << 8
+ if temp_r1 & 0xf000000000000000 == 0:
+ n += 4
+ temp_r1 = temp_r1 << 4
+ if temp_r1 & 0xc000000000000000 == 0:
+ n += 2
+ temp_r1 = temp_r1 << 2
+ if temp_r1 & 0x8000000000000000 == 0:
+ n += 1
+ return n
+
+def ctz32(r1):
+ if r1 == 0: return 32
+ temp_r1 = r1
+ n = 0
+ if temp_r1 & 0x0000ffff == 0:
+ n += 16
+ temp_r1 = temp_r1 >> 16
+ if temp_r1 & 0x000000ff == 0:
+ n += 8
+ temp_r1 = temp_r1 >> 8
+ if temp_r1 & 0x0000000f == 0:
+ n += 4
+ temp_r1 = temp_r1 >> 4
+ if temp_r1 & 0x00000003 == 0:
+ n += 2
+ temp_r1 = temp_r1 >> 2
+ if temp_r1 & 0x00000001 == 0:
+ n += 1
+ return n
+
+def ctz64(r1):
+ if r1 == 0: return 64
+ temp_r1 = r1
+ n = 0
+ if temp_r1 & 0x00000000ffffffff == 0:
+ n += 32
+ temp_r1 = temp_r1 >> 32
+ if temp_r1 & 0x000000000000ffff == 0:
+ n += 16
+ temp_r1 = temp_r1 >> 16
+ if temp_r1 & 0x00000000000000ff == 0:
+ n += 8
+ temp_r1 = temp_r1 >> 8
+ if temp_r1 & 0x000000000000000f == 0:
+ n += 4
+ temp_r1 = temp_r1 >> 4
+ if temp_r1 & 0x0000000000000003 == 0:
+ n += 2
+ temp_r1 = temp_r1 >> 2
+ if temp_r1 & 0x0000000000000001 == 0:
+ n += 1
+ return n