Exemple #1
0
int context_continue(Context * ctx) {
    int signal = 0;

    assert(is_dispatch_thread());
    assert(ctx->stopped);
    assert(!ctx->pending_intercept);
    assert(!EXT(ctx)->pending_step);
    assert(!ctx->exited);

    if (skip_breakpoint(ctx, 0)) return 0;

    if (!EXT(ctx)->ptrace_event) {
        while (ctx->pending_signals != 0) {
            while ((ctx->pending_signals & (1 << signal)) == 0) signal++;
            if (ctx->sig_dont_pass & (1 << signal)) {
                ctx->pending_signals &= ~(1 << signal);
                signal = 0;
            }
            else {
                break;
            }
        }
        assert(signal != SIGSTOP);
        assert(signal != SIGTRAP);
    }

    trace(LOG_CONTEXT, "context: resuming ctx %#lx, id %s, with signal %d", ctx, ctx->id, signal);
    if (EXT(ctx)->regs_dirty) {
        if (ptrace(PTRACE_SETREGS, EXT(ctx)->pid, 0, (int)EXT(ctx)->regs) < 0) {
            int err = errno;
            if (err == ESRCH) {
                EXT(ctx)->regs_dirty = 0;
                send_context_started_event(ctx);
                return 0;
            }
            trace(LOG_ALWAYS, "error: ptrace(PTRACE_SETREGS) failed: ctx %#lx, id %s, error %d %s",
                ctx, ctx->id, err, errno_to_str(err));
            errno = err;
            return -1;
        }
        EXT(ctx)->regs_dirty = 0;
    }
    if (ptrace(PTRACE_CONT, EXT(ctx)->pid, 0, signal) < 0) {
        int err = errno;
        if (err == ESRCH) {
            send_context_started_event(ctx);
            return 0;
        }
        trace(LOG_ALWAYS, "error: ptrace(PTRACE_CONT, ...) failed: ctx %#lx, id %s, error %d %s",
            ctx, ctx->id, err, errno_to_str(err));
        errno = err;
        return -1;
    }
    ctx->pending_signals &= ~(1 << signal);
    send_context_started_event(ctx);
    return 0;
}
Exemple #2
0
int context_single_step(Context * ctx) {
    assert(is_dispatch_thread());
    assert(context_has_state(ctx));
    assert(ctx->stopped);
    assert(!ctx->exited);
    assert(!EXT(ctx)->pending_step);

    if (skip_breakpoint(ctx, 1)) return 0;

    trace(LOG_CONTEXT, "context: single step ctx %#lx, id %s", ctx, ctx->id);
    if (EXT(ctx)->regs_dirty) {
        if (ptrace(PTRACE_SETREGS, EXT(ctx)->pid, 0, (int)EXT(ctx)->regs) < 0) {
            int err = errno;
            if (err == ESRCH) {
                EXT(ctx)->regs_dirty = 0;
                EXT(ctx)->pending_step = 1;
                send_context_started_event(ctx);
                return 0;
            }
            trace(LOG_ALWAYS, "error: ptrace(PTRACE_SETREGS) failed: ctx %#lx, id %s, error %d %s",
                ctx, ctx->id, err, errno_to_str(err));
            errno = err;
            return -1;
        }
        EXT(ctx)->regs_dirty = 0;
    }
    if (ptrace(PTRACE_SINGLESTEP, EXT(ctx)->pid, 0, 0) < 0) {
        int err = errno;
        if (err == ESRCH) {
            EXT(ctx)->pending_step = 1;
            send_context_started_event(ctx);
            return 0;
        }
        trace(LOG_ALWAYS, "error: ptrace(PTRACE_SINGLESTEP, ...) failed: ctx %#lx, id %s, error %d %s",
            ctx, ctx->id, err, errno_to_str(err));
        errno = err;
        return -1;
    }
    EXT(ctx)->pending_step = 1;
    send_context_started_event(ctx);
    return 0;
}
Exemple #3
0
int context_single_step(Context * ctx) {
    assert(is_dispatch_thread());
    assert(context_has_state(ctx));
    assert(ctx->stopped);
    assert(!ctx->exited);
    assert(!EXT(ctx)->pending_step);

    if (skip_breakpoint(ctx, 1)) return 0;

    if (syscall_never_returns(ctx)) return context_continue(ctx);
    trace(LOG_CONTEXT, "context: single step ctx %#lx, id %S", ctx, ctx->id);
    if (EXT(ctx)->regs_dirty) {
        unsigned int state_count;
        if (thread_set_state(EXT(ctx)->pid, x86_THREAD_STATE32, EXT(ctx)->regs, &state_count) != KERN_SUCCESS) {
            int err = errno;
            trace(LOG_ALWAYS, "error: thread_set_state failed: ctx %#lx, id %s, error %d %s",
                ctx, ctx->id, err, errno_to_str(err));
            errno = err;
            return -1;
        }
        EXT(ctx)->regs_dirty = 0;
    }
    if (ptrace(PT_STEP, EXT(ctx)->pid, 0, 0) < 0) {
        int err = errno;
        if (err == ESRCH) {
            EXT(ctx)->pending_step = 1;
            send_context_started_event(ctx);
            return 0;
        }
        trace(LOG_ALWAYS, "error: ptrace(PT_STEP, ...) failed: ctx %#lx, id %s, error %d %s",
            ctx, ctx->id, err, errno_to_str(err));
        errno = err;
        return -1;
    }
    EXT(ctx)->pending_step = 1;
    send_context_started_event(ctx);
    return 0;
}
Exemple #4
0
static int handle_breakpoint(struct task *task)
{
	struct breakpoint *bp = task->event.e_un.breakpoint;
	unsigned int hw = bp->hw;

	debug(DEBUG_EVENT, "+++ process pid=%d breakpoint  addr=%#lx", task->pid, bp->addr);

	assert(task->stopped);

	if (unlikely(options.verbose > 1))
		set_timer(&task->halt_time, hw ? &hw_bp_time : &sw_bp_time);

	if (unlikely(options.verbose))
		++bp->count;

	if (unlikely(task->skip_bp)) {
		struct breakpoint *skip_bp = task->skip_bp;

		task->skip_bp = NULL;

		breakpoint_put(skip_bp);

		if (likely(skip_bp == bp)) {
			skip_breakpoint(task, bp);
			goto end;
		}

		if (unlikely(options.verbose))
			fprintf(stderr, "!!!unhandled skip breakpoint for pid=%d\n", task->pid);
	}

	if (unlikely(bp->deleted)) {
		continue_task(task, 0);
		goto end;
	}

#if HW_BREAKPOINTS > 1
	if (bp->type >= BP_HW) {
		if (unlikely(++bp->hwcnt >= (BP_REORDER_THRESHOLD << hw))) {
			struct timespec start;

			if (unlikely(options.verbose > 1))
				start_time(&start);

			reorder_hw_bp(task);

			if (unlikely(options.verbose > 1))
				set_timer(&start, &reorder_time);
		}
	}
#endif

	if (bp->on_hit && bp->on_hit(task, bp)) {
		continue_task(task, 0);
		goto end;
	}

	if (likely(bp->libsym && !task->breakpoint)) {
		struct library_symbol *libsym = bp->libsym;

		save_param_context(task);

		if (libsym->func->report_out || !options.nocpp) {
			task->breakpoint = breakpoint_insert(task, get_return_addr(task), NULL, BP_HW_SCRATCH);
			if (likely(task->breakpoint)) {
				task->libsym = libsym;
				task->breakpoint->on_hit = handle_call_after;
#if HW_BREAKPOINTS > 0
				enable_scratch_hw_bp(task, task->breakpoint);
#endif
			}
		}

		if (libsym->func->report_in) {
			struct timespec start;

			if (unlikely(options.verbose > 1))
				start_time(&start);

			libsym->func->report_in(task, libsym);

			if (unlikely(options.verbose > 1))
				set_timer(&start, &report_in_time);
		}
	}

	if (task->bp_skipped)
		task->bp_skipped = 0;
	else
		skip_breakpoint(task, bp);
end:
	breakpoint_put(bp);
	return 0;
}
Exemple #5
0
int context_continue(Context * ctx) {
    int signal = 0;

    assert(is_dispatch_thread());
    assert(ctx->stopped);
    assert(!ctx->exited);
    assert(!ctx->pending_intercept);
    assert(!EXT(ctx)->pending_step);

    if (skip_breakpoint(ctx, 0)) return 0;

    if (!EXT(ctx)->syscall_enter) {
        unsigned n = 0;
        while (sigset_get_next(&ctx->pending_signals, &n)) {
            if (sigset_get(&ctx->sig_dont_pass, n)) {
                sigset_set(&ctx->pending_signals, n, 0);
            }
            else {
                signal = n;
                break;
            }
        }
        assert(signal != SIGSTOP);
        assert(signal != SIGTRAP);
    }

    trace(LOG_CONTEXT, "context: resuming ctx %#lx, id %s, with signal %d", ctx, ctx->id, signal);
#if defined(__i386__)
    if (EXT(ctx)->regs->__eflags & 0x100) {
        EXT(ctx)->regs->__eflags &= ~0x100;
        EXT(ctx)->regs_dirty = 1;
    }
#elif defined(__x86_64__)
    if (EXT(ctx)->regs->__rflags & 0x100) {
        EXT(ctx)->regs->__rflags &= ~0x100;
        EXT(ctx)->regs_dirty = 1;
    }
#endif
    if (EXT(ctx)->regs_dirty) {
        unsigned int state_count;
        if (thread_set_state(EXT(ctx)->pid, x86_THREAD_STATE32, EXT(ctx)->regs, &state_count) != KERN_SUCCESS) {
            int err = errno;
            trace(LOG_ALWAYS, "error: thread_set_state failed: ctx %#lx, id %s, error %d %s",
                ctx, ctx->id, err, errno_to_str(err));
            errno = err;
            return -1;
        }
        EXT(ctx)->regs_dirty = 0;
    }
    if (ptrace(PT_CONTINUE, EXT(ctx)->pid, 0, signal) < 0) {
        int err = errno;
        if (err == ESRCH) {
            send_context_started_event(ctx);
            return 0;
        }
        trace(LOG_ALWAYS, "error: ptrace(PT_CONTINUE, ...) failed: ctx %#lx, id %s, error %d %s",
            ctx, ctx->id, err, errno_to_str(err));
        errno = err;
        return -1;
    }
    sigset_set(&ctx->pending_signals, signal, 0);
    if (syscall_never_returns(ctx)) {
        EXT(ctx)->syscall_enter = 0;
        EXT(ctx)->syscall_exit = 0;
        EXT(ctx)->syscall_id = 0;
    }
    send_context_started_event(ctx);
    return 0;
}