int context_stop(Context * ctx) { ContextExtensionVxWorks * ext = EXT(ctx); struct event_info * info; VXDBG_CTX vxdbg_ctx; assert(is_dispatch_thread()); assert(ctx->parent != NULL); assert(!ctx->stopped); assert(!ctx->exited); assert(!ext->regs_dirty); if (ctx->pending_intercept) { trace(LOG_CONTEXT, "context: stop ctx %#lx, id %#x", ctx, ext->pid); } else { trace(LOG_CONTEXT, "context: temporary stop ctx %#lx, id %#x", ctx, ext->pid); } taskLock(); if (taskIsStopped(ext->pid)) { /* Workaround for situation when a task was stopped without notifying TCF agent */ int n = 0; SPIN_LOCK_ISR_TAKE(&events_lock); n = events_cnt; SPIN_LOCK_ISR_GIVE(&events_lock); if (n > 0) { trace(LOG_CONTEXT, "context: already stopped ctx %#lx, id %#x", ctx, ext->pid); taskUnlock(); return 0; } } else { vxdbg_ctx.ctxId = ext->pid; vxdbg_ctx.ctxType = VXDBG_CTX_TASK; if (vxdbgStop(vxdbg_clnt_id, &vxdbg_ctx) != OK) { int error = errno; taskUnlock(); if (error == S_vxdbgLib_INVALID_CTX) return 0; trace(LOG_ALWAYS, "context: can't stop ctx %#lx, id %#x: %s", ctx, ext->pid, errno_to_str(error)); return -1; } } assert(taskIsStopped(ext->pid)); info = event_info_alloc(EVENT_HOOK_STOP); if (info != NULL) { info->stopped_ctx.ctxId = ext->pid; event_info_post(info); } taskUnlock(); return 0; }
int run_test_process(ContextAttachCallBack * done, void * data) { #if defined(WIN32) char fnm[FILE_PATH_SIZE]; char cmd[FILE_PATH_SIZE]; int res = 0; STARTUPINFO si; PROCESS_INFORMATION prs; ContextAttachArgs * args; memset(&si, 0, sizeof(si)); memset(&prs, 0, sizeof(prs)); memset(fnm, 0, sizeof(fnm)); if (GetModuleFileName(NULL, fnm, sizeof(fnm)) == 0) { set_win32_errno(GetLastError()); return -1; } si.cb = sizeof(si); strcpy(cmd, "agent.exe -t"); if (CreateProcess(fnm, cmd, NULL, NULL, FALSE, CREATE_SUSPENDED | CREATE_DEFAULT_ERROR_MODE | CREATE_NO_WINDOW, NULL, NULL, &si, &prs) == 0) { set_win32_errno(GetLastError()); return -1; } args = (ContextAttachArgs *)loc_alloc(sizeof(ContextAttachArgs)); args->done = done; args->data = data; args->thread = prs.hThread; args->process = prs.hProcess; res = context_attach(prs.dwProcessId, done_context_attach, args, 0); if (res != 0) loc_free(args); return res; #elif defined(_WRS_KERNEL) int tid = taskCreate("tTcf", 100, 0, 0x4000, (FUNCPTR)test_proc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); if (tid == 0) return -1; taskStop(tid); taskActivate(tid); assert(taskIsStopped(tid)); return context_attach(tid, done, data, 0); #else /* Create child process to debug */ int pid = fork(); if (pid < 0) return -1; if (pid == 0) { int fd; if (context_attach_self() < 0) exit(1); fd = sysconf(_SC_OPEN_MAX); while (fd-- > 2) close(fd); if (tkill(getpid(), SIGSTOP) < 0) exit(1); test_proc(); exit(0); } return context_attach(pid, done, data, CONTEXT_ATTACH_SELF); #endif }
int context_continue(Context * ctx) { ContextExtensionVxWorks * ext = EXT(ctx); VXDBG_CTX vxdbg_ctx; assert(is_dispatch_thread()); assert(ctx->parent != NULL); assert(ctx->stopped); assert(!ctx->pending_intercept); assert(!ctx->exited); assert(taskIsStopped(ext->pid)); trace(LOG_CONTEXT, "context: continue 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 (vxdbgCont(vxdbg_clnt_id, &vxdbg_ctx) != OK) { int error = errno; taskUnlock(); trace(LOG_ALWAYS, "context: can't continue ctx %#lx, id %#x: %s", ctx, ext->pid, errno_to_str(error)); return -1; } assert(!taskIsStopped(ext->pid)); taskUnlock(); send_context_started_event(ctx); return 0; }
static void event_attach_done(void * x) { AttachDoneArgs * args = (AttachDoneArgs *)x; if (context_find_from_pid(args->pid, 0) != NULL) { args->done(ERR_ALREADY_ATTACHED, NULL, args->data); } else { Context * ctx = NULL; if (parent_ctx == NULL) { pid_t pid = taskIdSelf(); parent_ctx = create_context(pid2id(pid, 0)); EXT(parent_ctx)->pid = pid; parent_ctx->mem = parent_ctx; parent_ctx->mem_access |= MEM_ACCESS_INSTRUCTION; parent_ctx->mem_access |= MEM_ACCESS_DATA; parent_ctx->big_endian = big_endian_host(); link_context(parent_ctx); send_context_created_event(parent_ctx); } assert(parent_ctx->ref_count > 0); ctx = create_context(pid2id(args->pid, EXT(parent_ctx)->pid)); EXT(ctx)->pid = args->pid; EXT(ctx)->regs = (REG_SET *)loc_alloc(sizeof(REG_SET)); ctx->mem = parent_ctx; ctx->big_endian = parent_ctx->big_endian; (ctx->parent = parent_ctx)->ref_count++; list_add_last(&ctx->cldl, &parent_ctx->children); link_context(ctx); trace(LOG_CONTEXT, "context: attached: ctx %#lx, id %#x", ctx, EXT(ctx)->pid); send_context_created_event(ctx); args->done(0, ctx, args->data); if (taskIsStopped(args->pid)) { struct event_info * info; ctx->pending_intercept = 1; info = event_info_alloc(EVENT_HOOK_STOP); if (info != NULL) { info->stopped_ctx.ctxId = args->pid; event_info_post(info); } } } loc_free(x); }
static int context_terminate(Context * ctx) { ContextExtensionVxWorks * ext = EXT(ctx); VXDBG_CTX vxdbg_ctx; assert(is_dispatch_thread()); assert(ctx->parent != NULL); assert(ctx->stopped); assert(!ctx->pending_intercept); assert(!ctx->exited); assert(taskIsStopped(ext->pid)); trace(LOG_CONTEXT, "context: terminate ctx %#lx, id %#x", ctx, ext->pid); if (ext->regs_dirty) { taskRegsSet(ext->pid, ext->regs); ext->regs_dirty = 0; } return kill_context(ctx); }
static void event_handler(void * arg) { struct event_info * info = (struct event_info *)arg; Context * current_ctx = context_find_from_pid(info->current_ctx.ctxId, 1); Context * stopped_ctx = context_find_from_pid(info->stopped_ctx.ctxId, 1); switch (info->event) { case EVENT_HOOK_BREAKPOINT: if (stopped_ctx == NULL) break; assert(!stopped_ctx->stopped); assert(!EXT(stopped_ctx)->regs_dirty); if (EXT(stopped_ctx)->regs_error) { release_error_report(EXT(stopped_ctx)->regs_error); EXT(stopped_ctx)->regs_error = NULL; } memcpy(EXT(stopped_ctx)->regs, &info->regs, sizeof(REG_SET)); EXT(stopped_ctx)->event = 0; stopped_ctx->signal = SIGTRAP; stopped_ctx->stopped = 1; stopped_ctx->stopped_by_bp = info->bp_info_ok; stopped_ctx->stopped_by_exception = 0; assert(get_regs_PC(stopped_ctx) == info->addr); if (stopped_ctx->stopped_by_bp && !is_breakpoint_address(stopped_ctx, info->addr)) { /* Break instruction that is not planted by us */ stopped_ctx->stopped_by_bp = 0; stopped_ctx->pending_intercept = 1; } EXT(stopped_ctx)->bp_info = info->bp_info; if (current_ctx != NULL) EXT(stopped_ctx)->bp_pid = EXT(current_ctx)->pid; assert(taskIsStopped(EXT(stopped_ctx)->pid)); trace(LOG_CONTEXT, "context: stopped by breakpoint: ctx %#lx, id %#x", stopped_ctx, EXT(stopped_ctx)->pid); send_context_stopped_event(stopped_ctx); break; case EVENT_HOOK_STEP_DONE: if (current_ctx == NULL) break; assert(!current_ctx->stopped); assert(!EXT(current_ctx)->regs_dirty); if (EXT(current_ctx)->regs_error) { release_error_report(EXT(current_ctx)->regs_error); EXT(current_ctx)->regs_error = NULL; } memcpy(EXT(current_ctx)->regs, &info->regs, sizeof(REG_SET)); EXT(current_ctx)->event = TRACE_EVENT_STEP; current_ctx->signal = SIGTRAP; current_ctx->stopped = 1; current_ctx->stopped_by_bp = 0; current_ctx->stopped_by_exception = 0; assert(taskIsStopped(EXT(current_ctx)->pid)); trace(LOG_CONTEXT, "context: stopped by end of step: ctx %#lx, id %#x", current_ctx, EXT(current_ctx)->pid); send_context_stopped_event(current_ctx); break; case EVENT_HOOK_STOP: if (stopped_ctx == NULL) break; assert(!stopped_ctx->exited); if (stopped_ctx->stopped) break; if (EXT(stopped_ctx)->regs_error) { release_error_report(EXT(stopped_ctx)->regs_error); EXT(stopped_ctx)->regs_error = NULL; } if (taskRegsGet(EXT(stopped_ctx)->pid, EXT(stopped_ctx)->regs) != OK) { EXT(stopped_ctx)->regs_error = get_error_report(errno); assert(EXT(stopped_ctx)->regs_error != NULL); } EXT(stopped_ctx)->event = 0; stopped_ctx->signal = SIGSTOP; stopped_ctx->stopped = 1; stopped_ctx->stopped_by_bp = 0; stopped_ctx->stopped_by_exception = 0; assert(taskIsStopped(EXT(stopped_ctx)->pid)); trace(LOG_CONTEXT, "context: stopped by sofware request: ctx %#lx, id %#x", stopped_ctx, EXT(stopped_ctx)->pid); send_context_stopped_event(stopped_ctx); break; case EVENT_HOOK_TASK_ADD: if (current_ctx == NULL) break; assert(stopped_ctx == NULL); stopped_ctx = create_context(pid2id((pid_t)info->stopped_ctx.ctxId, EXT(current_ctx->parent)->pid)); EXT(stopped_ctx)->pid = (pid_t)info->stopped_ctx.ctxId; EXT(stopped_ctx)->regs = (REG_SET *)loc_alloc(sizeof(REG_SET)); stopped_ctx->mem = current_ctx->mem; stopped_ctx->big_endian = current_ctx->mem->big_endian; (stopped_ctx->creator = current_ctx)->ref_count++; (stopped_ctx->parent = current_ctx->parent)->ref_count++; assert(stopped_ctx->mem == stopped_ctx->parent->mem); list_add_last(&stopped_ctx->cldl, &stopped_ctx->parent->children); link_context(stopped_ctx); trace(LOG_CONTEXT, "context: created: ctx %#lx, id %#x", stopped_ctx, EXT(stopped_ctx)->pid); send_context_created_event(stopped_ctx); break; default: assert(0); break; } loc_free(info); SPIN_LOCK_ISR_TAKE(&events_lock); events_cnt--; SPIN_LOCK_ISR_GIVE(&events_lock); }
static int start_process(Channel * c, char ** envp, char * dir, char * exe, char ** args, int attach, int * pid, int * selfattach, ChildProcess ** prs) { int err = 0; char * ptr; SYM_TYPE type; if (symFindByName(sysSymTbl, exe, &ptr, &type) != OK) { err = errno; if (err == S_symLib_SYMBOL_NOT_FOUND) err = ERR_SYM_NOT_FOUND; assert(err != 0); } else { int i; int pipes[2][2]; /* TODO: arguments, environment */ *pid = taskCreate("tTcf", 100, 0, 0x4000, (FUNCPTR)ptr, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); for (i = 0; i < 2; i++) { char pnm[32]; char pnm_m[32]; char pnm_s[32]; snprintf(pnm, sizeof(pnm), "/pty/tcf-%0*lx-%d", sizeof(*pid) * 2, *pid, i); snprintf(pnm_m, sizeof(pnm_m), "%sM", pnm); snprintf(pnm_s, sizeof(pnm_m), "%sS", pnm); if (ptyDevCreate(pnm, PIPE_SIZE, PIPE_SIZE) == ERROR) { err = errno; break; } pipes[i][0] = open(pnm_m, O_RDWR, 0); pipes[i][1] = open(pnm_s, O_RDWR, 0); if (pipes[i][0] < 0 || pipes[i][1] < 0) { err = errno; break; } } if (err) { taskDelete(*pid); *pid = 0; } else { semTake(prs_list_lock, WAIT_FOREVER); ioTaskStdSet(*pid, 0, pipes[0][1]); ioTaskStdSet(*pid, 1, pipes[0][1]); ioTaskStdSet(*pid, 2, pipes[1][1]); *prs = loc_alloc_zero(sizeof(ChildProcess)); (*prs)->inp = pipes[0][0]; (*prs)->out = pipes[0][0]; (*prs)->err = pipes[1][0]; (*prs)->pid = *pid; (*prs)->bcg = c->bcg; list_add_first(&(*prs)->link, &prs_list); if (attach) { taskStop(*pid); taskActivate(*pid); assert(taskIsStopped(*pid)); } else { taskActivate(*pid); } semGive(prs_list_lock); } } if (!err) return 0; errno = err; return -1; }