Module Name:    src
Committed By:   dsl
Date:           Fri Jan  3 15:15:02 UTC 2014

Modified Files:
        src/sys/kern: core_elf32.c core_netbsd.c
        src/sys/uvm: uvm_coredump.c uvm_extern.h

Log Message:
Minor changes to the process coredump code.
- Add some extra comments.
- Add some XXX comments because the process state might not be stable,
- Add uvm_coredump_count_segs() to simplify the calling code.
- uvm code now only returns non-empty sections/segments.
- Put the 'iocookie' into the 'cookie' block passed to uvm_coredump_walkmap()
  instead of passing it through as an additional parameter.
amd64 can still generate core dumps that gdb can read.


To generate a diff of this commit:
cvs rdiff -u -r1.37 -r1.38 src/sys/kern/core_elf32.c
cvs rdiff -u -r1.19 -r1.20 src/sys/kern/core_netbsd.c
cvs rdiff -u -r1.3 -r1.4 src/sys/uvm/uvm_coredump.c
cvs rdiff -u -r1.186 -r1.187 src/sys/uvm/uvm_extern.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/kern/core_elf32.c
diff -u src/sys/kern/core_elf32.c:1.37 src/sys/kern/core_elf32.c:1.38
--- src/sys/kern/core_elf32.c:1.37	Wed Jan  1 18:57:16 2014
+++ src/sys/kern/core_elf32.c	Fri Jan  3 15:15:02 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: core_elf32.c,v 1.37 2014/01/01 18:57:16 dsl Exp $	*/
+/*	$NetBSD: core_elf32.c,v 1.38 2014/01/03 15:15:02 dsl Exp $	*/
 
 /*
  * Copyright (c) 2001 Wasabi Systems, Inc.
@@ -40,7 +40,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(1, "$NetBSD: core_elf32.c,v 1.37 2014/01/01 18:57:16 dsl Exp $");
+__KERNEL_RCSID(1, "$NetBSD: core_elf32.c,v 1.38 2014/01/03 15:15:02 dsl Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_coredump.h"
@@ -66,20 +66,13 @@ __KERNEL_RCSID(1, "$NetBSD: core_elf32.c
 
 #ifdef COREDUMP
 
-struct countsegs_state {
-	int	npsections;
-};
-
-static int	ELFNAMEEND(coredump_countsegs)(struct proc *,
-		    struct coredump_iostate *, struct uvm_coredump_state *);
-
 struct writesegs_state {
 	Elf_Phdr *psections;
 	off_t	secoff;
 };
 
-static int	ELFNAMEEND(coredump_writeseghdrs)(struct proc *,
-		    struct coredump_iostate *, struct uvm_coredump_state *);
+static int	ELFNAMEEND(coredump_getseghdrs)(struct proc *,
+		    struct uvm_coredump_state *);
 
 static int	ELFNAMEEND(coredump_notes)(struct proc *, struct lwp *,
 		    struct coredump_iostate *, size_t *);
@@ -105,7 +98,7 @@ ELFNAMEEND(coredump)(struct lwp *l, stru
 	Elf_Ehdr ehdr;
 	Elf_Phdr phdr, *psections;
 	size_t psectionssize;
-	struct countsegs_state cs;
+	int npsections;
 	struct writesegs_state ws;
 	off_t notestart, secstart, offset;
 	size_t notesize;
@@ -117,7 +110,7 @@ ELFNAMEEND(coredump)(struct lwp *l, stru
 	 * 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).
+	 *	   PT_LOAD sections in the dump).
 	 *
 	 *	2. Write the P-section headers.
 	 *
@@ -125,16 +118,11 @@ ELFNAMEEND(coredump)(struct lwp *l, stru
 	 */
 
 	/* Pass 1: count the entries. */
-	cs.npsections = 0;
-	error = uvm_coredump_walkmap(p, NULL,
-	    ELFNAMEEND(coredump_countsegs), &cs);
-	if (error)
-		goto out;
-
+	npsections = uvm_coredump_count_segs(p);
 	/* Count the PT_NOTE section. */
-	cs.npsections++;
+	npsections++;
 
-	/* Get the size of the notes. */
+	/* Get the size of the notes (mostly all the registers). */
 	error = ELFNAMEEND(coredump_notes)(p, l, NULL, &notesize);
 	if (error)
 		goto out;
@@ -162,7 +150,7 @@ ELFNAMEEND(coredump)(struct lwp *l, stru
 	ehdr.e_flags = 0;
 	ehdr.e_ehsize = sizeof(ehdr);
 	ehdr.e_phentsize = sizeof(Elf_Phdr);
-	ehdr.e_phnum = cs.npsections;
+	ehdr.e_phnum = npsections;
 	ehdr.e_shentsize = 0;
 	ehdr.e_shnum = 0;
 	ehdr.e_shstrndx = 0;
@@ -178,21 +166,20 @@ ELFNAMEEND(coredump)(struct lwp *l, stru
 
 	offset = sizeof(ehdr);
 
-	notestart = offset + sizeof(phdr) * cs.npsections;
+	notestart = offset + sizeof(phdr) * npsections;
 	secstart = notestart + notesize;
 
-	psectionssize = cs.npsections * sizeof(Elf_Phdr);
+	psectionssize = npsections * sizeof(Elf_Phdr);
 	psections = kmem_zalloc(psectionssize, KM_SLEEP);
 
-	/* Pass 2: now write the P-section headers. */
+	/* Pass 2: now find the P-section headers. */
 	ws.secoff = secstart;
 	ws.psections = psections;
-	error = uvm_coredump_walkmap(p, cookie,
-	    ELFNAMEEND(coredump_writeseghdrs), &ws);
+	error = uvm_coredump_walkmap(p, ELFNAMEEND(coredump_getseghdrs), &ws);
 	if (error)
 		goto out;
 
-	/* Write out the PT_NOTE header. */
+	/* Add the PT_NOTE header after the P-section headers. */
 	ws.psections->p_type = PT_NOTE;
 	ws.psections->p_offset = notestart;
 	ws.psections->p_vaddr = 0;
@@ -202,13 +189,14 @@ ELFNAMEEND(coredump)(struct lwp *l, stru
 	ws.psections->p_flags = PF_R;
 	ws.psections->p_align = ELFROUNDSIZE;
 
+	/* Write the P-section headers followed by the PT_NOTR header */
 	error = coredump_write(cookie, UIO_SYSSPACE, psections,
-	    cs.npsections * sizeof(Elf_Phdr));
+	    npsections * sizeof(Elf_Phdr));
 	if (error)
 		goto out;
 
 #ifdef DIAGNOSTIC
-	offset += cs.npsections * sizeof(Elf_Phdr);
+	offset += npsections * sizeof(Elf_Phdr);
 	if (offset != notestart)
 		panic("coredump: offset %lld != notestart %lld",
 		    (long long) offset, (long long) notestart);
@@ -227,7 +215,7 @@ ELFNAMEEND(coredump)(struct lwp *l, stru
 #endif
 
 	/* Pass 3: finally, write the sections themselves. */
-	for (i = 0; i < cs.npsections - 1; i++) {
+	for (i = 0; i < npsections - 1; i++) {
 		if (psections[i].p_filesz == 0)
 			continue;
 
@@ -256,18 +244,7 @@ ELFNAMEEND(coredump)(struct lwp *l, stru
 }
 
 static int
-ELFNAMEEND(coredump_countsegs)(struct proc *p,
-    struct coredump_iostate *iocookie, struct uvm_coredump_state *us)
-{
-	struct countsegs_state *cs = us->cookie;
-
-	cs->npsections++;
-	return (0);
-}
-
-static int
-ELFNAMEEND(coredump_writeseghdrs)(struct proc *p,
-    struct coredump_iostate *iocookie, struct uvm_coredump_state *us)
+ELFNAMEEND(coredump_getseghdrs)(struct proc *p, struct uvm_coredump_state *us)
 {
 	struct writesegs_state *ws = us->cookie;
 	Elf_Phdr phdr;
@@ -279,6 +256,7 @@ ELFNAMEEND(coredump_writeseghdrs)(struct
 	realsize = us->realend - us->start;
 	end = us->realend;
 
+	/* Don't bother writing out trailing zeros */
 	while (realsize > 0) {
 		long buf[1024 / sizeof(long)];
 		size_t slen = realsize > sizeof(buf) ? sizeof(buf) : realsize;

Index: src/sys/kern/core_netbsd.c
diff -u src/sys/kern/core_netbsd.c:1.19 src/sys/kern/core_netbsd.c:1.20
--- src/sys/kern/core_netbsd.c:1.19	Wed Jan  1 18:57:16 2014
+++ src/sys/kern/core_netbsd.c	Fri Jan  3 15:15:02 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: core_netbsd.c,v 1.19 2014/01/01 18:57:16 dsl Exp $	*/
+/*	$NetBSD: core_netbsd.c,v 1.20 2014/01/03 15:15:02 dsl Exp $	*/
 
 /*
  * Copyright (c) 1997 Charles D. Cranor and Washington University.
@@ -45,7 +45,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: core_netbsd.c,v 1.19 2014/01/01 18:57:16 dsl Exp $");
+__KERNEL_RCSID(0, "$NetBSD: core_netbsd.c,v 1.20 2014/01/03 15:15:02 dsl Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_coredump.h"
@@ -70,13 +70,12 @@ __KERNEL_RCSID(0, "$NetBSD: core_netbsd.
 #ifdef COREDUMP
 
 struct coredump_state {
+	struct coredump_iostate *iocookie;
 	struct CORENAME(core) core;
 };
 
-static int	CORENAME(coredump_countsegs_netbsd)(struct proc *,
-		    struct coredump_iostate *, struct uvm_coredump_state *);
 static int	CORENAME(coredump_writesegs_netbsd)(struct proc *,
-		    struct coredump_iostate *, struct uvm_coredump_state *);
+		    struct uvm_coredump_state *);
 
 int
 CORENAME(coredump_netbsd)(struct lwp *l, struct coredump_iostate *iocookie)
@@ -86,6 +85,7 @@ CORENAME(coredump_netbsd)(struct lwp *l,
 	struct vmspace *vm = p->p_vmspace;
 	int error;
 
+	cs.iocookie = iocookie;
 	cs.core.c_midmag = 0;
 	strncpy(cs.core.c_name, p->p_comm, MAXCOMLEN);
 	cs.core.c_nseg = 0;
@@ -99,10 +99,7 @@ CORENAME(coredump_netbsd)(struct lwp *l,
 	error = CORENAME(cpu_coredump)(l, NULL, &cs.core);
 	if (error)
 		return (error);
-	error = uvm_coredump_walkmap(p, NULL,
-	    CORENAME(coredump_countsegs_netbsd), &cs);
-	if (error)
-		return (error);
+	cs.core.c_nseg = uvm_coredump_count_segs(p);
 
 	/* First write out the core header. */
 	error = coredump_write(iocookie, UIO_SYSSPACE, &cs.core,
@@ -116,33 +113,18 @@ CORENAME(coredump_netbsd)(struct lwp *l,
 		return (error);
 
 	/* Finally, the address space dump */
-	return uvm_coredump_walkmap(p, iocookie,
-	    CORENAME(coredump_writesegs_netbsd), &cs);
-}
-
-static int
-CORENAME(coredump_countsegs_netbsd)(struct proc *p,
-    struct coredump_iostate *iocookie, struct uvm_coredump_state *us)
-{
-	struct coredump_state *cs = us->cookie;
-
-	if (us->start != us->realend)
-		cs->core.c_nseg++;
-
-	return (0);
+	return uvm_coredump_walkmap(p, CORENAME(coredump_writesegs_netbsd),
+	    &cs);
 }
 
 static int
 CORENAME(coredump_writesegs_netbsd)(struct proc *p,
-    struct coredump_iostate *iocookie, struct uvm_coredump_state *us)
+    struct uvm_coredump_state *us)
 {
 	struct coredump_state *cs = us->cookie;
 	struct CORENAME(coreseg) cseg;
 	int flag, error;
 
-	if (us->start == us->realend)
-		return (0);
-
 	if (us->flags & UVM_COREDUMP_STACK)
 		flag = CORE_STACK;
 	else
@@ -155,12 +137,12 @@ CORENAME(coredump_writesegs_netbsd)(stru
 	cseg.c_addr = us->start;
 	cseg.c_size = us->end - us->start;
 
-	error = coredump_write(iocookie, UIO_SYSSPACE,
+	error = coredump_write(cs->iocookie, UIO_SYSSPACE,
 	    &cseg, cs->core.c_seghdrsize);
 	if (error)
 		return (error);
 
-	return coredump_write(iocookie, UIO_USERSPACE,
+	return coredump_write(cs->iocookie, UIO_USERSPACE,
 	    (void *)(vaddr_t)us->start, cseg.c_size);
 }
 

Index: src/sys/uvm/uvm_coredump.c
diff -u src/sys/uvm/uvm_coredump.c:1.3 src/sys/uvm/uvm_coredump.c:1.4
--- src/sys/uvm/uvm_coredump.c:1.3	Wed Jan  1 18:57:16 2014
+++ src/sys/uvm/uvm_coredump.c	Fri Jan  3 15:15:02 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: uvm_coredump.c,v 1.3 2014/01/01 18:57:16 dsl Exp $	*/
+/*	$NetBSD: uvm_coredump.c,v 1.4 2014/01/03 15:15:02 dsl Exp $	*/
 
 /*
  * Copyright (c) 1997 Charles D. Cranor and Washington University.
@@ -62,7 +62,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: uvm_coredump.c,v 1.3 2014/01/01 18:57:16 dsl Exp $");
+__KERNEL_RCSID(0, "$NetBSD: uvm_coredump.c,v 1.4 2014/01/03 15:15:02 dsl Exp $");
 
 /*
  * uvm_coredump.c: glue functions for coredump
@@ -77,13 +77,15 @@ __KERNEL_RCSID(0, "$NetBSD: uvm_coredump
 /*
  * uvm_coredump_walkmap: walk a process's map for the purpose of dumping
  * a core file.
+ * XXX: I'm not entirely sure the locking is this function is in anyway
+ * correct.  If the process isn't actually stopped then the data passed
+ * to func() is at best stale, and horrid things might happen if the
+ * entry being processed is deleted (dsl).
  */
 
 int
-uvm_coredump_walkmap(struct proc *p, struct coredump_iostate *iocookie,
-    int (*func)(struct proc *, struct coredump_iostate *,
-	struct uvm_coredump_state *),
-    void *cookie)
+uvm_coredump_walkmap(struct proc *p, int (*func)(struct proc *,
+    struct uvm_coredump_state *), void *cookie)
 {
 	struct uvm_coredump_state state;
 	struct vmspace *vm = p->p_vmspace;
@@ -183,10 +185,13 @@ uvm_coredump_walkmap(struct proc *p, str
 				amap_unlock(entry->aref.ar_amap);
 			}
 		}
-		
 
+		/* Ignore empty sections */
+		if (state.start == state.realend)
+			continue;
+		
 		vm_map_unlock_read(map);
-		error = (*func)(p, iocookie, &state);
+		error = (*func)(p, &state);
 		if (error)
 			return (error);
 		vm_map_lock_read(map);
@@ -195,3 +200,20 @@ uvm_coredump_walkmap(struct proc *p, str
 
 	return (0);
 }
+
+static int
+count_segs(struct proc *p, struct uvm_coredump_state *s)
+{
+    (*(int *)s->cookie)++;
+
+    return 0;
+}
+
+int
+uvm_coredump_count_segs(struct proc *p)
+{
+	int count = 0;
+
+	uvm_coredump_walkmap(p, count_segs, &count);
+	return count;
+}

Index: src/sys/uvm/uvm_extern.h
diff -u src/sys/uvm/uvm_extern.h:1.186 src/sys/uvm/uvm_extern.h:1.187
--- src/sys/uvm/uvm_extern.h:1.186	Wed Jan  1 18:57:16 2014
+++ src/sys/uvm/uvm_extern.h	Fri Jan  3 15:15:02 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: uvm_extern.h,v 1.186 2014/01/01 18:57:16 dsl Exp $	*/
+/*	$NetBSD: uvm_extern.h,v 1.187 2014/01/03 15:15:02 dsl Exp $	*/
 
 /*
  * Copyright (c) 1997 Charles D. Cranor and Washington University.
@@ -591,10 +591,9 @@ void			uvm_proc_fork(struct proc *, stru
 void			uvm_lwp_fork(struct lwp *, struct lwp *,
 			    void *, size_t, void (*)(void *), void *);
 struct coredump_iostate;
-int			uvm_coredump_walkmap(struct proc *,
-			    struct coredump_iostate *,
-			    int (*)(struct proc *, struct coredump_iostate *,
-				    struct uvm_coredump_state *), void *);
+int			uvm_coredump_walkmap(struct proc *, int (*)(struct proc *,
+			    struct uvm_coredump_state *), void *);
+int			uvm_coredump_count_segs(struct proc *);
 void			uvm_proc_exit(struct proc *);
 void			uvm_lwp_exit(struct lwp *);
 void			uvm_init_limits(struct proc *);

Reply via email to