]> Zhao Yanbai Git Server - minix.git/commitdiff
new command 'dumpcore' that can write core files of running processes.
authorBen Gras <ben@minix3.org>
Tue, 15 Aug 2006 15:59:38 +0000 (15:59 +0000)
committerBen Gras <ben@minix3.org>
Tue, 15 Aug 2006 15:59:38 +0000 (15:59 +0000)
commands/simple/Makefile
commands/simple/dumpcore.c [new file with mode: 0644]
man/man1/dumpcore.1 [new file with mode: 0644]

index 02c64e7bfb88b41a054baee39d01bac858aab999..ed7b646fd937fa721b6c55176d76df21a7cdc37d 100755 (executable)
@@ -77,6 +77,7 @@ ALL   = \
        diff \
        dirname \
        du \
+       dumpcore \
        ed \
        eject \
        env \
@@ -364,6 +365,10 @@ du:        du.c
        $(CCLD) -o $@ $?
        @install -S 256kw $@
 
+dumpcore:      dumpcore.c
+       $(CCLD) -D_SYSTEM=1 -o $@ $? -lsysutil -lsys 
+       @install -S 32k $@
+
 ed:    ed.c
        $(CCLD) -o $@ $?
        @install -S 32kw $@
@@ -955,6 +960,7 @@ install:    \
        /usr/bin/diff \
        /usr/bin/dirname \
        /usr/bin/du \
+       /usr/bin/dumpcore \
        /usr/bin/ed \
        /usr/bin/eject \
        /usr/bin/env \
@@ -1251,6 +1257,9 @@ install:  \
 /usr/bin/du:   du
        install -cs -o bin $? $@
 
+/usr/bin/dumpcore:     dumpcore
+       install -cs -o bin $? $@
+
 /usr/bin/ed:   ed
        install -cs -o bin $? $@
 
diff --git a/commands/simple/dumpcore.c b/commands/simple/dumpcore.c
new file mode 100644 (file)
index 0000000..9b303d5
--- /dev/null
@@ -0,0 +1,166 @@
+
+#include <fcntl.h>
+#include <assert.h>
+#include <unistd.h>    
+#include <minix/config.h>
+#include <minix/type.h>
+#include <minix/callnr.h>
+#include <minix/safecopies.h>
+#include <minix/endpoint.h>
+#include <minix/com.h>
+#include <minix/syslib.h>
+#include <minix/const.h>
+#include <sys/ptrace.h>
+#include <sys/svrctl.h>
+#include <dirent.h>
+#include <timers.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "../../kernel/const.h"
+#include "../../kernel/type.h"
+#include "../../kernel/config.h"
+#include "../../kernel/debug.h"
+#include "../../kernel/proc.h"
+#include "../../kernel/ipc.h"
+
+#define SLOTS (NR_TASKS + NR_PROCS)
+struct proc proc[SLOTS];
+
+
+int write_seg(int fd, off_t off, endpoint_t proc_e, int seg,
+       off_t seg_off, phys_bytes seg_bytes)
+{
+  int r, block_size, fl;
+  off_t n, o, b_off;
+  block_t b;
+  struct buf *bp;
+  ssize_t w;
+  static char buf[1024];
+
+  for (o= seg_off; o < seg_off+seg_bytes; o += sizeof(buf))
+  {
+       /* Copy a chunk from user space to the block buffer. */
+       if(sys_vircopy(proc_e, seg, (phys_bytes) o,
+       SELF, D, (vir_bytes) buf, (phys_bytes) sizeof(buf)) != OK) {
+               printf("write_seg: sys_vircopy failed\n");
+               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 OK;
+}
+
+
+int dumpcore(endpoint_t proc_e)
+{
+       int r, seg, exists, fd;
+       mode_t omode;
+       vir_bytes len;
+       off_t off, seg_off;
+       long trace_off, trace_data;
+       struct mem_map segs[NR_LOCAL_SEGS];
+       struct proc procentry;
+       int proc_s;
+       ssize_t w;
+       char core_name[200];
+
+       if(sys_getproctab(proc) != OK) {
+               printf( "Couldn't get proc tab.\n");
+               return 1;
+       }
+
+       for(proc_s = 0; proc_s < SLOTS; proc_s++)
+               if(proc[proc_s].p_endpoint == proc_e &&
+                       !(proc[proc_s].p_rts_flags & SLOT_FREE))
+                       break;
+
+       if(proc_s >= SLOTS) {
+               printf( "endpoint %d not found.\n", proc_e);
+               return 1;
+       }
+
+       if(proc_s < 0 || proc_s >= SLOTS) {
+               printf( "Slot out of range (internal error).\n");
+               return 1;
+       }
+
+       if(proc[proc_s].p_rts_flags & SLOT_FREE) {
+               printf( "slot %d is no process (internal error).\n",
+                       proc_s);
+               return 1;
+       }
+
+       sprintf(core_name, "/tmp/core.%d", proc_e);
+
+       if((fd = open(core_name,
+               O_CREAT|O_WRONLY|O_EXCL|O_NONBLOCK, 0600)) < 0) {
+               printf("couldn't open %s (%s)\n",
+                       core_name, strerror(errno));
+               return 1;
+       }
+
+       proc[proc_s].p_name[P_NAME_LEN-1] = '\0';
+
+       memcpy(segs, proc[proc_s].p_memmap, sizeof(segs));
+
+       off= 0;
+       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));
+               return 1;
+       }
+       off += sizeof(segs);
+
+       /* Write out the whole kernel process table entry to get the regs. */
+       for (trace_off= 0;; trace_off += sizeof(long))
+       {
+               r= sys_trace(T_GETUSER, proc_e, trace_off, &trace_data);
+               if  (r != OK) 
+               {
+                       break;
+               }
+               r= write(fd, &trace_data, sizeof(trace_data));
+               if (r != sizeof(trace_data)) {
+                       printf( "trace_data write failed\n");
+                       return 1;
+               }
+               off += sizeof(trace_data);
+       }
+
+       /* 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, off, proc_e, seg, seg_off, len);
+               if (r != OK)
+               {
+                       printf( "write failed\n");
+                       return 1;
+               }
+               off += len;
+       }
+
+       close(fd);
+
+       return 0;
+}
+
+main(int argc, char *argv[])
+{
+       if(argc != 2) {
+               printf("usage: %s <endpoint>\n", argv[0]);
+               return 1;
+       }
+       dumpcore(atoi(argv[1]));
+       return 1;
+}
+
diff --git a/man/man1/dumpcore.1 b/man/man1/dumpcore.1
new file mode 100644 (file)
index 0000000..a2a90d0
--- /dev/null
@@ -0,0 +1,26 @@
+.TH DUMPCORE 1
+.SH NAME
+dumpcore \- generate core file of running process
+.SH SYNOPSIS
+service run /usr/bin/dumpcore -args \fIendpoint\fR
+.br
+.de FL
+.TP
+\\fB\\$1\\fR
+\\$2
+..
+.de EX
+.TP 20
+\\fB\\$1\\fR
+# \\$2
+..
+.SH DESCRIPTION
+\fIDumpcore\fR executes the same code that FS executes in order to
+generate a core dump of a currently running process, identified by
+endpoint number. Obtain an endpoint number by using the F1 debug
+dump, or ps with -E option.
+.SH BUGS
+\fIDumpcore\fR has duplicate code with FS, and has to be started with
+the service command.
+.SH "SEE ALSO"
+.BR ps (1).