Пример #1
0
/**
 * Continue until reaching either the "entry" of an emulated syscall,
 * or the entry or exit of an executed syscall.  |emu| is nonzero when
 * we're emulating the syscall.  Return 0 when the next syscall
 * boundary is reached, or nonzero if advancing to the boundary was
 * interrupted by an unknown trap.
 */
static int cont_syscall_boundary(struct context* ctx, int emu, int stepi)
{
	pid_t tid = ctx->child_tid;

	if (emu && stepi) {
		sys_ptrace_sysemu_singlestep(tid);
	} else if (emu) {
		sys_ptrace_sysemu(tid);
	} else if (stepi) {
		sys_ptrace_singlestep(tid);
	} else {
		sys_ptrace_syscall(tid);
	}
	sys_waitpid(tid, &ctx->status);

	switch ((ctx->child_sig = signal_pending(ctx->status))) {
	case 0:
		break;
	case SIGCHLD:
		/* SIGCHLD is pending, do not deliver it, wait for it
		 * to appear in the trace SIGCHLD is the only signal
		 * that should ever be generated as all other signals
		 * are emulated! */
		return cont_syscall_boundary(ctx, emu, stepi);
	case SIGTRAP:
		return 1;
	default:
		log_err("Replay got unrecorded signal %d", ctx->child_sig);
		emergency_debug(ctx);
	}

	assert(ctx->child_sig == 0);

	return 0;
}
Пример #2
0
static void continue_or_step(struct context* ctx, int stepi)
{
	pid_t tid = ctx->child_tid;

	if (stepi) {
		sys_ptrace_singlestep(tid);
	} else {
		/* We continue with PTRACE_SYSCALL for error checking:
		 * since the next event is supposed to be a signal,
		 * entering a syscall here means divergence.  There
		 * shouldn't be any straight-line execution overhead
		 * for SYSCALL vs. CONT, so the difference in cost
		 * should be neglible. */
		sys_ptrace_syscall(tid);
	}
	sys_waitpid(tid, &ctx->status);

	ctx->child_sig = signal_pending(ctx->status);
	if (0 == ctx->child_sig) {
		struct user_regs_struct regs;
		read_child_registers(ctx->child_tid, &regs);

		log_err("Replaying `%s' (line %d): expecting tracee signal or trap, but instead at `%s' (rcb: %llu)",
			strevent(ctx->trace.stop_reason),
			get_trace_file_lines_counter(),
			strevent(regs.orig_eax), read_rbc(ctx->hpc));
		emergency_debug(ctx);
	}
}
Пример #3
0
static void singlestep(struct context *ctx, int sig, int expected_val)
{
	sys_ptrace_singlestep(ctx->child_tid, sig);
	sys_waitpid(ctx->child_tid, &ctx->status);
	/* we get a simple SIGTRAP in this case */
	if (ctx->status != expected_val) {
		printf("status %x   expected %x\n", ctx->status, expected_val);
	}

	assert(ctx->status == expected_val);
	ctx->status = 0;
	ctx->child_sig = 0;
}