diff options
author | peter <peter@FreeBSD.org> | 2002-09-13 16:33:35 +0000 |
---|---|---|
committer | peter <peter@FreeBSD.org> | 2002-09-13 16:33:35 +0000 |
commit | 2efd9305d0db938b37aef47c41824b8683b83f06 (patch) | |
tree | b2153d434adbf0e393a7271db2de6d3a906ea97a /usr.bin/gcore | |
parent | f2ab40c05ef67ceaec6b13b8fe399b8b4ec384f3 (diff) | |
download | FreeBSD-src-2efd9305d0db938b37aef47c41824b8683b83f06.zip FreeBSD-src-2efd9305d0db938b37aef47c41824b8683b83f06.tar.gz |
Use a crowbar to move the a.out code out of gcore.c and into its own
file so that we have a chance of using gcore on non-i386 platforms. Use
linker sets to reduce the registration glue. Remove md-sparc.c, we do not
have an a.out sparc32 port. aoutcore.c was repocopied from gcore.c.
Diffstat (limited to 'usr.bin/gcore')
-rw-r--r-- | usr.bin/gcore/Makefile | 8 | ||||
-rw-r--r-- | usr.bin/gcore/aoutcore.c | 143 | ||||
-rw-r--r-- | usr.bin/gcore/elfcore.c | 22 | ||||
-rw-r--r-- | usr.bin/gcore/extern.h | 10 | ||||
-rw-r--r-- | usr.bin/gcore/gcore.c | 216 | ||||
-rw-r--r-- | usr.bin/gcore/md-nop.c | 57 | ||||
-rw-r--r-- | usr.bin/gcore/md-sparc.c | 189 |
7 files changed, 68 insertions, 577 deletions
diff --git a/usr.bin/gcore/Makefile b/usr.bin/gcore/Makefile index e2700ab..ff0e7bb 100644 --- a/usr.bin/gcore/Makefile +++ b/usr.bin/gcore/Makefile @@ -3,13 +3,11 @@ PROG= gcore SRCS= elfcore.c gcore.c + +.if ${MACHINE_ARCH} == i386 +SRCS+= aoutcore.c DPADD= ${LIBKVM} LDADD= -lkvm - -.if ${MACHINE_ARCH} != "sparc" -SRCS+= md-nop.c -.else -SRCS+= md-${MACHINE_ARCH}.c .endif .include <bsd.prog.mk> diff --git a/usr.bin/gcore/aoutcore.c b/usr.bin/gcore/aoutcore.c index 7c8ede6..dfb8718 100644 --- a/usr.bin/gcore/aoutcore.c +++ b/usr.bin/gcore/aoutcore.c @@ -63,6 +63,7 @@ __FBSDID("$FreeBSD$"); #include <sys/proc.h> #include <sys/user.h> #include <sys/sysctl.h> +#include <sys/linker_set.h> #include <arpa/inet.h> #include <machine/elf.h> @@ -81,75 +82,26 @@ __FBSDID("$FreeBSD$"); #include "extern.h" -static void core(int, int, struct kinfo_proc *); static void datadump(int, int, struct kinfo_proc *, u_long, int); -static void killed(int); -static void restart_target(void); -static void usage(void) __dead2; static void userdump(int, struct kinfo_proc *, u_long, int); -kvm_t *kd; +static kvm_t *kd; static int data_offset; -static pid_t pid; +static struct kinfo_proc *ki; -int -main(argc, argv) - int argc; - char *argv[]; +static int +aoutident(int efd, pid_t pid, char *binfile) { - struct kinfo_proc *ki = NULL; struct exec exec; - int ch, cnt, efd, fd, sflag; + int cnt; uid_t uid; - char *binfile, *corefile; - char errbuf[_POSIX2_LINE_MAX], fname[MAXPATHLEN]; - int is_aout; - - sflag = 0; - corefile = NULL; - while ((ch = getopt(argc, argv, "c:s")) != -1) { - switch (ch) { - case 'c': - corefile = optarg; - break; - case 's': - sflag = 1; - break; - default: - usage(); - break; - } - } - argv += optind; - argc -= optind; - - /* XXX we should check that the pid argument is really a number */ - switch (argc) { - case 1: - pid = atoi(argv[0]); - asprintf(&binfile, "/proc/%d/file", pid); - if (binfile == NULL) - errx(1, "allocation failure"); - break; - case 2: - pid = atoi(argv[1]); - binfile = argv[0]; - break; - default: - usage(); - } - - efd = open(binfile, O_RDONLY, 0); - if (efd < 0) - err(1, "%s", binfile); + char errbuf[_POSIX2_LINE_MAX]; cnt = read(efd, &exec, sizeof(exec)); if (cnt != sizeof(exec)) - errx(1, "%s exec header: %s", - binfile, cnt > 0 ? strerror(EIO) : strerror(errno)); + return (0); if (!N_BADMAG(exec)) { - is_aout = 1; /* * This legacy a.out support uses the kvm interface instead * of procfs. @@ -181,36 +133,9 @@ main(argc, argv) " process %d", binfile, pid, exec.a_text, ptoa(ki->ki_tsize)); data_offset = N_DATOFF(exec); - } else if (IS_ELF(*(Elf_Ehdr *)&exec)) { - is_aout = 0; - close(efd); - } else - errx(1, "Invalid executable file"); - - if (corefile == NULL) { - (void)snprintf(fname, sizeof(fname), "core.%d", pid); - corefile = fname; + return (1); } - fd = open(corefile, O_RDWR|O_CREAT|O_TRUNC, DEFFILEMODE); - 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); - } - - if (is_aout) - core(efd, fd, ki); - else - elf_coredump(fd, pid); - - (void)close(fd); - exit(0); + return (0); } /* @@ -218,10 +143,7 @@ main(argc, argv) * Build the core file. */ void -core(efd, fd, ki) - int efd; - int fd; - struct kinfo_proc *ki; +aoutcore(int efd, int fd, pid_t pid) { union { struct user user; @@ -265,20 +187,12 @@ core(efd, fd, ki) /* Dump stack segment */ userdump(fd, ki, USRSTACK - ctob(ssize), ssize); - - /* Dump machine dependent portions of the core. */ - md_core(kd, fd, ki); } void -datadump(efd, fd, kp, addr, npage) - register int efd; - register int fd; - struct kinfo_proc *kp; - register u_long addr; - register int npage; +datadump(int efd, int fd, struct kinfo_proc *kp, u_long addr, int npage) { - register int cc, delta; + int cc, delta; char buffer[PAGE_SIZE]; delta = data_offset - addr; @@ -304,29 +218,10 @@ datadump(efd, fd, kp, 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, kp, addr, npage) - register int fd; - struct kinfo_proc *kp; - register u_long addr; - register int npage; +userdump(int fd, struct kinfo_proc *kp, u_long addr, int npage) { - register int cc; + int cc; char buffer[PAGE_SIZE]; while (--npage >= 0) { @@ -342,9 +237,5 @@ userdump(fd, kp, addr, npage) } } -void -usage() -{ - (void)fprintf(stderr, "usage: gcore [-s] [-c core] [executable] pid\n"); - exit(1); -} +struct dumpers aoutdump = { aoutident, aoutcore }; +TEXT_SET(dumpset, aoutdump); diff --git a/usr.bin/gcore/elfcore.c b/usr.bin/gcore/elfcore.c index 83f68a9..0881ceb 100644 --- a/usr.bin/gcore/elfcore.c +++ b/usr.bin/gcore/elfcore.c @@ -29,6 +29,7 @@ __FBSDID("$FreeBSD$"); #include <sys/param.h> #include <sys/procfs.h> +#include <sys/linker_set.h> #include <machine/elf.h> #include <vm/vm_param.h> #include <vm/vm.h> @@ -77,11 +78,26 @@ 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); +static int +elf_ident(int efd, pid_t pid, char *binfile) +{ + Elf_Ehdr hdr; + int cnt; + uid_t uid; + + cnt = read(efd, &hdr, sizeof(hdr)); + if (cnt != sizeof(hdr)) + return (0); + if (IS_ELF(hdr)) + return (1); + return (0); +} + /* * Write an ELF coredump for the given pid to the given fd. */ void -elf_coredump(int fd, pid_t pid) +elf_coredump(int efd, int fd, pid_t pid) { vm_map_entry_t map; struct sseg_closure seginfo; @@ -357,6 +373,7 @@ elf_putnote(void *dst, size_t *off, const char *name, int type, static void freemap(vm_map_entry_t map) { + while (map != NULL) { vm_map_entry_t next = map->next; free(map); @@ -514,3 +531,6 @@ readmap(pid_t pid) free(mapbuf); return map; } + +struct dumpers elfdump = { elf_ident, elf_coredump }; +TEXT_SET(dumpset, elfdump); diff --git a/usr.bin/gcore/extern.h b/usr.bin/gcore/extern.h index 3d27fd9..1bd7095 100644 --- a/usr.bin/gcore/extern.h +++ b/usr.bin/gcore/extern.h @@ -34,9 +34,7 @@ * $FreeBSD$ */ -#include <sys/types.h> -#include <kvm.h> - -void err(int, const char *, ...); -void elf_coredump(int, pid_t); -void md_core(kvm_t *, int, struct kinfo_proc *); +struct dumpers { + int (*ident)(int efd, pid_t pid, char *binfile); + void (*dump)(int efd, int fd, pid_t pid); +}; diff --git a/usr.bin/gcore/gcore.c b/usr.bin/gcore/gcore.c index 7c8ede6..4db514d 100644 --- a/usr.bin/gcore/gcore.c +++ b/usr.bin/gcore/gcore.c @@ -60,19 +60,10 @@ __FBSDID("$FreeBSD$"); #include <sys/param.h> #include <sys/time.h> #include <sys/stat.h> -#include <sys/proc.h> -#include <sys/user.h> -#include <sys/sysctl.h> +#include <sys/linker_set.h> -#include <arpa/inet.h> -#include <machine/elf.h> -#include <machine/vmparam.h> - -#include <a.out.h> #include <err.h> #include <fcntl.h> -#include <kvm.h> -#include <limits.h> #include <signal.h> #include <stdio.h> #include <stdlib.h> @@ -81,30 +72,21 @@ __FBSDID("$FreeBSD$"); #include "extern.h" -static void core(int, int, struct kinfo_proc *); -static void datadump(int, int, struct kinfo_proc *, u_long, int); static void killed(int); static void restart_target(void); static void usage(void) __dead2; -static void userdump(int, struct kinfo_proc *, u_long, int); - -kvm_t *kd; -static int data_offset; static pid_t pid; +SET_DECLARE(dumpset, struct dumpers); + int -main(argc, argv) - int argc; - char *argv[]; +main(int argc, char *argv[]) { - struct kinfo_proc *ki = NULL; - struct exec exec; int ch, cnt, efd, fd, sflag; - uid_t uid; char *binfile, *corefile; - char errbuf[_POSIX2_LINE_MAX], fname[MAXPATHLEN]; - int is_aout; + char fname[MAXPATHLEN]; + struct dumpers **d, *dumper; sflag = 0; corefile = NULL; @@ -123,7 +105,6 @@ main(argc, argv) } argv += optind; argc -= optind; - /* XXX we should check that the pid argument is really a number */ switch (argc) { case 1: @@ -139,54 +120,20 @@ main(argc, argv) default: usage(); } - 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)) { - 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); - - if (ki->ki_ruid != uid && uid != 0) - errx(1, "%d: not owner", pid); - - if (ki->ki_stat == SZOMB) - errx(1, "%d: zombie", pid); - - if (ki->ki_flag & P_WEXIT) - errx(1, "%d: process exiting", pid); - if (ki->ki_flag & P_SYSTEM) /* Swapper or pagedaemon. */ - errx(1, "%d: system process", pid); - if (exec.a_text != ptoa(ki->ki_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->ki_tsize)); - data_offset = N_DATOFF(exec); - } else if (IS_ELF(*(Elf_Ehdr *)&exec)) { - is_aout = 0; - close(efd); - } else + dumper = NULL; + SET_FOREACH(d, dumpset) { + lseek(efd, 0, SEEK_SET); + if (((*d)->ident)(efd, pid, binfile)) { + dumper = (*d); + lseek(efd, 0, SEEK_SET); + break; + } + } + if (dumper == NULL) errx(1, "Invalid executable file"); - if (corefile == NULL) { (void)snprintf(fname, sizeof(fname), "core.%d", pid); corefile = fname; @@ -194,7 +141,6 @@ main(argc, argv) fd = open(corefile, O_RDWR|O_CREAT|O_TRUNC, DEFFILEMODE); if (fd < 0) err(1, "%s", corefile); - if (sflag) { signal(SIGHUP, killed); signal(SIGINT, killed); @@ -203,148 +149,32 @@ main(argc, argv) err(1, "%d: stop signal", pid); atexit(restart_target); } - - if (is_aout) - core(efd, fd, ki); - else - elf_coredump(fd, pid); - + dumper->dump(efd, fd, pid); (void)close(fd); + (void)close(efd); exit(0); } -/* - * core -- - * Build the core file. - */ -void -core(efd, fd, ki) - int efd; - int fd; - struct kinfo_proc *ki; -{ - union { - struct user user; - struct { - char uabytes[ctob(UAREA_PAGES)]; - char ksbytes[ctob(KSTACK_PAGES)]; - } bytes; - } uarea; - int tsize = ki->ki_tsize; - int dsize = ki->ki_dsize; - int ssize = ki->ki_ssize; - int cnt; - - /* Read in user struct */ - cnt = kvm_read(kd, (u_long)ki->ki_addr, uarea.bytes.uabytes, - ctob(UAREA_PAGES)); - if (cnt != ctob(UAREA_PAGES)) - errx(1, "read upages structure: %s", - cnt > 0 ? strerror(EIO) : strerror(errno)); - - cnt = kvm_read(kd, (u_long)ki->ki_kstack, uarea.bytes.ksbytes, - ctob(KSTACK_PAGES)); - if (cnt != ctob(KSTACK_PAGES)) - errx(1, "read kstack 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; - - /* Dump user area */ - cnt = write(fd, &uarea, sizeof(uarea)); - if (cnt != sizeof(uarea)) - errx(1, "write user structure: %s", - cnt > 0 ? strerror(EIO) : strerror(errno)); - - /* Dump data segment */ - datadump(efd, fd, ki, USRTEXT + ctob(tsize), dsize); - - /* Dump stack segment */ - userdump(fd, ki, USRSTACK - ctob(ssize), ssize); - - /* Dump machine dependent portions of the core. */ - md_core(kd, fd, ki); -} - -void -datadump(efd, fd, kp, addr, npage) - register int efd; - register int fd; - struct kinfo_proc *kp; - register u_long addr; - register int npage; -{ - register int cc, delta; - char buffer[PAGE_SIZE]; - - delta = data_offset - addr; - while (--npage >= 0) { - cc = kvm_uread(kd, kp, addr, buffer, PAGE_SIZE); - if (cc != PAGE_SIZE) { - /* Try to read the page from the executable. */ - if (lseek(efd, (off_t)addr + delta, SEEK_SET) == -1) - err(1, "seek executable"); - cc = read(efd, buffer, sizeof(buffer)); - if (cc != sizeof(buffer)) { - if (cc < 0) - err(1, "read executable"); - else /* Assume untouched bss page. */ - bzero(buffer, sizeof(buffer)); - } - } - cc = write(fd, buffer, PAGE_SIZE); - if (cc != PAGE_SIZE) - errx(1, "write data segment: %s", - cc > 0 ? strerror(EIO) : strerror(errno)); - addr += PAGE_SIZE; - } -} - static void -killed(sig) - int sig; +killed(int sig) { + restart_target(); signal(sig, SIG_DFL); kill(getpid(), sig); } static void -restart_target() +restart_target(void) { + kill(pid, SIGCONT); } void -userdump(fd, kp, addr, npage) - register int fd; - struct kinfo_proc *kp; - register u_long addr; - register int npage; +usage(void) { - register int cc; - char buffer[PAGE_SIZE]; - while (--npage >= 0) { - cc = kvm_uread(kd, kp, addr, buffer, PAGE_SIZE); - if (cc != PAGE_SIZE) - /* Could be an untouched fill-with-zero page. */ - bzero(buffer, PAGE_SIZE); - cc = write(fd, buffer, PAGE_SIZE); - if (cc != PAGE_SIZE) - errx(1, "write stack segment: %s", - cc > 0 ? strerror(EIO) : strerror(errno)); - addr += PAGE_SIZE; - } -} - -void -usage() -{ (void)fprintf(stderr, "usage: gcore [-s] [-c core] [executable] pid\n"); exit(1); } diff --git a/usr.bin/gcore/md-nop.c b/usr.bin/gcore/md-nop.c deleted file mode 100644 index af7072c..0000000 --- a/usr.bin/gcore/md-nop.c +++ /dev/null @@ -1,57 +0,0 @@ -/*- - * Copyright (c) 1992, 1993 - * The Regents of the University of California. 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. - */ - -#if 0 -#ifndef lint -static char sccsid[] = "@(#)md-nop.c 8.1 (Berkeley) 6/6/93"; -#endif /* not lint */ -#endif -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <sys/param.h> -#include <sys/sysctl.h> - -#include <stdio.h> -#include <kvm.h> -#include "extern.h" - -void -md_core(kd, fd, ki) - kvm_t *kd __unused; - int fd __unused; - struct kinfo_proc *ki __unused; -{ - /* Don't need to fix anything for this architecture. */ - return; -} diff --git a/usr.bin/gcore/md-sparc.c b/usr.bin/gcore/md-sparc.c deleted file mode 100644 index ef14361..0000000 --- a/usr.bin/gcore/md-sparc.c +++ /dev/null @@ -1,189 +0,0 @@ -/*- - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * This software was developed by the Computer Systems Engineering group - * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and - * contributed to Berkeley. - * - * 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. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. - */ - -#ifndef lint -static char sccsid[] = "@(#)md-sparc.c 8.1 (Berkeley) 6/6/93"; -#endif /* not lint */ -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - -#include <sys/param.h> -#include <sys/time.h> -#include <sys/file.h> -#include <sys/stat.h> -#include <sys/proc.h> -#include <sys/user.h> -#include <sys/sysctl.h> -#include <machine/vmparam.h> - -#include <err.h> -#include <kvm.h> -#include <unistd.h> -#include <stdio.h> -#include <string.h> -#include "extern.h" - -#ifndef offsetof -#define offsetof(s, f) ((int)&((s *)0)->f) -#endif - -static void -shift_page(fd, off, ssize) - register int fd; - register off_t off; - register int ssize; -{ - char buffer[NBPG]; - - (void)lseek(fd, (off_t)-NBPG, SEEK_END); - for (; ssize > 0; ssize -= NBPG) { - (void)read(fd, buffer, NBPG); - (void)write(fd, buffer, NBPG); - (void)lseek(fd, (off_t)-2 * NBPG, SEEK_CUR); - } -} - -/* - * Fix up the core image for the sparc. We need to flush any register - * windows that are cached in the pcb out to the user stack. - * Also, we need to get the trap frame and possible floating point state - * from the top of the kernel stack and store it in the pcb. - */ -void -md_core(kd, fd, ki) - kvm_t *kd; - int fd; - struct kinfo_proc *ki; -{ - register struct rwindow *rw; - register int nsaved, cc, ssize; - register off_t off, s; - register u_long sp; - struct pcb pcb; - struct trapframe tf; - - /* - * Before anything else read the trapframe. Synchronizing here - * is impossible if the process is running. - */ - cc = kvm_read(kd, (u_long)ki->kp_proc.p_md.md_tf, - /* XXX */ - (void *)&tf, sizeof(tf)); - if (cc < 0) - errx(1, "kvm_read: %s (reading kernel trapframe)", - kvm_geterr(kd)); - if (cc != sizeof(tf)) - errx(1, "cannot read kernel trapframe"); - - /* - * Write out the real trap frame. - */ - off = offsetof(struct user, u_md); - off += offsetof(struct md_coredump, md_tf); - if (lseek(fd, off, SEEK_SET) == -1) - err(1, "lseek"); - (void)write(fd, &tf, sizeof(tf)); - - if (ki->kp_proc.p_md.md_fpstate != 0) { - /* - * If floating point state is present, write it out too. - * It comes right after the trapframe so we don't need to seek. - */ - struct fpstate fs; - cc = kvm_read(kd, (u_long)ki->kp_proc.p_md.md_fpstate, - (void *)&fs, sizeof(fs)); - if (cc < 0) - errx(1, "kvm_read: %s (fpu state)", kvm_geterr(kd)); - if (cc != sizeof(fs)) - errx(1, "cannot read fpu state"); - (void)write(fd, (char *)&fs, sizeof(fs)); - } - /* - * Read pcb. - */ - if (lseek(fd, (off_t)offsetof(struct user, u_pcb), SEEK_SET) == -1) - err(1, "lseek"); - cc = read(fd, (char *)&pcb, sizeof(pcb)); - if (cc != sizeof(pcb)) { - if (cc < 0) - err(1, "read"); - errx(1, "couldn't read pcb from core file"); - } - - /* - * Write any unsaved windows to the appropriate stack locations. - */ - nsaved = pcb.pcb_nsaved; - if (nsaved == 0) - return; - - rw = &pcb.pcb_rw[0]; - off = ctob(UPAGES + ki->kp_eproc.e_vm.vm_dsize); - ssize = ctob(ki->kp_eproc.e_vm.vm_ssize); - sp = tf.tf_out[6]; - for (; --nsaved >= 0; ++rw) { - /* - * Copy register window into appropriate stack location. - */ - s = ssize - (USRSTACK - sp); - if (s < 0) { - if (s < -NBPG) - errx(1, "cannot copy pcb windows to stack"); - /* - * It's possible to be missing the bottomost - * page because a stack page hasn't been allocated - * for the register save area. Shift over - * the stack segment by a page, and update - * the u-area to reflect the new stack size. YECH! - */ - shift_page(fd, off, ssize); - ssize += NBPG; - s += NBPG; - ++ki->kp_eproc.e_vm.vm_ssize; - (void)lseek(fd, - (off_t)offsetof(struct user, u_kproc.kp_eproc.e_vm), - SEEK_SET); - (void)write(fd, - &ki->kp_eproc.e_vm, sizeof(ki->kp_eproc.e_vm)); - } - if (lseek(fd, off + s, SEEK_SET) == -1) - errx(1, "cannot copy pcb windows to stack"); - - (void)write(fd, rw, sizeof(*rw)); - sp = rw->rw_in[6]; - } -} |