Exemple #1
0
/**
 * Registers a new thread to the runtime system. This includes
 * initialization of the hardware performance counters
 */
void rec_sched_register_thread(pid_t parent, pid_t child, int flags)
{
	struct tasklist_entry* entry = sys_malloc_zero(sizeof(*entry));
	struct task* t = &entry->t;

	assert(child > 0 && child < MAX_TID);

	t->status = 0;
	t->rec_tid = t->tid = child;
	t->child_mem_fd = sys_open_child_mem(child);
	push_placeholder_event(t);
	if (parent) {
		struct task* parent_t = get_task(parent);
		struct sighandlers* parent_handlers = parent_t->sighandlers;

		t->syscallbuf_lib_start = parent_t->syscallbuf_lib_start;
		t->syscallbuf_lib_end = parent_t->syscallbuf_lib_end;
		t->task_group =
			(SHARE_TASK_GROUP & flags) ?
			task_group_add_and_ref(parent_t->task_group, t) :
			task_group_new_and_add(t);
		t->sighandlers = (SHARE_SIGHANDLERS & flags) ?
				 sighandlers_ref(parent_handlers) :
				 sighandlers_copy(parent_handlers);
	} else {
		/* After the first task is forked, we always need to
		 * know the parent in order to initialize some task
		 * state. */
		static int is_first_task = 1;
		assert(is_first_task);
		is_first_task = 0;
		t->task_group = task_group_new_and_add(t);
		/* The very first task we fork inherits our
		 * sighandlers (which should all be default at this
		 * point, but ...).  From there on, new tasks will
		 * transitively inherit from this first task.  */
		t->sighandlers = sighandlers_new();
		sighandlers_init_from_current_process(t->sighandlers);
	}
	/* These will be initialized when the syscall buffer is. */
	t->desched_fd = t->desched_fd_child = -1;

	sys_ptrace_setup(child);

	init_hpc(t);
	start_hpc(t, rr_flags()->max_rbc);

	CIRCLEQ_INSERT_TAIL(&head, entry, entries);
	num_active_threads++;

	tid_to_entry[child] = entry;
}
Exemple #2
0
static void set_sw_breakpoint(struct context *ctx,
			      const struct dbg_request* req)
{
	struct breakpoint* bp = sys_malloc_zero(sizeof(*bp));
	byte* orig_data_ptr;

	assert(sizeof(int_3_insn) == req->mem.len);

	bp->addr = req->mem.addr;

	orig_data_ptr = read_child_data(ctx, 1, bp->addr);
	bp->overwritten_data = *orig_data_ptr;
	sys_free((void**)&orig_data_ptr);

	write_child_data_n(ctx->child_tid,
			   sizeof(int_3_insn), bp->addr, &int_3_insn);

	add_breakpoint(bp);
}
Exemple #3
0
struct dbg_context* dbg_await_client_connection(const char* address, short port)
{
    struct dbg_context* dbg;
    int listen_fd;
    int reuseaddr;
    int autoprobe;
    struct sockaddr_in client_addr;
    int ret;
    socklen_t len;
    int flags;

#ifdef REDIRECT_DEBUGLOG
    out = fopen("/tmp/rr.debug.log", "w");
#endif

    dbg = sys_malloc_zero(sizeof(*dbg));
    dbg->insize = sizeof(dbg->inbuf);
    dbg->outsize = sizeof(dbg->outbuf);

    listen_fd = socket(AF_INET, SOCK_STREAM, 0);
    dbg->addr.sin_family = AF_INET;
    dbg->addr.sin_addr.s_addr = inet_addr(address);
    reuseaddr = 1;
    setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR,
               &reuseaddr, sizeof(reuseaddr));

    if (port <= 0) {
        autoprobe = 1;
        port = getpid();
    } else {
        autoprobe = 0;
    }
    do {
        dbg->addr.sin_port = htons(port);
        ret = bind(listen_fd,
                   (struct sockaddr*)&dbg->addr, sizeof(dbg->addr));
        if (ret == EADDRINUSE) {
            continue;
        } else if (ret != 0) {
            break;
        }
        ret = listen(listen_fd, 1/*backlogged connection*/);
        if (ret == 0 || ret != EADDRINUSE) {
            break;
        }
    } while (++port, autoprobe);
    if (ret) {
        fatal("Couldn't bind to server address");
    }
    log_info("(rr debug server listening on %s:%d)",
             !strcmp(address, "127.0.0.1") ? "" : address,
             ntohs(dbg->addr.sin_port));
    /* block until debugging client connects to us */
    len = sizeof(client_addr);
    dbg->fd = accept(listen_fd, (struct sockaddr*)&client_addr, &len);

    if (-1 == (flags = fcntl(dbg->fd, F_GETFD))) {
        fatal("Can't GETFD flags");
    }
    if (fcntl(dbg->fd, F_SETFD, flags | FD_CLOEXEC)) {
        fatal("Can't make client socket CLOEXEC");
    }
    if (fcntl(dbg->fd, F_SETFL, O_NONBLOCK)) {
        fatal("Can't make client socket NONBLOCK");
    }
    return dbg;
}