aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbloodstalker <thabogre@gmail.com>2018-05-25 23:45:50 +0000
committerbloodstalker <thabogre@gmail.com>2018-05-25 23:45:50 +0000
commita2afe6ff184bc20993f58388887a2d4f1454c140 (patch)
tree98c3928c40cd268bfbaeb78abbcce50914ef9ea2
parentwip:added a wasm backend. i need to setup an interface with the main c++ code... (diff)
downloadmutator-a2afe6ff184bc20993f58388887a2d4f1454c140.tar.gz
mutator-a2afe6ff184bc20993f58388887a2d4f1454c140.zip
load.py is now imported bt another python module, should cut down on startup time. added the WASM linking structures to dwasm. i can start working on the linker as soon as i get some tests.
-rw-r--r--.travis.yml1
-rwxr-xr-xbfd/delf.py27
-rwxr-xr-xbfd/load.py5
-rw-r--r--bruiser/wasm/OpCodes.py14
-rwxr-xr-xbruiser/wasm/dwasm.py986
-rw-r--r--bruiser/wasm/section_structs.py97
-rwxr-xr-xextra-tools/pretestprep.sh3
7 files changed, 118 insertions, 1015 deletions
diff --git a/.travis.yml b/.travis.yml
index 13fb9d7..88aabf3 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -34,6 +34,7 @@ before_script:
- travis_retry sudo apt-get install clang-5.0 libclang-5.0-dev libclang-common-5.0-dev libllvm5.0 llvm-5.0-dev llvm-5.0 llvm-5.0-runtime libclang1-5.0-dbg libllvm5.0-dbg lldb-5.0 -y
- sudo apt-get install gcc-4.9 g++-4.9
- sudo apt-get install libffi-dev -y
+ - sudo apt-get install bear -y
- sudo apt-get install luarocks -y
- luarocks install ansicolors --local
- ./extra-tools/capstoneubuntu14.sh
diff --git a/bfd/delf.py b/bfd/delf.py
new file mode 100755
index 0000000..60b2697
--- /dev/null
+++ b/bfd/delf.py
@@ -0,0 +1,27 @@
+#!/usr/bin/python3
+
+import argparse
+import code
+import readline
+import signal
+import sys
+from load import premain, CLIArgParser, SigHandler_SIGINT
+
+def main():
+ argparser = CLIArgParser()
+ if argparser.args.dbg:
+ try:
+ premain(argparser)
+ except Exception as e:
+ print(e.__doc__)
+ if e.message: print(e.message)
+ signal.signal(signal.SIGINT, SigHandler_SIGINT)
+ variables = globals().copy()
+ variables.update(locals())
+ shell = code.InteractiveConsole(variables)
+ shell.interact(banner="DELF REPL")
+ else:
+ premain(argparser)
+
+if __name__ == "__main__":
+ main()
diff --git a/bfd/load.py b/bfd/load.py
index ae0771f..73ff05e 100755
--- a/bfd/load.py
+++ b/bfd/load.py
@@ -16,6 +16,7 @@
#You should have received a copy of the GNU General Public License
#along with this program; if not, write to the Free Software
#Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.*/
+#**********************************************************************************************************************/
import argparse
import sys
import readline
@@ -1451,7 +1452,9 @@ def main():
if argparser.args.dbg:
try:
premain(argparser)
- except:
+ except Exception as e:
+ print(e.__doc__)
+ if e.message: print(e.message)
signal.signal(signal.SIGINT, SigHandler_SIGINT)
variables = globals().copy()
variables.update(locals())
diff --git a/bruiser/wasm/OpCodes.py b/bruiser/wasm/OpCodes.py
index ce813b0..f7c9a1b 100644
--- a/bruiser/wasm/OpCodes.py
+++ b/bruiser/wasm/OpCodes.py
@@ -11,6 +11,14 @@ class RelocType(Enum):
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
@@ -19,6 +27,12 @@ class TypeType(Enum):
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],
diff --git a/bruiser/wasm/dwasm.py b/bruiser/wasm/dwasm.py
index bb930f9..93217b4 100755
--- a/bruiser/wasm/dwasm.py
+++ b/bruiser/wasm/dwasm.py
@@ -1,57 +1,17 @@
-#!/bin/python3
+#!/usr/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 TBInit import *
-import readline
import code
+import readline
import signal
-
-_DBG_ = True
+import sys
+from parse import premain
+from utils import ParseFlags
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()
@@ -84,943 +44,15 @@ class Argparser(object):
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)
-
- # 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)
- 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():
+ signal.signal(signal.SIGINT, SigHandler_SIGINT)
argparser = Argparser()
if argparser.args.dbg:
try:
premain(argparser)
- except Exception:
+ except Exception as e:
+ print(e.__doc__)
+ if e.message: print(e.message)
variables = globals().copy()
variables.update(locals())
shell = code.InteractiveConsole(variables)
diff --git a/bruiser/wasm/section_structs.py b/bruiser/wasm/section_structs.py
index b254ff9..219f7ea 100644
--- a/bruiser/wasm/section_structs.py
+++ b/bruiser/wasm/section_structs.py
@@ -9,19 +9,75 @@ class WASM_SECTION(object):
self.name = str()
self.payload_data = bytes()
+class WASM_SEGMENT_INFO():
+ def __int__(self):
+ self.count = int()
+ self.segments = []
-class Reloc_Entry_1():
+class WASM_SEGMENT_INFO_SEGMENT():
def __init__(self):
- self.offset = int()
+ 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 Reloc_Entry_2():
+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()
- self.addend = 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):
@@ -31,7 +87,6 @@ class Relocation_Section():
self.count = int()
self.entries = int()
-
class Func_Type():
def __init__(self):
self.form = int()
@@ -40,26 +95,22 @@ class Func_Type():
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
@@ -67,23 +118,19 @@ class External_Kind():
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()
@@ -93,45 +140,38 @@ class Import_Entry():
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()
@@ -139,19 +179,16 @@ class Export_Entry():
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()
@@ -159,27 +196,23 @@ class Elem_Segment():
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()
@@ -190,14 +223,12 @@ class Func_Body():
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()
@@ -205,53 +236,45 @@ class Data_Segment():
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,
diff --git a/extra-tools/pretestprep.sh b/extra-tools/pretestprep.sh
new file mode 100755
index 0000000..30c564c
--- /dev/null
+++ b/extra-tools/pretestprep.sh
@@ -0,0 +1,3 @@
+#!/usr/bin/bash
+(cd ../obfuscator/test && make clean && bear make)
+(cd ../bfd/test && make)