xref: /illumos-gate/usr/src/uts/common/exec/elf/elf_notes.c (revision e6c4e893c6a9849a441fddbb31ea45dc6814ec6b)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 /*
28  * Copyright 2012 DEY Storage Systems, Inc.  All rights reserved.
29  * Copyright 2018 Joyent, Inc.
30  * Copyright 2020 OmniOS Community Edition (OmniOSce) Association.
31  * Copyright 2024 Oxide Computer Company
32  */
33 
34 #include <sys/types.h>
35 #include <sys/param.h>
36 #include <sys/thread.h>
37 #include <sys/sysmacros.h>
38 #include <sys/signal.h>
39 #include <sys/cred.h>
40 #include <sys/priv.h>
41 #include <sys/user.h>
42 #include <sys/file.h>
43 #include <sys/errno.h>
44 #include <sys/vnode.h>
45 #include <sys/mode.h>
46 #include <sys/vfs.h>
47 #include <sys/mman.h>
48 #include <sys/kmem.h>
49 #include <sys/proc.h>
50 #include <sys/pathname.h>
51 #include <sys/cmn_err.h>
52 #include <sys/systm.h>
53 #include <sys/elf.h>
54 #include <sys/vmsystm.h>
55 #include <sys/debug.h>
56 #include <sys/procfs.h>
57 #include <sys/regset.h>
58 #include <sys/auxv.h>
59 #include <sys/exec.h>
60 #include <sys/prsystm.h>
61 #include <sys/utsname.h>
62 #include <sys/zone.h>
63 #include <vm/as.h>
64 #include <vm/rm.h>
65 #include <sys/modctl.h>
66 #include <sys/systeminfo.h>
67 #include <sys/machelf.h>
68 #include <sys/sunddi.h>
69 #include "elf_impl.h"
70 #if defined(__i386_COMPAT)
71 #include <sys/sysi86.h>
72 #endif
73 
74 void
75 setup_note_header(Phdr *v, proc_t *p)
76 {
77 	int nlwp = p->p_lwpcnt;
78 	int nzomb = p->p_zombcnt;
79 	int nfd;
80 	size_t size;
81 	prcred_t *pcrp;
82 	uf_info_t *fip;
83 	uf_entry_t *ufp;
84 	int fd;
85 
86 	fip = P_FINFO(p);
87 	nfd = 0;
88 	mutex_enter(&fip->fi_lock);
89 	for (fd = 0; fd < fip->fi_nfiles; fd++) {
90 		UF_ENTER(ufp, fip, fd);
91 		if ((ufp->uf_file != NULL) && (ufp->uf_file->f_count > 0))
92 			nfd++;
93 		UF_EXIT(ufp);
94 	}
95 	mutex_exit(&fip->fi_lock);
96 
97 	v[0].p_type = PT_NOTE;
98 	v[0].p_flags = PF_R;
99 	v[0].p_filesz = (sizeof (Note) * (11 + 3 * nlwp + nzomb + nfd))
100 	    + roundup(sizeof (psinfo_t), sizeof (Word))
101 	    + roundup(sizeof (pstatus_t), sizeof (Word))
102 	    + roundup(prgetprivsize(), sizeof (Word))
103 	    + roundup(priv_get_implinfo_size(), sizeof (Word))
104 	    + roundup(strlen(platform) + 1, sizeof (Word))
105 	    + roundup(strlen(p->p_zone->zone_name) + 1, sizeof (Word))
106 	    + roundup(__KERN_NAUXV_IMPL * sizeof (aux_entry_t), sizeof (Word))
107 	    + roundup(sizeof (utsname), sizeof (Word))
108 	    + roundup(sizeof (core_content_t), sizeof (Word))
109 	    + roundup(sizeof (prsecflags_t), sizeof (Word))
110 	    + roundup(sizeof (prcwd_t), sizeof (Word))
111 	    + (nlwp + nzomb) * roundup(sizeof (lwpsinfo_t), sizeof (Word))
112 	    + nlwp * roundup(sizeof (lwpstatus_t), sizeof (Word))
113 	    + nlwp * roundup(sizeof (prlwpname_t), sizeof (Word))
114 	    + nfd * roundup(sizeof (prfdinfo_core_t), sizeof (Word));
115 
116 	if (curproc->p_agenttp != NULL) {
117 		v[0].p_filesz += sizeof (Note) +
118 		    roundup(sizeof (psinfo_t), sizeof (Word));
119 	}
120 
121 	size = sizeof (prcred_t) + sizeof (gid_t) * (ngroups_max - 1);
122 	pcrp = kmem_zalloc(size, KM_SLEEP);
123 	prgetcred(p, pcrp);
124 	if (pcrp->pr_ngroups != 0) {
125 		v[0].p_filesz += sizeof (Note) + roundup(sizeof (prcred_t) +
126 		    sizeof (gid_t) * (pcrp->pr_ngroups - 1), sizeof (Word));
127 	} else {
128 		v[0].p_filesz += sizeof (Note) +
129 		    roundup(sizeof (prcred_t), sizeof (Word));
130 	}
131 	kmem_free(pcrp, size);
132 
133 
134 #if defined(__i386_COMPAT)
135 	mutex_enter(&p->p_ldtlock);
136 	size = prnldt(p) * sizeof (struct ssd);
137 	mutex_exit(&p->p_ldtlock);
138 	if (size != 0)
139 		v[0].p_filesz += sizeof (Note) + roundup(size, sizeof (Word));
140 #endif	/* __i386_COMPAT */
141 
142 	if ((size = prhasx(p) ? prgetprxregsize(p) : 0) != 0)
143 		v[0].p_filesz += nlwp * sizeof (Note)
144 		    + nlwp * roundup(size, sizeof (Word));
145 
146 #if defined(__sparc)
147 	/*
148 	 * Figure out the number and sizes of register windows.
149 	 */
150 	{
151 		kthread_t *t = p->p_tlist;
152 		do {
153 			if ((size = prnwindows(ttolwp(t))) != 0) {
154 				size = sizeof (gwindows_t) -
155 				    (SPARC_MAXREGWINDOW - size) *
156 				    sizeof (struct rwindow);
157 				v[0].p_filesz += sizeof (Note) +
158 				    roundup(size, sizeof (Word));
159 			}
160 		} while ((t = t->t_forw) != p->p_tlist);
161 	}
162 	/*
163 	 * Space for the Ancillary State Registers.
164 	 */
165 	if (p->p_model == DATAMODEL_LP64)
166 		v[0].p_filesz += nlwp * sizeof (Note)
167 		    + nlwp * roundup(sizeof (asrset_t), sizeof (Word));
168 #endif /* __sparc */
169 
170 	mutex_enter(&p->p_lock);
171 	if ((p->p_upanicflag & P_UPF_PANICKED) != 0) {
172 		v[0].p_filesz += sizeof (Note) +
173 		    roundup(sizeof (prupanic_t), sizeof (Word));
174 	}
175 	mutex_exit(&p->p_lock);
176 }
177 
178 static void
179 fill_prcwd(proc_t *p, prcwd_t *cwd, vnode_t *vroot, cred_t *credp)
180 {
181 	vnode_t *vn;
182 	vfs_t *vfsp;
183 	dev32_t dev;
184 
185 	vn = p->p_user.u_cdir;
186 	vfsp = vn->v_vfsp;
187 
188 	/*
189 	 * Zero out the structure and ensure all the padding is zero as
190 	 * otherwise it may have garbage left over from another note. This also
191 	 * ensures that if we don't have a resource or mount point for some
192 	 * unexpected reason that we end up with an empty string.
193 	 */
194 	bzero(cwd, sizeof (prcwd_t));
195 
196 	/*
197 	 * We opt not to check the cached u_cwd as it may or may not exist.
198 	 */
199 	(void) vnodetopath(vroot, vn, cwd->prcwd_cwd,
200 	    sizeof (cwd->prcwd_cwd), credp);
201 	(void) cmpldev(&dev, vfsp->vfs_dev);
202 	cwd->prcwd_fsid = dev;
203 	(void) strlcpy(cwd->prcwd_fsname, vfssw[vfsp->vfs_fstype].vsw_name,
204 	    sizeof (cwd->prcwd_fsname));
205 	if (refstr_value(vfsp->vfs_mntpt) != NULL) {
206 		(void) strlcpy(cwd->prcwd_mntpt, refstr_value(vfsp->vfs_mntpt),
207 		    sizeof (cwd->prcwd_mntpt));
208 	}
209 
210 	if (refstr_value(vfsp->vfs_resource) != NULL) {
211 		(void) strlcpy(cwd->prcwd_mntspec,
212 		    refstr_value(vfsp->vfs_resource),
213 		    sizeof (cwd->prcwd_mntspec));
214 	}
215 }
216 
217 int
218 write_elfnotes(proc_t *p, int sig, vnode_t *vp, offset_t offset,
219     rlim64_t rlimit, cred_t *credp, core_content_t content)
220 {
221 	union {
222 		psinfo_t	psinfo;
223 		pstatus_t	pstatus;
224 		lwpsinfo_t	lwpsinfo;
225 		lwpstatus_t	lwpstatus;
226 #if defined(__sparc)
227 		gwindows_t	gwindows;
228 		asrset_t	asrset;
229 #endif /* __sparc */
230 		char		xregs[1];
231 		aux_entry_t	auxv[__KERN_NAUXV_IMPL];
232 		prcred_t	pcred;
233 		prpriv_t	ppriv;
234 		priv_impl_info_t prinfo;
235 		struct utsname	uts;
236 		prsecflags_t	psecflags;
237 		prupanic_t	upanic;
238 		prcwd_t		cwd;
239 	} *bigwad;
240 
241 	size_t xregsize = prhasx(p) ? prgetprxregsize(p) : 0;
242 	size_t crsize = sizeof (prcred_t) + sizeof (gid_t) * (ngroups_max - 1);
243 	size_t psize = prgetprivsize();
244 	size_t bigsize = MAX(psize, MAX(sizeof (*bigwad),
245 	    MAX(xregsize, crsize)));
246 
247 	priv_impl_info_t *prii;
248 
249 	lwpdir_t *ldp;
250 	lwpent_t *lep;
251 	kthread_t *t;
252 	klwp_t *lwp;
253 	user_t *up;
254 	int i;
255 	int nlwp;
256 	int nzomb;
257 	int error;
258 	uchar_t oldsig;
259 	uf_info_t *fip;
260 	int fd;
261 	vnode_t *vroot;
262 
263 #if defined(__i386_COMPAT)
264 	struct ssd *ssd;
265 	size_t ssdsize;
266 #endif	/* __i386_COMPAT */
267 
268 	bigsize = MAX(bigsize, priv_get_implinfo_size());
269 
270 	bigwad = kmem_alloc(bigsize, KM_SLEEP);
271 
272 	/*
273 	 * The order of the elfnote entries should be same here
274 	 * and in the gcore(1) command.  Synchronization is
275 	 * needed between the kernel and gcore(1).
276 	 */
277 
278 	/*
279 	 * Get the psinfo, and set the wait status to indicate that a core was
280 	 * dumped.  We have to forge this since p->p_wcode is not set yet.
281 	 */
282 	mutex_enter(&p->p_lock);
283 	prgetpsinfo(p, &bigwad->psinfo);
284 	mutex_exit(&p->p_lock);
285 	bigwad->psinfo.pr_wstat = wstat(CLD_DUMPED, sig);
286 
287 	error = elfnote(vp, &offset, NT_PSINFO, sizeof (bigwad->psinfo),
288 	    (caddr_t)&bigwad->psinfo, rlimit, credp);
289 	if (error)
290 		goto done;
291 
292 	/*
293 	 * Modify t_whystop and lwp_cursig so it appears that the current LWP
294 	 * is stopped after faulting on the signal that caused the core dump.
295 	 * As a result, prgetstatus() will record that signal, the saved
296 	 * lwp_siginfo, and its signal handler in the core file status.  We
297 	 * restore lwp_cursig in case a subsequent signal was received while
298 	 * dumping core.
299 	 */
300 	mutex_enter(&p->p_lock);
301 	lwp = ttolwp(curthread);
302 
303 	oldsig = lwp->lwp_cursig;
304 	lwp->lwp_cursig = (uchar_t)sig;
305 	curthread->t_whystop = PR_FAULTED;
306 
307 	prgetstatus(p, &bigwad->pstatus, p->p_zone);
308 	bigwad->pstatus.pr_lwp.pr_why = 0;
309 
310 	curthread->t_whystop = 0;
311 	lwp->lwp_cursig = oldsig;
312 	mutex_exit(&p->p_lock);
313 
314 	error = elfnote(vp, &offset, NT_PSTATUS, sizeof (bigwad->pstatus),
315 	    (caddr_t)&bigwad->pstatus, rlimit, credp);
316 	if (error)
317 		goto done;
318 
319 	error = elfnote(vp, &offset, NT_PLATFORM, strlen(platform) + 1,
320 	    platform, rlimit, credp);
321 	if (error)
322 		goto done;
323 
324 	up = PTOU(p);
325 	for (i = 0; i < __KERN_NAUXV_IMPL; i++) {
326 		bigwad->auxv[i].a_type = up->u_auxv[i].a_type;
327 		bigwad->auxv[i].a_un.a_val = up->u_auxv[i].a_un.a_val;
328 	}
329 	error = elfnote(vp, &offset, NT_AUXV, sizeof (bigwad->auxv),
330 	    (caddr_t)bigwad->auxv, rlimit, credp);
331 	if (error)
332 		goto done;
333 
334 	bcopy(&utsname, &bigwad->uts, sizeof (struct utsname));
335 	if (!INGLOBALZONE(p)) {
336 		bcopy(p->p_zone->zone_nodename, &bigwad->uts.nodename,
337 		    _SYS_NMLN);
338 	}
339 	error = elfnote(vp, &offset, NT_UTSNAME, sizeof (struct utsname),
340 	    (caddr_t)&bigwad->uts, rlimit, credp);
341 	if (error)
342 		goto done;
343 
344 	prgetsecflags(p, &bigwad->psecflags);
345 	error = elfnote(vp, &offset, NT_SECFLAGS, sizeof (prsecflags_t),
346 	    (caddr_t)&bigwad->psecflags, rlimit, credp);
347 	if (error)
348 		goto done;
349 
350 	bzero(bigwad, crsize);
351 	prgetcred(p, &bigwad->pcred);
352 
353 	if (bigwad->pcred.pr_ngroups != 0) {
354 		crsize = sizeof (prcred_t) +
355 		    sizeof (gid_t) * (bigwad->pcred.pr_ngroups - 1);
356 	} else
357 		crsize = sizeof (prcred_t);
358 
359 	error = elfnote(vp, &offset, NT_PRCRED, crsize,
360 	    (caddr_t)&bigwad->pcred, rlimit, credp);
361 	if (error)
362 		goto done;
363 
364 	error = elfnote(vp, &offset, NT_CONTENT, sizeof (core_content_t),
365 	    (caddr_t)&content, rlimit, credp);
366 	if (error)
367 		goto done;
368 
369 	prgetpriv(p, &bigwad->ppriv);
370 
371 	error = elfnote(vp, &offset, NT_PRPRIV, psize,
372 	    (caddr_t)&bigwad->ppriv, rlimit, credp);
373 	if (error)
374 		goto done;
375 
376 	prii = priv_hold_implinfo();
377 	error = elfnote(vp, &offset, NT_PRPRIVINFO, priv_get_implinfo_size(),
378 	    (caddr_t)prii, rlimit, credp);
379 	priv_release_implinfo();
380 	if (error)
381 		goto done;
382 
383 	/* zone can't go away as long as process exists */
384 	error = elfnote(vp, &offset, NT_ZONENAME,
385 	    strlen(p->p_zone->zone_name) + 1, p->p_zone->zone_name,
386 	    rlimit, credp);
387 	if (error)
388 		goto done;
389 
390 
391 	/* open file table */
392 	vroot = PTOU(p)->u_rdir;
393 	if (vroot == NULL)
394 		vroot = rootdir;
395 
396 	VN_HOLD(vroot);
397 
398 	fip = P_FINFO(p);
399 
400 	for (fd = 0; fd < fip->fi_nfiles; fd++) {
401 		uf_entry_t *ufp;
402 		vnode_t *fvp;
403 		struct file *fp;
404 		vattr_t vattr;
405 		prfdinfo_core_t fdinfo;
406 
407 		bzero(&fdinfo, sizeof (fdinfo));
408 
409 		mutex_enter(&fip->fi_lock);
410 		UF_ENTER(ufp, fip, fd);
411 		if (((fp = ufp->uf_file) == NULL) || (fp->f_count < 1)) {
412 			UF_EXIT(ufp);
413 			mutex_exit(&fip->fi_lock);
414 			continue;
415 		}
416 
417 		fdinfo.pr_fd = fd;
418 		fdinfo.pr_fdflags = ufp->uf_flag;
419 		fdinfo.pr_fileflags = fp->f_flag2;
420 		fdinfo.pr_fileflags <<= 16;
421 		fdinfo.pr_fileflags |= fp->f_flag;
422 		if ((fdinfo.pr_fileflags & (FSEARCH | FEXEC)) == 0)
423 			fdinfo.pr_fileflags += FOPEN;
424 		fdinfo.pr_offset = fp->f_offset;
425 
426 
427 		fvp = fp->f_vnode;
428 		VN_HOLD(fvp);
429 		UF_EXIT(ufp);
430 		mutex_exit(&fip->fi_lock);
431 
432 		/*
433 		 * There are some vnodes that have no corresponding
434 		 * path.  Its reasonable for this to fail, in which
435 		 * case the path will remain an empty string.
436 		 */
437 		(void) vnodetopath(vroot, fvp, fdinfo.pr_path,
438 		    sizeof (fdinfo.pr_path), credp);
439 
440 		if (VOP_GETATTR(fvp, &vattr, 0, credp, NULL) != 0) {
441 			/*
442 			 * Try to write at least a subset of information
443 			 */
444 			fdinfo.pr_major = 0;
445 			fdinfo.pr_minor = 0;
446 			fdinfo.pr_ino = 0;
447 			fdinfo.pr_mode = 0;
448 			fdinfo.pr_uid = (uid_t)-1;
449 			fdinfo.pr_gid = (gid_t)-1;
450 			fdinfo.pr_rmajor = 0;
451 			fdinfo.pr_rminor = 0;
452 			fdinfo.pr_size = -1;
453 
454 			error = elfnote(vp, &offset, NT_FDINFO,
455 			    sizeof (fdinfo), &fdinfo, rlimit, credp);
456 			VN_RELE(fvp);
457 			if (error) {
458 				VN_RELE(vroot);
459 				goto done;
460 			}
461 			continue;
462 		}
463 
464 		if (fvp->v_type == VSOCK)
465 			fdinfo.pr_fileflags |= sock_getfasync(fvp);
466 
467 		VN_RELE(fvp);
468 
469 		/*
470 		 * This logic mirrors fstat(), which we cannot use
471 		 * directly, as it calls copyout().
472 		 */
473 		fdinfo.pr_major = getmajor(vattr.va_fsid);
474 		fdinfo.pr_minor = getminor(vattr.va_fsid);
475 		fdinfo.pr_ino = (ino64_t)vattr.va_nodeid;
476 		fdinfo.pr_mode = VTTOIF(vattr.va_type) | vattr.va_mode;
477 		fdinfo.pr_uid = vattr.va_uid;
478 		fdinfo.pr_gid = vattr.va_gid;
479 		fdinfo.pr_rmajor = getmajor(vattr.va_rdev);
480 		fdinfo.pr_rminor = getminor(vattr.va_rdev);
481 		fdinfo.pr_size = (off64_t)vattr.va_size;
482 
483 		error = elfnote(vp, &offset, NT_FDINFO,
484 		    sizeof (fdinfo), &fdinfo, rlimit, credp);
485 		if (error) {
486 			VN_RELE(vroot);
487 			goto done;
488 		}
489 	}
490 
491 	/*
492 	 * Take care of grabbing the cwd while we're here and still have vroot
493 	 * held.
494 	 */
495 	fill_prcwd(p, &bigwad->cwd, vroot, credp);
496 	error = elfnote(vp, &offset, NT_CWD, sizeof (bigwad->cwd),
497 	    (caddr_t)&bigwad->cwd, rlimit, credp);
498 	VN_RELE(vroot);
499 	if (error)
500 		goto done;
501 
502 #if defined(__i386_COMPAT)
503 	mutex_enter(&p->p_ldtlock);
504 	ssdsize = prnldt(p) * sizeof (struct ssd);
505 	if (ssdsize != 0) {
506 		ssd = kmem_alloc(ssdsize, KM_SLEEP);
507 		prgetldt(p, ssd);
508 		error = elfnote(vp, &offset, NT_LDT, ssdsize,
509 		    (caddr_t)ssd, rlimit, credp);
510 		kmem_free(ssd, ssdsize);
511 	}
512 	mutex_exit(&p->p_ldtlock);
513 	if (error)
514 		goto done;
515 #endif	/* defined(__i386_COMPAT) */
516 
517 	nlwp = p->p_lwpcnt;
518 	nzomb = p->p_zombcnt;
519 	/* for each entry in the lwp directory ... */
520 	for (ldp = p->p_lwpdir; nlwp + nzomb != 0; ldp++) {
521 		prlwpname_t name = { 0, };
522 
523 		if ((lep = ldp->ld_entry) == NULL)	/* empty slot */
524 			continue;
525 
526 		if ((t = lep->le_thread) != NULL) {	/* active lwp */
527 			ASSERT(nlwp != 0);
528 			nlwp--;
529 			lwp = ttolwp(t);
530 			mutex_enter(&p->p_lock);
531 			prgetlwpsinfo(t, &bigwad->lwpsinfo);
532 			if (t->t_name != NULL) {
533 				(void) strlcpy(name.pr_lwpname, t->t_name,
534 				    sizeof (name.pr_lwpname));
535 			}
536 			mutex_exit(&p->p_lock);
537 		} else {				/* zombie lwp */
538 			ASSERT(nzomb != 0);
539 			nzomb--;
540 			bzero(&bigwad->lwpsinfo, sizeof (bigwad->lwpsinfo));
541 			bigwad->lwpsinfo.pr_lwpid = lep->le_lwpid;
542 			bigwad->lwpsinfo.pr_state = SZOMB;
543 			bigwad->lwpsinfo.pr_sname = 'Z';
544 			bigwad->lwpsinfo.pr_start.tv_sec = lep->le_start;
545 		}
546 
547 		name.pr_lwpid = bigwad->lwpsinfo.pr_lwpid;
548 
549 		error = elfnote(vp, &offset, NT_LWPSINFO,
550 		    sizeof (bigwad->lwpsinfo), (caddr_t)&bigwad->lwpsinfo,
551 		    rlimit, credp);
552 		if (error)
553 			goto done;
554 
555 		if (t == NULL)		/* nothing more to do for a zombie */
556 			continue;
557 
558 		mutex_enter(&p->p_lock);
559 		if (t == curthread) {
560 			/*
561 			 * Modify t_whystop and lwp_cursig so it appears that
562 			 * the current LWP is stopped after faulting on the
563 			 * signal that caused the core dump.  As a result,
564 			 * prgetlwpstatus() will record that signal, the saved
565 			 * lwp_siginfo, and its signal handler in the core file
566 			 * status.  We restore lwp_cursig in case a subsequent
567 			 * signal was received while dumping core.
568 			 */
569 			oldsig = lwp->lwp_cursig;
570 			lwp->lwp_cursig = (uchar_t)sig;
571 			t->t_whystop = PR_FAULTED;
572 
573 			prgetlwpstatus(t, &bigwad->lwpstatus, p->p_zone);
574 			bigwad->lwpstatus.pr_why = 0;
575 
576 			t->t_whystop = 0;
577 			lwp->lwp_cursig = oldsig;
578 		} else {
579 			prgetlwpstatus(t, &bigwad->lwpstatus, p->p_zone);
580 		}
581 		mutex_exit(&p->p_lock);
582 		error = elfnote(vp, &offset, NT_LWPSTATUS,
583 		    sizeof (bigwad->lwpstatus), (caddr_t)&bigwad->lwpstatus,
584 		    rlimit, credp);
585 		if (error)
586 			goto done;
587 
588 		if ((error = elfnote(vp, &offset, NT_LWPNAME, sizeof (name),
589 		    (caddr_t)&name, rlimit, credp)) != 0)
590 			goto done;
591 
592 
593 #if defined(__sparc)
594 		/*
595 		 * Unspilled SPARC register windows.
596 		 */
597 		{
598 			size_t size = prnwindows(lwp);
599 
600 			if (size != 0) {
601 				size = sizeof (gwindows_t) -
602 				    (SPARC_MAXREGWINDOW - size) *
603 				    sizeof (struct rwindow);
604 				prgetwindows(lwp, &bigwad->gwindows);
605 				error = elfnote(vp, &offset, NT_GWINDOWS,
606 				    size, (caddr_t)&bigwad->gwindows,
607 				    rlimit, credp);
608 				if (error)
609 					goto done;
610 			}
611 		}
612 		/*
613 		 * Ancillary State Registers.
614 		 */
615 		if (p->p_model == DATAMODEL_LP64) {
616 			prgetasregs(lwp, bigwad->asrset);
617 			error = elfnote(vp, &offset, NT_ASRS,
618 			    sizeof (asrset_t), (caddr_t)bigwad->asrset,
619 			    rlimit, credp);
620 			if (error)
621 				goto done;
622 		}
623 #endif /* __sparc */
624 
625 		if (xregsize) {
626 			prgetprxregs(lwp, (prxregset_t *)bigwad->xregs);
627 			error = elfnote(vp, &offset, NT_PRXREG,
628 			    xregsize, bigwad->xregs, rlimit, credp);
629 			if (error)
630 				goto done;
631 		}
632 
633 		if (t->t_lwp->lwp_spymaster != NULL) {
634 			void *psaddr = t->t_lwp->lwp_spymaster;
635 #ifdef _ELF32_COMPAT
636 			/*
637 			 * On a 64-bit kernel with 32-bit ELF compatibility,
638 			 * this file is compiled into two different objects:
639 			 * one is compiled normally, and the other is compiled
640 			 * with _ELF32_COMPAT set -- and therefore with a
641 			 * psinfo_t defined to be a psinfo32_t.  However, the
642 			 * psinfo_t denoting our spymaster is always of the
643 			 * native type; if we are in the _ELF32_COMPAT case,
644 			 * we need to explicitly convert it.
645 			 */
646 			if (p->p_model == DATAMODEL_ILP32) {
647 				psinfo_kto32(psaddr, &bigwad->psinfo);
648 				psaddr = &bigwad->psinfo;
649 			}
650 #endif
651 
652 			error = elfnote(vp, &offset, NT_SPYMASTER,
653 			    sizeof (psinfo_t), psaddr, rlimit, credp);
654 			if (error)
655 				goto done;
656 		}
657 	}
658 	ASSERT(nlwp == 0);
659 
660 	/*
661 	 * If a upanic occurred, add a note for it.
662 	 */
663 	mutex_enter(&p->p_lock);
664 	if ((p->p_upanicflag & P_UPF_PANICKED) != 0) {
665 		bzero(&bigwad->upanic, sizeof (prupanic_t));
666 		bigwad->upanic.pru_version = PRUPANIC_VERSION_1;
667 		if ((p->p_upanicflag & P_UPF_INVALMSG) != 0) {
668 			bigwad->upanic.pru_flags |= PRUPANIC_FLAG_MSG_ERROR;
669 		}
670 
671 		if ((p->p_upanicflag & P_UPF_TRUNCMSG) != 0) {
672 			bigwad->upanic.pru_flags |= PRUPANIC_FLAG_MSG_TRUNC;
673 		}
674 
675 		if ((p->p_upanicflag & P_UPF_HAVEMSG) != 0) {
676 			bigwad->upanic.pru_flags |= PRUPANIC_FLAG_MSG_VALID;
677 			bcopy(p->p_upanic, bigwad->upanic.pru_data,
678 			    PRUPANIC_BUFLEN);
679 		}
680 
681 		mutex_exit(&p->p_lock);
682 		error = elfnote(vp, &offset, NT_UPANIC, sizeof (prupanic_t),
683 		    &bigwad->upanic, rlimit, credp);
684 		if (error != 0) {
685 			goto done;
686 		}
687 	} else {
688 		mutex_exit(&p->p_lock);
689 	}
690 
691 done:
692 	kmem_free(bigwad, bigsize);
693 	return (error);
694 }
695