void DumpIseg(int first, int last) /* Display Iseg */ { printf("\nContents of Instruction Segment\n"); for (; first<=last; first++) PrintIns(first), printf("\n"); printf("\n"); }
void SetI(OP OpCode, int F, int Addr) /* write instruction*/ { Iseg[Pctr].Op = OpCode; /* opcode */ Iseg[Pctr].Reg = F; /* register flag */ Iseg[Pctr].Addr = Addr; /* address */ if (DebugSW) { PrintIns(Pctr); printf("\n"); } if (++Pctr > MaxPC) MaxPC = Pctr; /* Too long program... */ }
VOID Ins( INS ins, VOID *v ) { if (KnobDetach > 0 && scount > KnobDetach) return; if (KnobLog) { void *addr = Addrint2VoidStar(INS_Address(ins)); string disasm = INS_Disassemble(ins); PrintIns(addr, disasm.c_str()); } scount++; // call and return need also stack manipulation (see emu_stack.cpp) // conditional jumps need handling the condition (not supported yet) if (INS_IsCall(ins) || INS_IsRet(ins) || INS_Category(ins) == XED_CATEGORY_COND_BR) return; if (INS_IsIndirectBranchOrCall(ins)) { INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(EmuIndJmp), IARG_BRANCH_TARGET_ADDR, IARG_RETURN_REGS, scratchReg, IARG_END); INS_InsertIndirectJump(ins, IPOINT_AFTER, scratchReg); INS_Delete(ins); } else if (INS_IsDirectBranchOrCall(ins)) { ADDRINT tgt = INS_DirectBranchOrCallTargetAddress(ins); INS_InsertDirectJump(ins, IPOINT_AFTER, tgt); INS_Delete(ins); } }
int StartVSM(int StartAddr, int TraceSW) /* Start VSM */ { int addr, op; Pctr = StartAddr; /* Set Pctr */ SP = Freg = 0; /* Set register flag */ while (1) { if (SP >= STACK_SIZE || SP < 0) { /* check the range of stack pointer */ fprintf(stderr, "Illegal Stack pointer %d\n", SP); return -1; } op = Iseg[Pctr].Op; /* fetch instruction */ addr = Iseg[Pctr].Addr; /* calculate effective address */ if (Iseg[Pctr++].Reg & FP) /* FP register modification */ addr += Freg; /* add FP */ InsCount++; /* Increment the number of instructions */ if (SP > MaxSD) MaxSD = SP; /* check the max SP value */ if (TraceSW) { /* if trace flag is on, make trace */ PrintIns(Pctr-1); printf("%15d %5d %12d\n", addr, SP, Stack[SP]); } switch (op) { /* execute each instruction */ case NOP: continue; case ASSGN: addr = Stack[--SP]; Dseg[addr] = Stack[SP] = Stack[SP+1]; continue; case ADD: BINOP(+); continue; case SUB: BINOP(-); continue; case MUL: BINOP(*); continue; case DIV: if (Stack[SP] == 0) { yyerror("Zero divider detected"); return -2; } BINOP(/); continue; case MOD: if (Stack[SP] == 0) { yyerror("Zero divider detected"); return -2; } BINOP(%); continue; case CSIGN: Stack[SP] = -Stack[SP]; continue; case AND: BINOP(&&); continue; case OR: BINOP(||); continue; case NOT: Stack[SP] = !Stack[SP]; continue; case COMP: Stack[SP-1] = Stack[SP-1] > Stack[SP] ? 1 : Stack[SP-1] < Stack[SP] ? -1 : 0; SP--; continue; case COPY: ++SP; Stack[SP] = Stack[SP-1]; continue; case PUSH: Stack[++SP] = Dseg[addr]; continue; case PUSHI: Stack[++SP] = addr; continue; case REMOVE: --SP; continue; case POP: Dseg[addr] = Stack[SP--]; continue; case INC: Stack[SP] = ++Stack[SP]; continue; case DEC: Stack[SP] = --Stack[SP]; continue; case SETFR: Freg = addr; continue; case INCFR : if ((Freg += addr) >= DSEG_SIZE) { printf("Freg overflow at loc. %d\n", Pctr-1); return -3; } continue; case DECFR : Freg -= addr; if (Freg < MinFR) MinFR = Freg; continue; case JUMP: Pctr = addr; continue; case BLT: if (Stack[SP--] < 0) Pctr = addr; continue; case BLE: if (Stack[SP--] <= 0) Pctr = addr; continue; case BEQ: if (Stack[SP--] == 0) Pctr = addr; continue; case BNE: if (Stack[SP--] != 0) Pctr = addr; continue; case BGE: if (Stack[SP--] >= 0) Pctr = addr; continue; case BGT: if (Stack[SP--] > 0) Pctr = addr; continue; case CALL: Stack[++SP] = Pctr; Pctr = addr; CallC++; continue; case RET: Pctr = Stack[SP--]; continue; case HALT: return 0; case INPUT: scanf("%d", &Dseg[Stack[SP--]]); continue; case OUTPUT: printf("%15d\n", Stack[SP--]); continue; default: printf("Illegal Op. code at location %d\n", Pctr); return -4; } } }
VOID Ins( INS ins, VOID *v ) { if (KnobDetach > 0 && scount > KnobDetach) return; if (KnobLog) { void *addr = Addrint2VoidStar(INS_Address(ins)); string disasm = INS_Disassemble(ins); PrintIns(addr, disasm.c_str()); } scount++; if (INS_Opcode(ins) == XED_ICLASS_PUSH) { if (INS_OperandIsImmediate(ins, 0)) { ADDRINT value = INS_OperandImmediate(ins, 0); INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(EmuPushValue), IARG_REG_VALUE, REG_STACK_PTR, IARG_ADDRINT, value, IARG_RETURN_REGS, REG_STACK_PTR, IARG_END); INS_Delete(ins); } else if(INS_OperandIsReg(ins, 0)) { REG reg = INS_OperandReg(ins, 0); INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(EmuPushValue), IARG_REG_VALUE, REG_STACK_PTR, IARG_REG_VALUE, reg, IARG_RETURN_REGS, REG_STACK_PTR, IARG_END); INS_Delete(ins); } else if(INS_OperandIsMemory(ins, 0)) { INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(EmuPushMem), IARG_REG_VALUE, REG_STACK_PTR, IARG_MEMORYREAD_EA, IARG_RETURN_REGS, REG_STACK_PTR, IARG_END); INS_Delete(ins); } else { fprintf(stderr, "EmuPush: unsupported operand type (%p:'%s')\n", Addrint2VoidStar(INS_Address(ins)), INS_Disassemble(ins).c_str()); } } else if (INS_Opcode(ins) == XED_ICLASS_POP) { if(INS_OperandIsReg(ins, 0)) { INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(EmuPopReg), IARG_REG_VALUE, REG_STACK_PTR, IARG_REG_REFERENCE, INS_OperandReg(ins, 0), IARG_RETURN_REGS, REG_STACK_PTR, IARG_END); INS_Delete(ins); } else if(INS_OperandIsMemory(ins, 0)) { INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(EmuPopMem), IARG_REG_VALUE, REG_STACK_PTR, IARG_MEMORYWRITE_EA, IARG_RETURN_REGS, REG_STACK_PTR, IARG_END); INS_Delete(ins); } else { fprintf(stderr, "EmuPop: unsupported operand type (%p:'%s')\n", Addrint2VoidStar(INS_Address(ins)), INS_Disassemble(ins).c_str()); } } else if (INS_Opcode(ins) == XED_ICLASS_LEAVE) { INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(EmuLeave), IARG_REG_VALUE, REG_STACK_PTR, IARG_REG_REFERENCE, REG_GBP, IARG_RETURN_REGS, REG_STACK_PTR, IARG_END); INS_Delete(ins); } else if (INS_IsCall(ins)) { INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(EmuCall), IARG_ADDRINT, INS_NextAddress(ins), IARG_BRANCH_TARGET_ADDR, IARG_REG_REFERENCE, REG_STACK_PTR, IARG_RETURN_REGS, scratchReg, IARG_END); INS_InsertIndirectJump(ins, IPOINT_AFTER, scratchReg); INS_Delete(ins); } else if (INS_IsRet(ins)) { UINT64 imm = 0; if (INS_OperandCount(ins) > 0 && INS_OperandIsImmediate(ins, 0)) { imm = INS_OperandImmediate(ins, 0); } INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(EmuRet), IARG_CALL_ORDER, CALL_ORDER_FIRST, IARG_REG_REFERENCE, REG_STACK_PTR, IARG_ADDRINT, (ADDRINT)imm, IARG_RETURN_REGS, scratchReg, IARG_END); INS_InsertIndirectJump(ins, IPOINT_AFTER, scratchReg); INS_Delete(ins); } else if (INS_IsIndirectBranchOrCall(ins)) { // This is not a call (it was checked before) so this is indirect jump INS_InsertCall(ins, IPOINT_BEFORE, AFUNPTR(EmuIndJmp), IARG_BRANCH_TARGET_ADDR, IARG_RETURN_REGS, scratchReg, IARG_END); INS_InsertIndirectJump(ins, IPOINT_AFTER, scratchReg); INS_Delete(ins); } }