aboutsummaryrefslogblamecommitdiffstats
path: root/parse.py
blob: ba3d8d5b58ce8889bcc135752d0e50fbb397672e (plain) (tree)
1
2
3
4
5
6
7
8
9
10




                                     




                             
           


            
 



                                     
 





















                                                                      
                                                
                         
                  


                                      
                                                
                         

                  




                                          











                                                                              
                                                                               

















































                                                                                        
                                                                             














                                                                     

                                                                     



                                                                             

                            















                              








                                                                            


                                                               



                                              


                                                               





                                             



                                                                   







                                                                                 


                                                  


                          


                                              


                                    
                                                                              

                                                            
               




                                                            





                                                                                   
                       


                                     
                     

                     


                                                               



                                                                       










                                         



                                                
                        
                     

                       






















                                                                               
                                                     











                                                                              
                                      
                                  



                                                              


                                                           


                                                                  
                                                               
                                                       
                                                   



                                                              



                                                           



                                                                      
                                                                   
                                                           

                                                       


                                                               




                                                       
                                                      
                                                 




















                                                           
                                                                         



                               


                                                       

                                                             


                                                    






                                                                               


                                                              
                                             


                                                             









                                                                              


                                                                              


                                                                     


















                                                                              















                                                             
                 
















                                                           


                                                


                                    


                                                      




                                                                       
                                                   
                                


                                                    



                                                


                                                    

                                                      
                                                                              







                                                                
                 
















                                                                


                                                  


                              


                                                      






                                                                 


                                                      





                                                                
                                                                          



                                         


                                                          



                                                    


                                                             
                                               





                                                          
                                    


                                                              




                                                   





                                                          
                                    


                                                              



                                                    





                                                               






                                                               
                 















                                                                


                                                  


                                    


                                                      






                                                                
                                                                          

                                         
                                                                               





                                                                 
                 
















                                                           


                                                


                                    
                                                                          

                                      


                                                    







                                                                    


                                                   











                                                               
                 














                                                                   


                                                    


                                                


                                                        


                                             
                 


















                                                                   


                                                   


                                       


                                                       



                                                             
                                                      




                                                            


                                                       


                                                     


                                                           









                                                                
                 















                                                               


                                                  


                                   
                                                                             

                                        


                                                      


                                             


                                                          



                                                             
                 
















                                                             


                                                 


                               


                                                   

                                                       
                                                                            

                                        


                                                     


                                             


                                                         





                                                            
                 


















                                                               
                                                                           


                         


                                                  

                                                    


                                                     



                                                             
                                                     







                                                             


                          
                 













                                                       


                                                 
                                                  
                 

                                    



                                                           
                                                 


                                     
                 

                              



                                                          
                                                


                                     
                 








                                                           
                                    


                                                               












                                       





























                                                                 

                                            
 


                                                    













                                                                    
                           









                                                                      
                                                            

                                   
                             





                                                              
                                                                              


                                                                             











                                                                            
                                                       
























                                                                             

                        














                                                                              
                                                           












































                                                                               

                          
















                                                                             
                                                                   





                                            


                                                                               











                                                                             
                                                         























                                                  

                        














                                                                              
                                                           

















                                                  

                        














                                                                              
                                                               











                                            

                        














                                                                              
                                                             













                                                                               


                                                                               














                                                                             

                         














                                                                               
                                                             












                                                                               


                                                                             











                                                                            
                                                        











                                            
                                          











                                            
                                        
                                                                             

                                                                            






                                             
                                       






                                               
                                       





                                                    


                                                                             











                                                                            
                                                          







                                                                               



                                                            

                                             










                                                                            




                                                           
                 
                                                                           

















                                                                        


                                                                 
                                              


                                                                     
                           
                                        










                                                  
 












                                                      
 

                          
#!/bin/python3

from __future__ import print_function
import argparse
import sys
from section_structs import *
from utils import *
from opcodes import *
from copy import deepcopy
from init import *
import code

_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 type(name) == list:
                print(''.join([chr(elem) for elem in name]))
                name = ''.join([chr(elem) for elem in name])
            else:
                print(name)
            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
                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):
        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):
        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.purple
                    + "field str: "
                    + "".join([chr(elem) for elem in iter.field_str])
                    + Colors.ENDC
                )
                print(Colors.yellow + "kind: " + repr(iter.kind) + Colors.ENDC)
                print(Colors.grey + "type: " + repr(iter.type) + Colors.ENDC)
                if type(iter.type) == Table_Type:
                    print("element_type: " + repr(iter.type.element_type))
                    print("limit: " + repr(iter.type.limit))
                    print("flags: " + repr(iter.type.limit.flags))
                    print("initial: " + repr(iter.type.limit.initial))
                    print("maximum: " + repr(iter.type.limit.maximum))
                if type(iter.type) == Global_Type:
                    print("value_type: " + repr(iter.type.content_type))
                    print("mutability: " + repr(iter.type.mutability))
                if type(iter.type) == Memory_Type:
                    print("flags: " + repr(iter.type.limits.flags))
                    print("flags: " + repr(iter.type.limits.initial))
                    print("flags: " + repr(iter.type.limits.maximum))

        # 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
                )
            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()