예제 #1
0
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);
}
예제 #2
0
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);
}
예제 #3
0
void showsaving::premanentstep(int sp)
{
    speed = sp ;
    singlestep();
    if(id)
        killTimer(id);
    id = startTimer(speed);
}
예제 #4
0
void showqianzhi::timerEvent(QTimerEvent *event)
{
    if(step < imagenumber1+imagenumber2)
    {
        singlestep();
        id = startTimer(speed);
    }
    else killTimer(id);
}
예제 #5
0
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));
}
예제 #6
0
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);
}
예제 #7
0
파일: lgc.c 프로젝트: charleeli/srpc
/*
** 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);
  }
}
예제 #8
0
파일: lgc.c 프로젝트: Hooman3/minix
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);
  }
}
예제 #9
0
파일: lgc.c 프로젝트: charleeli/srpc
/*
** 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);
}
예제 #10
0
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, &regs);
		regs.eax = trace->recorded_regs.eax;
		regs.edx = trace->recorded_regs.edx;
		regs.eip += size;
		write_child_registers(tid, &regs);
		sys_free((void**) &inst);

		compare_register_files("rdtsv_now", &regs, "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, &regs);
		assert(compare_register_files("now", &regs, "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;
	}
}
예제 #11
0
void showqianzhi::premanentstep(int sp)
{
    speed = sp ;
    singlestep();
    id = startTimer(speed);
}
예제 #12
0
/*
 * 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.
		 */
	}
}
예제 #13
0
void showqianzhi::on_pushButton_2_clicked()
{
    singlestep();
}
예제 #14
0
void showsaving::on_pushButton_2_clicked()
{
    singlestep();
}
예제 #15
0
void showqianzhi::continuestep()
{
    singlestep();
    id = startTimer(speed);
}
예제 #16
0
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;
}
예제 #17
0
void showsaving::continuestep()
{
    singlestep();
    id = startTimer(speed);
}
예제 #18
0
/**
 * 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, &regs);
		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", &regs, "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);
	}
}
예제 #19
0
/*
 * 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.
		 */
	}
}