void luaC_fullgc (lua_State *L) { global_State *g = G(L); if(is_block_gc(L)) return; set_block_gc(L); if (g->gcstate <= GCSpropagate) { /* reset sweep marks to sweep all elements (returning them to white) */ g->sweepstrgc = 0; g->sweepgc = &g->rootgc; /* reset other collector lists */ g->gray = NULL; g->grayagain = NULL; g->weak = NULL; g->gcstate = GCSsweepstring; } lua_assert(g->gcstate != GCSpause && g->gcstate != GCSpropagate); /* finish any pending sweep phase */ while (g->gcstate != GCSfinalize) { lua_assert(g->gcstate == GCSsweepstring || g->gcstate == GCSsweep); singlestep(L); } markroot(L); while (g->gcstate != GCSpause) { singlestep(L); } setthreshold(g); unset_block_gc(L); }
void luaC_step (lua_State *L) { global_State *g = G(L); if(is_block_gc(L)) return; set_block_gc(L); l_mem lim = (GCSTEPSIZE/100) * g->gcstepmul; if (lim == 0) lim = (MAX_LUMEM-1)/2; /* no limit */ g->gcdept += g->totalbytes - g->GCthreshold; if (g->estimate > g->totalbytes) g->estimate = g->totalbytes; do { lim -= singlestep(L); if (g->gcstate == GCSpause) break; } while (lim > 0); if (g->gcstate != GCSpause) { if (g->gcdept < GCSTEPSIZE) g->GCthreshold = g->totalbytes + GCSTEPSIZE; /* - lim/g->gcstepmul;*/ else { g->gcdept -= GCSTEPSIZE; g->GCthreshold = g->totalbytes; } } else { lua_assert(g->totalbytes >= g->estimate); setthreshold(g); } unset_block_gc(L); }
void showsaving::premanentstep(int sp) { speed = sp ; singlestep(); if(id) killTimer(id); id = startTimer(speed); }
void showqianzhi::timerEvent(QTimerEvent *event) { if(step < imagenumber1+imagenumber2) { singlestep(); id = startTimer(speed); } else killTimer(id); }
static void step (lua_State *L) { global_State *g = G(L); l_mem lim = g->gcstepmul; /* how much to work */ do { /* always perform at least one single step */ lim -= singlestep(L); } while (lim > 0 && g->gcstate != GCSpause); if (g->gcstate != GCSpause) luaE_setdebt(g, g->GCdebt - GCSTEPSIZE); else luaE_setdebt(g, stddebt(g)); }
static void incstep (lua_State *L) { global_State *g = G(L); l_mem debt = g->GCdebt; int stepmul = g->gcstepmul; if (stepmul < 40) stepmul = 40; /* avoid ridiculous low values */ /* convert debt from Kb to 'work units' (avoid zero debt and overflows) */ debt = (debt / STEPMULADJ) + 1; debt = (debt < MAX_LMEM / stepmul) ? debt * stepmul : MAX_LMEM; do { /* always perform at least one single step */ lu_mem work = singlestep(L); /* do some work */ debt -= work; } while (debt > -GCSTEPSIZE && g->gcstate != GCSpause); if (g->gcstate == GCSpause) debt = stddebtest(g, g->GCestimate); /* pause until next cycle */ else debt = (debt / stepmul) * STEPMULADJ; /* convert 'work units' to Kb */ luaE_setdebt(g, debt); }
/* ** performs a basic GC step when collector is running */ void luaC_step (lua_State *L) { global_State *g = G(L); l_mem debt = getdebt(g); /* GC deficit (be paid now) */ if (!g->gcrunning) { /* not running? */ luaE_setdebt(g, -GCSTEPSIZE * 10); /* avoid being called too often */ return; } do { /* repeat until pause or enough "credit" (negative debt) */ lu_mem work = singlestep(L); /* perform one single step */ debt -= work; } while (debt > -GCSTEPSIZE && g->gcstate != GCSpause); if (g->gcstate == GCSpause) setpause(g); /* pause until next cycle */ else { debt = (debt / g->gcstepmul) * STEPMULADJ; /* convert 'work units' to Kb */ luaE_setdebt(g, debt); runafewfinalizers(L); } }
void luaC_step (lua_State *L) { global_State *g = G(L); l_mem lim = (GCSTEPSIZE/100) * g->gcstepmul; if (lim == 0) lim = (MAX_LUMEM-1)/2; /* no limit */ g->gcdept += g->totalbytes - g->GCthreshold; do { lim -= singlestep(L); if (g->gcstate == GCSpause) break; } while (lim > 0); if (g->gcstate != GCSpause) { if (g->gcdept < GCSTEPSIZE) g->GCthreshold = g->totalbytes + GCSTEPSIZE; /* - lim/g->gcstepmul;*/ else { g->gcdept -= GCSTEPSIZE; g->GCthreshold = g->totalbytes; } } else { setthreshold(g); } }
/* ** advances the garbage collector until it reaches a state allowed ** by 'statemask' */ void luaC_runtilstate (lua_State *L, int statesmask) { global_State *g = G(L); while (!testbit(statesmask, g->gcstate)) singlestep(L); }
void rep_process_signal(struct context *ctx) { struct trace* trace = &(ctx->trace); int tid = ctx->child_tid; int sig = -trace->stop_reason; /* if the there is still a signal pending here, two signals in a row must be delivered?\n */ assert(ctx->child_sig == 0); switch (sig) { /* set the eax and edx register to the recorded values */ case -SIG_SEGV_RDTSC: { struct user_regs_struct regs; int size; /* goto the event */ goto_next_event(ctx); /* make sure we are there */ assert(WSTOPSIG(ctx->status) == SIGSEGV); char* inst = get_inst(tid, 0, &size); assert(strncmp(inst,"rdtsc",5) == 0); read_child_registers(tid, ®s); regs.eax = trace->recorded_regs.eax; regs.edx = trace->recorded_regs.edx; regs.eip += size; write_child_registers(tid, ®s); sys_free((void**) &inst); compare_register_files("rdtsv_now", ®s, "rdsc_rec", &ctx->trace.recorded_regs, 1, 1); /* this signal should not be recognized by the application */ ctx->child_sig = 0; break; } case -USR_SCHED: { assert(trace->rbc_up > 0); /* if the current architecture over-counts the event in question, * substract the overcount here */ reset_hpc(ctx, trace->rbc_up - SKID_SIZE); goto_next_event(ctx); /* make sure that the signal came from hpc */ if (fcntl(ctx->hpc->rbc_down.fd, F_GETOWN) == ctx->child_tid) { /* this signal should not be recognized by the application */ ctx->child_sig = 0; stop_hpc_down(ctx); compensate_branch_count(ctx, sig); stop_hpc(ctx); } else { fprintf(stderr, "internal error: next event should be: %d but it is: %d -- bailing out\n", -USR_SCHED, ctx->event); sys_exit(); } break; } case SIGIO: case SIGCHLD: { /* synchronous signal (signal received in a system call) */ if (trace->rbc_up == 0) { ctx->replay_sig = sig; return; } // setup and start replay counters reset_hpc(ctx, trace->rbc_up - SKID_SIZE); /* single-step if the number of instructions to the next event is "small" */ if (trace->rbc_up <= 10000) { stop_hpc_down(ctx); compensate_branch_count(ctx, sig); stop_hpc(ctx); } else { printf("large count\n"); sys_ptrace_syscall(tid); sys_waitpid(tid, &ctx->status); // make sure we ere interrupted by ptrace assert(WSTOPSIG(ctx->status) == SIGIO); /* reset the penig sig, since it did not occur in the original execution */ ctx->child_sig = 0; ctx->status = 0; //DO NOT FORGET TO STOP HPC!!! compensate_branch_count(ctx, sig); stop_hpc(ctx); stop_hpc_down(ctx); } break; } case SIGSEGV: { /* synchronous signal (signal received in a system call) */ if (trace->rbc_up == 0 && trace->page_faults == 0) { ctx->replay_sig = sig; return; } sys_ptrace_syscall(ctx->child_tid); sys_waitpid(ctx->child_tid, &ctx->status); assert(WSTOPSIG(ctx->status) == SIGSEGV); struct user_regs_struct regs; read_child_registers(ctx->child_tid, ®s); assert(compare_register_files("now", ®s, "rec", &ctx->trace.recorded_regs, 1, 1) == 0); /* deliver the signal */ singlestep(ctx, SIGSEGV, 0x57f); break; } default: printf("unknown signal %d -- bailing out\n", sig); sys_exit(); break; } }
void showqianzhi::premanentstep(int sp) { speed = sp ; singlestep(); id = startTimer(speed); }
/* * Called with IRQs disabled. IRQs must remain disabled from that point * all the way until processing this kprobe is complete. The current * kprobes implementation cannot process more than one nested level of * kprobe, and that level is reserved for user kprobe handlers, so we can't * risk encountering a new kprobe in an interrupt handler. */ void __kprobes kprobe_handler(struct pt_regs *regs) { struct kprobe *p, *cur; struct kprobe_ctlblk *kcb; kcb = get_kprobe_ctlblk(); cur = kprobe_running(); #ifdef CONFIG_THUMB2_KERNEL /* * First look for a probe which was registered using an address with * bit 0 set, this is the usual situation for pointers to Thumb code. * If not found, fallback to looking for one with bit 0 clear. */ p = get_kprobe((kprobe_opcode_t *)(regs->ARM_pc | 1)); if (!p) p = get_kprobe((kprobe_opcode_t *)regs->ARM_pc); #else /* ! CONFIG_THUMB2_KERNEL */ p = get_kprobe((kprobe_opcode_t *)regs->ARM_pc); #endif if (p) { if (cur) { /* Kprobe is pending, so we're recursing. */ switch (kcb->kprobe_status) { case KPROBE_HIT_ACTIVE: case KPROBE_HIT_SSDONE: /* A pre- or post-handler probe got us here. */ kprobes_inc_nmissed_count(p); save_previous_kprobe(kcb); set_current_kprobe(p); kcb->kprobe_status = KPROBE_REENTER; singlestep(p, regs, kcb); restore_previous_kprobe(kcb); break; default: /* impossible cases */ BUG(); } } else if (p->ainsn.insn_check_cc(regs->ARM_cpsr)) { /* Probe hit and conditional execution check ok. */ set_current_kprobe(p); kcb->kprobe_status = KPROBE_HIT_ACTIVE; /* * If we have no pre-handler or it returned 0, we * continue with normal processing. If we have a * pre-handler and it returned non-zero, it prepped * for calling the break_handler below on re-entry, * so get out doing nothing more here. */ if (!p->pre_handler || !p->pre_handler(p, regs)) { kcb->kprobe_status = KPROBE_HIT_SS; singlestep(p, regs, kcb); if (p->post_handler) { kcb->kprobe_status = KPROBE_HIT_SSDONE; p->post_handler(p, regs, 0); } reset_current_kprobe(); } } else { /* * Probe hit but conditional execution check failed, * so just skip the instruction and continue as if * nothing had happened. */ singlestep_skip(p, regs); } } else if (cur) { /* We probably hit a jprobe. Call its break handler. */ if (cur->break_handler && cur->break_handler(cur, regs)) { kcb->kprobe_status = KPROBE_HIT_SS; singlestep(cur, regs, kcb); if (cur->post_handler) { kcb->kprobe_status = KPROBE_HIT_SSDONE; cur->post_handler(cur, regs, 0); } } reset_current_kprobe(); } else { /* * The probe was removed and a race is in progress. * There is nothing we can do about it. Let's restart * the instruction. By the time we can restart, the * real instruction will be there. */ } }
void showqianzhi::on_pushButton_2_clicked() { singlestep(); }
void showsaving::on_pushButton_2_clicked() { singlestep(); }
void showqianzhi::continuestep() { singlestep(); id = startTimer(speed); }
int fprintf_process(pid_t pid) { // attach to the process if (ptrace(PTRACE_ATTACH, pid, NULL, NULL)) { perror("PTRACE_ATTACH"); check_yama(); return -1; } // wait for the process to actually stop if (waitpid(pid, 0, WSTOPPED) == -1) { perror("wait"); return -1; } // save the register state of the remote process struct user_regs_struct oldregs; if (ptrace(PTRACE_GETREGS, pid, NULL, &oldregs)) { perror("PTRACE_GETREGS"); ptrace(PTRACE_DETACH, pid, NULL, NULL); return -1; } void *rip = (void *)oldregs.rip; printf("their %%rip %p\n", rip); // First, we are going to allocate some memory for ourselves so we don't // need // to stop on the remote process' memory. We will do this by directly // invoking // the mmap(2) system call and asking for a single page. struct user_regs_struct newregs; memmove(&newregs, &oldregs, sizeof(newregs)); newregs.rax = 9; // mmap newregs.rdi = 0; // addr newregs.rsi = PAGE_SIZE; // length newregs.rdx = PROT_READ | PROT_EXEC; // prot newregs.r10 = MAP_PRIVATE | MAP_ANONYMOUS; // flags newregs.r8 = -1; // fd newregs.r9 = 0; // offset uint8_t old_word[8]; uint8_t new_word[8]; new_word[0] = 0x0f; // SYSCALL new_word[1] = 0x05; // SYSCALL new_word[2] = 0xff; // JMP %rax new_word[3] = 0xe0; // JMP %rax // insert the SYSCALL instruction into the process, and save the old word if (poke_text(pid, rip, new_word, old_word, sizeof(new_word))) { goto fail; } // set the new registers with our syscall arguments if (ptrace(PTRACE_SETREGS, pid, NULL, &newregs)) { perror("PTRACE_SETREGS"); goto fail; } // invoke mmap(2) if (singlestep(pid)) { goto fail; } // read the new register state, so we can see where the mmap went if (ptrace(PTRACE_GETREGS, pid, NULL, &newregs)) { perror("PTRACE_GETREGS"); return -1; } // this is the address of the memory we allocated void *mmap_memory = (void *)newregs.rax; if (mmap_memory == (void *)-1) { printf("failed to mmap\n"); goto fail; } printf("allocated memory at %p\n", mmap_memory); printf("executing jump to mmap region\n"); if (singlestep(pid)) { goto fail; } if (ptrace(PTRACE_GETREGS, pid, NULL, &newregs)) { perror("PTRACE_GETREGS"); goto fail; } if (newregs.rip == (long)mmap_memory) { printf("successfully jumped to mmap area\n"); } else { printf("unexpectedly jumped to %p\n", (void *)newregs.rip); goto fail; } // Calculate the position of the fprintf routine in the other process' // address // space. This is a little bit tricky because of ASLR on Linux. What we do // is // we find the offset in memory that libc has been loaded in their process, // and then we find the offset in memory that libc has been loaded in our // process. Then we take the delta betwen our fprintf and our libc start, // and // assume that the same delta will apply to the other process. // // For this mechanism to work, this program must be compiled with -fPIC to // ensure that our fprintf has an address relative to the one in libc. // // Additionally, this could fail if libc has been updated since the remote // process has been restarted. This is a pretty unlikely situation, but if // the // remote process has been running for a long time and you update libc, the // offset of the symbols could have changed slightly. void *their_libc = find_library(pid, libc_string); void *our_libc = find_library(getpid(), libc_string); void *their_fprintf = their_libc + ((void *)fprintf - our_libc); FILE *their_stderr = their_libc + ((void *)stderr - our_libc); printf("their libc %p\n", their_libc); printf("their fprintf %p\n", their_libc); printf("their stderr %p\n", their_stderr); // We want to make a call like: // // fprintf(stderr, "instruction pointer = %p\n", rip); // // To do this we're going to do the following: // // * put a CALL instruction into the mmap area that calls fprintf // * put a TRAP instruction right after the CALL // * put the format string right after the TRAP // * use the TRAP to restore the original text/program state // memory we are going to copy into our mmap area uint8_t new_text[32]; memset(new_text, 0, sizeof(new_text)); // insert a CALL instruction size_t offset = 0; new_text[offset++] = 0xe8; // CALL rel32 int32_t fprintf_delta = compute_jmp(mmap_memory, their_fprintf); memmove(new_text + offset, &fprintf_delta, sizeof(fprintf_delta)); offset += sizeof(fprintf_delta); // insert a TRAP instruction new_text[offset++] = 0xcc; // copy our fprintf format string right after the TRAP instruction memmove(new_text + offset, format, strlen(format)); // update the mmap area printf("inserting code/data into the mmap area at %p\n", mmap_memory); if (poke_text(pid, mmap_memory, new_text, NULL, sizeof(new_text))) { goto fail; } if (poke_text(pid, rip, new_word, NULL, sizeof(new_word))) { goto fail; } // set up our registers with the args to fprintf // memmove(&newregs, &oldregs, sizeof(newregs)); newregs.rax = 0; // no vector registers are used newregs.rdi = (long)their_stderr; // pointer to stderr in the caller newregs.rsi = (long)mmap_memory + offset; // pointer to the format string newregs.rdx = oldregs.rip; // the integer we want to print printf("setting the registers of the remote process\n"); if (ptrace(PTRACE_SETREGS, pid, NULL, &newregs)) { perror("PTRACE_SETREGS"); goto fail; } // continue the program, and wait for the trap printf("continuing execution\n"); ptrace(PTRACE_CONT, pid, NULL, NULL); if (do_wait("PTRACE_CONT")) { goto fail; } if (ptrace(PTRACE_GETREGS, pid, NULL, &newregs)) { perror("PTRACE_GETREGS"); goto fail; } newregs.rax = (long)rip; if (ptrace(PTRACE_SETREGS, pid, NULL, &newregs)) { perror("PTRACE_SETREGS"); goto fail; } new_word[0] = 0xff; // JMP %rax new_word[1] = 0xe0; // JMP %rax poke_text(pid, (void *)newregs.rip, new_word, NULL, sizeof(new_word)); printf("jumping back to original rip\n"); if (singlestep(pid)) { goto fail; } if (ptrace(PTRACE_GETREGS, pid, NULL, &newregs)) { perror("PTRACE_GETREGS"); goto fail; } if (newregs.rip == (long)rip) { printf("successfully jumped back to original %%rip at %p\n", rip); } else { printf("unexpectedly jumped to %p (expected to be at %p)\n", (void *)newregs.rip, rip); goto fail; } // unmap the memory we allocated newregs.rax = 11; // munmap newregs.rdi = (long)mmap_memory; // addr newregs.rsi = PAGE_SIZE; // size if (ptrace(PTRACE_SETREGS, pid, NULL, &newregs)) { perror("PTRACE_SETREGS"); goto fail; } // make the system call printf("making call to mmap\n"); if (singlestep(pid)) { goto fail; } if (ptrace(PTRACE_GETREGS, pid, NULL, &newregs)) { perror("PTRACE_GETREGS"); goto fail; } printf("munmap returned with status %llu\n", newregs.rax); printf("restoring old text at %p\n", rip); poke_text(pid, rip, old_word, NULL, sizeof(old_word)); printf("restoring old registers\n"); if (ptrace(PTRACE_SETREGS, pid, NULL, &oldregs)) { perror("PTRACE_SETREGS"); goto fail; } // detach the process printf("detaching\n"); if (ptrace(PTRACE_DETACH, pid, NULL, NULL)) { perror("PTRACE_DETACH"); goto fail; } return 0; fail: poke_text(pid, rip, old_word, NULL, sizeof(old_word)); if (ptrace(PTRACE_DETACH, pid, NULL, NULL)) { perror("PTRACE_DETACH"); } return 1; }
void showsaving::continuestep() { singlestep(); id = startTimer(speed); }
/** * function goes to the n-th conditional branch */ static void compensate_branch_count(struct context *ctx, int sig) { uint64_t rbc_now, rbc_rec; rbc_rec = ctx->trace.rbc_up; rbc_now = read_rbc_up(ctx->hpc); /* if the skid size was too small, go back to the last checkpoint and * re-execute the program. */ if (rbc_now > rbc_rec) { /* checkpointing is not implemented yet - so we fail */ fprintf(stderr, "hpc overcounted in asynchronous event, recorded: %llu now: %llu\n", rbc_rec, rbc_now); fprintf(stderr,"event: %d, flobal_time %u\n",ctx->trace.stop_reason, ctx->trace.global_time); assert(0); } int found_spot = 0; rbc_now = read_rbc_up(ctx->hpc); while (rbc_now < rbc_rec) { singlestep(ctx, 0, 0x57f); rbc_now = read_rbc_up(ctx->hpc); } while (rbc_now == rbc_rec) { struct user_regs_struct regs; read_child_registers(ctx->child_tid, ®s); if (sig == SIGSEGV) { /* we should now stop at the instruction that caused the SIGSEGV */ sys_ptrace_syscall(ctx->child_tid); sys_waitpid(ctx->child_tid, &ctx->status); } /* the eflags register has two bits that are set when an interrupt is pending: * bit 8: TF (trap flag) * bit 17: VM (virtual 8086 mode) * * we enable these two bits in the eflags register to make sure that the register * files match * */ int check = compare_register_files("now", ®s, "rec", &ctx->trace.recorded_regs, 0, 0); if (check == 0 || check == 0x80) { found_spot++; /* A SIGSEGV can be triggered by a regular instruction; it is not necessarily sent by * another process. We check this condition here. */ if (sig == SIGSEGV) { //print_inst(ctx->child_tid); /* here we ensure that the we get a SIGSEGV at the right spot */ singlestep(ctx, 0, 0xb7f); /* deliver the signal */ break; } else { break; } /* set the signal such that it is delivered when the process continues */ } /* check that we do not get unexpected signal in the single-stepping process */ singlestep(ctx, 0, 0x57f); rbc_now = read_rbc_up(ctx->hpc); } if (found_spot != 1) { printf("cannot find signal %d time: %u\n",sig,ctx->trace.global_time); assert(found_spot == 1); } }
/* * Called with IRQs disabled. IRQs must remain disabled from that point * all the way until processing this kprobe is complete. The current * kprobes implementation cannot process more than one nested level of * kprobe, and that level is reserved for user kprobe handlers, so we can't * risk encountering a new kprobe in an interrupt handler. */ void __kprobes kprobe_handler(struct pt_regs *regs) { struct kprobe *p, *cur; struct kprobe_ctlblk *kcb; kprobe_opcode_t *addr = (kprobe_opcode_t *)regs->ARM_pc; kcb = get_kprobe_ctlblk(); cur = kprobe_running(); p = get_kprobe(addr); if (p) { if (cur) { /* Kprobe is pending, so we're recursing. */ switch (kcb->kprobe_status) { case KPROBE_HIT_ACTIVE: case KPROBE_HIT_SSDONE: /* A pre- or post-handler probe got us here. */ kprobes_inc_nmissed_count(p); save_previous_kprobe(kcb); set_current_kprobe(p); kcb->kprobe_status = KPROBE_REENTER; singlestep(p, regs, kcb); restore_previous_kprobe(kcb); break; default: /* impossible cases */ BUG(); } } else { set_current_kprobe(p); kcb->kprobe_status = KPROBE_HIT_ACTIVE; /* * If we have no pre-handler or it returned 0, we * continue with normal processing. If we have a * pre-handler and it returned non-zero, it prepped * for calling the break_handler below on re-entry, * so get out doing nothing more here. */ if (!p->pre_handler || !p->pre_handler(p, regs)) { kcb->kprobe_status = KPROBE_HIT_SS; singlestep(p, regs, kcb); if (p->post_handler) { kcb->kprobe_status = KPROBE_HIT_SSDONE; p->post_handler(p, regs, 0); } reset_current_kprobe(); } } } else if (cur) { /* We probably hit a jprobe. Call its break handler. */ if (cur->break_handler && cur->break_handler(cur, regs)) { kcb->kprobe_status = KPROBE_HIT_SS; singlestep(cur, regs, kcb); if (cur->post_handler) { kcb->kprobe_status = KPROBE_HIT_SSDONE; cur->post_handler(cur, regs, 0); } } reset_current_kprobe(); } else { /* * The probe was removed and a race is in progress. * There is nothing we can do about it. Let's restart * the instruction. By the time we can restart, the * real instruction will be there. */ } }