Exemplo n.º 1
0
void send_event_memory_changed(Context * ctx, ContextAddress addr, unsigned long size) {
    OutputStream * out = &broadcast_group->out;

    if (!context_has_state(ctx) || is_intercepted(ctx)) {
        write_stringz(out, "E");
        write_stringz(out, MEMORY);
        write_stringz(out, "memoryChanged");

        json_write_string(out, ctx->id);
        write_stream(out, 0);

        /* <array of addres ranges> */
        write_stream(out, '[');
        write_stream(out, '{');

        json_write_string(out, "addr");
        write_stream(out, ':');
        json_write_uint64(out, addr);

        write_stream(out, ',');

        json_write_string(out, "size");
        write_stream(out, ':');
        json_write_ulong(out, size);

        write_stream(out, '}');
        write_stream(out, ']');
        write_stream(out, 0);

        write_stream(out, MARKER_EOM);
    }
}
Exemplo n.º 2
0
static void send_event_context_removed(OutputStream * out, Context * ctx) {
    write_stringz(out, "E");
    write_stringz(out, RUN_CONTROL);
    write_stringz(out, "contextRemoved");

    /* <array of context IDs> */
    write_stream(out, '[');
    if (context_has_state(ctx)) json_write_string(out, thread_id(ctx));
    if (ctx->parent == NULL && list_is_empty(&ctx->children)) {
        if (context_has_state(ctx)) write_stream(out, ',');
        json_write_string(out, container_id(ctx));
    }
    write_stream(out, ']');
    write_stream(out, 0);

    write_stream(out, MARKER_EOM);
}
Exemplo n.º 3
0
int context_can_resume(Context * ctx, int mode) {
    switch (mode) {
    case RM_RESUME:
        return 1;
    case RM_STEP_INTO:
    case RM_TERMINATE:
        return context_has_state(ctx);
    }
    return 0;
}
Exemplo n.º 4
0
int is_all_stopped(pid_t mem) {
    LINK * qp;
    for (qp = context_root.next; qp != &context_root; qp = qp->next) {
        Context * ctx = ctxl2ctxp(qp);
        if (ctx->exited || ctx->exiting) continue;
        if (!context_has_state(ctx)) continue;
        if (mem > 0 && ctx->mem != mem) continue;
        if (!ctx->stopped) return 0;
    }
    return are_channels_suspended(suspend_group);
}
Exemplo n.º 5
0
const char * frame2id(Context * ctx, int frame) {
    static char id[256];

    assert(frame >= 0);
    if (!context_has_state(ctx)) {
        errno = ERR_INV_CONTEXT;
        return NULL;
    }
    snprintf(id, sizeof(id), "FP%d.%s", frame, ctx->id);
    return id;
}
Exemplo n.º 6
0
static void command_get_children(char * token, Channel * c) {
    char id[256];

    json_read_string(&c->inp, id, sizeof(id));
    if (read_stream(&c->inp) != 0) exception(ERR_JSON_SYNTAX);
    if (read_stream(&c->inp) != MARKER_EOM) exception(ERR_JSON_SYNTAX);

    write_stringz(&c->out, "R");
    write_stringz(&c->out, token);

    write_errno(&c->out, 0);

    write_stream(&c->out, '[');
    if (id[0] == 0) {
        LINK * qp;
        int cnt = 0;
        for (qp = context_root.next; qp != &context_root; qp = qp->next) {
            Context * ctx = ctxl2ctxp(qp);
            if (ctx->exited) continue;
            if (ctx->parent != NULL) continue;
            if (cnt > 0) write_stream(&c->out, ',');
            json_write_string(&c->out, container_id(ctx));
            cnt++;
        }
    }
    else if (id[0] == 'P') {
        LINK * qp;
        int cnt = 0;
        pid_t ppd = 0;
        Context * parent = id2ctx(id);
        id2pid(id, &ppd);
        if (parent != NULL && parent->parent == NULL && ppd == 0) {
            if (!parent->exited && context_has_state(parent)) {
                if (cnt > 0) write_stream(&c->out, ',');
                json_write_string(&c->out, thread_id(parent));
                cnt++;
            }
            for (qp = parent->children.next; qp != &parent->children; qp = qp->next) {
                Context * ctx = cldl2ctxp(qp);
                assert(!ctx->exited);
                assert(ctx->parent == parent);
                if (cnt > 0) write_stream(&c->out, ',');
                json_write_string(&c->out,thread_id(ctx));
                cnt++;
            }
        }
    }
    write_stream(&c->out, ']');
    write_stream(&c->out, 0);

    write_stream(&c->out, MARKER_EOM);
}
Exemplo n.º 7
0
static void command_get_cache_client(void * x) {
    GetArgs * args = (GetArgs *)x;
    Channel * c  = cache_channel();
    Trap trap;

    bbf_pos = 0;
    if (set_trap(&trap)) {
        int frame = 0;
        Context * ctx = NULL;
        RegisterDefinition * reg_def = NULL;

        if (id2register(args->id, &ctx, &frame, &reg_def) < 0) exception(errno);
        if (ctx->exited) exception(ERR_ALREADY_EXITED);
        if ((ctx->reg_access & REG_ACCESS_RD_STOP) != 0) {
            check_all_stopped(ctx);
        }
        if ((ctx->reg_access & REG_ACCESS_RD_RUNNING) == 0) {
            if (!ctx->stopped && context_has_state(ctx))
                str_exception(ERR_IS_RUNNING, "Cannot read register if not stopped");
        }
        if (reg_def->size > bbf_len) {
            bbf_len += 0x100 + reg_def->size;
            bbf = (uint8_t *)loc_realloc(bbf, bbf_len);
        }

        bbf_pos = reg_def->size;
        memset(bbf, 0, reg_def->size);
        if (frame < 0 || is_top_frame(ctx, frame)) {
            if (context_read_reg(ctx, reg_def, 0, reg_def->size, bbf) < 0) exception(errno);
        }
        else {
            StackFrame * info = NULL;
            if (get_frame_info(ctx, frame, &info) < 0) exception(errno);
            if (read_reg_bytes(info, reg_def, 0, reg_def->size, bbf) < 0) exception(errno);
        }

        clear_trap(&trap);
    }

    cache_exit();

    write_stringz(&c->out, "R");
    write_stringz(&c->out, args->token);
    write_errno(&c->out, trap.error);
    json_write_binary(&c->out, bbf, bbf_pos);
    write_stream(&c->out, 0);
    write_stream(&c->out, MARKER_EOM);
}
Exemplo n.º 8
0
int context_read_reg(Context * ctx, RegisterDefinition * def, unsigned offs, unsigned size, void * buf) {
    ContextExtensionVxWorks * ext = EXT(ctx);

    assert(is_dispatch_thread());
    assert(context_has_state(ctx));
    assert(ctx->stopped);
    assert(!ctx->exited);
    assert(offs + size <= def->size);

    if (ext->regs_error) {
        set_error_report_errno(ext->regs_error);
        return -1;
    }
    memcpy(buf, (uint8_t *)ext->regs + def->offset + offs, size);
    return 0;
}
Exemplo n.º 9
0
static void send_event_context_changed(OutputStream * out, Context * ctx) {
    write_stringz(out, "E");
    write_stringz(out, RUN_CONTROL);
    write_stringz(out, "contextChanged");

    /* <array of context data> */
    write_stream(out, '[');
    if (ctx->parent == NULL) {
        write_context(out, ctx, 0);
    }
    if (context_has_state(ctx)) {
        if (ctx->parent == NULL) write_stream(out, ',');
        write_context(out, ctx, 1);
    }
    write_stream(out, ']');
    write_stream(out, 0);

    write_stream(out, MARKER_EOM);
}
Exemplo n.º 10
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;
}
Exemplo n.º 11
0
static void command_set_cache_client(void * x) {
    SetArgs * args = (SetArgs *)x;
    Channel * c  = cache_channel();
    int notify = 0;
    Trap trap;

    if (set_trap(&trap)) {
        int frame = 0;
        Context * ctx = NULL;
        RegisterDefinition * reg_def = NULL;

        if (id2register(args->id, &ctx, &frame, &reg_def) < 0) exception(errno);
        if (frame >= 0 && !is_top_frame(ctx, frame)) exception(ERR_INV_CONTEXT);
        if (ctx->exited) exception(ERR_ALREADY_EXITED);
        if ((ctx->reg_access & REG_ACCESS_WR_STOP) != 0) {
            check_all_stopped(ctx);
        }
        if ((ctx->reg_access & REG_ACCESS_WR_RUNNING) == 0) {
            if (!ctx->stopped && context_has_state(ctx))
                str_exception(ERR_IS_RUNNING, "Cannot write register if not stopped");
        }
        if ((size_t)args->data_len > reg_def->size) exception(ERR_INV_DATA_SIZE);
        if (args->data_len > 0) {
            if (context_write_reg(ctx, reg_def, 0, args->data_len, args->data) < 0) exception(errno);
            notify = 1;
        }
        clear_trap(&trap);
    }

    cache_exit();

    if (notify) send_event_register_changed(args->id);

    write_stringz(&c->out, "R");
    write_stringz(&c->out, args->token);
    write_errno(&c->out, trap.error);
    write_stream(&c->out, MARKER_EOM);

    loc_free(args->data);
}
Exemplo n.º 12
0
static void check_location_list(Location * locs, unsigned cnt, int setm) {
    unsigned pos;
    for (pos = 0; pos < cnt; pos++) {
        Location * loc = locs + pos;

        if (id2register(loc->id, &loc->ctx, &loc->frame, &loc->reg_def) < 0) exception(errno);
        if (loc->ctx->exited) exception(ERR_ALREADY_EXITED);
        if ((loc->ctx->reg_access & setm ? REG_ACCESS_WR_STOP : REG_ACCESS_RD_STOP) != 0) {
            check_all_stopped(loc->ctx);
        }
        if ((loc->ctx->reg_access & setm ? REG_ACCESS_WR_RUNNING : REG_ACCESS_RD_RUNNING) == 0) {
            if (!loc->ctx->stopped && context_has_state(loc->ctx))
                str_fmt_exception(ERR_IS_RUNNING, "Cannot %s register if not stopped", setm ? "write" : "read");
        }
        if (loc->offs + loc->size > loc->reg_def->size) exception(ERR_INV_DATA_SIZE);

        if (loc->frame < 0 || is_top_frame(loc->ctx, loc->frame)) continue;

        if (setm) exception(ERR_INV_CONTEXT);
        if (get_frame_info(loc->ctx, loc->frame, &loc->frame_info) < 0) exception(errno);
    }
}
Exemplo n.º 13
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;
}
Exemplo n.º 14
0
int context_single_step(Context * ctx) {
    ContextExtensionVxWorks * ext = EXT(ctx);
    VXDBG_CTX vxdbg_ctx;

    assert(is_dispatch_thread());
    assert(context_has_state(ctx));
    assert(ctx->parent != NULL);
    assert(ctx->stopped);
    assert(!ctx->exited);
    assert(taskIsStopped(ext->pid));

    trace(LOG_CONTEXT, "context: single step ctx %#lx, id %#x", ctx, ext->pid);

    if (ext->regs_dirty) {
        if (taskRegsSet(ext->pid, ext->regs) != OK) {
            int error = errno;
            trace(LOG_ALWAYS, "context: can't set regs ctx %#lx, id %#x: %s",
                    ctx, ext->pid, errno_to_str(error));
            return -1;
        }
        ext->regs_dirty = 0;
    }

    vxdbg_ctx.ctxId = ext->pid;
    vxdbg_ctx.ctxType = VXDBG_CTX_TASK;
    taskLock();
    if (vxdbgStep(vxdbg_clnt_id, &vxdbg_ctx, NULL, NULL) != OK) {
        int error = errno;
        taskUnlock();
        trace(LOG_ALWAYS, "context: can't step ctx %#lx, id %#x: %d",
                ctx, ext->pid, errno_to_str(error));
        return -1;
    }
    taskUnlock();
    send_context_started_event(ctx);
    return 0;
}
Exemplo n.º 15
0
int get_symbol_update_policy(const Symbol * sym, char ** id, int * policy) {
    assert(sym->magic == SYMBOL_MAGIC);
    *id = sym->ctx->id;
    *policy = context_has_state(sym->ctx) ? UPDATE_ON_EXE_STATE_CHANGES : UPDATE_ON_MEMORY_MAP_CHANGES;
    return 0;
}
Exemplo n.º 16
0
RegisterDefinition * get_PC_definition(Context * ctx) {
    if (!context_has_state(ctx)) return NULL;
    return pc_def;
}
Exemplo n.º 17
0
static void run_safe_events(void * arg) {
    LINK * qp;
    pid_t mem;

    if ((uintptr_t)arg != safe_event_generation) return;
    assert(safe_event_list != NULL);
    assert(are_channels_suspended(suspend_group));

    safe_event_pid_count = 0;
    mem = safe_event_list->mem;

    for (qp = context_root.next; qp != &context_root; qp = qp->next) {
        Context * ctx = ctxl2ctxp(qp);
        if (ctx->exited || ctx->exiting || ctx->stopped || !context_has_state(ctx)) {
            ctx->pending_safe_event = 0;
            continue;
        }
        if (mem > 0 && ctx->mem != mem) {
            ctx->pending_safe_event = 0;
            continue;
        }
        if (!ctx->pending_step || ctx->pending_safe_event >= STOP_ALL_MAX_CNT / 2) {
            if (context_stop(ctx) < 0) {
                int error = errno;
#ifdef _WRS_KERNEL
                if (error == S_vxdbgLib_INVALID_CTX) {
                    /* Most often this means that context has exited,
                     * but exit event is not delivered yet.
                     * Not an error. */
                    error = 0;
                }
#endif
                if (error) {
                    trace(LOG_ALWAYS, "error: can't temporary stop pid %d; error %d: %s",
                        ctx->pid, error, errno_to_str(error));
                }
            }
            assert(!ctx->stopped);
        }
        if (ctx->pending_safe_event >= STOP_ALL_MAX_CNT) {
            trace(LOG_ALWAYS, "error: can't temporary stop pid %d; error: timeout", ctx->pid);
            ctx->exiting = 1;
            ctx->pending_safe_event = 0;
        }
        else {
            ctx->pending_safe_event++;
            safe_event_pid_count++;
        }
    }

    while (safe_event_list) {
        Trap trap;
        SafeEvent * i = safe_event_list;
        assert((uintptr_t)arg == safe_event_generation);
        if (safe_event_pid_count > 0) {
            post_event_with_delay(run_safe_events, (void *)++safe_event_generation, STOP_ALL_TIMEOUT);
            return;
        }
        if (mem > 0 && i->mem != mem) {
            post_event(run_safe_events, (void *)++safe_event_generation);
            return;
        }
        assert(is_all_stopped(i->mem));
        safe_event_list = i->next;
        if (set_trap(&trap)) {
            i->done(i->arg);
            clear_trap(&trap);
        }
        else {
            trace(LOG_ALWAYS, "Unhandled exception in \"safe\" event dispatch: %d %s",
                  trap.error, errno_to_str(trap.error));
        }
        loc_free(i);
        if ((uintptr_t)arg != safe_event_generation) return;
    }

    channels_resume(suspend_group);
    cmdline_resume();
    /* Lazily continue execution of temporary stopped contexts */
    post_event(continue_temporary_stopped, (void *)safe_event_generation);
}