From bf195531b3cac5911f5a493acb9421c0a783e7e9 Mon Sep 17 00:00:00 2001 From: Ben Gras Date: Tue, 15 Aug 2006 15:59:38 +0000 Subject: [PATCH] new command 'dumpcore' that can write core files of running processes. --- commands/simple/Makefile | 9 ++ commands/simple/dumpcore.c | 166 +++++++++++++++++++++++++++++++++++++ man/man1/dumpcore.1 | 26 ++++++ 3 files changed, 201 insertions(+) create mode 100644 commands/simple/dumpcore.c create mode 100644 man/man1/dumpcore.1 diff --git a/commands/simple/Makefile b/commands/simple/Makefile index 02c64e7bf..ed7b646fd 100755 --- a/commands/simple/Makefile +++ b/commands/simple/Makefile @@ -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 index 000000000..9b303d578 --- /dev/null +++ b/commands/simple/dumpcore.c @@ -0,0 +1,166 @@ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 \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 index 000000000..a2a90d0ab --- /dev/null +++ b/man/man1/dumpcore.1 @@ -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). -- 2.44.0