def __init__(self, params=dict()): self.num_threads = int( params["NUM_THREAD"]) if "NUM_THREAD" in params.keys( ) else NUM_THREADS self.num_stages = int( params["NUM_STAGES"]) if "NUM_STAGES" in params.keys( ) else NUM_STAGES self.stages = FIFOQueue(self.num_stages) self.stages.set_q_list([Instruction.empty_inst(0)] * self.num_stages) # Statistics self.committed_inst = Instruction() self.count_flushed_inst = 0 self.count_committed_inst = 0 self.num_of_flushes = 0 # Resources # TODO-? # Pointer to relevant units units self.thread_unit = None self.issue_unit = None self.fetch_unit = None self.generate_csv() # bp self.bp_en = params["BP_EN"] == "True" if "BP_EN" in params.keys( ) else BP_EN
def decode(self, address, inst): """ Find the type of an instruction, and call for it to be decoded. """ i = Instruction() i.address = address i.inst = inst i.decode() # Pass on to specific op if i.system: decoder = sys_ops[i.op] else: decoder = ops[i.op][i.subop] if decoder == None: # unknown instruction # system, op, subop return i else: # Use specific decoder i = decoder(i) try: i.decode() except DecodeError, e: # Error decoding instruction i.warnings.append(e.message) return i
def move_inst_unit_unpipelined(self, to_unit, from_unit, number_of_cycles): if (to_unit.is_free()): if (from_unit == None): if (self.all_inst_fetched == False): from_unit_complete_inst = Instruction( self.set_of_instructions[self.registers['PC']].strip(), self.current_inst) self.registers['PC'] += 1 self.current_inst += 1 else: return else: from_unit_complete_inst = from_unit.get_completed_inst() if (from_unit_complete_inst != False): if (to_unit.add_new_inst_unpipelined( from_unit_complete_inst, number_of_cycles) == False): print "Debugging Time" return False return from_unit_complete_inst else: if (from_unit != None and from_unit != self.IF): if (from_unit.peek_completed_inst() != False): self.result[ from_unit.peek_completed_inst().inst_addr][7] = 'Y' return False
def detectMemAccess(self, reil_code, callstack, inputs, counter): pins = parse_reil(reil_code[-1]) ins = Instruction(pins, None) assert (ins.instruction in ["stm", "ldm"]) addr_op = ins.getMemReg() #print "op:", addr_op, ins.address val = getTypedValueFromCode(reil_code, callstack, inputs, self, addr_op) #print val if (val.isMem()): #if self.__isArgMem__(val, callstack.callstack[1]): # print "arg detected at", ins, "with", str(val) # self.access[counter] = self.__getArgMemAccess__(ins, val, callstack.callstack[1]) #else: #print val self.access[counter] = self.__getMemAccess__(ins, val) elif (val.isImm): self.access[counter] = self.__getGlobalMemAccess__( ins, int(val.name)) else: assert (0)
def _get_corresponding_inst(self, label): for i in range(len(self.set_of_instructions)): instruction = Instruction(self.set_of_instructions[i], i) if instruction.label == label: return i print "Error: Invalid instruction: missing label" exit()
def __init__(self, in_filename, out_filename): # Set initial values for MIPS engine print("Loading...") self._offset = 0 self._program = {} self._PC = 0 self._error = False # Read in hex file self._f = open(in_filename) inst_all = self._f.read() inst_temp = inst_all.split('\n') # Store all instructions by initializing Instruction objects into _program dictionary # indexed by _PC self._program_len = len(inst_temp) self._PC_last = self._program_len - 1 print('# instructions: {}\tLast Instruction: {}'.format( len(inst_temp), self._PC_last)) for i in range(0, len(inst_temp)): self._program[self._PC] = Instruction.Instruction(inst_temp[i]) self._PC = self._PC + 1 # Output assembly file self._output_f = open(out_filename, 'w') for key in self._program: self._program[key].print_inst() self._output_f.write(self._program[key].get_inst() + '\n') self._output_f.close() print() self._PC = 0 #self.print_state() self._save_cur_state() print('...Program loaded successfully')
def disassemble(self, filename): #Exécution d'opdis et récupération du XML xml = subprocess.Popen( ["opdis", "-q", "-d", "-f", "xml", "-N", "main", filename], stdout=subprocess.PIPE, stderr=subprocess.DEVNULL).stdout.read() document = parseString(xml).documentElement #Création de la liste des instructions instructions_table = [] vma_instructions_table = {} for instructionNode in document.getElementsByTagName("instruction"): instruction = Instruction.Instruction( self.get_xml_child_value(instructionNode, "offset"), self.get_xml_child_value(instructionNode, "vma"), self.get_xml_child_value(instructionNode, "ascii"), self.get_xml_child_value(instructionNode, "mnemonic")) if (self.xml_node_has_child(instructionNode, "operands")): for operandNode in instructionNode.getElementsByTagName( "operand"): operand = Operand.Operand( operandNode.attributes["name"] if ("name" in operandNode.attributes) else "", self.get_xml_child_value(operandNode, "ascii")) instruction.add_operand(operand) instructions_table.append(instruction) vma_instructions_table[int(instruction.vma, 0)] = instruction return (instructions_table, vma_instructions_table)
def detectFuncParameters(self, reil_code, memaccess, callstack, inputs, counter): pins = parse_reil(reil_code[-1]) ins = Instruction(pins, None) assert (ins.instruction == "call" and ins.called_function <> None) # first we locate the stack pointer to know where the parameters are located esp = Operand("esp", "DWORD") pbase = getTypedValueFromCode(reil_code, callstack, inputs, memaccess, esp) #print pbase.name #print pbase.mem_source # func_cons = funcs.get(ins.called_function, Function) func = func_cons(pbase=pbase) parameters = [] for (par_type, location, needed) in func.getParameterLocations(): #print (ins.called_function, par_type, location.mem_source, needed) if needed: reil_code.reverse() reil_code.reset() val = getTypedValueFromCode(reil_code, callstack, inputs, memaccess, location) #print "parameter of",ins.called_function, "at", str(location) , "has value:", val.name parameters.append((location, val)) else: parameters.append((None, None)) if parameters <> []: self.parameters[counter] = self.__getParameters__(ins, parameters)
def getJumpConditions(trace, addr): raw_ins = parse_reil(trace["code"][-1]) addr = int(addr, 16) pos = trace["code"].last - 1 if (raw_ins.instruction == "jcc"): ins = Instruction(raw_ins, None) jmp_op = ins.operands[2] if (jmp_op.isVar()): #print addr trace["final_conditions"] = dict([(jmp_op, Operand(str(addr), "DWORD"))]) sol = getPathConditions(trace) if (sol <> None): print "SAT conditions found!" filename = raw_ins.instruction + "[" + str(pos) + "]" dumped = sol.dump(filename, input_vars) for filename in dumped: print filename, "dumped!" else: print "Impossible to jump to", hex( addr), "from", raw_ins.instruction, "at", pos else: return None else: return None
def __init__(self, in_filename, out_filename, mem_config=0): # Set initial values for MIPS engine self._offset = 0 self._program = {} self._PC = 0 # Initialize memory configuration self._mem = Memory.Memory(mem_config) # Read in hex file self._f = open(in_filename) inst_all = self._f.read() inst_temp = inst_all.split('\n') # Store all instructions by initializing Instruction objects into _program dictionary # indexed by _PC self._program_len = len(inst_temp) self._PC_last = (self._program_len * 4) - 4 print('# instructions: {}\tLast Instruction: {}'.format( len(inst_temp), self._PC_last)) for i in range(0, len(inst_temp)): self._program[self._PC] = Instruction.Instruction(inst_temp[i]) self._PC = self._PC + 4 # Output assembly file self._output_f = open(out_filename, 'w') for key in self._program: self._program[key].print_inst() self._output_f.write(self._program[key].get_inst() + '\n') self._output_f.close() print() self._PC = 0 self.print_state() self._save_cur_state()
def test_SLL(self): instrn_list = [ '00050018', '00010001', '00432020', '009E001C', '009E001E', '0121482E', '00031025', '34830000', 'ACC40000', '00C60001', '10050002', '0BFFFFF6', ] human_instrn_list = [ '00050018', '00010001', '00432020', '009E001C', '009E001E', '0121482E', '00031025', '34830000', 'ACC40000', '00C60001', '10050002', '0BFFFFF6', ] for instrn, human_instrn in zip(instrn_list, human_instrn_list): print 'instrn: ', instrn bin_string = Memory.Memory.get_bin_from_hex_instruction(instrn) instruction = Instruction.Instruction(bin_string) print instruction
def __init__(self, reil_code): # The first instruction should be a call self.callstack = [None] self.stack_diff = [] self.index = 0 #self.prev_callstack = [None] # aditional information need to compute the callstack self.calls = [None] self.esp_diffs = [None] self.reil_code = reil_code reil_size = len(reil_code) start = 0 for (end, ins_str) in enumerate(self.reil_code): #print ins_str.strip("\n") pins = parse_reil(ins_str) ins = Instruction(pins, None) if (ins.instruction == "call" and ins.called_function == None) or ins.instruction == "ret": self.__getStackDiff__(ins.instruction, ins.address, reil_code[start:end]) start = end if (start <> reil_size - 1): pins = parse_reil(reil_code[start]) self.__getStackDiff__(pins.instruction, pins.address, reil_code[start:reil_size]) self.index = len(self.callstack) - 1
def advance(self): #Fetch the next instruction according to simulator program counter # ...if we are not outside instruction memory if self.simulator.programCounter < ( len(self.simulator.instrCollection) * 4 + 0x0): self.instr = self.simulator.instructionMemory[ self.simulator.programCounter] # Non-NOP instruction if (self.instr and self.instr.op != "nop" and self.instr.op != None): self.simulator.instrCount += 1 # NOP if (self.instr.op is 'nop'): self.simulator.instrCount += 1 self.simulator.nopCount += 1 # Instruction is a core instruction if (self.instr.coreInstr): self.simulator.coreInstrCount += 1 # Instruction is a core instruction and a NOP if (self.instr.op is 'nop'): self.simulator.coreNopCount += 1 else: # Something wrong (outside memory range) - ignore instruction self.instr = Instruction(op='nop', coreInstr=False) # Advance PC self.simulator.programCounter += 4
def generate_csv(self): if EX_DUMP_TO_CSV: with open(EX_DUMP_CSV_PATH, 'w', newline='') as csv_file: report_writer = csv.writer(csv_file) if EX_DUMP_TO_CSV: empty = Instruction() header = empty.csv_list(header=True) report_writer.writerow(header)
def populateJumps(self): #jumps self.__m_Jumps.append(Instruction.Instruction('null', '000')) self.__m_Jumps.append(Instruction.Instruction('JGT', '001')) self.__m_Jumps.append(Instruction.Instruction('JEQ', '010')) self.__m_Jumps.append(Instruction.Instruction('JGE', '011')) self.__m_Jumps.append(Instruction.Instruction('JLT', '100')) self.__m_Jumps.append(Instruction.Instruction('JNE', '101')) self.__m_Jumps.append(Instruction.Instruction('JLE', '110')) self.__m_Jumps.append(Instruction.Instruction('JMP', '111'))
def populateDests(self): #dest self.__m_Dests.append(Instruction.Instruction('null', '000')) self.__m_Dests.append(Instruction.Instruction('M', '001')) self.__m_Dests.append(Instruction.Instruction('D', '010')) self.__m_Dests.append(Instruction.Instruction('MD', '011')) self.__m_Dests.append(Instruction.Instruction('A', '100')) self.__m_Dests.append(Instruction.Instruction('AM', '101')) self.__m_Dests.append(Instruction.Instruction('AD', '110')) self.__m_Dests.append(Instruction.Instruction('AMD', '111'))
def addUserLabels(self): for line in self.__m_rawCommands: if (self.isLabel(line)): #cut out first and last () name = line[1:-1] #append label and rom to label table self.__m_Symbols.append((Instruction.Instruction(name, self.__m_rom))) else: self.__m_rom += 1
def getValueFromCode(inss, initial_values, op): assert (len(inss) > 0) # code should be copied and reversed inss.reverse() # counter is set counter = len(inss) ssa = SSA() smt_conds = SMT() # we will track op mvars = set([op]) ssa.getMap(mvars, set(), set()) for ins_str in inss: #print ins_str.strip("\n") pins = parse_reil(ins_str) ins = Instruction(pins, None) # no memory and callstack are available ins_write_vars = set(ins.getWriteVarOperands()) ins_read_vars = set(ins.getReadVarOperands()) if len(ins_write_vars.intersection(mvars)) > 0: ssa_map = ssa.getMap(ins_read_vars.difference(mvars), ins_write_vars, ins_read_vars.intersection(mvars)) cons = conds.get(pins.instruction, Condition) condition = cons(ins, ssa_map) mvars = mvars.difference(ins_write_vars) mvars = ins_read_vars.union(mvars) mvars = set(filter(lambda o: o.name <> "ebp", mvars)) smt_conds.add(condition.getEq()) counter = counter - 1 for iop in initial_values.keys(): if not (iop in ssa): del initial_values[iop] ssa_map = ssa.getMap(set(), set(), set(initial_values.keys())) eq = Eq(None, None) for iop in initial_values: smt_conds.add(eq.getEq(ssa_map[iop.name], initial_values[iop])) op.name = op.name + "_0" smt_conds.solve() return smt_conds.getValue(op)
def addUserSymbols(self): self.addUserLabels() #user defined symbols (check on address start and increment) for line in self.__m_rawCommands: name = line[1:] if self.isA(line) and (not name.isdigit()) and (not self.isNameInTable(name, self.__m_Symbols)): #test if symbol is added at the right address #print("symbol is {0}, address is {1}".format(name, self.__m_ram)) #end test self.__m_Symbols.append(Instruction.Instruction(name, self.__m_ram)) self.__m_ram += 1
def doBranch(self): # Read target value targetval = int(self.instr.immed) # Debug output if in verbose mode if (self.simulator.verbose): print "Branching to target ", hex(targetval) # Update PC self.simulator.programCounter = targetval + 4 # Set the other instructions currently in the pipeline to NOPS (depending on the number of IF stages) self.simulator.pipeline[0] = FetchStage( Instruction(op='nop', coreInstr=True), self) if (self.simulator.nIFit >= 2): self.simulator.pipeline[1] = FetchStage( Instruction(op='nop', coreInstr=True), self) if (self.simulator.nIFit == 3): self.simulator.pipeline[2] = FetchStage( Instruction(op='nop', coreInstr=True), self) # Indicate branch by setting branched flag self.simulator.branched = True
def x64_x32_inst(op, args, line): """ Converts x64 and x32 type instructions. Args: args: the operation (eg. mov), a list of arguments (eg. r0, r2) and the correspondent line on input file. Returns: instruction: instruction converted into machine code. Raises: None """ inst = Instruction() if len(args) == 2 and op != 'neg' and op != 'neg32': if isRegValid(args[0]) and not isRegValid(args[1]): if isNumericDataValid(args[1]): inst.setDst(reg_set[args[0]]) inst.setImm(completeBinary(dataTypeConversor(args[1]), 32)) inst.setOpc(x64_x32_inst_set[op]['opcodeImm']) else: print("ebpf_ic: line " + str(line) + ": invalid immediate") return None elif isRegValid(args[0]) and isRegValid(args[1]): inst.setDst(reg_set[args[0]]) inst.setSrc(reg_set[args[1]]) inst.setOpc(x64_x32_inst_set[op]['opcode']) else: print("ebpf_ic: line " + str(line) + ": invalid arguments") return None elif len(args) == 1 and op == 'neg' or op == 'neg32': if isRegValid(args[0]): inst.setDst(reg_set[args[0]]) else: print("ebpf_ic: line " + str(line) + ": " + args[0] + ": unknown register") return None inst.setOpc(x64_x32_inst_set[op]['opcode']) elif len(args) > 2: print("ebpf_ic: line " + str(line) + ": too many arguments") return None else: print("ebpf_ic: line " + str(line) + ": not enough arguments") return None return inst.toString()
def setUp(self): self.instruction_string = 'R ADD R1 R2 R3' self.instr = Instruction.Instruction( self.instruction_string.strip().split()) self.npc = 4 self.PC = 0 self.input_dict = { 'instr': self.instr, 'npc': self.npc, 'PC': self.PC, } self.fetcher_buffer = fetcher_buffer.FetcherBuffer(self.input_dict)
def setUp(self): self.instruction_string = 'R ADD R1 R2 R3' self.instr = Instruction.Instruction( self.instruction_string.strip().split()) self.memory = Memory.Memory([self.instruction_string.strip().split()]) self.fetch_input_buffer = FetchInputBuffer({ 'PC': 0, 'instr_count': 0, }) self.fetcher_buffer = FetcherBuffer({}) self.fetch_stage = fetch_stage.FetchStage(self.memory, self.fetch_input_buffer, self.fetcher_buffer)
def set_up_write_back_stage(self, instruction_string): """Set up WriteBackStage with the appropriate memory_buffer, etc. """ self.instruction_string = instruction_string self.instr = Instruction.Instruction( self.instruction_string.strip().split()) self.memory = Memory.Memory([self.instruction_string.strip().split()]) self.memory_buffer = Processor.Processor.get_stage_output( self.memory, self.register_file, 0, 0, 'memory') self.write_back_stage = write_back_stage.WriteBackStage( self.memory_buffer, self.register_file)
def create_graph(self, instructions_table, vma_instructions_table): graph = nx.DiGraph() start = Instruction.Instruction("-0x1", "-0x1", "\\<start\\>", "\\<start\\>") end = Instruction.Instruction("-0x1", "-0x1", "\\<end\\>", "\\<end\\>") instructions_table.insert(0, start) instructions_table.append(end) for i in range(len(instructions_table)): if (i != 0): graph.add_edge( "\"" + instructions_table[i - 1].create_string() + "\"", "\"" + instructions_table[i].create_string() + "\"") instruction = instructions_table[i] if super(RegularDriver, self).is_jump(instruction): targetVma = instruction.operands[0].ascii graph.add_edge( "\"" + instruction.create_string() + "\"", "\"" + vma_instructions_table[int(targetVma, 0)].create_string() + "\"") return graph
def step(self): # Increment cycle count self.cycles += 1 # Move instructions in EX to WB for i in range(self.nIFit + self.nIDit + self.nEXit + self.nWBit, self.nIFit + self.nIDit + self.nEXit + 1, -1): self.pipeline[i - 1] = DummyWriteStage(self.pipeline[i - 2].instr, self) self.pipeline[self.nIFit + self.nIDit + self.nEXit] = WriteStage( self.pipeline[self.nIFit + self.nIDit + self.nEXit - 1].instr, self) # Move instructions in ID to EX for i in range(self.nIFit + self.nIDit + self.nEXit, self.nIFit + self.nIDit + 1, -1): self.pipeline[i - 1] = DummyExecStage(self.pipeline[i - 2].instr, self) self.pipeline[self.nIFit + self.nIDit] = ExecStage( self.pipeline[self.nIFit + self.nIDit - 1].instr, self) # Move instructions in IF to ID for i in range(self.nIFit + self.nIDit, self.nIFit + 1, -1): self.pipeline[i - 1] = DummyReadStage(self.pipeline[i - 2].instr, self) self.pipeline[self.nIFit] = ReadStage( self.pipeline[self.nIFit - 1].instr, self) # Move instruction pointed to by PC in instruction memory to IF (= perform Instruction Fetch) for i in range(self.nIFit, 1, -1): self.pipeline[i - 1] = DummyFetchStage(self.pipeline[i - 2].instr, self) self.pipeline[0] = FetchStage(Instruction(op='nop', coreInstr=False), self) # Call advance on each instruction in the pipeline for pi in self.pipeline: pi.advance() # Remove finished instructions from Hazard list if (self.pipeline[1].instr.regWrite and len(self.hazardList) > 0): self.hazardList.pop(0) # Check for END directive self.checkDone() # If we stalled the pipeline, keep the program counter where it is if self.stall or self.branched: self.programCounter -= 0x4 self.branched = False
def decode(mode, instr): re_line = re.compile( r'^(?:\S+\s+)?(?P<instr>add|sub|xor|not|mul)\s+(?P<arg1>([A-Za-z0-9_\[\]+*\-]|\s)+)\s*' r'(?:,\s*(?P<arg2>([A-Za-z0-9_\[\]+*\-]|\s)+))?' ) instruction = re_line.search(instr) if instruction is None: return '>>> Invalid instruction! Please try again.' instruction = instruction.groupdict() instruction = Instruction(mode, instruction['instr'], instruction['arg1'], instruction['arg2']) instruction.validate_arguments() ans = instruction.translate() ans = ' '.join([ans[i : i + 4] for i in range(0, len(ans), 4)]) return ans
def set_up_execute_stage(self, instruction_string): """Set up Execute Stage with the appropriate decoder_buffer, etc. Arguments: - `instruction_string`: """ self.instruction_string = instruction_string self.instr = Instruction.Instruction( self.instruction_string.strip().split()) self.memory = Memory.Memory([self.instruction_string.strip().split()]) self.decoder_buffer = Processor.Processor.get_stage_output( self.memory, self.register_file, 0, 0, 'decode') self.executer_buffer = ExecuterBuffer() self.execute_stage = execute_stage.ExecuteStage( self.decoder_buffer, self.executer_buffer)
def __parse_instructions(self): # parse instruction # return list [instruction-type, arg1, arg2, ...] for child in self.__root: if (child.tag != 'instruction'): raise XmlParserException( "Unknown tag '{0}' where 'instruction '" "tag expected".format(child.tag)) if ('order' not in child.attrib): raise XmlParserException("Missing 'order' attribute") if ('opcode' not in child.attrib): raise XmlParserException("Missing 'opcode' attribute") new_instruction = Instruction.Instruction(child) self.__instructions.append(new_instruction)
def processFloatingPoint(operation, coordinates): """creates Assembly for all the different Binary Operations (+,-,*,...) using floatingPoint Data and therefore instructions Source Registers f1, f2 Destination Register f0 f0 = f1 - f2""" assem = Assembly() if operation == '+': assem.AppendInstruction( Instruction('ADD', ['f0', 'f2'], 'add source B')) elif operation == '-': assem.AppendInstruction( Instruction('SUB', ['f0', 'f2'], 'sub source B')) elif operation == '*': assem.AppendInstruction( Instruction('MUL', ['f0', 'f2'], 'mul source B')) elif operation == '/': assem.AppendInstruction( Instruction('DIV', ['f0', 'f2'], 'div by source B')) else: return None return assem