int ffiPushDoubleFloat(double value) { DPRINTF(("ffiPushDoubleFloat %f\n", (float)value)); if (fprCount < FPR_MAX) ffiFPRs[fprCount++]= value; else { dalignStack(); checkStack(); ffiStack[stackIndex++]= ((int *)(&value))[0]; checkStack(); ffiStack[stackIndex++]= ((int *)(&value))[1]; } return 1; }
PVOID __KernelAllocateMemory ( ULONG ulSize, PCSTR pFileName, ULONG LineNumber ) { PAL_MEM_PREHEADER pHeader; if ( !gMemAllocMonitorInitialized ) { __KernelInitializeMemAllocMonitor(); } pHeader = RealKernelAllocateMemory(ulSize + sizeof(AL_MEM_PREHEADER) + AL_MEM_POST_PAD_SIZE); if ( pHeader ) { if ( GlobalDebugLevel >= 8 ) { KernelTrace("__KernelAllocateMemory -- %s:%lu, allocated pMem = 0x%x ...\n", pFileName, LineNumber, ACCESS_MEM_FROM_PREHEADER(pHeader)); } KernelZeroMemory(pHeader, ulSize + sizeof(AL_MEM_PREHEADER) + AL_MEM_POST_PAD_SIZE); pHeader->MemTrueSize = ulSize; KernelAcquireLock(&gMemAllocMonitorLock); gMemAllocTotalSize += ulSize; gNumberMemAllocated ++; KernelReleaseLock(&gMemAllocMonitorLock); return ACCESS_MEM_FROM_PREHEADER(pHeader); } else { KernelTrace("KernelAllocateMemory -- insufficient resources for %lu bytes -- %s:%lu!!!\n", ulSize, pFileName, LineNumber); KernelTrace("KernelAllocateMemory -- current number of allocated = %lu, size = %lu.\n", gNumberMemAllocated, gMemAllocTotalSize); /*DH DEBUG*/ memShow(0); taskShow(taskIdSelf(), 1); checkStack(0); /*force an exception*/ *(PULONG)0 = 0; return NULL; } }
int ffiPushSingleFloat(double value) { DPRINTF(("ffiPushSingleFloat %f\n", (float)value)); if (fprCount < FPR_MAX) ffiFPRs[fprCount++]= value; else { float floatValue= (float)value; checkStack(); ffiStack[stackIndex++]= *(int *)&floatValue; } return 1; }
// static int mutatorTest(BPatch_thread *appThread, BPatch_image *appImage) test_results_t test_stack_1_Mutator::executeTest() { appProc->continueExecution(); static const frameInfo_t correct_frame_info[] = { #if defined( os_linux_test ) && (defined( arch_x86_test ) || defined( arch_x86_64_test )) { true, true, BPatch_frameNormal, "_dl_sysinfo_int80" }, #endif #if !defined(rs6000_ibm_aix4_1_test) { false, false, BPatch_frameNormal, NULL }, #endif #if !defined(i386_unknown_nt4_0_test) { true, false, BPatch_frameNormal, "stop_process_" }, #endif { true, false, BPatch_frameNormal, "test_stack_1_func3" }, { true, false, BPatch_frameNormal, "test_stack_1_func2" }, { true, false, BPatch_frameNormal, "test_stack_1_func1" }, { true, false, BPatch_frameNormal, "test_stack_1_mutateeTest" }, { true, false, BPatch_frameNormal, "main" }, }; if (waitUntilStopped(bpatch, appProc, 1, "getCallStack") < 0) { appProc->terminateExecution(); return FAILED; } if (checkStack(appThread, correct_frame_info, sizeof(correct_frame_info)/sizeof(frameInfo_t), 1, "getCallStack")) { logerror("Passed test #1 (getCallStack)\n"); } else { appProc->terminateExecution(); return FAILED; } appProc->continueExecution(); while (!appProc->isTerminated()) { bpatch->waitForStatusChange(); } return PASSED; }
// static int mutatorTest( BPatch_thread * appThread, BPatch_image * appImage ) { test_results_t test_stack_3_Mutator::executeTest() { bool passedTest; BPatch::bpatch->setInstrStackFrames(true); appProc->continueExecution(); static const frameInfo_t correct_frame_info[] = { #if defined( os_linux_test ) && (defined( arch_x86_test ) || defined( arch_x86_64_test )) { true, true, BPatch_frameNormal, "_dl_sysinfo_int80" }, #endif #if defined( os_aix_test ) && defined( arch_power_test ) /* AIX uses kill(), but the PC of a process in a syscall can not be correctly determined, and appears to be the address to which the syscall function will return. */ #elif defined( os_windows_test ) && (defined( arch_x86 ) || defined( arch_x86_64_test )) /* Windows/x86 does not use kill(), so its lowermost frame will be something unidentifiable in a system DLL. */ { false, false, BPatch_frameNormal, NULL }, #else { true, false, BPatch_frameNormal, "kill" }, #endif #if ! defined( os_windows_test ) /* Windows/x86's stop_process_() calls DebugBreak(); it's apparently normal to lose this frame. */ { true, false, BPatch_frameNormal, "stop_process_" }, #endif { true, false, BPatch_frameNormal, "test_stack_3_func3" }, { true, false, BPatch_frameTrampoline, NULL }, /* On AIX and x86 (and others), if our instrumentation fires before frame construction or after frame destruction, it's acceptable to not report the function (since, after all, it doesn't have a frame on the stack. */ { true, true, BPatch_frameNormal, "test_stack_3_func2" }, { true, false, BPatch_frameNormal, "test_stack_3_func1" }, { true, false, BPatch_frameNormal, "test_stack_3_mutateeTest" }, { true, false, BPatch_frameNormal, "main" } }; /* Wait for the mutatee to stop in test_stack_3_func1(). */ if (waitUntilStopped( bpatch, appProc, 1, "getCallStack through instrumentation") < 0) { appProc->terminateExecution(); return FAILED; } /* Instrument test_stack_3_func2() to call test_stack_3_func3(), which will trip another breakpoint. */ BPatch_Vector<BPatch_function *> instrumentedFunctions; const char *fName = "test_stack_3_func2"; appImage->findFunction(fName, instrumentedFunctions ); if (instrumentedFunctions.size() != 1) { // FIXME Print out a useful error message logerror("**Failed** test_stack_3\n"); logerror(" Unable to find function '%s'\n", fName); appProc->terminateExecution(); return FAILED; } BPatch_Vector<BPatch_point *> * functionEntryPoints = instrumentedFunctions[0]->findPoint( BPatch_entry ); if (functionEntryPoints->size() != 1) { // FIXME Print out a useful error message logerror("**Failed** test_stack_3\n"); logerror(" Unable to find entry point to function '%s'\n", fName); appProc->terminateExecution(); return FAILED; } BPatch_Vector<BPatch_function *> calledFunctions; const char *fName2 = "test_stack_3_func3"; appImage->findFunction(fName2, calledFunctions ); if (calledFunctions.size() != 1) { //FIXME Print out a useful error message logerror("**Failed** test_stack_3\n"); logerror(" Unable to find function '%s'\n", fName2); appProc->terminateExecution(); return FAILED; } BPatch_Vector<BPatch_snippet *> functionArguments; BPatch_funcCallExpr functionCall( * calledFunctions[0], functionArguments ); appProc->insertSnippet( functionCall, functionEntryPoints[0] ); /* Repeat for all three types of instpoints. */ BPatch_Vector<BPatch_point *> * functionCallPoints = instrumentedFunctions[0]->findPoint( BPatch_subroutine ); if (functionCallPoints->size() != 1) { logerror("**Failed** test_stack_3\n"); logerror(" Unable to find subroutine call points in '%s'\n", fName); appProc->terminateExecution(); return FAILED; } appProc->insertSnippet( functionCall, functionCallPoints[0] ); BPatch_Vector<BPatch_point *> * functionExitPoints = instrumentedFunctions[0]->findPoint( BPatch_exit ); if (functionExitPoints->size() != 1) { logerror("**Failed** test_stack_3\n"); logerror(" Unable to find exit points in '%s'\n", fName); appProc->terminateExecution(); return FAILED; } appProc->insertSnippet( functionCall, functionExitPoints[0] ); #if defined( DEBUG ) for( int i = 0; i < 80; i++ ) { ptrace( PTRACE_SINGLESTEP, appThread->getPid(), NULL, NULL ); } for( int i = 80; i < 120; i++ ) { ptrace( PTRACE_SINGLESTEP, appThread->getPid(), NULL, NULL ); BPatch_Vector<BPatch_frame> stack; appThread->getCallStack( stack ); dprintf("single-step stack walk, %d instructions after stop for instrumentation.\n", i ); for( unsigned i = 0; i < stack.size(); i++ ) { char name[ 40 ]; BPatch_function * func = stack[i].findFunction(); if( func == NULL ) { strcpy( name, "[UNKNOWN]" ); } else { func->getName( name, 40 ); } dprintf(" %10p: %s, fp = %p\n", stack[i].getPC(), name, stack[i].getFP() ); } /* end stack walk dumper */ dprintf("end of stack walk.\n" ); } /* end single-step iterator */ #endif /* defined( DEBUG ) */ /* After inserting the instrumentation, let it be called. */ appProc->continueExecution(); /* Wait for the mutatee to stop because of the instrumentation we just inserted. */ if (waitUntilStopped( bpatch, appProc, 1, "getCallStack through instrumentation (entry)") < 0) { appProc->terminateExecution(); return FAILED; } passedTest = true; if( !checkStack( appThread, correct_frame_info, sizeof(correct_frame_info)/sizeof(frameInfo_t), 3, "getCallStack through instrumentation (entry)" ) ) { passedTest = false; } /* Repeat for other two types of instpoints. */ appProc->continueExecution(); /* Wait for the mutatee to stop because of the instrumentation we just inserted. */ if (waitUntilStopped( bpatch, appProc, 1, "getCallStack through instrumentation (call)") < 0) { appProc->terminateExecution(); return FAILED; } if( !checkStack( appThread, correct_frame_info, sizeof(correct_frame_info)/sizeof(frameInfo_t), 3, "getCallStack through instrumentation (call)" ) ) { passedTest = false; } appProc->continueExecution(); /* Wait for the mutatee to stop because of the instrumentation we just inserted. */ if (waitUntilStopped( bpatch, appProc, 1, "getCallStack through instrumentation (exit)") < 0) { appProc->terminateExecution(); return FAILED; } if( !checkStack( appThread, correct_frame_info, sizeof(correct_frame_info)/sizeof(frameInfo_t), 3, "getCallStack through instrumentation (exit)" ) ) { passedTest = false; } if (passedTest) logerror("Passed test #3 (unwind through base and mini tramps)\n"); /* Return the mutatee to its normal state. */ appProc->continueExecution(); while (!appProc->isTerminated()) { // Workaround for issue with pgCC_high mutatee bpatch->waitForStatusChange(); } if (passedTest) return PASSED; return FAILED; } /* end mutatorTest3() */
bool funcCallPrologue(Thread* t, Function* func, AbsStack returnSlot, word expectedResults, AbsStack paramSlot, uword numParams, bool isTailcall) { if(numParams > func->maxParams) croc_eh_throwStd(*t, "ParamError", "Function %s expected at most %" CROC_SIZE_T_FORMAT " parameters but was given %" CROC_SIZE_T_FORMAT, func->name->toCString(), func->maxParams - 1, numParams - 1); if(!func->isNative) { // Script function auto funcdef = func->scriptFunc; auto ar = isTailcall ? t->currentAR : pushAR(t); if(isTailcall) { assert(ar && ar->func && !ar->func->isNative); assert(paramSlot == returnSlot + 1); closeUpvals(t, ar->base); ar->numTailcalls++; memmove(&t->stack[ar->returnSlot], &t->stack[returnSlot], sizeof(Value) * (numParams + 1)); returnSlot = ar->returnSlot; paramSlot = returnSlot + 1; } if(funcdef->isVararg && numParams > func->numParams) { // In this case, we move the formal parameters after the varargs and null out where the formal // params used to be. ar->base = paramSlot + numParams; ar->vargBase = paramSlot + func->numParams; checkStack(t, ar->base + funcdef->stackSize - 1); auto oldParams = t->stack.slice(paramSlot, paramSlot + func->numParams); t->stack.slicea(ar->base, ar->base + func->numParams, oldParams); oldParams.fill(Value::nullValue); // For nulling out the stack. numParams = func->numParams; } else { // In this case, everything is where it needs to be already. ar->base = paramSlot; ar->vargBase = paramSlot; checkStack(t, ar->base + funcdef->stackSize - 1); // If we have too few params, the extra param slots will be nulled out. } // Null out the stack frame after the parameters. t->stack.slice(ar->base + numParams, ar->base + funcdef->stackSize).fill(Value::nullValue); // Fill in the rest of the activation record. ar->returnSlot = returnSlot; ar->func = func; ar->pc = funcdef->code.ptr; ar->firstResult = 0; ar->numResults = 0; ar->savedTop = ar->base + funcdef->stackSize; ar->unwindCounter = 0; ar->unwindReturn = nullptr; if(!isTailcall) { ar->expectedResults = expectedResults; ar->numTailcalls = 0; } // Set the stack indices. t->stackBase = ar->base; t->stackIndex = ar->savedTop; // Call any hook. if(t->hooks & CrocThreadHook_Call) callHook(t, isTailcall ? CrocThreadHook_TailCall : CrocThreadHook_Call); return true; } else { // Native function t->stackIndex = paramSlot + numParams; checkStack(t, t->stackIndex); auto ar = pushAR(t); ar->base = paramSlot; ar->vargBase = paramSlot; ar->returnSlot = returnSlot; ar->func = func; ar->expectedResults = expectedResults; ar->firstResult = 0; ar->numResults = 0; ar->savedTop = t->stackIndex; ar->numTailcalls = 0; ar->unwindCounter = 0; ar->unwindReturn = nullptr; t->stackBase = ar->base; if(t->hooks & CrocThreadHook_Call) callHook(t, CrocThreadHook_Call); t->vm->curThread = t; t->nativeCallDepth++; auto savedState = t->state; t->state = CrocThreadState_Running; word actualResults = func->nativeFunc(*t); t->state = savedState; t->nativeCallDepth--; assert(actualResults >= 0); // for now, will change in the future if(cast(uword)actualResults > (t->stackIndex - (t->stackBase + 1))) croc_eh_throwStd(*t, "ApiError", "Native function '%s' returned an invalid number of results", func->name->toCString()); saveResults(t, t, t->stackIndex - actualResults, actualResults); callEpilogue(t); return false; } }
int run(void) { Instruction* code = codeBlock->code; int count = 0; int number; char s[100]; WINDOW* win = initscr(); nonl(); cbreak(); noecho(); scrollok(win,TRUE); ps = PS_ACTIVE; while (ps == PS_ACTIVE) { if (debugMode) { sprintInstruction(s,&(code[pc])); wprintw(win, "%6d-%-4d: %s\n",count++,pc,s); } switch (code[pc].op) { case OP_LA: t ++; if (checkStack()) stack[t] = base(code[pc].p) + code[pc].q; break; case OP_LV: t ++; if (checkStack()) stack[t] = stack[base(code[pc].p) + code[pc].q]; break; case OP_LC: t ++; if (checkStack()) stack[t] = code[pc].q; break; case OP_LI: stack[t] = stack[stack[t]]; break; case OP_INT: t += code[pc].q; checkStack(); break; case OP_DCT: t -= code[pc].q; checkStack(); break; case OP_J: pc = code[pc].q - 1; break; case OP_FJ: if (stack[t] == FALSE) pc = code[pc].q - 1; t --; checkStack(); break; case OP_HL: ps = PS_NORMAL_EXIT; break; case OP_ST: stack[stack[t-1]] = stack[t]; t -= 2; checkStack(); break; case OP_CALL: stack[t+2] = b; // Dynamic Link stack[t+3] = pc; // Return Address stack[t+4] = base(code[pc].p); // Static Link b = t + 1; // Base & Result pc = code[pc].q - 1; break; case OP_EP: t = b - 1; // Previous top pc = stack[b+2]; // Saved return address b = stack[b+1]; // Saved base break; case OP_EF: t = b; // return value is on the top of the stack pc = stack[b+2]; // Saved return address b = stack[b+1]; // saved base break; case OP_RC: t ++; echo(); wscanw(win,"%c",&number); noecho(); stack[t] = number; checkStack(); break; case OP_RI: t ++; echo(); wscanw(win,"%d",&number); noecho(); stack[t] = number; checkStack(); break; case OP_WRC: wprintw(win,"%c",stack[t]); t --; checkStack(); break; case OP_WRI: wprintw(win,"%d",stack[t]); t --; checkStack(); break; case OP_WLN: wprintw(win,"\n"); break; case OP_AD: t --; if (checkStack()) stack[t] += stack[t+1]; break; case OP_SB: t --; if (checkStack()) stack[t] -= stack[t+1]; break; case OP_ML: t --; if (checkStack()) stack[t] *= stack[t+1]; break; case OP_DV: t --; if (checkStack()) { if (stack[t+1] == 0) ps = PS_DIVIDE_BY_ZERO; else stack[t] /= stack[t+1]; } break; case OP_NEG: stack[t] = - stack[t]; break; case OP_CV: stack[t+1] = stack[t]; t ++; checkStack(); break; case OP_EQ: t --; if (stack[t] == stack[t+1]) stack[t] = TRUE; else stack[t] = FALSE; checkStack(); break; case OP_NE: t --; if (stack[t] != stack[t+1]) stack[t] = TRUE; else stack[t] = FALSE; checkStack(); break; case OP_GT: t --; if (stack[t] > stack[t+1]) stack[t] = TRUE; else stack[t] = FALSE; checkStack(); break; case OP_LT: t --; if (stack[t] < stack[t+1]) stack[t] = TRUE; else stack[t] = FALSE; checkStack(); break; case OP_GE: t --; if (stack[t] >= stack[t+1]) stack[t] = TRUE; else stack[t] = FALSE; checkStack(); break; case OP_LE: t --; if (stack[t] <= stack[t+1]) stack[t] = TRUE; else stack[t] = FALSE; checkStack(); break; case OP_BP: // Just for debugging debugMode = 1; break; default: break; } if (debugMode) { int command; int level, offset; int interactive = 1; do { interactive = 0; command = getch(); switch (command) { case 'a': case 'A': wprintw(win,"\nEnter memory location (level, offset):"); wscanw(win,"%d %d", &level, &offset); wprintw(win,"Absolute address = %d\n", base(level) + offset); interactive = 1; break; case 'm': case 'M': wprintw(win,"\nEnter memory location (level, offset):"); wscanw(win,"%d %d", &level, &offset); wprintw(win,"Value = %d\n", stack[base(level) + offset]); interactive = 1; break; case 't': case 'T': wprintw(win,"Top (%d) = %d\n", t, stack[t]); interactive = 1; break; case 'c': case 'C': debugMode = 0; break; case 'h': case 'H': ps = PS_NORMAL_EXIT; break; default: break; } } while (interactive); } pc ++; } wprintw(win,"\nPress any key to exit...");getch(); endwin(); return ps; }
void LuaInterface::pushInteger(long v) { lua_pushinteger(L, v); checkStack(); }
void LuaInterface::pushCFunction(LuaCFunction func, int n) { lua_pushcclosure(L, func, n); checkStack(); }
void LuaInterface::pushThread() { lua_pushthread(L); checkStack(); }
void LuaInterface::pushLightUserdata(void* p) { lua_pushlightuserdata(L, p); checkStack(); }
void LuaInterface::pushString(const std::string& v) { lua_pushlstring(L, v.c_str(), v.length()); checkStack(); }
void LuaInterface::pushCString(const char* v) { assert(v); lua_pushstring(L, v); checkStack(); }
void LuaInterface::pushBoolean(bool v) { lua_pushboolean(L, v); checkStack(); }
void LuaInterface::pushNumber(double v) { lua_pushnumber(L, v); checkStack(); }
void LuaInterface::pushValue(int index) { assert(hasIndex(index)); lua_pushvalue(L, index); checkStack(); }
/* N.B.!! We do *not* execute in the context of the dying task here, but rather that of tExcTask - we do get a pointer to the task's TCB though - this pointer is in fact also the task's ID. */ static void save_reclaim(WIND_TCB *tcbp) { int i, var, oldfd; struct task_data *tdp; struct mall_data *mdp, *mdnextp; if ((var = taskVarGet((int)tcbp, (int *)&task_data)) != ERROR && var != 0) { tdp = (struct task_data *)var; if (tdp->version == (FUNCPTR)save_reclaim) { /* Only handle our own */ #ifdef DEBUG fdprintf(2, "Reclaiming for task id 0x%x:\nFiles: ", (int)tcbp); #endif /* Ugh! VxWorks doesn't even flush stdout/err - we need to get at those (which are task-private of course, i.e. we can't just do fflush(stdout) here) - we could be really pedantic and try to redefine stdout/err (which "are" function calls) too, snarfing the values when they are used - but besides the overhead this is problematic since they are actually #defines already... We'll peek in the TCB instead (no documentation of course). And of course, we must also meddle with the *file descriptor* indirections, or we'll just flush out on tExcTask's descriptors... */ for (i = 1; i <= 2; i++) { if (tcbp->taskStdFp[i] != NULL) { #ifdef DEBUG fdprintf(2, "fflush(%s) ", i == 1 ? "stdout" : "stderr"); #endif oldfd = ioTaskStdGet(0, i); ioTaskStdSet(0, i, tcbp->taskStd[i]); fflush(tcbp->taskStdFp[i]); ioTaskStdSet(0, i, oldfd); } } for (i = 3; i < tdp->max_files; i++) { if (FD_ISSET(i, &tdp->open_fds)) { #ifdef DEBUG fdprintf(2, "close(%d) ", i); #endif (void) close(i); } if (tdp->open_fps[i] != NULL) { #ifdef DEBUG fdprintf(2, "fclose(%0x%x) ", (int)tdp->open_fps[i]); #endif (void) fclose(tdp->open_fps[i]); } } i = 0; mdp = tdp->mall_data; while (mdp != NULL) { mdnextp = mdp->next; if(reclaim_free_function != NULL) (*reclaim_free_function)(mdp->self); else free(mdp->self); i++; mdp = mdnextp; } #ifdef DEBUG fdprintf(2, "\nFreeing memory: total %d mallocs\n", i); #endif if (tdp->delete_hook != NULL) { #ifdef DEBUG fdprintf(2, "Calling delete hook at 0x%08x\n", tdp->delete_hook); #endif (*tdp->delete_hook)(tdp->hook_data); #ifdef DEBUG fdprintf(2, "Called delete hook at 0x%08x\n", tdp->delete_hook); #endif } #ifdef DEBUG fdprintf(2, "Freeing own mem at 0x%08x\n", tdp); #endif (void) free((char *)tdp); #ifdef DEBUG fdprintf(2, "Freed own mem at 0x%08x, done (0x%08x)\n**********\n", tdp, taskIdSelf()); checkStack(0); #endif } } #ifdef DEBUG else fdprintf(2, "No task data found for id 0x%x, var = %d\n", (int)tcbp, var); #endif }
void LuaInterface::pushNil() { lua_pushnil(L); checkStack(); }