]> Zhao Yanbai Git Server - minix.git/commitdiff
dumpcore: use ptrace function to trigger a coredump
authorBen Gras <ben@minix3.org>
Fri, 15 Jun 2012 00:38:00 +0000 (02:38 +0200)
committerBen Gras <ben@minix3.org>
Fri, 15 Jun 2012 10:13:50 +0000 (12:13 +0200)
. dumpcore currently relies on minix segments
. also ptrace dumpcore fix

commands/dumpcore/dumpcore.c
servers/vfs/main.c
servers/vfs/misc.c

index a33f13250c01880bbd1cbf5fe6ce4ed8487b1d46..ca6b70bc62229dc87691174aa37f97d77640a91c 100644 (file)
 
 #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",
index eb752d0eb2d6213bd0373c7b73b32a7154b33511..8a319176f2e45c9ec563853eaee923ca989c37b4 100644 (file)
@@ -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) {
index d0ee9e898c444e82449de3e476197842a0bd214b..7711c7b79027ba0601d44874c29c394606e54fcb 100644 (file)
@@ -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);
 }