* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
* %sccs.include.redist.c%
static char copyright
[] =
"@(#) Copyright (c) 1992, 1993\n\
The Regents of the University of California. All rights reserved.\n";
static char sccsid
[] = "@(#)gcore.c 8.1 (Berkeley) %G%";
* Originally written by Eric Cooper in Fall 1981.
* Inspired by a version 6 program by Len Levin, 1978.
* Several pieces of code lifted from Bill Joy's 4BSD ps.
* Most recently, hacked beyond recognition for 4.4BSD by Steven McCanne,
* Lawrence Berkeley Laboratory.
* Portions of this software were developed by the Computer Systems
* Engineering group at Lawrence Berkeley Laboratory under DARPA
* contract BG 91-66 and contributed to Berkeley.
#include <machine/vmparam.h>
void core
__P((int, int, struct kinfo_proc
*));
void datadump
__P((int, int, struct proc
*, u_long
, int));
void userdump
__P((int, struct proc
*, u_long
, int));
/* XXX undocumented routine, should be in kvm.h? */
ssize_t kvm_uread
__P((kvm_t
*, struct proc
*, u_long
, char *, size_t));
int ch
, cnt
, efd
, fd
, pid
, sflag
, uid
;
char *corefile
, errbuf
[_POSIX2_LINE_MAX
], fname
[MAXPATHLEN
+ 1];
while ((ch
= getopt(argc
, argv
, "c:s")) != EOF
) {
kd
= kvm_openfiles(0, 0, 0, O_RDONLY
, errbuf
);
ki
= kvm_getprocs(kd
, KERN_PROC_PID
, pid
, &cnt
);
if (ki
== NULL
|| cnt
!= 1)
err(1, "%d: not found", pid
);
if (ki
->kp_eproc
.e_pcred
.p_ruid
!= uid
&& uid
!= 0)
err(1, "%d: not owner", pid
);
err(1, "%d: zombie", pid
);
err(0, "process exiting");
if (p
->p_flag
& SSYS
) /* Swapper or pagedaemon. */
err(1, "%d: system process");
(void)snprintf(fname
, sizeof(fname
), "core.%d", pid
);
fd
= open(corefile
, O_RDWR
|O_CREAT
|O_TRUNC
, DEFFILEMODE
);
err(1, "%s: %s\n", corefile
, strerror(errno
));
efd
= open(argv
[0], O_RDONLY
, 0);
err(1, "%s: %s\n", argv
[0], strerror(errno
));
cnt
= read(efd
, &exec
, sizeof(exec
));
err(1, "%s exec header: %s",
argv
[0], cnt
> 0 ? strerror(EIO
) : strerror(errno
));
data_offset
= N_DATOFF(exec
);
if (sflag
&& kill(pid
, SIGSTOP
) < 0)
err(0, "%d: stop signal: %s", pid
, strerror(errno
));
if (sflag
&& kill(pid
, SIGCONT
) < 0)
err(0, "%d: continue signal: %s", pid
, strerror(errno
));
char ubytes
[ctob(UPAGES
)];
struct proc
*p
= &ki
->kp_proc
;
int tsize
= ki
->kp_eproc
.e_vm
.vm_tsize
;
int dsize
= ki
->kp_eproc
.e_vm
.vm_dsize
;
int ssize
= ki
->kp_eproc
.e_vm
.vm_ssize
;
/* Read in user struct */
cnt
= kvm_read(kd
, (u_long
)p
->p_addr
, &uarea
, sizeof(uarea
));
if (cnt
!= sizeof(uarea
))
err(1, "read user structure: %s",
cnt
> 0 ? strerror(EIO
) : strerror(errno
));
* Fill in the eproc vm parameters, since these are garbage unless
* the kernel is dumping core or something.
uarea
.user
.u_kproc
= *ki
;
cnt
= write(fd
, &uarea
, sizeof(uarea
));
if (cnt
!= sizeof(uarea
))
err(1, "write user structure: %s",
cnt
> 0 ? strerror(EIO
) : strerror(errno
));
datadump(efd
, fd
, p
, USRTEXT
+ ctob(tsize
), dsize
);
userdump(fd
, p
, USRSTACK
- ctob(ssize
), ssize
);
/* Dump machine dependent portions of the core. */
datadump(efd
, fd
, p
, addr
, npage
)
delta
= data_offset
- addr
;
cc
= kvm_uread(kd
, p
, addr
, buffer
, NBPG
);
/* Try to read the page from the executable. */
if (lseek(efd
, (off_t
)addr
+ delta
, SEEK_SET
) == -1)
err(1, "seek executable: %s", strerror(errno
));
cc
= read(efd
, buffer
, sizeof(buffer
));
if (cc
!= sizeof(buffer
))
err(1, "read executable: %s",
else /* Assume untouched bss page. */
bzero(buffer
, sizeof(buffer
));
cc
= write(fd
, buffer
, NBPG
);
err(1, "write data segment: %s",
cc
> 0 ? strerror(EIO
) : strerror(errno
));
userdump(fd
, p
, addr
, npage
)
cc
= kvm_uread(kd
, p
, addr
, buffer
, NBPG
);
/* Could be an untouched fill-with-zero page. */
cc
= write(fd
, buffer
, NBPG
);
err(1, "write stack segment: %s",
cc
> 0 ? strerror(EIO
) : strerror(errno
));
(void)fprintf(stderr
, "usage: gcore [-s] [-c core] executable pid\n");
err(int fatal
, const char *fmt
, ...)
err(fatal
, fmt
, va_alist
)
(void)fprintf(stderr
, "gcore: ");
(void)vfprintf(stderr
, fmt
, ap
);
(void)fprintf(stderr
, "\n");