xref: /onnv-gate/usr/src/uts/common/exec/elf/elf_notes.c (revision 0:68f95e015346)
1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  * CDDL HEADER START
3*0Sstevel@tonic-gate  *
4*0Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*0Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*0Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*0Sstevel@tonic-gate  * with the License.
8*0Sstevel@tonic-gate  *
9*0Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*0Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*0Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*0Sstevel@tonic-gate  * and limitations under the License.
13*0Sstevel@tonic-gate  *
14*0Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*0Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*0Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*0Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*0Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*0Sstevel@tonic-gate  *
20*0Sstevel@tonic-gate  * CDDL HEADER END
21*0Sstevel@tonic-gate  */
22*0Sstevel@tonic-gate /*
23*0Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24*0Sstevel@tonic-gate  * Use is subject to license terms.
25*0Sstevel@tonic-gate  */
26*0Sstevel@tonic-gate 
27*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*0Sstevel@tonic-gate 
29*0Sstevel@tonic-gate #include <sys/types.h>
30*0Sstevel@tonic-gate #include <sys/param.h>
31*0Sstevel@tonic-gate #include <sys/thread.h>
32*0Sstevel@tonic-gate #include <sys/sysmacros.h>
33*0Sstevel@tonic-gate #include <sys/signal.h>
34*0Sstevel@tonic-gate #include <sys/cred.h>
35*0Sstevel@tonic-gate #include <sys/priv.h>
36*0Sstevel@tonic-gate #include <sys/user.h>
37*0Sstevel@tonic-gate #include <sys/errno.h>
38*0Sstevel@tonic-gate #include <sys/vnode.h>
39*0Sstevel@tonic-gate #include <sys/mman.h>
40*0Sstevel@tonic-gate #include <sys/kmem.h>
41*0Sstevel@tonic-gate #include <sys/proc.h>
42*0Sstevel@tonic-gate #include <sys/pathname.h>
43*0Sstevel@tonic-gate #include <sys/cmn_err.h>
44*0Sstevel@tonic-gate #include <sys/systm.h>
45*0Sstevel@tonic-gate #include <sys/elf.h>
46*0Sstevel@tonic-gate #include <sys/vmsystm.h>
47*0Sstevel@tonic-gate #include <sys/debug.h>
48*0Sstevel@tonic-gate #include <sys/procfs.h>
49*0Sstevel@tonic-gate #include <sys/regset.h>
50*0Sstevel@tonic-gate #include <sys/auxv.h>
51*0Sstevel@tonic-gate #include <sys/exec.h>
52*0Sstevel@tonic-gate #include <sys/prsystm.h>
53*0Sstevel@tonic-gate #include <sys/utsname.h>
54*0Sstevel@tonic-gate #include <sys/zone.h>
55*0Sstevel@tonic-gate #include <vm/as.h>
56*0Sstevel@tonic-gate #include <vm/rm.h>
57*0Sstevel@tonic-gate #include <sys/modctl.h>
58*0Sstevel@tonic-gate #include <sys/systeminfo.h>
59*0Sstevel@tonic-gate #include <sys/machelf.h>
60*0Sstevel@tonic-gate #include "elf_impl.h"
61*0Sstevel@tonic-gate #if defined(__i386) || defined(__i386_COMPAT)
62*0Sstevel@tonic-gate #include <sys/sysi86.h>
63*0Sstevel@tonic-gate #endif
64*0Sstevel@tonic-gate 
65*0Sstevel@tonic-gate void
setup_note_header(Phdr * v,proc_t * p)66*0Sstevel@tonic-gate setup_note_header(Phdr *v, proc_t *p)
67*0Sstevel@tonic-gate {
68*0Sstevel@tonic-gate 	int nlwp = p->p_lwpcnt;
69*0Sstevel@tonic-gate 	int nzomb = p->p_zombcnt;
70*0Sstevel@tonic-gate 	size_t size;
71*0Sstevel@tonic-gate 	prcred_t *pcrp;
72*0Sstevel@tonic-gate 
73*0Sstevel@tonic-gate 	v[0].p_type = PT_NOTE;
74*0Sstevel@tonic-gate 	v[0].p_flags = PF_R;
75*0Sstevel@tonic-gate 	v[0].p_filesz = (sizeof (Note) * (9 + 2 * nlwp + nzomb))
76*0Sstevel@tonic-gate 	    + roundup(sizeof (psinfo_t), sizeof (Word))
77*0Sstevel@tonic-gate 	    + roundup(sizeof (pstatus_t), sizeof (Word))
78*0Sstevel@tonic-gate 	    + roundup(prgetprivsize(), sizeof (Word))
79*0Sstevel@tonic-gate 	    + roundup(priv_get_implinfo_size(), sizeof (Word))
80*0Sstevel@tonic-gate 	    + roundup(strlen(platform) + 1, sizeof (Word))
81*0Sstevel@tonic-gate 	    + roundup(strlen(p->p_zone->zone_name) + 1, sizeof (Word))
82*0Sstevel@tonic-gate 	    + roundup(__KERN_NAUXV_IMPL * sizeof (aux_entry_t), sizeof (Word))
83*0Sstevel@tonic-gate 	    + roundup(sizeof (utsname), sizeof (Word))
84*0Sstevel@tonic-gate 	    + roundup(sizeof (core_content_t), sizeof (Word))
85*0Sstevel@tonic-gate 	    + (nlwp + nzomb) * roundup(sizeof (lwpsinfo_t), sizeof (Word))
86*0Sstevel@tonic-gate 	    + nlwp * roundup(sizeof (lwpstatus_t), sizeof (Word));
87*0Sstevel@tonic-gate 
88*0Sstevel@tonic-gate 	size = sizeof (prcred_t) + sizeof (gid_t) * (ngroups_max - 1);
89*0Sstevel@tonic-gate 	pcrp = kmem_alloc(size, KM_SLEEP);
90*0Sstevel@tonic-gate 	prgetcred(p, pcrp);
91*0Sstevel@tonic-gate 	if (pcrp->pr_ngroups != 0) {
92*0Sstevel@tonic-gate 		v[0].p_filesz += sizeof (Note) + roundup(sizeof (prcred_t) +
93*0Sstevel@tonic-gate 		    sizeof (gid_t) * (pcrp->pr_ngroups - 1), sizeof (Word));
94*0Sstevel@tonic-gate 	} else {
95*0Sstevel@tonic-gate 		v[0].p_filesz += sizeof (Note) +
96*0Sstevel@tonic-gate 		    roundup(sizeof (prcred_t), sizeof (Word));
97*0Sstevel@tonic-gate 	}
98*0Sstevel@tonic-gate 	kmem_free(pcrp, size);
99*0Sstevel@tonic-gate 
100*0Sstevel@tonic-gate #if defined(__i386) || defined(__i386_COMPAT)
101*0Sstevel@tonic-gate 	mutex_enter(&p->p_ldtlock);
102*0Sstevel@tonic-gate 	size = prnldt(p) * sizeof (struct ssd);
103*0Sstevel@tonic-gate 	mutex_exit(&p->p_ldtlock);
104*0Sstevel@tonic-gate 	if (size != 0)
105*0Sstevel@tonic-gate 		v[0].p_filesz += sizeof (Note) + roundup(size, sizeof (Word));
106*0Sstevel@tonic-gate #endif	/* __i386 || __i386_COMPAT */
107*0Sstevel@tonic-gate 
108*0Sstevel@tonic-gate 	if ((size = prhasx(p)? prgetprxregsize(p) : 0) != 0)
109*0Sstevel@tonic-gate 		v[0].p_filesz += nlwp * sizeof (Note)
110*0Sstevel@tonic-gate 		    + nlwp * roundup(size, sizeof (Word));
111*0Sstevel@tonic-gate 
112*0Sstevel@tonic-gate #if defined(__sparc)
113*0Sstevel@tonic-gate 	/*
114*0Sstevel@tonic-gate 	 * Figure out the number and sizes of register windows.
115*0Sstevel@tonic-gate 	 */
116*0Sstevel@tonic-gate 	{
117*0Sstevel@tonic-gate 		kthread_t *t = p->p_tlist;
118*0Sstevel@tonic-gate 		do {
119*0Sstevel@tonic-gate 			if ((size = prnwindows(ttolwp(t))) != 0) {
120*0Sstevel@tonic-gate 				size = sizeof (gwindows_t) -
121*0Sstevel@tonic-gate 				    (SPARC_MAXREGWINDOW - size) *
122*0Sstevel@tonic-gate 				    sizeof (struct rwindow);
123*0Sstevel@tonic-gate 				v[0].p_filesz += sizeof (Note) +
124*0Sstevel@tonic-gate 				    roundup(size, sizeof (Word));
125*0Sstevel@tonic-gate 			}
126*0Sstevel@tonic-gate 		} while ((t = t->t_forw) != p->p_tlist);
127*0Sstevel@tonic-gate 	}
128*0Sstevel@tonic-gate 	/*
129*0Sstevel@tonic-gate 	 * Space for the Ancillary State Registers.
130*0Sstevel@tonic-gate 	 */
131*0Sstevel@tonic-gate 	if (p->p_model == DATAMODEL_LP64)
132*0Sstevel@tonic-gate 		v[0].p_filesz += nlwp * sizeof (Note)
133*0Sstevel@tonic-gate 		    + nlwp * roundup(sizeof (asrset_t), sizeof (Word));
134*0Sstevel@tonic-gate #endif /* __sparc */
135*0Sstevel@tonic-gate }
136*0Sstevel@tonic-gate 
137*0Sstevel@tonic-gate int
write_elfnotes(proc_t * p,int sig,vnode_t * vp,offset_t offset,rlim64_t rlimit,cred_t * credp,core_content_t content)138*0Sstevel@tonic-gate write_elfnotes(proc_t *p, int sig, vnode_t *vp, offset_t offset,
139*0Sstevel@tonic-gate     rlim64_t rlimit, cred_t *credp, core_content_t content)
140*0Sstevel@tonic-gate {
141*0Sstevel@tonic-gate 	union {
142*0Sstevel@tonic-gate 		psinfo_t	psinfo;
143*0Sstevel@tonic-gate 		pstatus_t	pstatus;
144*0Sstevel@tonic-gate 		lwpsinfo_t	lwpsinfo;
145*0Sstevel@tonic-gate 		lwpstatus_t	lwpstatus;
146*0Sstevel@tonic-gate #if defined(__sparc)
147*0Sstevel@tonic-gate 		gwindows_t	gwindows;
148*0Sstevel@tonic-gate 		asrset_t	asrset;
149*0Sstevel@tonic-gate #endif /* __sparc */
150*0Sstevel@tonic-gate 		char		xregs[1];
151*0Sstevel@tonic-gate 		aux_entry_t	auxv[__KERN_NAUXV_IMPL];
152*0Sstevel@tonic-gate 		prcred_t	pcred;
153*0Sstevel@tonic-gate 		prpriv_t	ppriv;
154*0Sstevel@tonic-gate 		priv_impl_info_t prinfo;
155*0Sstevel@tonic-gate 		struct utsname	uts;
156*0Sstevel@tonic-gate 	} *bigwad;
157*0Sstevel@tonic-gate 
158*0Sstevel@tonic-gate 	size_t xregsize = prhasx(p)? prgetprxregsize(p) : 0;
159*0Sstevel@tonic-gate 	size_t crsize = sizeof (prcred_t) + sizeof (gid_t) * (ngroups_max - 1);
160*0Sstevel@tonic-gate 	size_t psize = prgetprivsize();
161*0Sstevel@tonic-gate 	size_t bigsize = MAX(psize, MAX(sizeof (*bigwad),
162*0Sstevel@tonic-gate 					MAX(xregsize, crsize)));
163*0Sstevel@tonic-gate 
164*0Sstevel@tonic-gate 	priv_impl_info_t *prii;
165*0Sstevel@tonic-gate 
166*0Sstevel@tonic-gate 	lwpdir_t *ldp;
167*0Sstevel@tonic-gate 	lwpent_t *lep;
168*0Sstevel@tonic-gate 	kthread_t *t;
169*0Sstevel@tonic-gate 	klwp_t *lwp;
170*0Sstevel@tonic-gate 	user_t *up;
171*0Sstevel@tonic-gate 	int i;
172*0Sstevel@tonic-gate 	int nlwp;
173*0Sstevel@tonic-gate 	int nzomb;
174*0Sstevel@tonic-gate 	int error;
175*0Sstevel@tonic-gate 	uchar_t oldsig;
176*0Sstevel@tonic-gate #if defined(__i386) || defined(__i386_COMPAT)
177*0Sstevel@tonic-gate 	struct ssd *ssd;
178*0Sstevel@tonic-gate 	size_t ssdsize;
179*0Sstevel@tonic-gate #endif	/* __i386 || __i386_COMPAT */
180*0Sstevel@tonic-gate 
181*0Sstevel@tonic-gate 	bigsize = MAX(bigsize, priv_get_implinfo_size());
182*0Sstevel@tonic-gate 
183*0Sstevel@tonic-gate 	bigwad = kmem_alloc(bigsize, KM_SLEEP);
184*0Sstevel@tonic-gate 
185*0Sstevel@tonic-gate 	/*
186*0Sstevel@tonic-gate 	 * The order of the elfnote entries should be same here
187*0Sstevel@tonic-gate 	 * and in the gcore(1) command.  Synchronization is
188*0Sstevel@tonic-gate 	 * needed between the kernel and gcore(1).
189*0Sstevel@tonic-gate 	 */
190*0Sstevel@tonic-gate 
191*0Sstevel@tonic-gate 	/*
192*0Sstevel@tonic-gate 	 * Get the psinfo, and set the wait status to indicate that a core was
193*0Sstevel@tonic-gate 	 * dumped.  We have to forge this since p->p_wcode is not set yet.
194*0Sstevel@tonic-gate 	 */
195*0Sstevel@tonic-gate 	mutex_enter(&p->p_lock);
196*0Sstevel@tonic-gate 	prgetpsinfo(p, &bigwad->psinfo);
197*0Sstevel@tonic-gate 	mutex_exit(&p->p_lock);
198*0Sstevel@tonic-gate 	bigwad->psinfo.pr_wstat = wstat(CLD_DUMPED, sig);
199*0Sstevel@tonic-gate 
200*0Sstevel@tonic-gate 	error = elfnote(vp, &offset, NT_PSINFO, sizeof (bigwad->psinfo),
201*0Sstevel@tonic-gate 	    (caddr_t)&bigwad->psinfo, rlimit, credp);
202*0Sstevel@tonic-gate 	if (error)
203*0Sstevel@tonic-gate 		goto done;
204*0Sstevel@tonic-gate 
205*0Sstevel@tonic-gate 	/*
206*0Sstevel@tonic-gate 	 * Modify t_whystop and lwp_cursig so it appears that the current LWP
207*0Sstevel@tonic-gate 	 * is stopped after faulting on the signal that caused the core dump.
208*0Sstevel@tonic-gate 	 * As a result, prgetstatus() will record that signal, the saved
209*0Sstevel@tonic-gate 	 * lwp_siginfo, and its signal handler in the core file status.  We
210*0Sstevel@tonic-gate 	 * restore lwp_cursig in case a subsequent signal was received while
211*0Sstevel@tonic-gate 	 * dumping core.
212*0Sstevel@tonic-gate 	 */
213*0Sstevel@tonic-gate 	mutex_enter(&p->p_lock);
214*0Sstevel@tonic-gate 	lwp = ttolwp(curthread);
215*0Sstevel@tonic-gate 
216*0Sstevel@tonic-gate 	oldsig = lwp->lwp_cursig;
217*0Sstevel@tonic-gate 	lwp->lwp_cursig = (uchar_t)sig;
218*0Sstevel@tonic-gate 	curthread->t_whystop = PR_FAULTED;
219*0Sstevel@tonic-gate 
220*0Sstevel@tonic-gate 	prgetstatus(p, &bigwad->pstatus, p->p_zone);
221*0Sstevel@tonic-gate 	bigwad->pstatus.pr_lwp.pr_why = 0;
222*0Sstevel@tonic-gate 
223*0Sstevel@tonic-gate 	curthread->t_whystop = 0;
224*0Sstevel@tonic-gate 	lwp->lwp_cursig = oldsig;
225*0Sstevel@tonic-gate 	mutex_exit(&p->p_lock);
226*0Sstevel@tonic-gate 
227*0Sstevel@tonic-gate 	error = elfnote(vp, &offset, NT_PSTATUS, sizeof (bigwad->pstatus),
228*0Sstevel@tonic-gate 	    (caddr_t)&bigwad->pstatus, rlimit, credp);
229*0Sstevel@tonic-gate 	if (error)
230*0Sstevel@tonic-gate 		goto done;
231*0Sstevel@tonic-gate 
232*0Sstevel@tonic-gate 	error = elfnote(vp, &offset, NT_PLATFORM, strlen(platform) + 1,
233*0Sstevel@tonic-gate 	    platform, rlimit, credp);
234*0Sstevel@tonic-gate 	if (error)
235*0Sstevel@tonic-gate 		goto done;
236*0Sstevel@tonic-gate 
237*0Sstevel@tonic-gate 	up = PTOU(p);
238*0Sstevel@tonic-gate 	for (i = 0; i < __KERN_NAUXV_IMPL; i++) {
239*0Sstevel@tonic-gate 		bigwad->auxv[i].a_type = up->u_auxv[i].a_type;
240*0Sstevel@tonic-gate 		bigwad->auxv[i].a_un.a_val = up->u_auxv[i].a_un.a_val;
241*0Sstevel@tonic-gate 	}
242*0Sstevel@tonic-gate 	error = elfnote(vp, &offset, NT_AUXV, sizeof (bigwad->auxv),
243*0Sstevel@tonic-gate 	    (caddr_t)bigwad->auxv, rlimit, credp);
244*0Sstevel@tonic-gate 	if (error)
245*0Sstevel@tonic-gate 		goto done;
246*0Sstevel@tonic-gate 
247*0Sstevel@tonic-gate 	bcopy(&utsname, &bigwad->uts, sizeof (struct utsname));
248*0Sstevel@tonic-gate 	if (!INGLOBALZONE(p)) {
249*0Sstevel@tonic-gate 		bcopy(p->p_zone->zone_nodename, &bigwad->uts.nodename,
250*0Sstevel@tonic-gate 		    _SYS_NMLN);
251*0Sstevel@tonic-gate 	}
252*0Sstevel@tonic-gate 	error = elfnote(vp, &offset, NT_UTSNAME, sizeof (struct utsname),
253*0Sstevel@tonic-gate 	    (caddr_t)&bigwad->uts, rlimit, credp);
254*0Sstevel@tonic-gate 	if (error)
255*0Sstevel@tonic-gate 		goto done;
256*0Sstevel@tonic-gate 
257*0Sstevel@tonic-gate 	prgetcred(p, &bigwad->pcred);
258*0Sstevel@tonic-gate 
259*0Sstevel@tonic-gate 	if (bigwad->pcred.pr_ngroups != 0) {
260*0Sstevel@tonic-gate 		crsize = sizeof (prcred_t) +
261*0Sstevel@tonic-gate 		    sizeof (gid_t) * (bigwad->pcred.pr_ngroups - 1);
262*0Sstevel@tonic-gate 	} else
263*0Sstevel@tonic-gate 		crsize = sizeof (prcred_t);
264*0Sstevel@tonic-gate 
265*0Sstevel@tonic-gate 	error = elfnote(vp, &offset, NT_PRCRED, crsize,
266*0Sstevel@tonic-gate 	    (caddr_t)&bigwad->pcred, rlimit, credp);
267*0Sstevel@tonic-gate 	if (error)
268*0Sstevel@tonic-gate 		goto done;
269*0Sstevel@tonic-gate 
270*0Sstevel@tonic-gate 	error = elfnote(vp, &offset, NT_CONTENT, sizeof (core_content_t),
271*0Sstevel@tonic-gate 	    (caddr_t)&content, rlimit, credp);
272*0Sstevel@tonic-gate 	if (error)
273*0Sstevel@tonic-gate 		goto done;
274*0Sstevel@tonic-gate 
275*0Sstevel@tonic-gate 	prgetpriv(p, &bigwad->ppriv);
276*0Sstevel@tonic-gate 
277*0Sstevel@tonic-gate 	error = elfnote(vp, &offset, NT_PRPRIV, psize,
278*0Sstevel@tonic-gate 	    (caddr_t)&bigwad->ppriv, rlimit, credp);
279*0Sstevel@tonic-gate 	if (error)
280*0Sstevel@tonic-gate 		goto done;
281*0Sstevel@tonic-gate 
282*0Sstevel@tonic-gate 	prii = priv_hold_implinfo();
283*0Sstevel@tonic-gate 	error = elfnote(vp, &offset, NT_PRPRIVINFO, priv_get_implinfo_size(),
284*0Sstevel@tonic-gate 	    (caddr_t)prii, rlimit, credp);
285*0Sstevel@tonic-gate 	priv_release_implinfo();
286*0Sstevel@tonic-gate 	if (error)
287*0Sstevel@tonic-gate 		goto done;
288*0Sstevel@tonic-gate 
289*0Sstevel@tonic-gate 	/* zone can't go away as long as process exists */
290*0Sstevel@tonic-gate 	error = elfnote(vp, &offset, NT_ZONENAME,
291*0Sstevel@tonic-gate 	    strlen(p->p_zone->zone_name) + 1, p->p_zone->zone_name,
292*0Sstevel@tonic-gate 	    rlimit, credp);
293*0Sstevel@tonic-gate 	if (error)
294*0Sstevel@tonic-gate 		goto done;
295*0Sstevel@tonic-gate 
296*0Sstevel@tonic-gate #if defined(__i386) || defined(__i386_COMPAT)
297*0Sstevel@tonic-gate 	mutex_enter(&p->p_ldtlock);
298*0Sstevel@tonic-gate 	ssdsize = prnldt(p) * sizeof (struct ssd);
299*0Sstevel@tonic-gate 	if (ssdsize != 0) {
300*0Sstevel@tonic-gate 		ssd = kmem_alloc(ssdsize, KM_SLEEP);
301*0Sstevel@tonic-gate 		prgetldt(p, ssd);
302*0Sstevel@tonic-gate 		error = elfnote(vp, &offset, NT_LDT, ssdsize,
303*0Sstevel@tonic-gate 		    (caddr_t)ssd, rlimit, credp);
304*0Sstevel@tonic-gate 		kmem_free(ssd, ssdsize);
305*0Sstevel@tonic-gate 	}
306*0Sstevel@tonic-gate 	mutex_exit(&p->p_ldtlock);
307*0Sstevel@tonic-gate 	if (error)
308*0Sstevel@tonic-gate 		goto done;
309*0Sstevel@tonic-gate #endif	/* __i386 || defined(__i386_COMPAT) */
310*0Sstevel@tonic-gate 
311*0Sstevel@tonic-gate 	nlwp = p->p_lwpcnt;
312*0Sstevel@tonic-gate 	nzomb = p->p_zombcnt;
313*0Sstevel@tonic-gate 	/* for each entry in the lwp directory ... */
314*0Sstevel@tonic-gate 	for (ldp = p->p_lwpdir; nlwp + nzomb != 0; ldp++) {
315*0Sstevel@tonic-gate 
316*0Sstevel@tonic-gate 		if ((lep = ldp->ld_entry) == NULL)	/* empty slot */
317*0Sstevel@tonic-gate 			continue;
318*0Sstevel@tonic-gate 
319*0Sstevel@tonic-gate 		if ((t = lep->le_thread) != NULL) {	/* active lwp */
320*0Sstevel@tonic-gate 			ASSERT(nlwp != 0);
321*0Sstevel@tonic-gate 			nlwp--;
322*0Sstevel@tonic-gate 			lwp = ttolwp(t);
323*0Sstevel@tonic-gate 			mutex_enter(&p->p_lock);
324*0Sstevel@tonic-gate 			prgetlwpsinfo(t, &bigwad->lwpsinfo);
325*0Sstevel@tonic-gate 			mutex_exit(&p->p_lock);
326*0Sstevel@tonic-gate 		} else {				/* zombie lwp */
327*0Sstevel@tonic-gate 			ASSERT(nzomb != 0);
328*0Sstevel@tonic-gate 			nzomb--;
329*0Sstevel@tonic-gate 			bzero(&bigwad->lwpsinfo, sizeof (bigwad->lwpsinfo));
330*0Sstevel@tonic-gate 			bigwad->lwpsinfo.pr_lwpid = lep->le_lwpid;
331*0Sstevel@tonic-gate 			bigwad->lwpsinfo.pr_state = SZOMB;
332*0Sstevel@tonic-gate 			bigwad->lwpsinfo.pr_sname = 'Z';
333*0Sstevel@tonic-gate 			bigwad->lwpsinfo.pr_start.tv_sec = lep->le_start;
334*0Sstevel@tonic-gate 		}
335*0Sstevel@tonic-gate 		error = elfnote(vp, &offset, NT_LWPSINFO,
336*0Sstevel@tonic-gate 		    sizeof (bigwad->lwpsinfo), (caddr_t)&bigwad->lwpsinfo,
337*0Sstevel@tonic-gate 		    rlimit, credp);
338*0Sstevel@tonic-gate 		if (error)
339*0Sstevel@tonic-gate 			goto done;
340*0Sstevel@tonic-gate 		if (t == NULL)		/* nothing more to do for a zombie */
341*0Sstevel@tonic-gate 			continue;
342*0Sstevel@tonic-gate 
343*0Sstevel@tonic-gate 		mutex_enter(&p->p_lock);
344*0Sstevel@tonic-gate 		if (t == curthread) {
345*0Sstevel@tonic-gate 			/*
346*0Sstevel@tonic-gate 			 * Modify t_whystop and lwp_cursig so it appears that
347*0Sstevel@tonic-gate 			 * the current LWP is stopped after faulting on the
348*0Sstevel@tonic-gate 			 * signal that caused the core dump.  As a result,
349*0Sstevel@tonic-gate 			 * prgetlwpstatus() will record that signal, the saved
350*0Sstevel@tonic-gate 			 * lwp_siginfo, and its signal handler in the core file
351*0Sstevel@tonic-gate 			 * status.  We restore lwp_cursig in case a subsequent
352*0Sstevel@tonic-gate 			 * signal was received while dumping core.
353*0Sstevel@tonic-gate 			 */
354*0Sstevel@tonic-gate 			oldsig = lwp->lwp_cursig;
355*0Sstevel@tonic-gate 			lwp->lwp_cursig = (uchar_t)sig;
356*0Sstevel@tonic-gate 			t->t_whystop = PR_FAULTED;
357*0Sstevel@tonic-gate 
358*0Sstevel@tonic-gate 			prgetlwpstatus(t, &bigwad->lwpstatus, p->p_zone);
359*0Sstevel@tonic-gate 			bigwad->lwpstatus.pr_why = 0;
360*0Sstevel@tonic-gate 
361*0Sstevel@tonic-gate 			t->t_whystop = 0;
362*0Sstevel@tonic-gate 			lwp->lwp_cursig = oldsig;
363*0Sstevel@tonic-gate 		} else {
364*0Sstevel@tonic-gate 			prgetlwpstatus(t, &bigwad->lwpstatus, p->p_zone);
365*0Sstevel@tonic-gate 		}
366*0Sstevel@tonic-gate 		mutex_exit(&p->p_lock);
367*0Sstevel@tonic-gate 		error = elfnote(vp, &offset, NT_LWPSTATUS,
368*0Sstevel@tonic-gate 		    sizeof (bigwad->lwpstatus), (caddr_t)&bigwad->lwpstatus,
369*0Sstevel@tonic-gate 		    rlimit, credp);
370*0Sstevel@tonic-gate 		if (error)
371*0Sstevel@tonic-gate 			goto done;
372*0Sstevel@tonic-gate 
373*0Sstevel@tonic-gate #if defined(__sparc)
374*0Sstevel@tonic-gate 		/*
375*0Sstevel@tonic-gate 		 * Unspilled SPARC register windows.
376*0Sstevel@tonic-gate 		 */
377*0Sstevel@tonic-gate 		{
378*0Sstevel@tonic-gate 			size_t size = prnwindows(lwp);
379*0Sstevel@tonic-gate 
380*0Sstevel@tonic-gate 			if (size != 0) {
381*0Sstevel@tonic-gate 				size = sizeof (gwindows_t) -
382*0Sstevel@tonic-gate 				    (SPARC_MAXREGWINDOW - size) *
383*0Sstevel@tonic-gate 				    sizeof (struct rwindow);
384*0Sstevel@tonic-gate 				prgetwindows(lwp, &bigwad->gwindows);
385*0Sstevel@tonic-gate 				error = elfnote(vp, &offset, NT_GWINDOWS,
386*0Sstevel@tonic-gate 				    size, (caddr_t)&bigwad->gwindows,
387*0Sstevel@tonic-gate 				    rlimit, credp);
388*0Sstevel@tonic-gate 				if (error)
389*0Sstevel@tonic-gate 					goto done;
390*0Sstevel@tonic-gate 			}
391*0Sstevel@tonic-gate 		}
392*0Sstevel@tonic-gate 		/*
393*0Sstevel@tonic-gate 		 * Ancillary State Registers.
394*0Sstevel@tonic-gate 		 */
395*0Sstevel@tonic-gate 		if (p->p_model == DATAMODEL_LP64) {
396*0Sstevel@tonic-gate 			prgetasregs(lwp, bigwad->asrset);
397*0Sstevel@tonic-gate 			error = elfnote(vp, &offset, NT_ASRS,
398*0Sstevel@tonic-gate 			    sizeof (asrset_t), (caddr_t)bigwad->asrset,
399*0Sstevel@tonic-gate 			    rlimit, credp);
400*0Sstevel@tonic-gate 			if (error)
401*0Sstevel@tonic-gate 				goto done;
402*0Sstevel@tonic-gate 		}
403*0Sstevel@tonic-gate #endif /* __sparc */
404*0Sstevel@tonic-gate 
405*0Sstevel@tonic-gate 		if (xregsize) {
406*0Sstevel@tonic-gate 			prgetprxregs(lwp, bigwad->xregs);
407*0Sstevel@tonic-gate 			error = elfnote(vp, &offset, NT_PRXREG,
408*0Sstevel@tonic-gate 			    xregsize, bigwad->xregs, rlimit, credp);
409*0Sstevel@tonic-gate 			if (error)
410*0Sstevel@tonic-gate 				goto done;
411*0Sstevel@tonic-gate 		}
412*0Sstevel@tonic-gate 	}
413*0Sstevel@tonic-gate 	ASSERT(nlwp == 0);
414*0Sstevel@tonic-gate 
415*0Sstevel@tonic-gate done:
416*0Sstevel@tonic-gate 	kmem_free(bigwad, bigsize);
417*0Sstevel@tonic-gate 	return (error);
418*0Sstevel@tonic-gate }
419