Subject: Kernel support for ELF-format core files
To: None <tech-kern@netbsd.org>
From: Jason R Thorpe <thorpej@wasabisystems.com>
List: tech-kern
Date: 12/07/2001 17:16:40
--tThc/1wpZn/ma/RB
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

The attached patch implements support for dumping ELF-format core files.

ELF format core dumps basically are comprised of several PT_LOAD sections
(one for each chunk of the process's address space represented in the
core file) and a PT_NOTE section that contains other various bits of
information.

I had to invent a format for the notes in our ELF-format files, mostly
because the existing practice in Solaris and Linux wasn't flexible
enough to do what I wanted to do.

The goals of these changes are the following:

	* Support for processes with multiple LWPs.  This is
	  something that has to be supported for the nathanw_sa
	  branch (and the associated pthreads library).

	* Support for arbitrary extended register sets.  This includes
	  SSE/SSE2 on the x86, and AltiVec on the PowerPC.

The notes in the PT_NOTE section have the following names:

	* "NetBSD-CORE" for each note that applies to the entire
	  process (e.g. a procinfo note).

	* "NetBSD-CORE@nn" (where nn is the lwpid of the LWP) for
	  notes that apply only to the specified LWP (e.g. register
	  contents).  Since the kernel on the trunk doesn't yet support
	  LWPs, these currently just look like "NetBSD-CORE@0".

The notes in the PT_NOTE section have the following types and contents:

	* ELF_NOTE_NETBSD_CORE_PROCINFO (value 1).  The definition of
	  this structure is in the patch (obviously).  The structure
	  uses fixed-size types and is versioned for future expandability.

	* Machine-dependent note types.  These have the value of
	  the ptrace(2) request that would fetch the data that the
	  note contains, e.g. PT_GETREGS or PT_GETFPREGS.  I chose
	  these values because once they're selected for ptrace(2),
	  they're set in stone (for ABI compatibility), and they
	  happen to describe exactly what the note contains.

I have also updated BFD (bfd/elf.c) and GDB (gdb/i386nbsd-nat.c) to
support the new core file format.  Additional target support in GDB
will be trivial, since it's just a matter of adding a little bit
of glue code.  I will post my changes to the toolchain to tech-toolchain
separately.

-- 
        -- Jason R. Thorpe <thorpej@wasabisystems.com>

--tThc/1wpZn/ma/RB
Content-Type: text/plain; charset=us-ascii
Content-Description: elfcore.diff
Content-Disposition: attachment; filename="elfcore.diff"

Index: arch/alpha/include/elf_machdep.h
===================================================================
RCS file: /cvsroot/syssrc/sys/arch/alpha/include/elf_machdep.h,v
retrieving revision 1.9
diff -c -r1.9 elf_machdep.h
*** arch/alpha/include/elf_machdep.h	2001/11/01 12:54:35	1.9
--- arch/alpha/include/elf_machdep.h	2001/12/08 00:49:03
***************
*** 22,27 ****
--- 22,29 ----
  		case EM_ALPHA_EXP:					\
  			break;
  
+ #define	ELF64_MACHDEP_ID	EM_ALPHA_EXP	/* XXX */
+ 
  #define ARCH_ELFSIZE		64	/* MD native binary size */
  
  /*
Index: arch/arm/include/elf_machdep.h
===================================================================
RCS file: /cvsroot/syssrc/sys/arch/arm/include/elf_machdep.h,v
retrieving revision 1.2
diff -c -r1.2 elf_machdep.h
*** arch/arm/include/elf_machdep.h	2001/01/18 23:50:50	1.2
--- arch/arm/include/elf_machdep.h	2001/12/08 00:49:03
***************
*** 22,27 ****
--- 22,29 ----
  		case EM_ARM:						\
  			break;
  
+ #define	ELF32_MACHDEP_ID	EM_ARM
+ 
  #define ARCH_ELFSIZE		32	/* MD native binary size */
  
  /* Processor specific relocation types */
Index: arch/i386/include/elf_machdep.h
===================================================================
RCS file: /cvsroot/syssrc/sys/arch/i386/include/elf_machdep.h,v
retrieving revision 1.8
diff -c -r1.8 elf_machdep.h
*** arch/i386/include/elf_machdep.h	2000/04/02 15:35:49	1.8
--- arch/i386/include/elf_machdep.h	2001/12/08 00:49:03
***************
*** 10,15 ****
--- 10,17 ----
  #define	ELF64_MACHDEP_ID_CASES						\
  		/* no 64-bit ELF machine types supported */
  
+ #define	ELF32_MACHDEP_ID		EM_386
+ 
  #define ARCH_ELFSIZE		32	/* MD native binary size */
  
  /* i386 relocations */
Index: arch/m68k/include/elf_machdep.h
===================================================================
RCS file: /cvsroot/syssrc/sys/arch/m68k/include/elf_machdep.h,v
retrieving revision 1.5
diff -c -r1.5 elf_machdep.h
*** arch/m68k/include/elf_machdep.h	2000/04/02 15:35:49	1.5
--- arch/m68k/include/elf_machdep.h	2001/12/08 00:49:03
***************
*** 9,14 ****
--- 9,16 ----
  #define	ELF64_MACHDEP_ID_CASES						\
  		/* no 64-bit ELF machine types supported */
  
+ #define	ELF32_MACHDEP_ID	EM_68K
+ 
  #define ARCH_ELFSIZE		32	/* MD native binary size */
  
  /* m68k relocation types */
Index: arch/mips/include/elf_machdep.h
===================================================================
RCS file: /cvsroot/syssrc/sys/arch/mips/include/elf_machdep.h,v
retrieving revision 1.7
diff -c -r1.7 elf_machdep.h
*** arch/mips/include/elf_machdep.h	2000/04/02 15:35:50	1.7
--- arch/mips/include/elf_machdep.h	2001/12/08 00:49:03
***************
*** 8,13 ****
--- 8,16 ----
  		/* no 64-bit ELF machine types supported */
  
  
+ #define	ELF32_MACHDEP_ID	EM_MIPS
+ #define	ELF64_MACHDEP_ID	EM_MIPS
+ 
  #define ARCH_ELFSIZE		32	/* MD native binary size */
  
  /* mips relocs.  */
Index: arch/powerpc/include/elf_machdep.h
===================================================================
RCS file: /cvsroot/syssrc/sys/arch/powerpc/include/elf_machdep.h,v
retrieving revision 1.4
diff -c -r1.4 elf_machdep.h
*** arch/powerpc/include/elf_machdep.h	2000/04/02 15:35:50	1.4
--- arch/powerpc/include/elf_machdep.h	2001/12/08 00:49:03
***************
*** 9,14 ****
--- 9,16 ----
  #define	ELF64_MACHDEP_ID_CASES						\
  		/* no 64-bit ELF machine types supported */
  
+ #define	ELF32_MACHDEP_ID	EM_PPC
+ 
  #define ARCH_ELFSIZE		32	/* MD native binary size */
  
  #include <machine/reloc.h>		/* XXX */
Index: arch/sh3/include/elf_machdep.h
===================================================================
RCS file: /cvsroot/syssrc/sys/arch/sh3/include/elf_machdep.h,v
retrieving revision 1.4
diff -c -r1.4 elf_machdep.h
*** arch/sh3/include/elf_machdep.h	2001/03/29 03:23:33	1.4
--- arch/sh3/include/elf_machdep.h	2001/12/08 00:49:03
***************
*** 17,20 ****
--- 17,22 ----
  #define	ELF64_MACHDEP_ID_CASES						\
  		/* no 64-bit ELF machine types supported */
  
+ #define	ELF32_MACHDEP_ID	EM_SH
+ 
  #define ARCH_ELFSIZE		32	/* MD native binary size */
Index: arch/sparc/include/elf_machdep.h
===================================================================
RCS file: /cvsroot/syssrc/sys/arch/sparc/include/elf_machdep.h,v
retrieving revision 1.5
diff -c -r1.5 elf_machdep.h
*** arch/sparc/include/elf_machdep.h	2000/04/02 15:35:50	1.5
--- arch/sparc/include/elf_machdep.h	2001/12/08 00:49:03
***************
*** 12,17 ****
--- 12,19 ----
  		case EM_SPARCV9:					\
  		/* no 64-bit ELF machine types supported */
  
+ #define	ELF32_MACHDEP_ID	EM_SPARC	/* XXX right? */
+ 
  #define ARCH_ELFSIZE		32	/* MD native binary size */
  
  #define R_SPARC_NONE		0
Index: arch/sparc64/include/elf_machdep.h
===================================================================
RCS file: /cvsroot/syssrc/sys/arch/sparc64/include/elf_machdep.h,v
retrieving revision 1.7
diff -c -r1.7 elf_machdep.h
*** arch/sparc64/include/elf_machdep.h	2001/02/11 00:18:49	1.7
--- arch/sparc64/include/elf_machdep.h	2001/12/08 00:49:03
***************
*** 12,17 ****
--- 12,20 ----
  		case EM_SPARCV9:					\
  			break;
  
+ #define	ELF32_MACHDEP_ID	EM_SPARC32PLUS	/* XXX right? */
+ #define	ELF64_MACHDEP_ID	EM_SPARCV9	/* XXX right? */
+ 
  #ifdef __arch64__
  #define ARCH_ELFSIZE		64	/* MD native binary size */
  #else
Index: arch/sun2/include/elf_machdep.h
===================================================================
RCS file: /cvsroot/syssrc/sys/arch/sun2/include/elf_machdep.h,v
retrieving revision 1.2
diff -c -r1.2 elf_machdep.h
*** arch/sun2/include/elf_machdep.h	2001/06/27 19:20:22	1.2
--- arch/sun2/include/elf_machdep.h	2001/12/08 00:49:03
***************
*** 10,13 ****
--- 10,16 ----
                  case EM_68000:						\
                          break;
  
+ #undef	ELF32_MACHDEP_ID
+ #define	ELF32_MACHDEP_ID	EM_68000
+ 
  #endif
Index: arch/vax/include/elf_machdep.h
===================================================================
RCS file: /cvsroot/syssrc/sys/arch/vax/include/elf_machdep.h,v
retrieving revision 1.4
diff -c -r1.4 elf_machdep.h
*** arch/vax/include/elf_machdep.h	2000/07/13 03:18:22	1.4
--- arch/vax/include/elf_machdep.h	2001/12/08 00:49:03
***************
*** 9,14 ****
--- 9,16 ----
  #define	ELF64_MACHDEP_ID_CASES						\
  		/* no 64-bit ELF machine types supported */
  
+ #define	ELF32_MACHDEP_ID	EM_VAX
+ 
  #define ARCH_ELFSIZE		32	/* MD native binary size */
  
  /* VAX relocations */
Index: arch/x86_64/include/elf_machdep.h
===================================================================
RCS file: /cvsroot/syssrc/sys/arch/x86_64/include/elf_machdep.h,v
retrieving revision 1.2
diff -c -r1.2 elf_machdep.h
*** arch/x86_64/include/elf_machdep.h	2001/06/20 01:20:33	1.2
--- arch/x86_64/include/elf_machdep.h	2001/12/08 00:49:03
***************
*** 10,15 ****
--- 10,18 ----
  		case EM_X86_64:						\
  			break;
  
+ #define	ELF32_MACHDEP_ID	EM_386
+ #define	ELF64_MACHDEP_ID	EM_X86_64
+ 
  #define ARCH_ELFSIZE		64	/* MD native binary size */
  
  /* x86-64 relocations */
Index: kern/core_elf32.c
===================================================================
RCS file: core_elf32.c
diff -N core_elf32.c
*** /dev/null	Fri Dec  7 03:15:07 2001
--- core_elf32.c	Sat Dec  8 02:49:04 2001
***************
*** 0 ****
--- 1,424 ----
+ /*	$NetBSD$	*/
+ 
+ /*
+  * 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.
+  */
+ 
+ /*
+  * core_elf32.c/core_elf64.c: Support for the Elf32/Elf64 core file format.
+  */
+ 
+ #include <sys/cdefs.h>
+ __KERNEL_RCSID(1, "$NetBSD$");
+ 
+ /* If not included by core_elf64.c, ELFSIZE won't be defined. */
+ #ifndef ELFSIZE
+ #define	ELFSIZE		32
+ #endif
+ 
+ #include <sys/param.h>
+ #include <sys/systm.h>
+ #include <sys/proc.h>
+ #include <sys/vnode.h>
+ #include <sys/exec_elf.h>
+ #include <sys/ptrace.h>
+ 
+ #include <machine/reg.h>
+ 
+ #include <uvm/uvm.h>
+ 
+ int	ELFNAMEEND(coredump_notes)(struct proc *, struct vnode *,
+ 	    struct ucred *, int *, off_t);
+ 
+ #define	ELFROUNDSIZE	4	/* XXX Should it be sizeof(Elf_Word)? */
+ #define	elfround(x)	roundup((x), ELFROUNDSIZE)
+ 
+ int
+ ELFNAMEEND(coredump)(struct proc *p, struct vnode *vp, struct ucred *cred)
+ {
+ 	Elf_Ehdr ehdr;
+ 	Elf_Phdr phdr;
+ 	struct vmspace *vm = p->p_vmspace;
+ 	struct vm_map *map = &vm->vm_map;
+ 	struct vm_map_entry *entry;
+ 	vaddr_t start, end, maxstack;
+ 	vsize_t size;
+ 	off_t offset, secoff, notestart, secstart;
+ 	int npsections, notesize, error;
+ 
+ 	maxstack = trunc_page(USRSTACK - ctob(vm->vm_ssize));
+ 
+ 	/*
+ 	 * 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. */
+ 	npsections = 0;
+ 	for (entry = map->header.next; entry != &map->header;
+ 	     entry = entry->next) {
+ 		/* Should never happen for a user process. */
+ 		if (UVM_ET_ISSUBMAP(entry))
+ 			panic("coredump_elf: user process with submap?");
+ 
+ 		if (entry->start >= VM_MAXUSER_ADDRESS)
+ 			continue;
+ 
+ 		if (entry->start >= (vaddr_t)vm->vm_maxsaddr &&
+ 		    entry->end <= maxstack)
+ 			continue;
+ 
+ 		npsections++;
+ 	}
+ 
+ 	/* Get the size of the notes. */
+ 	error = ELFNAMEEND(coredump_notes)(p, vp, cred, &notesize, 0);
+ 	if (error)
+ 		return (error);
+ 
+ 	/* Count the PT_NOTE section. */
+ 	npsections++;
+ 
+ 	memcpy(ehdr.e_ident, ELFMAG, SELFMAG);
+ #if ELFSIZE == 32
+ 	ehdr.e_ident[EI_CLASS] = ELFCLASS32;
+ #elif ELFSIZE == 64
+ 	ehdr.e_ident[EI_CLASS] = ELFCLASS64;
+ #endif
+ 	ehdr.e_ident[EI_DATA] = ELFDEFNNAME(MACHDEP_ENDIANNESS);
+ 	ehdr.e_ident[EI_VERSION] = EV_CURRENT;
+ 
+ 	ehdr.e_type = ET_CORE;
+ 	/* XXX This should be the e_machine of the executable. */
+ 	ehdr.e_machine = ELFDEFNNAME(MACHDEP_ID);
+ 	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 = npsections;
+ 	ehdr.e_shentsize = 0;
+ 	ehdr.e_shnum = 0;
+ 	ehdr.e_shstrndx = 0;
+ 
+ 	/* Write out the ELF header. */
+ 	error = vn_rdwr(UIO_WRITE, vp, (caddr_t)&ehdr,
+ 	    (int)sizeof(ehdr), (off_t)0,
+ 	    UIO_SYSSPACE, IO_NODELOCKED|IO_UNIT, cred, NULL, p);
+ 
+ 	offset = ehdr.e_phoff;
+ 	notestart = offset + (sizeof(phdr) * npsections);
+ 	secstart = round_page(notestart + notesize);
+ 
+ 	/*
+ 	 * Now write the P-section headers.
+ 	 */
+ 	secoff = secstart;
+ 	for (entry = map->header.next; entry != &map->header;
+ 	     entry = entry->next) {
+ 		start = entry->start;
+ 		end = entry->end;
+ 
+ 		if (start >= VM_MAXUSER_ADDRESS)
+ 			continue;
+ 
+ 		if (end > VM_MAXUSER_ADDRESS)
+ 			end = VM_MAXUSER_ADDRESS;
+ 
+ 		if (start >= (vaddr_t)vm->vm_maxsaddr) {
+ 			if (end <= maxstack)
+ 				continue;
+ 			if (start < maxstack)
+ 				start = maxstack; 
+ 		}
+ 
+ 		size = end - start;
+ 
+ 		phdr.p_type = PT_LOAD;
+ 		phdr.p_offset = secoff;
+ 		phdr.p_vaddr = start;
+ 		phdr.p_paddr = 0;
+ 		phdr.p_filesz = (entry->protection & VM_PROT_WRITE) ? size : 0;
+ 		phdr.p_memsz = 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;
+ 		phdr.p_align = PAGE_SIZE;
+ 
+ 		error = vn_rdwr(UIO_WRITE, vp,
+ 		    (caddr_t)&phdr, sizeof(phdr),
+ 		    offset, UIO_SYSSPACE,
+ 		    IO_NODELOCKED|IO_UNIT, cred, NULL, p);
+ 		if (error)
+ 			return (error);
+ 
+ 		offset += sizeof(phdr);
+ 		secoff += phdr.p_filesz;
+ 	}
+ 
+ 	/* Write out the PT_NOTE header. */
+ 	phdr.p_type = PT_NOTE;
+ 	phdr.p_offset = notestart;
+ 	phdr.p_vaddr = 0;
+ 	phdr.p_paddr = 0;
+ 	phdr.p_filesz = notesize;
+ 	phdr.p_memsz = 0;
+ 	phdr.p_flags = PF_R;
+ 	phdr.p_align = ELFROUNDSIZE;
+ 
+ 	error = vn_rdwr(UIO_WRITE, vp,
+ 	    (caddr_t)&phdr, sizeof(phdr),
+ 	    offset, UIO_SYSSPACE,
+ 	    IO_NODELOCKED|IO_UNIT, cred, NULL, p);
+ 	if (error)
+ 		return (error);
+ 
+ 	offset += sizeof(phdr);
+ 
+ 	KASSERT(offset == notestart);
+ 
+ 	/* Write out the notes. */
+ 	error = ELFNAMEEND(coredump_notes)(p, vp, cred, &notesize, offset);
+ 	if (error)
+ 		return (error);
+ 
+ 	offset += notesize;
+ 
+ 	/* ...and write out the sections. */
+ 	secoff = secstart;
+ 	for (entry = map->header.next; entry != &map->header;
+ 	     entry = entry->next) {
+ 		start = entry->start;
+ 		end = entry->end;
+ 
+ 		if (start >= VM_MAXUSER_ADDRESS)
+ 			continue;
+ 
+ 		if (end > VM_MAXUSER_ADDRESS)
+ 			end = VM_MAXUSER_ADDRESS;
+ 
+ 		if (start >= (vaddr_t)vm->vm_maxsaddr) {
+ 			if (end <= maxstack)
+ 				continue;
+ 			if (start < maxstack)
+ 				start = maxstack; 
+ 		}
+ 
+ 		size = end - start;
+ 
+ 		if ((entry->protection & VM_PROT_WRITE) == 0) {
+ 			/* Not actually written out. */
+ 			continue;
+ 		}
+ 
+ 		error = vn_rdwr(UIO_WRITE, vp,
+ 		    (caddr_t)start, size,
+ 		    secoff, UIO_USERSPACE,
+ 		    IO_NODELOCKED|IO_UNIT, cred, NULL, p);
+ 		if (error)
+ 			return (error);
+ 
+ 		secoff += size;
+ 	}
+ 
+ 	return (0);
+ }
+ 
+ int
+ ELFNAMEEND(coredump_notes)(struct proc *p, struct vnode *vp,
+     struct ucred *cred, int *sizep, off_t offset)
+ {
+ 	struct netbsd_elfcore_procinfo cpi;
+ 	Elf_Nhdr nhdr;
+ 	int size, notesize, error;
+ 	char name[64];
+ 	int namesize;
+ 	struct reg intreg;
+ #ifdef PT_GETFPREGS
+ 	struct fpreg freg;
+ #endif
+ 
+ 	size = 0;
+ 
+ 	/* First, write an elfcore_procinfo. */
+ 	notesize = sizeof(nhdr) + elfround(sizeof(ELF_NOTE_NETBSD_CORE_NAME)) +
+ 	    elfround(sizeof(cpi));
+ 	if (offset) {
+ 		cpi.cpi_version = NETBSD_ELFCORE_PROCINFO_VERSION;
+ 		cpi.cpi_cpisize = sizeof(cpi);
+ 		cpi.cpi_signo = p->p_sigctx.ps_sig;
+ 		cpi.cpi_sigcode = p->p_sigctx.ps_code;
+ 
+ 		memcpy(&cpi.cpi_sigpend, &p->p_sigctx.ps_siglist,
+ 		    sizeof(cpi.cpi_sigpend));
+ 		memcpy(&cpi.cpi_sigmask, &p->p_sigctx.ps_sigmask,
+ 		    sizeof(cpi.cpi_sigmask));
+ 		memcpy(&cpi.cpi_sigignore, &p->p_sigctx.ps_sigignore,
+ 		    sizeof(cpi.cpi_sigignore));
+ 		memcpy(&cpi.cpi_sigcatch, &p->p_sigctx.ps_sigcatch,
+ 		    sizeof(cpi.cpi_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_sid;
+ 
+ 		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;
+ 
+ 		cpi.cpi_nlwps = 1;	/* XXX for now */
+ 		strcpy(cpi.cpi_name, p->p_comm);
+ 
+ 		nhdr.n_namesz = sizeof(ELF_NOTE_NETBSD_CORE_NAME);
+ 		nhdr.n_descsz = sizeof(cpi);
+ 		nhdr.n_type = ELF_NOTE_NETBSD_CORE_PROCINFO;
+ 
+ 		error = ELFNAMEEND(coredump_writenote)(p, vp, cred, offset,
+ 		    &nhdr, ELF_NOTE_NETBSD_CORE_NAME, &cpi);
+ 		if (error)
+ 			return (error);
+ 
+ 		offset += notesize;
+ 	}
+ 
+ 	size += notesize;
+ 
+ 	/* XXX Add hook for machdep per-proc notes. */
+ 
+ 	/*
+ 	 * Now, for each LWP, write the register info and any other
+ 	 * per-LWP notes.
+ 	 */
+ 	do {
+ 		/* XXX Only one LWP for now. */
+ 		sprintf(name, "%s@%d", ELF_NOTE_NETBSD_CORE_NAME, 0);
+ 		namesize = strlen(name) + 1;
+ 
+ 		notesize = sizeof(nhdr) + elfround(namesize) +
+ 		    elfround(sizeof(intreg));
+ 		if (offset) {
+ 			error = process_read_regs(p, &intreg);
+ 			if (error)
+ 				return (error);
+ 
+ 			nhdr.n_namesz = namesize;
+ 			nhdr.n_descsz = sizeof(intreg);
+ 			nhdr.n_type = PT_GETREGS;
+ 
+ 			error = ELFNAMEEND(coredump_writenote)(p, vp, cred,
+ 			    offset, &nhdr, name, &intreg);
+ 			if (error)
+ 				return (error);
+ 
+ 			offset += notesize;
+ 		}
+ 		size += notesize;
+ 
+ #ifdef PT_GETFPREGS
+ 		notesize = sizeof(nhdr) + elfround(namesize) +
+ 		    elfround(sizeof(freg));
+ 		if (offset) {
+ 			error = process_read_fpregs(p, &freg);
+ 			if (error)
+ 				return (error);
+ 
+ 			nhdr.n_namesz = namesize;
+ 			nhdr.n_descsz = sizeof(freg);
+ 			nhdr.n_type = PT_GETFPREGS;
+ 
+ 			error = ELFNAMEEND(coredump_writenote)(p, vp, cred,
+ 			    offset, &nhdr, name, &freg);
+ 			if (error)
+ 				return (error);
+ 
+ 			offset += notesize;
+ 		}
+ 		size += notesize;
+ #endif
+ 		/* XXX Add hook for machdep per-LWP notes. */
+ 	} while (/*CONSTCOND*/0);
+ 
+ 	*sizep = size;
+ 	return (0);
+ }
+ 
+ int
+ ELFNAMEEND(coredump_writenote)(struct proc *p, struct vnode *vp,
+     struct ucred *cred, off_t offset, Elf_Nhdr *nhdr, const char *name,
+     void *data)
+ {
+ 	int error;
+ 
+ 	error = vn_rdwr(UIO_WRITE, vp,
+ 	    (caddr_t) nhdr, sizeof(*nhdr),
+ 	    offset, UIO_SYSSPACE,
+ 	    IO_NODELOCKED|IO_UNIT, cred, NULL, p);
+ 	if (error)
+ 		return (error);
+ 
+ 	offset += sizeof(*nhdr);
+ 
+ 	error = vn_rdwr(UIO_WRITE, vp,
+ 	    (caddr_t)name, nhdr->n_namesz,
+ 	    offset, UIO_SYSSPACE,
+ 	    IO_NODELOCKED|IO_UNIT, cred, NULL, p);
+ 	if (error)
+ 		return (error);
+ 
+ 	offset += elfround(nhdr->n_namesz);
+ 
+ 	error = vn_rdwr(UIO_WRITE, vp,
+ 	    data, nhdr->n_descsz,
+ 	    offset, UIO_SYSSPACE,
+ 	    IO_NODELOCKED|IO_UNIT, cred, NULL, p);
+ 
+ 	return (error);
+ }
Index: kern/core_elf64.c
===================================================================
RCS file: core_elf64.c
diff -N core_elf64.c
*** /dev/null	Fri Dec  7 03:15:07 2001
--- core_elf64.c	Sat Dec  8 02:49:04 2001
***************
*** 0 ****
--- 1,43 ----
+ /*	$NetBSD$	*/
+ 
+ /*
+  * 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/cdefs.h>
+ __KERNEL_RCSID(0, "$NetBSD$");
+ 
+ #define	ELFSIZE	64
+ 
+ #include "core_elf32.c"
Index: sys/exec_elf.h
===================================================================
RCS file: /cvsroot/syssrc/sys/sys/exec_elf.h,v
retrieving revision 1.58
diff -c -r1.58 exec_elf.h
*** sys/exec_elf.h	2001/10/31 18:05:35	1.58
--- sys/exec_elf.h	2001/12/08 00:49:05
***************
*** 650,655 ****
--- 650,709 ----
  /* NetBSD-specific note name */
  #define	ELF_NOTE_NETBSD_NAME		"NetBSD\0\0"
  
+ /*
+  * NetBSD-specific core file information.
+  *
+  * NetBSD ELF core files use notes to provide information about
+  * the process's state.  The note name is "NetBSD-CORE" for
+  * information that is global to the process, and "NetBSD-CORE@nn",
+  * where "nn" is the lwpid of the LWP that the information belongs
+  * to (such as register state).
+  *
+  * We use the following note identifiers:
+  *
+  *	ELF_NOTE_NETBSD_CORE_PROCINFO
+  *		Note is a "netbsd_elfcore_procinfo" structure.
+  *
+  * We also use ptrace(2) request numbers (the ones that exist in
+  * machine-dependent space) to identify register info notes.  The
+  * info in such notes is in the same format that ptrace(2) would
+  * export that information.
+  *
+  * Please try to keep the members of this structure nicely aligned,
+  * and if you add elements, add them to the end and bump the version.
+  */
+ 
+ #define	ELF_NOTE_NETBSD_CORE_NAME	"NetBSD-CORE"
+ 
+ #define	ELF_NOTE_NETBSD_CORE_PROCINFO	1
+ 
+ #define	NETBSD_ELFCORE_PROCINFO_VERSION	1
+ 
+ struct netbsd_elfcore_procinfo {
+ 	/* Version 1 fields start here. */
+ 	uint32_t	cpi_version;	/* netbsd_elfcore_procinfo version */
+ 	uint32_t	cpi_cpisize;	/* sizeof(netbsd_elfcore_procinfo) */
+ 	uint32_t	cpi_signo;	/* killing signal */
+ 	uint32_t	cpi_sigcode;	/* signal code */
+ 	uint32_t	cpi_sigpend[4];	/* pending signals */
+ 	uint32_t	cpi_sigmask[4];	/* blocked signals */
+ 	uint32_t	cpi_sigignore[4];/* blocked signals */
+ 	uint32_t	cpi_sigcatch[4];/* blocked signals */
+ 	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 */
+ 	uint32_t	cpi_nlwps;	/* number of LWPs */
+ 	int8_t		cpi_name[32];	/* copy of p->p_comm */
+ 	/* Add version 2 fields below here. */
+ };
+ 
  #if defined(ELFSIZE)
  #define	CONCAT(x,y)	__CONCAT(x,y)
  #define	ELFNAME(x)	CONCAT(elf,CONCAT(ELFSIZE,CONCAT(_,x)))
***************
*** 736,741 ****
--- 790,799 ----
  int	exec_elf32_makecmds __P((struct proc *, struct exec_package *));
  int	elf32_copyargs __P((struct exec_package *, struct ps_strings *,
      char **, void *));
+ 
+ int	coredump_elf32 __P((struct proc *, struct vnode *, struct ucred *));
+ int	coredump_writenote_elf32 __P((struct proc *, struct vnode *,
+ 	    struct ucred *, off_t, Elf32_Nhdr *, const char *, void *));
  #endif
  
  #ifdef EXEC_ELF64
***************
*** 744,749 ****
--- 802,811 ----
      caddr_t, int));
  int	elf64_copyargs __P((struct exec_package *, struct ps_strings *,
      char **, void *));
+ 
+ int	coredump_elf64 __P((struct proc *, struct vnode *, struct ucred *));
+ int	coredump_writenote_elf64 __P((struct proc *, struct vnode *,
+ 	    struct ucred *, off_t, Elf64_Nhdr *, const char *, void *));
  #endif
  
  /* common */

--tThc/1wpZn/ma/RB--