new command 'dumpcore' that can write core files of running processes.
This commit is contained in:
		
							parent
							
								
									5a6052119f
								
							
						
					
					
						commit
						bf195531b3
					
				@ -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 $? $@
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										166
									
								
								commands/simple/dumpcore.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										166
									
								
								commands/simple/dumpcore.c
									
									
									
									
									
										Normal file
									
								
							@ -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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										26
									
								
								man/man1/dumpcore.1
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								man/man1/dumpcore.1
									
									
									
									
									
										Normal file
									
								
							@ -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).
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user