def enum_func_static(instructions): functions = list() # first function of NeoContract is *usually* the Main function function = Function(instructions[0].offset, start_instr=instructions[0], name='Main') # parse the instructions and create Function object new_func = False for inst in instructions: if new_func: name = 'func_%x' % inst.offset function = Function(inst.offset, start_instr=inst, name=name) new_func = False # associate current instruction to the function # Worked because instruction between # function.start_offset and function.end_offset # are on the same function on Neo # i.e linear disassembly function.instructions.append(inst) # terminator instruction or last one if inst.is_halt or inst == instructions[-1]: function.size = inst.offset_end - function.start_offset function.end_offset = inst.offset_end function.end_instr = inst functions.append(function) new_func = True return functions
def enum_func_static(instructions): functions = list() # first function is *usually* the function dispatcher function = Function(start_offset=0, start_instr=instructions[0], name='Dispatcher', prefered_name='Dispatcher') functions.append(function) # parse the instructions and create Function object for inst in instructions: try: # PUSH4 are used to push the function signature on the stack if inst.name == 'PUSH4': index = instructions.index(inst) list_inst = instructions[index:index + 4] push4, eq, push, jumpi = list_inst[0], list_inst[1], list_inst[ 2], list_inst[3] # check if this basicblock test function signature if eq.name == 'EQ' and push.name in [ 'PUSH1', 'PUSH2' ] and jumpi.name == 'JUMPI': xref = int.from_bytes(push.operand, byteorder='big') sign = int.from_bytes(push4.operand, byteorder='big') name = 'func_%x' % sign prefered_name = find_signature(sign) # find instr with offset == xref begin_function = next( filter(lambda i: i.offset == xref, instructions)) # create new function function = Function(xref, start_instr=begin_function, name=name, prefered_name=prefered_name) functions.append(function) except: log.info('enum_func_static Exception') pass return functions
def enum_func(module_bytecode): ''' return a list of Function see:: octopus.core.function ''' functions = list() analyzer = WasmModuleAnalyzer(module_bytecode) protos = analyzer.func_prototypes import_len = len(analyzer.imports_func) for idx, code in enumerate(analyzer.codes): # get corresponding function prototype name, param_str, return_str, _ = protos[import_len + idx] name = format_func_name(name, param_str, return_str) instructions = WasmDisassembler().disassemble(code) cur_function = Function(0, instructions[0], name=name) cur_function.instructions = instructions functions.append(cur_function) return functions
def extract_functions_code(self, module_bytecode): functions = list() mod_iter = iter(decode_module(module_bytecode)) _, _ = next(mod_iter) sections = list(mod_iter) # iterate over all section #code_data = [cur_sec_data for cur_sec, cur_sec_data in sections if isinstance(cur_sec_data.get_decoder_meta()['types']['payload'], CodeSection)][0] for cur_sec, cur_sec_data in sections: sec = cur_sec_data.get_decoder_meta()['types']['payload'] if isinstance(sec, CodeSection): code_data = cur_sec_data break if not code_data: raise ValueError('No functions/codes in the module') for idx, func in enumerate(code_data.payload.bodies): instructions = self.disassemble(func.code.tobytes()) cur_function = Function(0, instructions[0]) cur_function.instructions = instructions functions.append(cur_function) return functions