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