From: Ben Gras Date: Fri, 15 Jun 2012 00:38:00 +0000 (+0200) Subject: dumpcore: use ptrace function to trigger a coredump X-Git-Tag: v3.2.1~543 X-Git-Url: http://zhaoyanbai.com/repos/%22http:/www.isc.org/icons/soc.html?a=commitdiff_plain;h=85ff5a947e4f03ff5402ba4a512617b5c6c40ae6;p=minix.git dumpcore: use ptrace function to trigger a coredump . dumpcore currently relies on minix segments . also ptrace dumpcore fix --- diff --git a/commands/dumpcore/dumpcore.c b/commands/dumpcore/dumpcore.c index a33f13250..ca6b70bc6 100644 --- a/commands/dumpcore/dumpcore.c +++ b/commands/dumpcore/dumpcore.c @@ -20,172 +20,6 @@ #define CLICK_WORDS (CLICK_SIZE / sizeof(unsigned long)) -int adjust_stack(pid_t pid, struct mem_map *seg) -{ - static unsigned long buf[CLICK_WORDS]; - struct ptrace_range pr; - size_t off, top, bottom; - int i; - - /* FIXME: kernel/VM strangeness */ - seg->mem_vir -= seg->mem_len - 1; - - /* Scan the stack, top to bottom, to find the lowest accessible region. - * In practice that will be at 64MB, so we also scan for the lowest non-zero - * region in order to keep the core file size managable. - * Portability note: this code assumes that the stack grows down. - */ - top = seg->mem_vir + seg->mem_len; - - pr.pr_space = TS_DATA; - pr.pr_addr = (top - 1) << CLICK_SHIFT; - pr.pr_size = sizeof(buf); - pr.pr_ptr = buf; - - for (off = top - 1; off >= seg->mem_vir; off--) { - if (ptrace(T_GETRANGE, pid, (long) &pr, 0)) { - if (errno == EFAULT) - break; - - perror("ptrace(T_GETRANGE)"); - return 1; - } - - for (i = 0; i < CLICK_WORDS; i += sizeof(buf[0])) - if (buf[i] != 0) - bottom = off; - - pr.pr_addr -= sizeof(buf); - } - - /* Add one extra zero page as margin. */ - if (bottom > off && bottom > seg->mem_vir) - bottom--; - - seg->mem_len -= bottom - seg->mem_vir; - seg->mem_vir = bottom; - - return 0; -} - -int write_seg(int fd, pid_t pid, int seg, off_t seg_off, phys_bytes seg_bytes) -{ - ssize_t w; - static char buf[CLICK_SIZE]; - struct ptrace_range pr; - - pr.pr_space = (seg == T) ? TS_INS : TS_DATA; - pr.pr_addr = seg_off; - pr.pr_size = sizeof(buf); - pr.pr_ptr = buf; - - for ( ; pr.pr_addr < seg_off + seg_bytes; pr.pr_addr += sizeof(buf)) - { - /* Copy a chunk from user space to the block buffer. */ - if (ptrace(T_GETRANGE, pid, (long) &pr, 0)) { - /* Create holes for inaccessible areas. */ - if (errno == EFAULT) { - lseek(fd, sizeof(buf), SEEK_CUR); - continue; - } - - perror("ptrace(T_GETRANGE)"); - return 1; - } - - if((w=write(fd, buf, sizeof(buf))) != sizeof(buf)) { - if(w < 0) printf("write error: %s\n", strerror(errno)); - printf("write_seg: write failed: %d/%d\n", w, sizeof(buf)); - return 1; - } - } - - return 0; -} - -int dumpcore(pid_t pid) -{ - int r, seg, fd; - vir_bytes len; - off_t off, seg_off; - long data; - struct mem_map segs[NR_LOCAL_SEGS]; - struct proc procentry; - ssize_t w; - char core_name[PATH_MAX]; - - /* Get the process table entry for this process. */ - len = sizeof(struct proc) / sizeof(long); - for (off = 0; off < len; off++) - { - errno = 0; - data = ptrace(T_GETUSER, pid, off * sizeof(long), 0); - if (data == -1 && errno != 0) - { - perror("ptrace(T_GETUSER)"); - return 1; - } - - ((long *) &procentry)[off] = data; - } - - memcpy(segs, procentry.p_memmap, sizeof(segs)); - - /* Correct and reduce the stack segment. */ - r = adjust_stack(pid, &segs[S]); - if (r != 0) - goto error; - - /* Create a core file with a temporary, unique name. */ - sprintf(core_name, "core.%d", pid); - - if((fd = open(core_name, O_CREAT|O_EXCL|O_WRONLY, 0600)) < 0) { - fprintf(stderr, "couldn't open %s (%s)\n", core_name, - strerror(errno)); - return 1; - } - - /* Write out the process's segments. */ - if((w=write(fd, segs, sizeof(segs))) != sizeof(segs)) { - if(w < 0) printf("write error: %s\n", strerror(errno)); - printf( "segs write failed: %d/%d\n", w, sizeof(segs)); - goto error; - } - - /* Write out the whole kernel process table entry to get the regs. */ - if((w=write(fd, &procentry, sizeof(procentry))) != sizeof(procentry)) { - if(w < 0) printf("write error: %s\n", strerror(errno)); - printf( "proc write failed: %d/%d\n", w, sizeof(procentry)); - goto error; - } - - /* Loop through segments and write the segments themselves out. */ - for (seg = 0; seg < NR_LOCAL_SEGS; seg++) { - len= segs[seg].mem_len << CLICK_SHIFT; - seg_off= segs[seg].mem_vir << CLICK_SHIFT; - r= write_seg(fd, pid, seg, seg_off, len); - if (r != 0) - goto error; - } - - /* Give the core file its final name. */ - if (rename(core_name, "core")) { - perror("rename"); - goto error; - } - - close(fd); - - return 0; - -error: - close(fd); - - unlink(core_name); - - return 1; -} - int main(int argc, char *argv[]) { pid_t pid; @@ -223,7 +57,10 @@ int main(int argc, char *argv[]) return 1; } - r = dumpcore(pid); + if (ptrace(T_DUMPCORE, pid, 0, 0) != 0) { + fprintf(stderr, "warning, dumpcore failed (%s)\n", + strerror(errno)); + } if (ptrace(T_DETACH, pid, 0, 0)) { fprintf(stderr, "warning, detaching failed (%s)\n", diff --git a/servers/vfs/main.c b/servers/vfs/main.c index eb752d0eb..8a319176f 100644 --- a/servers/vfs/main.c +++ b/servers/vfs/main.c @@ -839,7 +839,13 @@ static void service_pm_postponed(void) proc_e = job_m_in.PM_PROC; traced_proc_e = job_m_in.PM_TRACED_PROC; - term_signal = job_m_in.PM_TERM_SIG; + if(job_m_in.PM_PROC != job_m_in.PM_TRACED_PROC) { + /* dumpcore request */ + term_signal = 0; + } else { + /* dumpcore on exit */ + term_signal = job_m_in.PM_TERM_SIG; + } core_path = (vir_bytes) job_m_in.PM_PATH; r = pm_dumpcore(proc_e, term_signal, core_path); @@ -918,7 +924,12 @@ static void service_pm() case PM_DUMPCORE: { endpoint_t proc_e = job_m_in.PM_PROC; - okendpt(proc_e, &slot); + + if(isokendpt(proc_e, &slot) != OK) { + printf("VFS: proc ep %d not ok\n", proc_e); + return; + } + fp = &fproc[slot]; if (fp->fp_flags & FP_PENDING) { diff --git a/servers/vfs/misc.c b/servers/vfs/misc.c index d0ee9e898..7711c7b79 100644 --- a/servers/vfs/misc.c +++ b/servers/vfs/misc.c @@ -717,7 +717,8 @@ int pm_dumpcore(endpoint_t proc_e, int csig, vir_bytes exe_name) unlock_filp(f); (void) close_fd(fp, core_fd); /* ignore failure, we're exiting anyway */ - free_proc(fp, FP_EXITING); + if(csig) + free_proc(fp, FP_EXITING); return(OK); }