diff options
| author | cvs2svn <cvs2svn@FreeBSD.org> | 1999-01-21 00:55:32 +0000 | 
|---|---|---|
| committer | cvs2svn <cvs2svn@FreeBSD.org> | 1999-01-21 00:55:32 +0000 | 
| commit | 76b5366091f76c9bc73570149ef5055648fc2c39 (patch) | |
| tree | 590d020e0f2a5bea6e09d66d951a674443b21d67 /usr.bin/gcore | |
| parent | 4b4d01da6f07f7754ff6a6e4f5223e9f0984d1a6 (diff) | |
Diffstat (limited to 'usr.bin/gcore')
| -rw-r--r-- | usr.bin/gcore/Makefile | 3 | ||||
| -rw-r--r-- | usr.bin/gcore/elfcore.c | 514 | ||||
| -rw-r--r-- | usr.bin/gcore/extern.h | 4 | ||||
| -rw-r--r-- | usr.bin/gcore/gcore.c | 142 | 
4 files changed, 60 insertions, 603 deletions
| diff --git a/usr.bin/gcore/Makefile b/usr.bin/gcore/Makefile index 7f6a3eed905ac..664813febb927 100644 --- a/usr.bin/gcore/Makefile +++ b/usr.bin/gcore/Makefile @@ -1,8 +1,7 @@  #	@(#)Makefile	8.1 (Berkeley) 6/6/93  PROG=	gcore -SRCS=	elfcore.c gcore.c -CFLAGS+=-Wall +SRCS=	gcore.c  DPADD=	${LIBKVM}  LDADD=	-lkvm diff --git a/usr.bin/gcore/elfcore.c b/usr.bin/gcore/elfcore.c deleted file mode 100644 index af199ca8f705c..0000000000000 --- a/usr.bin/gcore/elfcore.c +++ /dev/null @@ -1,514 +0,0 @@ -/*- - * Copyright (c) 1998 John D. Polstra - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - *    notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - *    notice, this list of conditions and the following disclaimer in the - *    documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - *	$Id: elfcore.c,v 1.1 1998/10/19 19:42:18 jdp Exp $ - */ - -#include <sys/param.h> -#include <sys/lock.h> -#include <sys/procfs.h> -#include <vm/vm_param.h> -#include <vm/vm.h> -#include <vm/pmap.h> -#include <vm/vm_map.h> -#include <vm/vm_prot.h> -#include <elf.h> -#include <err.h> -#include <errno.h> -#include <fcntl.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - -#include "extern.h" - -/* - * Code for generating ELF core dumps. - */ - -typedef void (*segment_callback)(vm_map_entry_t, void *); - -/* Closure for cb_put_phdr(). */ -struct phdr_closure { -	Elf_Phdr *phdr;		/* Program header to fill in */ -	Elf_Off offset;		/* Offset of segment in core file */ -}; - -/* Closure for cb_size_segment(). */ -struct sseg_closure { -	int count;		/* Count of writable segments. */ -	size_t size;		/* Total size of all writable segments. */ -}; - -static void cb_put_phdr(vm_map_entry_t, void *); -static void cb_size_segment(vm_map_entry_t, void *); -static void each_writable_segment(vm_map_entry_t, segment_callback, -    void *closure); -static void elf_corehdr(int fd, pid_t, vm_map_entry_t, int numsegs, -    void *hdr, size_t hdrsize); -static void elf_puthdr(vm_map_entry_t, void *, size_t *, -    const prstatus_t *, const prfpregset_t *, const prpsinfo_t *, int numsegs); -static void elf_putnote(void *dst, size_t *off, const char *name, int type, -    const void *desc, size_t descsz); -static void freemap(vm_map_entry_t); -static void readhdrinfo(pid_t, prstatus_t *, prfpregset_t *, prpsinfo_t *); -static vm_map_entry_t readmap(pid_t); - -/* - * Write an ELF coredump for the given pid to the given fd. - */ -void -elf_coredump(int fd, pid_t pid) -{ -	vm_map_entry_t map; -	struct sseg_closure seginfo; -	void *hdr; -	size_t hdrsize; -	char memname[64]; -	int memfd; -	Elf_Phdr *php; -	int i; - -	/* Get the program's memory map. */ -	map = readmap(pid); - -	/* Size the program segments. */ -	seginfo.count = 0; -	seginfo.size = 0; -	each_writable_segment(map, cb_size_segment, &seginfo); - -	/* -	 * Calculate the size of the core file header area by making -	 * a dry run of generating it.  Nothing is written, but the -	 * size is calculated. -	 */ -	hdrsize = 0; -	elf_puthdr(map, (void *)NULL, &hdrsize, -	    (const prstatus_t *)NULL, (const prfpregset_t *)NULL, -	    (const prpsinfo_t *)NULL, seginfo.count); - -	/* -	 * Allocate memory for building the header, fill it up, -	 * and write it out. -	 */ -	hdr = malloc(hdrsize); -	if ((hdr = malloc(hdrsize)) == NULL) -		errx(1, "out of memory"); -	elf_corehdr(fd, pid, map, seginfo.count, hdr, hdrsize); - -	/* Write the contents of all of the writable segments. */ -	snprintf(memname, sizeof memname, "/proc/%d/mem", pid); -	if ((memfd = open(memname, O_RDONLY)) == -1) -		err(1, "cannot open %s", memname); - -	php = (Elf_Phdr *)((char *)hdr + sizeof(Elf_Ehdr)) + 1; -	for (i = 0;  i < seginfo.count;  i++) { -		int nleft = php->p_filesz; - -		lseek(memfd, (off_t)php->p_vaddr, SEEK_SET); -		while (nleft > 0) { -			char buf[8*1024]; -			int nwant; -			int ngot; - -			nwant = nleft; -			if (nwant > sizeof buf) -				nwant = sizeof buf; -			ngot = read(memfd, buf, nwant); -			if (ngot == -1) -				err(1, "read from %s", memname); -			if (ngot < nwant) -				errx(1, "short read from %s:" -				    " wanted %d, got %d\n", memname, -				    nwant, ngot); -			ngot = write(fd, buf, nwant); -			if (ngot == -1) -				err(1, "write of segment %d failed", i); -			if (ngot != nwant) -				errx(1, "short write"); -			nleft -= nwant; -		} -		php++; -	} -	close(memfd); -	free(hdr); -	freemap(map); -} - -/* - * A callback for each_writable_segment() to write out the segment's - * program header entry. - */ -static void -cb_put_phdr(vm_map_entry_t entry, void *closure) -{ -	struct phdr_closure *phc = (struct phdr_closure *)closure; -	Elf_Phdr *phdr = phc->phdr; - -	phc->offset = round_page(phc->offset); - -	phdr->p_type = PT_LOAD; -	phdr->p_offset = phc->offset; -	phdr->p_vaddr = entry->start; -	phdr->p_paddr = 0; -	phdr->p_filesz = phdr->p_memsz = entry->end - entry->start; -	phdr->p_align = PAGE_SIZE; -	phdr->p_flags = 0; -	if (entry->protection & VM_PROT_READ) -		phdr->p_flags |= PF_R; -	if (entry->protection & VM_PROT_WRITE) -		phdr->p_flags |= PF_W; -	if (entry->protection & VM_PROT_EXECUTE) -		phdr->p_flags |= PF_X; - -	phc->offset += phdr->p_filesz; -	phc->phdr++; -} - -/* - * A callback for each_writable_segment() to gather information about - * the number of segments and their total size. - */ -static void -cb_size_segment(vm_map_entry_t entry, void *closure) -{ -	struct sseg_closure *ssc = (struct sseg_closure *)closure; - -	ssc->count++; -	ssc->size += entry->end - entry->start; -} - -/* - * For each segment in the given memory map, call the given function - * with a pointer to the map entry and some arbitrary caller-supplied - * data. - */ -static void -each_writable_segment(vm_map_entry_t map, segment_callback func, void *closure) -{ -	vm_map_entry_t entry; - -	for (entry = map;  entry != NULL;  entry = entry->next) -		(*func)(entry, closure); -} - -/* - * Write the core file header to the file, including padding up to - * the page boundary. - */ -static void -elf_corehdr(int fd, pid_t pid, vm_map_entry_t map, int numsegs, void *hdr, -    size_t hdrsize) -{ -	size_t off; -	prstatus_t status; -	prfpregset_t fpregset; -	prpsinfo_t psinfo; - -	/* Gather the information for the header. */ -	readhdrinfo(pid, &status, &fpregset, &psinfo); - -	/* Fill in the header. */ -	memset(hdr, 0, hdrsize); -	off = 0; -	elf_puthdr(map, hdr, &off, &status, &fpregset, &psinfo, numsegs); - -	/* Write it to the core file. */ -	if (write(fd, hdr, hdrsize) == -1) -		err(1, "write"); -} - -/* - * Generate the ELF coredump header into the buffer at "dst".  "dst" may - * be NULL, in which case the header is sized but not actually generated. - */ -static void -elf_puthdr(vm_map_entry_t map, void *dst, size_t *off, const prstatus_t *status, -    const prfpregset_t *fpregset, const prpsinfo_t *psinfo, int numsegs) -{ -	size_t ehoff; -	size_t phoff; -	size_t noteoff; -	size_t notesz; - -	ehoff = *off; -	*off += sizeof(Elf_Ehdr); - -	phoff = *off; -	*off += (numsegs + 1) * sizeof(Elf_Phdr); - -	noteoff = *off; -	elf_putnote(dst, off, "FreeBSD", NT_PRSTATUS, status, -	    sizeof *status); -	elf_putnote(dst, off, "FreeBSD", NT_FPREGSET, fpregset, -	    sizeof *fpregset); -	elf_putnote(dst, off, "FreeBSD", NT_PRPSINFO, psinfo, -	    sizeof *psinfo); -	notesz = *off - noteoff; - -	/* Align up to a page boundary for the program segments. */ -	*off = round_page(*off); - -	if (dst != NULL) { -		Elf_Ehdr *ehdr; -		Elf_Phdr *phdr; -		struct phdr_closure phc; - -		/* -		 * Fill in the ELF header. -		 */ -		ehdr = (Elf_Ehdr *)((char *)dst + ehoff); -		ehdr->e_ident[EI_MAG0] = ELFMAG0; -		ehdr->e_ident[EI_MAG1] = ELFMAG1; -		ehdr->e_ident[EI_MAG2] = ELFMAG2; -		ehdr->e_ident[EI_MAG3] = ELFMAG3; -		ehdr->e_ident[EI_CLASS] = ELF_CLASS; -		ehdr->e_ident[EI_DATA] = ELF_DATA; -		ehdr->e_ident[EI_VERSION] = EV_CURRENT; -		ehdr->e_ident[EI_PAD] = 0; -		strncpy(ehdr->e_ident + EI_BRAND, "FreeBSD", -		    EI_NIDENT - EI_BRAND); -		ehdr->e_type = ET_CORE; -		ehdr->e_machine = ELF_ARCH; -		ehdr->e_version = EV_CURRENT; -		ehdr->e_entry = 0; -		ehdr->e_phoff = phoff; -		ehdr->e_flags = 0; -		ehdr->e_ehsize = sizeof(Elf_Ehdr); -		ehdr->e_phentsize = sizeof(Elf_Phdr); -		ehdr->e_phnum = numsegs + 1; -		ehdr->e_shentsize = sizeof(Elf_Shdr); -		ehdr->e_shnum = 0; -		ehdr->e_shstrndx = SHN_UNDEF; - -		/* -		 * Fill in the program header entries. -		 */ -		phdr = (Elf_Phdr *)((char *)dst + phoff); - -		/* The note segement. */ -		phdr->p_type = PT_NOTE; -		phdr->p_offset = noteoff; -		phdr->p_vaddr = 0; -		phdr->p_paddr = 0; -		phdr->p_filesz = notesz; -		phdr->p_memsz = 0; -		phdr->p_flags = 0; -		phdr->p_align = 0; -		phdr++; - -		/* All the writable segments from the program. */ -		phc.phdr = phdr; -		phc.offset = *off; -		each_writable_segment(map, cb_put_phdr, &phc); -	} -} - -/* - * Emit one note section to "dst", or just size it if "dst" is NULL. - */ -static void -elf_putnote(void *dst, size_t *off, const char *name, int type, -    const void *desc, size_t descsz) -{ -	Elf_Note note; - -	note.n_namesz = strlen(name) + 1; -	note.n_descsz = descsz; -	note.n_type = type; -	if (dst != NULL) -		bcopy(¬e, (char *)dst + *off, sizeof note); -	*off += sizeof note; -	if (dst != NULL) -		bcopy(name, (char *)dst + *off, note.n_namesz); -	*off += roundup2(note.n_namesz, sizeof(Elf_Size)); -	if (dst != NULL) -		bcopy(desc, (char *)dst + *off, note.n_descsz); -	*off += roundup2(note.n_descsz, sizeof(Elf_Size)); -} - -/* - * Free the memory map. - */ -static void -freemap(vm_map_entry_t map) -{ -	while (map != NULL) { -		vm_map_entry_t next = map->next; -		free(map); -		map = next; -	} -} - -/* - * Read the process information necessary to fill in the core file's header. - */ -static void -readhdrinfo(pid_t pid, prstatus_t *status, prfpregset_t *fpregset, -    prpsinfo_t *psinfo) -{ -	char name[64]; -	char line[256]; -	int fd; -	int i; -	int n; - -	memset(status, 0, sizeof *status); -	status->pr_version = PRSTATUS_VERSION; -	status->pr_statussz = sizeof(prstatus_t); -	status->pr_gregsetsz = sizeof(gregset_t); -	status->pr_fpregsetsz = sizeof(fpregset_t); -	status->pr_osreldate = __FreeBSD_version; -	status->pr_pid = pid; - -	memset(fpregset, 0, sizeof *fpregset); - -	memset(psinfo, 0, sizeof *psinfo); -	psinfo->pr_version = PRPSINFO_VERSION; -	psinfo->pr_psinfosz = sizeof(prpsinfo_t); - -	/* Read the general registers. */ -	snprintf(name, sizeof name, "/proc/%d/regs", pid); -	if ((fd = open(name, O_RDONLY)) == -1) -		err(1, "cannot open %s", name); -	if ((n = read(fd, &status->pr_reg, sizeof status->pr_reg)) == -1) -		err(1, "read error from %s", name); -	if (n < sizeof status->pr_reg) -		errx(1, "short read from %s: wanted %u, got %d", name, -		    sizeof status->pr_reg, n); -	close(fd); - -	/* Read the floating point registers. */ -	snprintf(name, sizeof name, "/proc/%d/fpregs", pid); -	if ((fd = open(name, O_RDONLY)) == -1) -		err(1, "cannot open %s", name); -	if ((n = read(fd, fpregset, sizeof *fpregset)) == -1) -		err(1, "read error from %s", name); -	if (n < sizeof *fpregset) -		errx(1, "short read from %s: wanted %u, got %d", name, -		    sizeof *fpregset, n); -	close(fd); - -	/* Read and parse the process status. */ -	snprintf(name, sizeof name, "/proc/%d/status", pid); -	if ((fd = open(name, O_RDONLY)) == -1) -		err(1, "cannot open %s", name); -	if ((n = read(fd, line, sizeof line - 1)) == -1) -		err(1, "read error from %s", name); -	if (n > MAXCOMLEN) -		n = MAXCOMLEN; -	for (i = 0;  i < n && line[i] != ' ';  i++) -		psinfo->pr_fname[i] = line[i]; -	strncpy(psinfo->pr_psargs, psinfo->pr_fname, PRARGSZ); -	close(fd); -} - -/* - * Read the process's memory map using procfs, and return a list of - * VM map entries.  Only the non-device read/writable segments are - * returned.  The map entries in the list aren't fully filled in; only - * the items we need are present. - */ -static vm_map_entry_t -readmap(pid_t pid) -{ -	char mapname[64]; -	int mapfd; -	ssize_t mapsize; -	size_t bufsize; -	char *mapbuf; -	int pos; -	vm_map_entry_t map; -	vm_map_entry_t *linkp; - -	snprintf(mapname, sizeof mapname, "/proc/%d/map", pid); -	if ((mapfd = open(mapname, O_RDONLY)) == -1) -		err(1, "cannot open %s", mapname); - -	/* -	 * Procfs requires (for consistency) that the entire memory map -	 * be read with a single read() call.  Start with a reasonbly sized -	 * buffer, and double it until it is big enough. -	 */ -	bufsize = 8 * 1024; -	mapbuf = NULL; -	for ( ; ; ) { -		if ((mapbuf = realloc(mapbuf, bufsize)) == NULL) -			errx(1, "out of memory"); -		mapsize = read(mapfd, mapbuf, bufsize); -		if (mapsize != -1 || errno != EFBIG) -			break; -		bufsize *= 2; -		/* This lseek shouldn't be necessary, but it is. */ -		lseek(mapfd, (off_t)0, SEEK_SET); -	} -	if (mapsize == -1) -		err(1, "read error from %s", mapname); -	if (mapsize == 0) -		errx(1, "empty map file %s", mapname); -	close(mapfd); - -	pos = 0; -	map = NULL; -	linkp = ↦ -	while (pos < mapsize) { -		vm_map_entry_t ent; -		vm_offset_t start; -		vm_offset_t end; -		char prot[4]; -		char type[16]; -		int n; -		int len; - -		len = 0; -		n = sscanf(mapbuf + pos, "%x %x %*d %*d %*d %3[-rwx]" -		    " %*d %*d %*x %*s %*s %16s%*[\n]%n", -		    &start, &end, prot, type, &len); -		if (n != 4) -			errx(1, "ill-formed line in %s", mapname); -		pos += len; - -		/* Ignore segments of the wrong kind, and unwritable ones */ -		if (strncmp(prot, "rw", 2) != 0 || -		    (strcmp(type, "default") != 0 && -		    strcmp(type, "vnode") != 0 && -		    strcmp(type, "swap") != 0)) -			continue; - -		if ((ent = (vm_map_entry_t)calloc(1, sizeof *ent)) == NULL) -			errx(1, "out of memory"); -		ent->start = start; -		ent->end = end; -		ent->protection = VM_PROT_READ | VM_PROT_WRITE; -		if (prot[2] == 'x') -		    ent->protection |= VM_PROT_EXECUTE; - -		*linkp = ent; -		linkp = &ent->next; -	} -	free(mapbuf); -	return map; -} diff --git a/usr.bin/gcore/extern.h b/usr.bin/gcore/extern.h index f157e531a5f3a..3dccafe70845c 100644 --- a/usr.bin/gcore/extern.h +++ b/usr.bin/gcore/extern.h @@ -33,9 +33,5 @@   *	@(#)extern.h	8.1 (Berkeley) 6/6/93   */ -#include <sys/types.h> -#include <kvm.h> -  void	err __P((int, const char *, ...)); -void	elf_coredump __P((int, pid_t));  void	md_core __P((kvm_t *, int, struct kinfo_proc *)); diff --git a/usr.bin/gcore/gcore.c b/usr.bin/gcore/gcore.c index 4702003b8afc1..8ab7b0bdbe613 100644 --- a/usr.bin/gcore/gcore.c +++ b/usr.bin/gcore/gcore.c @@ -42,7 +42,7 @@ static const char copyright[] =  static char sccsid[] = "@(#)gcore.c	8.2 (Berkeley) 9/23/93";  #endif  static const char rcsid[] = -	"$Id: gcore.c,v 1.12 1998/10/22 04:02:37 jdp Exp $"; +	"$Id: gcore.c,v 1.9 1998/09/14 10:09:30 des Exp $";  #endif /* not lint */  /* @@ -79,19 +79,17 @@ static const char rcsid[] =  #include "extern.h" -static void	core __P((int, int, struct kinfo_proc *)); -static void	datadump __P((int, int, struct proc *, u_long, int)); -static void	killed __P((int)); -static void	restart_target __P((void)); -static void	usage __P((void)) __dead2; -static void	userdump __P((int, struct proc *, u_long, int)); +void	core __P((int, int, struct kinfo_proc *)); +void	datadump __P((int, int, struct proc *, u_long, int)); +void	usage __P((void)); +void	userdump __P((int, struct proc *, u_long, int));  kvm_t *kd;  /* XXX undocumented routine, should be in kvm.h? */  ssize_t kvm_uread __P((kvm_t *, const struct proc *, u_long, char *, size_t)); +  static int data_offset; -static pid_t pid;  int  main(argc, argv) @@ -99,12 +97,11 @@ main(argc, argv)  	char *argv[];  {  	register struct proc *p; -	struct kinfo_proc *ki = NULL; +	struct kinfo_proc *ki;  	struct exec exec; -	int ch, cnt, efd, fd, sflag, uid; +	int ch, cnt, efd, fd, pid, sflag, uid;  	char *binfile, *corefile;  	char errbuf[_POSIX2_LINE_MAX], fname[MAXPATHLEN + 1]; -	int is_aout;  	sflag = 0;  	corefile = NULL; @@ -140,53 +137,27 @@ main(argc, argv)  		usage();  	} -	efd = open(binfile, O_RDONLY, 0); -	if (efd < 0) -		err(1, "%s", binfile); +	kd = kvm_openfiles(0, 0, 0, O_RDONLY, errbuf); +	if (kd == NULL) +		errx(1, "%s", errbuf); -	cnt = read(efd, &exec, sizeof(exec)); -	if (cnt != sizeof(exec)) -		errx(1, "%s exec header: %s", -		    binfile, cnt > 0 ? strerror(EIO) : strerror(errno)); -	if (!N_BADMAG(exec)) { -		is_aout = 1; -		/* -		 * This legacy a.out support uses the kvm interface instead -		 * of procfs. -		 */ -		kd = kvm_openfiles(0, 0, 0, O_RDONLY, errbuf); -		if (kd == NULL) -			errx(1, "%s", errbuf); - -		uid = getuid(); - -		ki = kvm_getprocs(kd, KERN_PROC_PID, pid, &cnt); -		if (ki == NULL || cnt != 1) -			errx(1, "%d: not found", pid); - -		p = &ki->kp_proc; -		if (ki->kp_eproc.e_pcred.p_ruid != uid && uid != 0) -			errx(1, "%d: not owner", pid); - -		if (p->p_stat == SZOMB) -			errx(1, "%d: zombie", pid); - -		if (p->p_flag & P_WEXIT) -			errx(1, "%d: process exiting", pid); -		if (p->p_flag & P_SYSTEM)	/* Swapper or pagedaemon. */ -			errx(1, "%d: system process", pid); -		if (exec.a_text != ptoa(ki->kp_eproc.e_vm.vm_tsize)) -			errx(1, "The executable %s does not belong to" -			    " process %d!\n" -			    "Text segment size (in bytes): executable %ld," -			    " process %d", binfile, pid, exec.a_text,  -			     ptoa(ki->kp_eproc.e_vm.vm_tsize)); -		data_offset = N_DATOFF(exec); -	} else if (IS_ELF(*(Elf_Ehdr *)&exec)) { -		is_aout = 0; -		close(efd); -	} else -		errx(1, "Invalid executable file"); +	uid = getuid(); + +	ki = kvm_getprocs(kd, KERN_PROC_PID, pid, &cnt); +	if (ki == NULL || cnt != 1) +		errx(1, "%d: not found", pid); + +	p = &ki->kp_proc; +	if (ki->kp_eproc.e_pcred.p_ruid != uid && uid != 0) +		errx(1, "%d: not owner", pid); + +	if (p->p_stat == SZOMB) +		errx(1, "%d: zombie", pid); + +	if (p->p_flag & P_WEXIT) +		errx(1, "%d: process exiting", pid); +	if (p->p_flag & P_SYSTEM)	/* Swapper or pagedaemon. */ +		errx(1, "%d: system process", pid);  	if (corefile == NULL) {  		(void)snprintf(fname, sizeof(fname), "core.%d", pid); @@ -196,21 +167,41 @@ main(argc, argv)  	if (fd < 0)  		err(1, "%s", corefile); -	if (sflag) { -		signal(SIGHUP, killed); -		signal(SIGINT, killed); -		signal(SIGTERM, killed); -		if (kill(pid, SIGSTOP) == -1) -			err(1, "%d: stop signal", pid); -		atexit(restart_target); +	efd = open(binfile, O_RDONLY, 0); +	if (efd < 0) +		err(1, "%s", binfile); + +	cnt = read(efd, &exec, sizeof(exec)); +	if (cnt != sizeof(exec)) +		errx(1, "%s exec header: %s", +		    binfile, cnt > 0 ? strerror(EIO) : strerror(errno)); +	if (N_BADMAG(exec)) { +		const Elf_Ehdr *ehdr = (const Elf_Ehdr *)&exec; + +		if (IS_ELF(*ehdr)) +			errx(1, "ELF executables are not supported yet"); +		errx(1, "Invalid executable file");  	} -	if (is_aout) -		core(efd, fd, ki); -	else -		elf_coredump(fd, pid); +	/* check the text segment size of the executable and the process */ +	if (exec.a_text != ptoa(ki->kp_eproc.e_vm.vm_tsize)) +		errx(1,  +		     "The executable %s does not belong to process %d!\n" +		     "Text segment size (in bytes): executable %d, process %d", +		     binfile, pid, exec.a_text,  +		     ptoa(ki->kp_eproc.e_vm.vm_tsize)); + +	data_offset = N_DATOFF(exec); + +	if (sflag && kill(pid, SIGSTOP) < 0) +		err(1, "%d: stop signal", pid); +	core(efd, fd, ki); + +	if (sflag && kill(pid, SIGCONT) < 0) +		err(1, "%d: continue signal", pid);  	(void)close(fd); +  	exit(0);  } @@ -295,21 +286,6 @@ datadump(efd, fd, p, addr, npage)  	}  } -static void -killed(sig) -	int sig; -{ -	restart_target(); -	signal(sig, SIG_DFL); -	kill(getpid(), sig); -} - -static void -restart_target() -{ -	kill(pid, SIGCONT); -} -  void  userdump(fd, p, addr, npage)  	register int fd; | 
