summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/arch/sparc/sparc/process_machdep.c6
-rw-r--r--sys/arch/sparc64/sparc64/process_machdep.c6
-rw-r--r--sys/compat/aout/compat_aout.c4
-rw-r--r--sys/compat/bsdos/bsdos_exec.c4
-rw-r--r--sys/compat/freebsd/freebsd_exec.c5
-rw-r--r--sys/compat/hpux/hppa/hpux_exec.c4
-rw-r--r--sys/compat/hpux/m68k/hpux_exec.c4
-rw-r--r--sys/compat/ibcs2/ibcs2_exec.c4
-rw-r--r--sys/compat/linux/linux_exec.c5
-rw-r--r--sys/compat/osf1/osf1_exec.c4
-rw-r--r--sys/compat/sunos/sunos_exec.c4
-rw-r--r--sys/compat/svr4/svr4_exec.c4
-rw-r--r--sys/compat/ultrix/ultrix_misc.c4
-rw-r--r--sys/kern/exec_elf.c476
-rw-r--r--sys/kern/init_main.c4
-rw-r--r--sys/kern/kern_sig.c67
-rw-r--r--sys/sys/core.h8
-rw-r--r--sys/sys/exec_elf.h60
-rw-r--r--sys/sys/proc.h3
-rw-r--r--sys/uvm/uvm_extern.h20
-rw-r--r--sys/uvm/uvm_unix.c75
21 files changed, 737 insertions, 34 deletions
diff --git a/sys/arch/sparc/sparc/process_machdep.c b/sys/arch/sparc/sparc/process_machdep.c
index 6a42d97e2a4..93a5ff26dd5 100644
--- a/sys/arch/sparc/sparc/process_machdep.c
+++ b/sys/arch/sparc/sparc/process_machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: process_machdep.c,v 1.12 2005/12/30 00:18:30 kettenis Exp $ */
+/* $OpenBSD: process_machdep.c,v 1.13 2009/03/05 19:52:23 kettenis Exp $ */
/* $NetBSD: process_machdep.c,v 1.6 1996/03/14 21:09:26 christos Exp $ */
/*
@@ -162,11 +162,11 @@ process_write_fpregs(p, regs)
return 0;
}
+#endif /* PTRACE */
+
register_t
process_get_wcookie(p)
struct proc *p;
{
return p->p_addr->u_pcb.pcb_wcookie;
}
-
-#endif /* PTRACE */
diff --git a/sys/arch/sparc64/sparc64/process_machdep.c b/sys/arch/sparc64/sparc64/process_machdep.c
index d57c0887ebd..fb403b4513c 100644
--- a/sys/arch/sparc64/sparc64/process_machdep.c
+++ b/sys/arch/sparc64/sparc64/process_machdep.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: process_machdep.c,v 1.11 2007/10/31 22:46:52 kettenis Exp $ */
+/* $OpenBSD: process_machdep.c,v 1.12 2009/03/05 19:52:23 kettenis Exp $ */
/* $NetBSD: process_machdep.c,v 1.10 2000/09/26 22:05:50 eeh Exp $ */
/*
@@ -231,10 +231,10 @@ process_write_fpregs(p, regs)
return 0;
}
+#endif /* PTRACE */
+
register_t
process_get_wcookie(struct proc *p)
{
return p->p_addr->u_pcb.pcb_wcookie;
}
-
-#endif /* PTRACE */
diff --git a/sys/compat/aout/compat_aout.c b/sys/compat/aout/compat_aout.c
index ec86e0158f7..924d5d228d0 100644
--- a/sys/compat/aout/compat_aout.c
+++ b/sys/compat/aout/compat_aout.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: compat_aout.c,v 1.2 2003/08/23 19:28:53 tedu Exp $ */
+/* $OpenBSD: compat_aout.c,v 1.3 2009/03/05 19:52:23 kettenis Exp $ */
/*
* Copyright (c) 2003 Marc Espie
@@ -30,6 +30,7 @@
#include <sys/mount.h>
#include <sys/syscallargs.h>
#include <sys/fcntl.h>
+#include <sys/core.h>
#include <compat/common/compat_util.h>
void aout_compat_setup(struct exec_package *epp);
@@ -54,6 +55,7 @@ struct emul emul_aout = {
copyargs,
setregs,
NULL,
+ coredump_trad,
sigcode,
esigcode,
};
diff --git a/sys/compat/bsdos/bsdos_exec.c b/sys/compat/bsdos/bsdos_exec.c
index 04e013c0435..f8011c9044f 100644
--- a/sys/compat/bsdos/bsdos_exec.c
+++ b/sys/compat/bsdos/bsdos_exec.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: bsdos_exec.c,v 1.4 2001/11/06 19:53:17 miod Exp $ */
+/* $OpenBSD: bsdos_exec.c,v 1.5 2009/03/05 19:52:23 kettenis Exp $ */
/*
* Copyright (c) 1993, 1994 Christopher G. Demetriou
@@ -36,6 +36,7 @@
#include <sys/signalvar.h>
#include <sys/malloc.h>
#include <sys/vnode.h>
+#include <sys/core.h>
#include <sys/exec.h>
#include <sys/resourcevar.h>
#include <uvm/uvm_extern.h>
@@ -70,6 +71,7 @@ struct emul emul_bsdos = {
copyargs,
setregs,
NULL,
+ coredump_trad,
sigcode,
esigcode,
};
diff --git a/sys/compat/freebsd/freebsd_exec.c b/sys/compat/freebsd/freebsd_exec.c
index 3a750dce41d..91beeeb0239 100644
--- a/sys/compat/freebsd/freebsd_exec.c
+++ b/sys/compat/freebsd/freebsd_exec.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: freebsd_exec.c,v 1.18 2008/06/12 04:32:57 miod Exp $ */
+/* $OpenBSD: freebsd_exec.c,v 1.19 2009/03/05 19:52:23 kettenis Exp $ */
/* $NetBSD: freebsd_exec.c,v 1.2 1996/05/18 16:02:08 christos Exp $ */
/*
@@ -36,6 +36,7 @@
#include <sys/proc.h>
#include <sys/malloc.h>
#include <sys/vnode.h>
+#include <sys/core.h>
#include <sys/exec.h>
#include <sys/resourcevar.h>
#include <uvm/uvm_extern.h>
@@ -71,6 +72,7 @@ struct emul emul_freebsd_aout = {
copyargs,
setregs,
NULL,
+ coredump_trad,
freebsd_sigcode,
freebsd_esigcode,
};
@@ -91,6 +93,7 @@ struct emul emul_freebsd_elf = {
elf32_copyargs,
setregs,
exec_elf32_fixup,
+ coredump_trad,
freebsd_sigcode,
freebsd_esigcode,
};
diff --git a/sys/compat/hpux/hppa/hpux_exec.c b/sys/compat/hpux/hppa/hpux_exec.c
index 163ce3dbad8..8c7bd9114c3 100644
--- a/sys/compat/hpux/hppa/hpux_exec.c
+++ b/sys/compat/hpux/hppa/hpux_exec.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: hpux_exec.c,v 1.3 2005/12/30 19:46:53 miod Exp $ */
+/* $OpenBSD: hpux_exec.c,v 1.4 2009/03/05 19:52:23 kettenis Exp $ */
/*
* Copyright (c) 2004 Michael Shalayeff. All rights reserved.
@@ -46,6 +46,7 @@
#include <sys/vnode.h>
#include <sys/mman.h>
#include <sys/stat.h>
+#include <sys/core.h>
#include <uvm/uvm_extern.h>
@@ -89,6 +90,7 @@ struct emul emul_hpux = {
copyargs,
hpux_setregs,
NULL,
+ coredump_trad,
hpux_sigcode,
hpux_esigcode,
};
diff --git a/sys/compat/hpux/m68k/hpux_exec.c b/sys/compat/hpux/m68k/hpux_exec.c
index ac83a6ff412..97653f9c56d 100644
--- a/sys/compat/hpux/m68k/hpux_exec.c
+++ b/sys/compat/hpux/m68k/hpux_exec.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: hpux_exec.c,v 1.3 2007/11/02 19:18:54 martin Exp $ */
+/* $OpenBSD: hpux_exec.c,v 1.4 2009/03/05 19:52:23 kettenis Exp $ */
/* $NetBSD: hpux_exec.c,v 1.8 1997/03/16 10:14:44 thorpej Exp $ */
/*
@@ -46,6 +46,7 @@
#include <sys/vnode.h>
#include <sys/mman.h>
#include <sys/stat.h>
+#include <sys/core.h>
#include <uvm/uvm_extern.h>
@@ -89,6 +90,7 @@ struct emul emul_hpux = {
copyargs,
hpux_setregs,
NULL,
+ coredump_trad,
sigcode,
esigcode,
};
diff --git a/sys/compat/ibcs2/ibcs2_exec.c b/sys/compat/ibcs2/ibcs2_exec.c
index 1649bbb29b0..cedbc2bbf73 100644
--- a/sys/compat/ibcs2/ibcs2_exec.c
+++ b/sys/compat/ibcs2/ibcs2_exec.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ibcs2_exec.c,v 1.18 2006/12/29 13:04:37 pedro Exp $ */
+/* $OpenBSD: ibcs2_exec.c,v 1.19 2009/03/05 19:52:23 kettenis Exp $ */
/* $NetBSD: ibcs2_exec.c,v 1.12 1996/10/12 02:13:52 thorpej Exp $ */
/*
@@ -38,6 +38,7 @@
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/proc.h>
+#include <sys/core.h>
#include <sys/exec.h>
#include <sys/malloc.h>
#include <sys/vnode.h>
@@ -100,6 +101,7 @@ struct emul emul_ibcs2 = {
copyargs,
setregs,
NULL,
+ coredump_trad,
sigcode,
esigcode,
};
diff --git a/sys/compat/linux/linux_exec.c b/sys/compat/linux/linux_exec.c
index ae11761ae17..67d36895e2a 100644
--- a/sys/compat/linux/linux_exec.c
+++ b/sys/compat/linux/linux_exec.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: linux_exec.c,v 1.30 2008/06/26 05:42:14 ray Exp $ */
+/* $OpenBSD: linux_exec.c,v 1.31 2009/03/05 19:52:24 kettenis Exp $ */
/* $NetBSD: linux_exec.c,v 1.13 1996/04/05 00:01:10 christos Exp $ */
/*-
@@ -39,6 +39,7 @@
#include <sys/namei.h>
#include <sys/vnode.h>
#include <sys/mount.h>
+#include <sys/core.h>
#include <sys/exec.h>
#include <sys/exec_elf.h>
#include <sys/exec_olf.h>
@@ -101,6 +102,7 @@ struct emul emul_linux_aout = {
linux_aout_copyargs,
setregs,
NULL,
+ coredump_trad,
linux_sigcode,
linux_esigcode,
0,
@@ -126,6 +128,7 @@ struct emul emul_linux_elf = {
elf32_copyargs,
setregs,
exec_elf32_fixup,
+ coredump_trad,
linux_sigcode,
linux_esigcode,
0,
diff --git a/sys/compat/osf1/osf1_exec.c b/sys/compat/osf1/osf1_exec.c
index 7e30538baa8..b9fcd97a7b6 100644
--- a/sys/compat/osf1/osf1_exec.c
+++ b/sys/compat/osf1/osf1_exec.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: osf1_exec.c,v 1.5 2004/06/22 23:52:18 jfb Exp $ */
+/* $OpenBSD: osf1_exec.c,v 1.6 2009/03/05 19:52:24 kettenis Exp $ */
/* $NetBSD$ */
/*
@@ -39,6 +39,7 @@
#include <sys/namei.h>
#include <sys/vnode.h>
#include <sys/mount.h>
+#include <sys/core.h>
#include <sys/exec.h>
#include <sys/exec_ecoff.h>
#include <sys/signalvar.h>
@@ -90,6 +91,7 @@ struct emul emul_osf1 = {
osf1_copyargs,
cpu_exec_ecoff_setregs,
NULL,
+ coredump_trad,
osf1_sigcode,
osf1_esigcode,
};
diff --git a/sys/compat/sunos/sunos_exec.c b/sys/compat/sunos/sunos_exec.c
index ac79176802c..35dbc70bded 100644
--- a/sys/compat/sunos/sunos_exec.c
+++ b/sys/compat/sunos/sunos_exec.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sunos_exec.c,v 1.18 2005/12/30 19:46:55 miod Exp $ */
+/* $OpenBSD: sunos_exec.c,v 1.19 2009/03/05 19:52:24 kettenis Exp $ */
/* $NetBSD: sunos_exec.c,v 1.11 1996/05/05 12:01:47 briggs Exp $ */
/*
@@ -37,6 +37,7 @@
#include <sys/signalvar.h>
#include <sys/vnode.h>
#include <sys/file.h>
+#include <sys/core.h>
#include <sys/exec.h>
#include <sys/resourcevar.h>
#include <sys/wait.h>
@@ -91,6 +92,7 @@ struct emul emul_sunos = {
copyargs,
setregs,
NULL,
+ coredump_trad,
sigcode,
esigcode,
};
diff --git a/sys/compat/svr4/svr4_exec.c b/sys/compat/svr4/svr4_exec.c
index d7b9cc55853..fd047282d39 100644
--- a/sys/compat/svr4/svr4_exec.c
+++ b/sys/compat/svr4/svr4_exec.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: svr4_exec.c,v 1.16 2008/06/12 04:32:59 miod Exp $ */
+/* $OpenBSD: svr4_exec.c,v 1.17 2009/03/05 19:52:24 kettenis Exp $ */
/* $NetBSD: svr4_exec.c,v 1.16 1995/10/14 20:24:20 christos Exp $ */
/*
@@ -35,6 +35,7 @@
#include <sys/malloc.h>
#include <sys/namei.h>
#include <sys/vnode.h>
+#include <sys/core.h>
#include <sys/exec.h>
#include <sys/exec_elf.h>
#include <sys/exec_olf.h>
@@ -77,6 +78,7 @@ struct emul emul_svr4 = {
svr4_copyargs,
setregs,
exec_elf32_fixup,
+ coredump_trad,
svr4_sigcode,
svr4_esigcode,
};
diff --git a/sys/compat/ultrix/ultrix_misc.c b/sys/compat/ultrix/ultrix_misc.c
index bfac657c5ac..ae56326ac42 100644
--- a/sys/compat/ultrix/ultrix_misc.c
+++ b/sys/compat/ultrix/ultrix_misc.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ultrix_misc.c,v 1.30 2007/06/06 17:15:13 deraadt Exp $ */
+/* $OpenBSD: ultrix_misc.c,v 1.31 2009/03/05 19:52:24 kettenis Exp $ */
/* $NetBSD: ultrix_misc.c,v 1.23 1996/04/07 17:23:04 jonathan Exp $ */
/*
@@ -89,6 +89,7 @@
/*#include <sys/stat.h>*/
/*#include <sys/ioctl.h>*/
#include <sys/kernel.h>
+#include <sys/core.h>
#include <sys/exec.h>
#include <sys/malloc.h>
#include <sys/mbuf.h>
@@ -161,6 +162,7 @@ struct emul emul_ultrix = {
copyargs,
ULTRIX_EXEC_SETREGS,
NULL,
+ coredump_trad,
sigcode,
esigcode,
};
diff --git a/sys/kern/exec_elf.c b/sys/kern/exec_elf.c
index 2a0083906db..59197aba4a9 100644
--- a/sys/kern/exec_elf.c
+++ b/sys/kern/exec_elf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: exec_elf.c,v 1.67 2008/11/10 03:56:16 deraadt Exp $ */
+/* $OpenBSD: exec_elf.c,v 1.68 2009/03/05 19:52:24 kettenis Exp $ */
/*
* Copyright (c) 1996 Per Fogelstrom
@@ -31,6 +31,41 @@
*
*/
+/*
+ * Copyright (c) 2001 Wasabi Systems, Inc.
+ * All rights reserved.
+ *
+ * Written by Jason R. Thorpe for Wasabi Systems, Inc.
+ *
+ * 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 for the NetBSD Project by
+ * Wasabi Systems, Inc.
+ * 4. The name of Wasabi Systems, Inc. may not be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``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 WASABI SYSTEMS, INC
+ * 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.
+ */
+
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
@@ -40,10 +75,12 @@
#include <sys/mount.h>
#include <sys/namei.h>
#include <sys/vnode.h>
+#include <sys/core.h>
#include <sys/exec.h>
#include <sys/exec_elf.h>
#include <sys/exec_olf.h>
#include <sys/file.h>
+#include <sys/ptrace.h>
#include <sys/syscall.h>
#include <sys/signalvar.h>
#include <sys/stat.h>
@@ -90,6 +127,7 @@ int ELFNAME(check_header)(Elf_Ehdr *);
int ELFNAME(read_from)(struct proc *, struct vnode *, u_long, caddr_t, int);
void ELFNAME(load_psection)(struct exec_vmcmd_set *, struct vnode *,
Elf_Phdr *, Elf_Addr *, Elf_Addr *, int *, int);
+int ELFNAMEEND(coredump)(struct proc *, void *);
extern char sigcode[], esigcode[];
#ifdef SYSCALL_DEBUG
@@ -125,6 +163,7 @@ struct emul ELFNAMEEND(emul) = {
ELFNAME(copyargs),
setregs,
ELFNAME2(exec,fixup),
+ ELFNAMEEND(coredump),
sigcode,
esigcode,
EMUL_ENABLED | EMUL_NATIVE,
@@ -881,3 +920,438 @@ out1:
free(hph, M_TEMP);
return error;
}
+
+struct countsegs_state {
+ int npsections;
+};
+
+int ELFNAMEEND(coredump_countsegs)(struct proc *, void *,
+ struct uvm_coredump_state *);
+
+struct writesegs_state {
+ Elf_Phdr *psections;
+ off_t secoff;
+};
+
+int ELFNAMEEND(coredump_writeseghdrs)(struct proc *, void *,
+ struct uvm_coredump_state *);
+
+int ELFNAMEEND(coredump_notes)(struct proc *, void *, size_t *);
+int ELFNAMEEND(coredump_note)(struct proc *, void *, size_t *);
+int ELFNAMEEND(coredump_writenote)(struct proc *, void *, Elf_Note *,
+ const char *, void *);
+
+#define ELFROUNDSIZE 4 /* XXX Should it be sizeof(Elf_Word)? */
+#define elfround(x) roundup((x), ELFROUNDSIZE)
+
+int
+ELFNAMEEND(coredump)(struct proc *p, void *cookie)
+{
+ Elf_Ehdr ehdr;
+ Elf_Phdr phdr, *psections;
+ struct countsegs_state cs;
+ struct writesegs_state ws;
+ off_t notestart, secstart, offset;
+ size_t notesize;
+ int error, i;
+
+ psections = NULL;
+ /*
+ * We have to make a total of 3 passes across the map:
+ *
+ * 1. Count the number of map entries (the number of
+ * PT_LOAD sections).
+ *
+ * 2. Write the P-section headers.
+ *
+ * 3. Write the P-sections.
+ */
+
+ /* Pass 1: count the entries. */
+ cs.npsections = 0;
+ error = uvm_coredump_walkmap(p, NULL,
+ ELFNAMEEND(coredump_countsegs), &cs);
+ if (error)
+ goto out;
+
+ /* Count the PT_NOTE section. */
+ cs.npsections++;
+
+ /* Get the size of the notes. */
+ error = ELFNAMEEND(coredump_notes)(p, NULL, &notesize);
+ if (error)
+ goto out;
+
+ memset(&ehdr, 0, sizeof(ehdr));
+ memcpy(ehdr.e_ident, ELFMAG, SELFMAG);
+ ehdr.e_ident[EI_CLASS] = ELF_TARG_CLASS;
+ ehdr.e_ident[EI_DATA] = ELF_TARG_DATA;
+ ehdr.e_ident[EI_VERSION] = EV_CURRENT;
+ /* XXX Should be the OSABI/ABI version of the executable. */
+ ehdr.e_ident[EI_OSABI] = ELFOSABI_SYSV;
+ ehdr.e_ident[EI_ABIVERSION] = 0;
+ ehdr.e_type = ET_CORE;
+ /* XXX This should be the e_machine of the executable. */
+ ehdr.e_machine = ELF_TARG_MACH;
+ ehdr.e_version = EV_CURRENT;
+ ehdr.e_entry = 0;
+ ehdr.e_phoff = sizeof(ehdr);
+ ehdr.e_shoff = 0;
+ ehdr.e_flags = 0;
+ ehdr.e_ehsize = sizeof(ehdr);
+ ehdr.e_phentsize = sizeof(Elf_Phdr);
+ ehdr.e_phnum = cs.npsections;
+ ehdr.e_shentsize = 0;
+ ehdr.e_shnum = 0;
+ ehdr.e_shstrndx = 0;
+
+ /* Write out the ELF header. */
+ error = coredump_write(cookie, UIO_SYSSPACE, &ehdr, sizeof(ehdr));
+ if (error)
+ goto out;
+
+ offset = sizeof(ehdr);
+
+ notestart = offset + sizeof(phdr) * cs.npsections;
+ secstart = notestart + notesize;
+
+ psections = malloc(cs.npsections * sizeof(Elf_Phdr),
+ M_TEMP, M_WAITOK|M_ZERO);
+
+ /* Pass 2: now write the P-section headers. */
+ ws.secoff = secstart;
+ ws.psections = psections;
+ error = uvm_coredump_walkmap(p, cookie,
+ ELFNAMEEND(coredump_writeseghdrs), &ws);
+ if (error)
+ goto out;
+
+ /* Write out the PT_NOTE header. */
+ ws.psections->p_type = PT_NOTE;
+ ws.psections->p_offset = notestart;
+ ws.psections->p_vaddr = 0;
+ ws.psections->p_paddr = 0;
+ ws.psections->p_filesz = notesize;
+ ws.psections->p_memsz = 0;
+ ws.psections->p_flags = PF_R;
+ ws.psections->p_align = ELFROUNDSIZE;
+
+ error = coredump_write(cookie, UIO_SYSSPACE, psections,
+ cs.npsections * sizeof(Elf_Phdr));
+ if (error)
+ goto out;
+
+#ifdef DIAGNOSTIC
+ offset += cs.npsections * sizeof(Elf_Phdr);
+ if (offset != notestart)
+ panic("coredump: offset %lld != notestart %lld",
+ (long long) offset, (long long) notestart);
+#endif
+
+ /* Write out the notes. */
+ error = ELFNAMEEND(coredump_notes)(p, cookie, &notesize);
+ if (error)
+ goto out;
+
+#ifdef DIAGNOSTIC
+ offset += notesize;
+ if (offset != secstart)
+ panic("coredump: offset %lld != secstart %lld",
+ (long long) offset, (long long) secstart);
+#endif
+
+ /* Pass 3: finally, write the sections themselves. */
+ for (i = 0; i < cs.npsections - 1; i++) {
+ if (psections[i].p_filesz == 0)
+ continue;
+
+#ifdef DIAGNOSTIC
+ if (offset != psections[i].p_offset)
+ panic("coredump: offset %lld != p_offset[%d] %lld",
+ (long long) offset, i,
+ (long long) psections[i].p_filesz);
+#endif
+
+ error = coredump_write(cookie, UIO_USERSPACE,
+ (void *)(vaddr_t)psections[i].p_vaddr,
+ psections[i].p_filesz);
+ if (error)
+ goto out;
+
+#ifdef DIAGNOSTIC
+ offset += psections[i].p_filesz;
+#endif
+ }
+
+out:
+ return (error);
+}
+
+int
+ELFNAMEEND(coredump_countsegs)(struct proc *p, void *iocookie,
+ struct uvm_coredump_state *us)
+{
+ struct countsegs_state *cs = us->cookie;
+
+ cs->npsections++;
+ return (0);
+}
+
+int
+ELFNAMEEND(coredump_writeseghdrs)(struct proc *p, void *iocookie,
+ struct uvm_coredump_state *us)
+{
+ struct writesegs_state *ws = us->cookie;
+ Elf_Phdr phdr;
+ vsize_t size, realsize;
+
+ size = us->end - us->start;
+ realsize = us->realend - us->start;
+
+ phdr.p_type = PT_LOAD;
+ phdr.p_offset = ws->secoff;
+ phdr.p_vaddr = us->start;
+ phdr.p_paddr = 0;
+ phdr.p_filesz = realsize;
+ phdr.p_memsz = size;
+ phdr.p_flags = 0;
+ if (us->prot & VM_PROT_READ)
+ phdr.p_flags |= PF_R;
+ if (us->prot & VM_PROT_WRITE)
+ phdr.p_flags |= PF_W;
+ if (us->prot & VM_PROT_EXECUTE)
+ phdr.p_flags |= PF_X;
+ phdr.p_align = PAGE_SIZE;
+
+ ws->secoff += phdr.p_filesz;
+ *ws->psections++ = phdr;
+
+ return (0);
+}
+
+int
+ELFNAMEEND(coredump_notes)(struct proc *p, void *iocookie, size_t *sizep)
+{
+ struct ps_strings pss;
+ struct iovec iov;
+ struct uio uio;
+ struct elfcore_procinfo cpi;
+ Elf_Note nhdr;
+#ifdef RTHREADS
+ struct proc *q;
+#endif
+ size_t size, notesize;
+ int error;
+
+ size = 0;
+
+ /* First, write an elfcore_procinfo. */
+ notesize = sizeof(nhdr) + elfround(sizeof("OpenBSD")) +
+ elfround(sizeof(cpi));
+ if (iocookie) {
+ bzero(&cpi, sizeof(cpi));
+
+ cpi.cpi_version = ELFCORE_PROCINFO_VERSION;
+ cpi.cpi_cpisize = sizeof(cpi);
+ cpi.cpi_signo = p->p_sigacts->ps_sig;
+ cpi.cpi_sigcode = p->p_sigacts->ps_code;
+
+ cpi.cpi_sigpend = p->p_siglist;
+ cpi.cpi_sigmask = p->p_sigmask;
+ cpi.cpi_sigignore = p->p_sigignore;
+ cpi.cpi_sigcatch = p->p_sigcatch;
+
+ cpi.cpi_pid = p->p_pid;
+ cpi.cpi_ppid = p->p_pptr->p_pid;
+ cpi.cpi_pgrp = p->p_pgid;
+ cpi.cpi_sid = p->p_session->s_leader->p_pid;
+
+ cpi.cpi_ruid = p->p_cred->p_ruid;
+ cpi.cpi_euid = p->p_ucred->cr_uid;
+ cpi.cpi_svuid = p->p_cred->p_svuid;
+
+ cpi.cpi_rgid = p->p_cred->p_rgid;
+ cpi.cpi_egid = p->p_ucred->cr_gid;
+ cpi.cpi_svgid = p->p_cred->p_svgid;
+
+ (void)strlcpy(cpi.cpi_name, p->p_comm, sizeof(cpi.cpi_name));
+
+ nhdr.namesz = sizeof("OpenBSD");
+ nhdr.descsz = sizeof(cpi);
+ nhdr.type = NT_OPENBSD_PROCINFO;
+
+ error = ELFNAMEEND(coredump_writenote)(p, iocookie, &nhdr,
+ "OpenBSD", &cpi);
+ if (error)
+ return (error);
+ }
+ size += notesize;
+
+ /* Second, write an NT_OPENBSD_AUXV note. */
+ notesize = sizeof(nhdr) + elfround(sizeof("OpenBSD")) +
+ elfround(p->p_emul->e_arglen * sizeof(char *));
+ if (iocookie) {
+ iov.iov_base = &pss;
+ iov.iov_len = sizeof(pss);
+ uio.uio_iov = &iov;
+ uio.uio_iovcnt = 1;
+ uio.uio_offset = (off_t)PS_STRINGS;
+ uio.uio_resid = sizeof(pss);
+ uio.uio_segflg = UIO_SYSSPACE;
+ uio.uio_rw = UIO_READ;
+ uio.uio_procp = NULL;
+
+ error = uvm_io(&p->p_vmspace->vm_map, &uio, 0);
+ if (error)
+ return (error);
+
+ if (pss.ps_envstr == NULL)
+ return (EIO);
+
+ nhdr.namesz = sizeof("OpenBSD");
+ nhdr.descsz = p->p_emul->e_arglen * sizeof(char *);
+ nhdr.type = NT_OPENBSD_AUXV;
+
+ error = coredump_write(iocookie, UIO_SYSSPACE,
+ &nhdr, sizeof(nhdr));
+ if (error)
+ return (error);
+
+ error = coredump_write(iocookie, UIO_SYSSPACE,
+ "OpenBSD", elfround(nhdr.namesz));
+ if (error)
+ return (error);
+
+ error = coredump_write(iocookie, UIO_USERSPACE,
+ pss.ps_envstr + pss.ps_nenvstr + 1, nhdr.descsz);
+ if (error)
+ return (error);
+ }
+ size += notesize;
+
+#ifdef PT_WCOOKIE
+ notesize = sizeof(nhdr) + elfround(sizeof("OpenBSD")) +
+ elfround(sizeof(register_t));
+ if (iocookie) {
+ register_t wcookie;
+
+ nhdr.namesz = sizeof("OpenBSD");
+ nhdr.descsz = sizeof(register_t);
+ nhdr.type = NT_OPENBSD_WCOOKIE;
+
+ wcookie = process_get_wcookie(p);
+ error = ELFNAMEEND(coredump_writenote)(p, iocookie, &nhdr,
+ "OpenBSD", &wcookie);
+ if (error)
+ return (error);
+ }
+ size += notesize;
+#endif
+
+ /*
+ * Now write the register info for the thread that caused the
+ * coredump.
+ */
+ error = ELFNAMEEND(coredump_note)(p, iocookie, &notesize);
+ if (error)
+ return (error);
+ size += notesize;
+
+#ifdef RTHREADS
+ /*
+ * Now, for each thread, write the register info and any other
+ * per-thread notes. Since we're dumping core, we don't bother
+ * locking.
+ */
+ TAILQ_FOREACH(q, &p->p_p->ps_threads, p_thr_link) {
+ if (q == p) /* we've taken care of this thread */
+ continue;
+ error = ELFNAMEEND(coredump_note)(q, iocookie, &notesize);
+ if (error)
+ return (error);
+ size += notesize;
+ }
+#endif
+
+ *sizep = size;
+ return (0);
+}
+
+int
+ELFNAMEEND(coredump_note)(struct proc *p, void *iocookie, size_t *sizep)
+{
+ Elf_Note nhdr;
+ int size, notesize, error;
+ int namesize;
+ char name[64+ELFROUNDSIZE];
+ struct reg intreg;
+#ifdef PT_GETFPREGS
+ struct fpreg freg;
+#endif
+
+ size = 0;
+
+ snprintf(name, sizeof(name)-ELFROUNDSIZE, "%s@%d",
+ "OpenBSD", p->p_pid);
+ namesize = strlen(name) + 1;
+ memset(name + namesize, 0, elfround(namesize) - namesize);
+
+ notesize = sizeof(nhdr) + elfround(namesize) + elfround(sizeof(intreg));
+ if (iocookie) {
+ error = process_read_regs(p, &intreg);
+ if (error)
+ return (error);
+
+ nhdr.namesz = namesize;
+ nhdr.descsz = sizeof(intreg);
+ nhdr.type = NT_OPENBSD_REGS;
+
+ error = ELFNAMEEND(coredump_writenote)(p, iocookie, &nhdr,
+ name, &intreg);
+ if (error)
+ return (error);
+
+ }
+ size += notesize;
+
+#ifdef PT_GETFPREGS
+ notesize = sizeof(nhdr) + elfround(namesize) + elfround(sizeof(freg));
+ if (iocookie) {
+ error = process_read_fpregs(p, &freg);
+ if (error)
+ return (error);
+
+ nhdr.namesz = namesize;
+ nhdr.descsz = sizeof(freg);
+ nhdr.type = NT_OPENBSD_FPREGS;
+
+ error = ELFNAMEEND(coredump_writenote)(p, iocookie, &nhdr,
+ name, &freg);
+ if (error)
+ return (error);
+ }
+ size += notesize;
+#endif
+
+ *sizep = size;
+ /* XXX Add hook for machdep per-LWP notes. */
+ return (0);
+}
+
+int
+ELFNAMEEND(coredump_writenote)(struct proc *p, void *cookie, Elf_Note *nhdr,
+ const char *name, void *data)
+{
+ int error;
+
+ error = coredump_write(cookie, UIO_SYSSPACE, nhdr, sizeof(*nhdr));
+ if (error)
+ return error;
+
+ error = coredump_write(cookie, UIO_SYSSPACE, name,
+ elfround(nhdr->namesz));
+ if (error)
+ return error;
+
+ return coredump_write(cookie, UIO_SYSSPACE, data, nhdr->descsz);
+}
diff --git a/sys/kern/init_main.c b/sys/kern/init_main.c
index b9b7010788f..b65ebbc9393 100644
--- a/sys/kern/init_main.c
+++ b/sys/kern/init_main.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: init_main.c,v 1.157 2009/02/13 19:58:27 deraadt Exp $ */
+/* $OpenBSD: init_main.c,v 1.158 2009/03/05 19:52:24 kettenis Exp $ */
/* $NetBSD: init_main.c,v 1.84.4.1 1996/06/02 09:08:06 mrg Exp $ */
/*
@@ -39,6 +39,7 @@
*/
#include <sys/param.h>
+#include <sys/core.h>
#include <sys/filedesc.h>
#include <sys/file.h>
#include <sys/errno.h>
@@ -163,6 +164,7 @@ struct emul emul_native = {
copyargs,
setregs,
NULL,
+ coredump_trad,
sigcode,
esigcode,
EMUL_ENABLED | EMUL_NATIVE,
diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c
index ed52c212eca..15053a45b20 100644
--- a/sys/kern/kern_sig.c
+++ b/sys/kern/kern_sig.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kern_sig.c,v 1.102 2009/01/29 22:18:06 guenther Exp $ */
+/* $OpenBSD: kern_sig.c,v 1.103 2009/03/05 19:52:24 kettenis Exp $ */
/* $NetBSD: kern_sig.c,v 1.54 1996/04/22 01:38:32 christos Exp $ */
/*
@@ -1380,6 +1380,13 @@ sigexit(struct proc *p, int signum)
int nosuidcoredump = 1;
+struct coredump_iostate {
+ struct proc *io_proc;
+ struct vnode *io_vp;
+ struct ucred *io_cred;
+ off_t io_offset;
+};
+
/*
* Dump core, into a file named "progname.core", unless the process was
* setuid/setgid.
@@ -1392,10 +1399,10 @@ coredump(struct proc *p)
struct vmspace *vm = p->p_vmspace;
struct nameidata nd;
struct vattr vattr;
+ struct coredump_iostate io;
int error, error1, len;
char name[sizeof("/var/crash/") + MAXCOMLEN + sizeof(".core")];
char *dir = "";
- struct core core;
/*
* Don't dump if not root and the process has used set user or
@@ -1455,6 +1462,31 @@ coredump(struct proc *p)
bcopy(p, &p->p_addr->u_kproc.kp_proc, sizeof(struct proc));
fill_eproc(p, &p->p_addr->u_kproc.kp_eproc);
+ io.io_proc = p;
+ io.io_vp = vp;
+ io.io_cred = cred;
+ io.io_offset = 0;
+
+ error = (*p->p_emul->e_coredump)(p, &io);
+out:
+ VOP_UNLOCK(vp, 0, p);
+ error1 = vn_close(vp, FWRITE, cred, p);
+ crfree(cred);
+ if (error == 0)
+ error = error1;
+ return (error);
+}
+
+int
+coredump_trad(struct proc *p, void *cookie)
+{
+ struct coredump_iostate *io = cookie;
+ struct vmspace *vm = io->io_proc->p_vmspace;
+ struct vnode *vp = io->io_vp;
+ struct ucred *cred = io->io_cred;
+ struct core core;
+ int error;
+
core.c_midmag = 0;
strlcpy(core.c_name, p->p_comm, sizeof(core.c_name));
core.c_nseg = 0;
@@ -1466,26 +1498,41 @@ coredump(struct proc *p)
core.c_ssize = (u_long)round_page(ptoa(vm->vm_ssize));
error = cpu_coredump(p, vp, cred, &core);
if (error)
- goto out;
+ return (error);
/*
* uvm_coredump() spits out all appropriate segments.
* All that's left to do is to write the core header.
*/
error = uvm_coredump(p, vp, cred, &core);
if (error)
- goto out;
+ return (error);
error = vn_rdwr(UIO_WRITE, vp, (caddr_t)&core,
(int)core.c_hdrsize, (off_t)0,
UIO_SYSSPACE, IO_NODELOCKED|IO_UNIT, cred, NULL, p);
-out:
- VOP_UNLOCK(vp, 0, p);
- error1 = vn_close(vp, FWRITE, cred, p);
- crfree(cred);
- if (error == 0)
- error = error1;
return (error);
}
+int
+coredump_write(void *cookie, enum uio_seg segflg, const void *data, size_t len)
+{
+ struct coredump_iostate *io = cookie;
+ int error;
+
+ error = vn_rdwr(UIO_WRITE, io->io_vp, (void *)data, len,
+ io->io_offset, segflg,
+ IO_NODELOCKED|IO_UNIT, io->io_cred, NULL, io->io_proc);
+ if (error) {
+ printf("pid %d (%s): %s write of %zu@%p at %lld failed: %d\n",
+ io->io_proc->p_pid, io->io_proc->p_comm,
+ segflg == UIO_USERSPACE ? "user" : "system",
+ len, data, (long long) io->io_offset, error);
+ return (error);
+ }
+
+ io->io_offset += len;
+ return (0);
+}
+
/*
* Nonexistent system call-- signal process (may want to handle it).
* Flag error in case process won't see signal immediately (blocked or ignored).
diff --git a/sys/sys/core.h b/sys/sys/core.h
index 5aeb41b7dcc..941b63b32b0 100644
--- a/sys/sys/core.h
+++ b/sys/sys/core.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: core.h,v 1.3 2003/10/30 21:38:09 jmc Exp $ */
+/* $OpenBSD: core.h,v 1.4 2009/03/05 19:52:24 kettenis Exp $ */
/* $NetBSD: core.h,v 1.4 1994/10/29 08:20:14 cgd Exp $ */
/*
@@ -86,3 +86,9 @@ struct coreseg {
u_long c_addr; /* Virtual address of segment */
u_long c_size; /* Size of this segment */
};
+
+#ifdef _KERNEL
+int coredump_trad(struct proc *, void *);
+
+int coredump_write(void *, enum uio_seg, const void *, size_t);
+#endif
diff --git a/sys/sys/exec_elf.h b/sys/sys/exec_elf.h
index 6b8fb1c0a2f..72c4a5b2568 100644
--- a/sys/sys/exec_elf.h
+++ b/sys/sys/exec_elf.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: exec_elf.h,v 1.43 2007/05/14 05:04:58 tedu Exp $ */
+/* $OpenBSD: exec_elf.h,v 1.44 2009/03/05 19:52:24 kettenis Exp $ */
/*
* Copyright (c) 1995, 1996 Erik Theisen. All rights reserved.
*
@@ -481,6 +481,64 @@ typedef struct {
} Elf64_Note;
/*
+ * OpenBSD-specific core file information.
+ *
+ * OpenBSDBSD ELF core files use notes to provide information about
+ * the process's state. The note name is "OpenBSD" for information
+ * that is global to the process, and "OpenBSD@nn", where "nn" is the
+ * thread ID of the thread that the information belongs to (such as
+ * register state).
+ *
+ * We use the following note identifiers:
+ *
+ * NT_OPENBSD_PROCINFO
+ * Note is a "elfcore_procinfo" structure.
+ * NT_OPENBSD_AUXV
+ * Note is a a bunch of Auxilliary Vectors, terminted by
+ * an AT_NULL entry.
+ * NT_OPENBSD_REGS
+ * Note is a "reg" structure.
+ * NT_OPENBSD_FPREGS
+ * Note is a "fpreg" structure.
+ *
+ * Please try to keep the members of the "elfcore_procinfo" structure
+ * nicely aligned, and if you add elements, add them to the end and
+ * bump the version.
+ */
+
+#define NT_OPENBSD_PROCINFO 10
+#define NT_OPENBSD_AUXV 11
+
+#define NT_OPENBSD_REGS 20
+#define NT_OPENBSD_FPREGS 21
+#define NT_OPENBSD_XFPREGS 22
+#define NT_OPENBSD_WCOOKIE 23
+
+struct elfcore_procinfo {
+ /* Version 1 fields start here. */
+ uint32_t cpi_version; /* netbsd_elfcore_procinfo version */
+#define ELFCORE_PROCINFO_VERSION 1
+ uint32_t cpi_cpisize; /* sizeof(netbsd_elfcore_procinfo) */
+ uint32_t cpi_signo; /* killing signal */
+ uint32_t cpi_sigcode; /* signal code */
+ uint32_t cpi_sigpend; /* pending signals */
+ uint32_t cpi_sigmask; /* blocked signals */
+ uint32_t cpi_sigignore; /* ignored signals */
+ uint32_t cpi_sigcatch; /* signals being caught by user */
+ int32_t cpi_pid; /* process ID */
+ int32_t cpi_ppid; /* parent process ID */
+ int32_t cpi_pgrp; /* process group ID */
+ int32_t cpi_sid; /* session ID */
+ uint32_t cpi_ruid; /* real user ID */
+ uint32_t cpi_euid; /* effective user ID */
+ uint32_t cpi_svuid; /* saved user ID */
+ uint32_t cpi_rgid; /* real group ID */
+ uint32_t cpi_egid; /* effective group ID */
+ uint32_t cpi_svgid; /* saved group ID */
+ int8_t cpi_name[32]; /* copy of p->p_comm */
+};
+
+/*
* XXX - these _KERNEL items aren't part of the ABI!
*/
#if defined(_KERNEL) || defined(_DYN_LOADER)
diff --git a/sys/sys/proc.h b/sys/sys/proc.h
index d50bcdfc9b7..aeec114cec4 100644
--- a/sys/sys/proc.h
+++ b/sys/sys/proc.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: proc.h,v 1.111 2008/12/16 07:57:28 guenther Exp $ */
+/* $OpenBSD: proc.h,v 1.112 2009/03/05 19:52:24 kettenis Exp $ */
/* $NetBSD: proc.h,v 1.44 1996/04/22 01:23:21 christos Exp $ */
/*-
@@ -100,6 +100,7 @@ struct emul {
void (*e_setregs)(struct proc *, struct exec_package *,
u_long, register_t *);
int (*e_fixup)(struct proc *, struct exec_package *);
+ int (*e_coredump)(struct proc *, void *cookie);
char *e_sigcode; /* Start of sigcode */
char *e_esigcode; /* End of sigcode */
int e_flags; /* Flags, see below */
diff --git a/sys/uvm/uvm_extern.h b/sys/uvm/uvm_extern.h
index 2ec3f3431da..2e97ced5933 100644
--- a/sys/uvm/uvm_extern.h
+++ b/sys/uvm/uvm_extern.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: uvm_extern.h,v 1.73 2009/02/11 11:09:36 mikeb Exp $ */
+/* $OpenBSD: uvm_extern.h,v 1.74 2009/03/05 19:52:24 kettenis Exp $ */
/* $NetBSD: uvm_extern.h,v 1.57 2001/03/09 01:02:12 chs Exp $ */
/*
@@ -406,6 +406,20 @@ struct vmspace {
#ifdef _KERNEL
/*
+ * used to keep state while iterating over the map for a core dump.
+ */
+struct uvm_coredump_state {
+ void *cookie; /* opaque for the caller */
+ vaddr_t start; /* start of region */
+ vaddr_t realend; /* real end of region */
+ vaddr_t end; /* virtual end of region */
+ vm_prot_t prot; /* protection of region */
+ int flags; /* flags; see below */
+};
+
+#define UVM_COREDUMP_STACK 0x01 /* region is user stack */
+
+/*
* the various kernel maps, owned by MD code
*/
extern struct vm_map *exec_map;
@@ -574,6 +588,10 @@ void uvm_swap_init(void);
/* uvm_unix.c */
int uvm_coredump(struct proc *, struct vnode *,
struct ucred *, struct core *);
+int uvm_coredump_walkmap(struct proc *,
+ void *,
+ int (*)(struct proc *, void *,
+ struct uvm_coredump_state *), void *);
void uvm_grow(struct proc *, vaddr_t);
/* uvm_user.c */
diff --git a/sys/uvm/uvm_unix.c b/sys/uvm/uvm_unix.c
index 88601d6a810..118072ea12e 100644
--- a/sys/uvm/uvm_unix.c
+++ b/sys/uvm/uvm_unix.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uvm_unix.c,v 1.34 2008/03/02 20:29:20 kettenis Exp $ */
+/* $OpenBSD: uvm_unix.c,v 1.35 2009/03/05 19:52:24 kettenis Exp $ */
/* $NetBSD: uvm_unix.c,v 1.18 2000/09/13 15:00:25 thorpej Exp $ */
/*
@@ -255,3 +255,76 @@ uvm_coredump(p, vp, cred, chdr)
return (error);
}
+int
+uvm_coredump_walkmap(struct proc *p, void *iocookie,
+ int (*func)(struct proc *, void *, struct uvm_coredump_state *),
+ void *cookie)
+{
+ struct uvm_coredump_state state;
+ struct vmspace *vm = p->p_vmspace;
+ struct vm_map *map = &vm->vm_map;
+ struct vm_map_entry *entry;
+ vaddr_t top;
+ int error;
+
+ for (entry = map->header.next; entry != &map->header;
+ entry = entry->next) {
+
+ state.cookie = cookie;
+ state.prot = entry->protection;
+ state.flags = 0;
+
+ /* should never happen for a user process */
+ if (UVM_ET_ISSUBMAP(entry)) {
+ panic("uvm_coredump: user process with submap?");
+ }
+
+ if (!(entry->protection & VM_PROT_WRITE) &&
+ entry->start != p->p_sigcode)
+ continue;
+
+ /*
+ * Don't dump mmaped devices.
+ */
+ if (entry->object.uvm_obj != NULL &&
+ UVM_OBJ_IS_DEVICE(entry->object.uvm_obj))
+ continue;
+
+ state.start = entry->start;
+ state.realend = entry->end;
+ state.end = entry->end;
+
+ if (state.start >= VM_MAXUSER_ADDRESS)
+ continue;
+
+ if (state.end > VM_MAXUSER_ADDRESS)
+ state.end = VM_MAXUSER_ADDRESS;
+
+#ifdef MACHINE_STACK_GROWS_UP
+ if (USRSTACK <= state.start &&
+ state.start < (USRSTACK + MAXSSIZ)) {
+ top = round_page(USRSTACK + ptoa(vm->vm_ssize));
+ if (state.end > top)
+ state.end = top;
+
+ if (state.start >= state.end)
+ continue;
+#else
+ if (state.start >= (vaddr_t)vm->vm_maxsaddr) {
+ top = trunc_page(USRSTACK - ptoa(vm->vm_ssize));
+ if (state.start < top)
+ state.start = top;
+
+ if (state.start >= state.end)
+ continue;
+#endif
+ state.flags |= UVM_COREDUMP_STACK;
+ }
+
+ error = (*func)(p, iocookie, &state);
+ if (error)
+ return (error);
+ }
+
+ return (0);
+}