/* argv[1]: serial name, e.g.: /dev/ttyUSB0 argv[2]: serial bps, e.g.: 9600 argv[3]: display data mode, BM: binary mode, CM: character mode */ int main(int argc, char **argv) { int fp; if (-1 == sig_proc()) { printf("error sig set\n"); return -1; } fp = serial_init(argc, argv); if (fp == -1) { printf("error open\n"); return -1; } int cnt = 0; while (0 == exit_main) { unsigned char wv = cnt; char str[] = "abcdEf\r\n"; char rstr[32]; unsigned char rv; int len; len = strlen(str); int w = serial_write(str, len); if (w < 0) { printf("write error"); break; } //printf("write ok\n"); int r = serial_read(rstr, 32); if (r > 0) { //printf("%.2X\n", rv); serial_display(&rstr, r); } else { printf("dont recv\n"); break; } //printf("sleep\n"); sleep(1); cnt++; } serail_close(); printf("\nexit\n"); return 0; }
/*===========================================================================* * do_trace * *===========================================================================*/ PUBLIC int do_trace() { register struct mproc *child; /* the T_OK call is made by the child fork of the debugger before it execs * the process to be traced */ if (m_in.request == T_OK) { /* enable tracing by parent for this proc */ mp->mp_flags |= TRACED; mp->mp_reply.reply_trace = 0; return(OK); } if ((child=find_proc(m_in.pid))==NIL_MPROC || !(child->mp_flags & STOPPED)) { return(ESRCH); } /* all the other calls are made by the parent fork of the debugger to * control execution of the child */ switch (m_in.request) { case T_EXIT: /* exit */ pm_exit(child, (int) m_in.data); mp->mp_reply.reply_trace = 0; return(OK); case T_RESUME: case T_STEP: /* resume execution */ if (m_in.data < 0 || m_in.data > _NSIG) return(EIO); if (m_in.data > 0) { /* issue signal */ child->mp_flags &= ~TRACED; /* so signal is not diverted */ sig_proc(child, (int) m_in.data); child->mp_flags |= TRACED; } child->mp_flags &= ~STOPPED; break; } if (sys_trace(m_in.request,(int)(child-mproc),m_in.taddr,&m_in.data) != OK) return(-errno); mp->mp_reply.reply_trace = m_in.data; return(OK); }
/*===========================================================================* * do_fork * *===========================================================================*/ PUBLIC int do_fork() { /* The process pointed to by 'mp' has forked. Create a child process. */ register struct mproc *rmp; /* pointer to parent */ register struct mproc *rmc; /* pointer to child */ pid_t new_pid; static int next_child; int i, n = 0, s; endpoint_t child_ep; message m; /* If tables might fill up during FORK, don't even start since recovery half * way through is such a nuisance. */ rmp = mp; if ((procs_in_use == NR_PROCS) || (procs_in_use >= NR_PROCS-LAST_FEW && rmp->mp_effuid != 0)) { printf("PM: warning, process table is full!\n"); return(EAGAIN); } /* Find a slot in 'mproc' for the child process. A slot must exist. */ do { next_child = (next_child+1) % NR_PROCS; n++; } while((mproc[next_child].mp_flags & IN_USE) && n <= NR_PROCS); if(n > NR_PROCS) panic("do_fork can't find child slot"); if(next_child < 0 || next_child >= NR_PROCS || (mproc[next_child].mp_flags & IN_USE)) panic("do_fork finds wrong child slot: %d", next_child); /* Memory part of the forking. */ if((s=vm_fork(rmp->mp_endpoint, next_child, &child_ep)) != OK) { printf("PM: vm_fork failed: %d\n", s); return s; } /* PM may not fail fork after call to vm_fork(), as VM calls sys_fork(). */ rmc = &mproc[next_child]; /* Set up the child and its memory map; copy its 'mproc' slot from parent. */ procs_in_use++; *rmc = *rmp; /* copy parent's process slot to child's */ rmc->mp_parent = who_p; /* record child's parent */ if (!(rmc->mp_trace_flags & TO_TRACEFORK)) { rmc->mp_tracer = NO_TRACER; /* no tracer attached */ rmc->mp_trace_flags = 0; (void) sigemptyset(&rmc->mp_sigtrace); } /* Some system servers like to call regular fork, such as RS spawning * recovery scripts; in this case PM will take care of their scheduling * because RS cannot do so for non-system processes */ if (rmc->mp_flags & PRIV_PROC) { assert(rmc->mp_scheduler == NONE); rmc->mp_scheduler = SCHED_PROC_NR; } /* Inherit only these flags. In normal fork(), PRIV_PROC is not inherited. */ rmc->mp_flags &= (IN_USE|DELAY_CALL); rmc->mp_child_utime = 0; /* reset administration */ rmc->mp_child_stime = 0; /* reset administration */ rmc->mp_exitstatus = 0; rmc->mp_sigstatus = 0; rmc->mp_endpoint = child_ep; /* passed back by VM */ for (i = 0; i < NR_ITIMERS; i++) rmc->mp_interval[i] = 0; /* reset timer intervals */ /* Find a free pid for the child and put it in the table. */ new_pid = get_free_pid(); rmc->mp_pid = new_pid; /* assign pid to child */ m.m_type = PM_FORK; m.PM_PROC = rmc->mp_endpoint; m.PM_PPROC = rmp->mp_endpoint; m.PM_CPID = rmc->mp_pid; tell_vfs(rmc, &m); /* Tell the tracer, if any, about the new child */ if (rmc->mp_tracer != NO_TRACER) sig_proc(rmc, SIGSTOP, TRUE /*trace*/, FALSE /* ksig */); /* Do not reply until VFS is ready to process the fork * request */ return SUSPEND; }
/*===========================================================================* * do_srv_fork * *===========================================================================*/ PUBLIC int do_srv_fork() { /* The process pointed to by 'mp' has forked. Create a child process. */ register struct mproc *rmp; /* pointer to parent */ register struct mproc *rmc; /* pointer to child */ int s; pid_t new_pid; static int next_child; int i, n = 0; endpoint_t child_ep; message m; /* Only RS is allowed to use srv_fork. */ if (mp->mp_endpoint != RS_PROC_NR) return EPERM; /* If tables might fill up during FORK, don't even start since recovery half * way through is such a nuisance. */ rmp = mp; if ((procs_in_use == NR_PROCS) || (procs_in_use >= NR_PROCS-LAST_FEW && rmp->mp_effuid != 0)) { printf("PM: warning, process table is full!\n"); return(EAGAIN); } /* Find a slot in 'mproc' for the child process. A slot must exist. */ do { next_child = (next_child+1) % NR_PROCS; n++; } while((mproc[next_child].mp_flags & IN_USE) && n <= NR_PROCS); if(n > NR_PROCS) panic("do_fork can't find child slot"); if(next_child < 0 || next_child >= NR_PROCS || (mproc[next_child].mp_flags & IN_USE)) panic("do_fork finds wrong child slot: %d", next_child); if((s=vm_fork(rmp->mp_endpoint, next_child, &child_ep)) != OK) { printf("PM: vm_fork failed: %d\n", s); return s; } rmc = &mproc[next_child]; /* Set up the child and its memory map; copy its 'mproc' slot from parent. */ procs_in_use++; *rmc = *rmp; /* copy parent's process slot to child's */ rmc->mp_parent = who_p; /* record child's parent */ if (!(rmc->mp_trace_flags & TO_TRACEFORK)) { rmc->mp_tracer = NO_TRACER; /* no tracer attached */ rmc->mp_trace_flags = 0; (void) sigemptyset(&rmc->mp_sigtrace); } /* inherit only these flags */ rmc->mp_flags &= (IN_USE|PRIV_PROC|DELAY_CALL); rmc->mp_child_utime = 0; /* reset administration */ rmc->mp_child_stime = 0; /* reset administration */ rmc->mp_exitstatus = 0; rmc->mp_sigstatus = 0; rmc->mp_endpoint = child_ep; /* passed back by VM */ for (i = 0; i < NR_ITIMERS; i++) rmc->mp_interval[i] = 0; /* reset timer intervals */ /* Find a free pid for the child and put it in the table. */ new_pid = get_free_pid(); rmc->mp_pid = new_pid; /* assign pid to child */ m.m_type = PM_SRV_FORK; m.PM_PROC = rmc->mp_endpoint; m.PM_PPROC = rmp->mp_endpoint; m.PM_CPID = rmc->mp_pid; tell_vfs(rmc, &m); /* Tell the tracer, if any, about the new child */ if (rmc->mp_tracer != NO_TRACER) sig_proc(rmc, SIGSTOP, TRUE /*trace*/, FALSE /* ksig */); /* Wakeup the newly created process */ setreply(rmc-mproc, OK); return rmc->mp_pid; }
/*===========================================================================* * do_trace * *===========================================================================*/ PUBLIC int do_trace() { register struct mproc *child; struct ptrace_range pr; int i, r, seg, req; req = m_in.request; /* The T_OK call is made by the child fork of the debugger before it execs * the process to be traced. The T_ATTACH call is made by the debugger itself * to attach to an existing process. */ switch (req) { case T_OK: /* enable tracing by parent for this proc */ if (mp->mp_tracer != NO_TRACER) return(EBUSY); mp->mp_tracer = mp->mp_parent; mp->mp_reply.reply_trace = 0; return(OK); case T_ATTACH: /* attach to an existing process */ if ((child = find_proc(m_in.pid)) == NULL) return(ESRCH); if (child->mp_flags & EXITING) return(ESRCH); /* For non-root processes, user and group ID must match. */ if (mp->mp_effuid != SUPER_USER && (mp->mp_effuid != child->mp_effuid || mp->mp_effgid != child->mp_effgid || child->mp_effuid != child->mp_realuid || child->mp_effgid != child->mp_realgid)) return(EPERM); /* Only root may trace system servers. */ if (mp->mp_effuid != SUPER_USER && (child->mp_flags & PRIV_PROC)) return(EPERM); /* System servers may not trace anyone. They can use sys_trace(). */ if (mp->mp_flags & PRIV_PROC) return(EPERM); /* Can't trace self, PM or VM. */ if (child == mp || child->mp_endpoint == PM_PROC_NR || child->mp_endpoint == VM_PROC_NR) return(EPERM); /* Can't trace a process that is already being traced. */ if (child->mp_tracer != NO_TRACER) return(EBUSY); child->mp_tracer = who_p; child->mp_trace_flags = TO_NOEXEC; sig_proc(child, SIGSTOP, TRUE /*trace*/, FALSE /* ksig */); mp->mp_reply.reply_trace = 0; return(OK); case T_STOP: /* stop the process */ /* This call is not exposed to user programs, because its effect can be * achieved better by sending the traced process a signal with kill(2). */ return(EINVAL); case T_READB_INS: /* special hack for reading text segments */ if (mp->mp_effuid != SUPER_USER) return(EPERM); if ((child = find_proc(m_in.pid)) == NULL) return(ESRCH); if (child->mp_flags & EXITING) return(ESRCH); r = sys_trace(req, child->mp_endpoint, m_in.PMTRACE_ADDR, &m_in.data); if (r != OK) return(r); mp->mp_reply.reply_trace = m_in.data; return(OK); case T_WRITEB_INS: /* special hack for patching text segments */ if (mp->mp_effuid != SUPER_USER) return(EPERM); if ((child = find_proc(m_in.pid)) == NULL) return(ESRCH); if (child->mp_flags & EXITING) return(ESRCH); #if 0 /* Should check for shared text */ /* Make sure the text segment is not used as a source for shared * text. */ child->mp_ino = 0; child->mp_dev = 0; child->mp_ctime = 0; #endif r = sys_trace(req, child->mp_endpoint, m_in.PMTRACE_ADDR, &m_in.data); if (r != OK) return(r); mp->mp_reply.reply_trace = m_in.data; return(OK); } /* All the other calls are made by the tracing process to control execution * of the child. For all these calls, the child must be stopped. */ if ((child = find_proc(m_in.pid)) == NULL) return(ESRCH); if (child->mp_flags & EXITING) return(ESRCH); if (child->mp_tracer != who_p) return(ESRCH); if (!(child->mp_flags & STOPPED)) return(EBUSY); switch (req) { case T_EXIT: /* exit */ child->mp_flags |= TRACE_EXIT; /* Defer the exit if the traced process has an VFS call pending. */ if (child->mp_flags & VFS_CALL) child->mp_exitstatus = (int) m_in.data; /* save for later */ else exit_proc(child, (int) m_in.data, FALSE /*dump_core*/); /* Do not reply to the caller until VFS has processed the exit * request. */ return(SUSPEND); case T_SETOPT: /* set trace options */ child->mp_trace_flags = m_in.data; mp->mp_reply.reply_trace = 0; return(OK); case T_GETRANGE: case T_SETRANGE: /* get/set range of values */ r = sys_datacopy(who_e, (vir_bytes) m_in.PMTRACE_ADDR, SELF, (vir_bytes) &pr, (phys_bytes) sizeof(pr)); if (r != OK) return(r); if (pr.pr_space != TS_INS && pr.pr_space != TS_DATA) return(EINVAL); if (pr.pr_size == 0 || pr.pr_size > LONG_MAX) return(EINVAL); seg = (pr.pr_space == TS_INS) ? T : D; if (req == T_GETRANGE) r = sys_vircopy(child->mp_endpoint, seg, (vir_bytes) pr.pr_addr, who_e, D, (vir_bytes) pr.pr_ptr, (phys_bytes) pr.pr_size); else r = sys_vircopy(who_e, D, (vir_bytes) pr.pr_ptr, child->mp_endpoint, seg, (vir_bytes) pr.pr_addr, (phys_bytes) pr.pr_size); if (r != OK) return(r); mp->mp_reply.reply_trace = 0; return(OK); case T_DETACH: /* detach from traced process */ if (m_in.data < 0 || m_in.data >= _NSIG) return(EINVAL); child->mp_tracer = NO_TRACER; /* Let all tracer-pending signals through the filter. */ for (i = 1; i < _NSIG; i++) { if (sigismember(&child->mp_sigtrace, i)) { (void) sigdelset(&child->mp_sigtrace, i); check_sig(child->mp_pid, i, FALSE /* ksig */); } } if (m_in.data > 0) { /* issue signal */ sig_proc(child, (int) m_in.data, TRUE /*trace*/, FALSE /* ksig */); } /* Resume the child as if nothing ever happened. */ child->mp_flags &= ~STOPPED; child->mp_trace_flags = 0; check_pending(child); break; case T_RESUME: case T_STEP: case T_SYSCALL: /* resume execution */ if (m_in.data < 0 || m_in.data >= _NSIG) return(EINVAL); if (m_in.data > 0) { /* issue signal */ sig_proc(child, (int) m_in.data, FALSE /*trace*/, FALSE /* ksig */); } /* If there are any other signals waiting to be delivered, * feign a successful resumption. */ for (i = 1; i < _NSIG; i++) { if (sigismember(&child->mp_sigtrace, i)) { mp->mp_reply.reply_trace = 0; return(OK); } } child->mp_flags &= ~STOPPED; check_pending(child); break; } r = sys_trace(req, child->mp_endpoint, m_in.PMTRACE_ADDR, &m_in.data); if (r != OK) return(r); mp->mp_reply.reply_trace = m_in.data; return(OK); }