17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 57c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 67c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 77c478bd9Sstevel@tonic-gate * with the License. 87c478bd9Sstevel@tonic-gate * 97c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 107c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 117c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 127c478bd9Sstevel@tonic-gate * and limitations under the License. 137c478bd9Sstevel@tonic-gate * 147c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 157c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 167c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 177c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 187c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 197c478bd9Sstevel@tonic-gate * 207c478bd9Sstevel@tonic-gate * CDDL HEADER END 217c478bd9Sstevel@tonic-gate */ 227c478bd9Sstevel@tonic-gate /* 237c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 2734bdffbfSGarrett D'Amore /* 2834bdffbfSGarrett D'Amore * Copyright 2012 DEY Storage Systems, Inc. All rights reserved. 294b835deeSRobert Mustacchi * Copyright (c) 2014, Joyent, Inc. All rights reserved. 3034bdffbfSGarrett D'Amore */ 317c478bd9Sstevel@tonic-gate 327c478bd9Sstevel@tonic-gate #include <sys/types.h> 337c478bd9Sstevel@tonic-gate #include <sys/param.h> 347c478bd9Sstevel@tonic-gate #include <sys/thread.h> 357c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h> 367c478bd9Sstevel@tonic-gate #include <sys/signal.h> 377c478bd9Sstevel@tonic-gate #include <sys/cred.h> 387c478bd9Sstevel@tonic-gate #include <sys/priv.h> 397c478bd9Sstevel@tonic-gate #include <sys/user.h> 4034bdffbfSGarrett D'Amore #include <sys/file.h> 417c478bd9Sstevel@tonic-gate #include <sys/errno.h> 427c478bd9Sstevel@tonic-gate #include <sys/vnode.h> 4334bdffbfSGarrett D'Amore #include <sys/mode.h> 4434bdffbfSGarrett D'Amore #include <sys/vfs.h> 457c478bd9Sstevel@tonic-gate #include <sys/mman.h> 467c478bd9Sstevel@tonic-gate #include <sys/kmem.h> 477c478bd9Sstevel@tonic-gate #include <sys/proc.h> 487c478bd9Sstevel@tonic-gate #include <sys/pathname.h> 497c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h> 507c478bd9Sstevel@tonic-gate #include <sys/systm.h> 517c478bd9Sstevel@tonic-gate #include <sys/elf.h> 527c478bd9Sstevel@tonic-gate #include <sys/vmsystm.h> 537c478bd9Sstevel@tonic-gate #include <sys/debug.h> 547c478bd9Sstevel@tonic-gate #include <sys/procfs.h> 557c478bd9Sstevel@tonic-gate #include <sys/regset.h> 567c478bd9Sstevel@tonic-gate #include <sys/auxv.h> 577c478bd9Sstevel@tonic-gate #include <sys/exec.h> 587c478bd9Sstevel@tonic-gate #include <sys/prsystm.h> 597c478bd9Sstevel@tonic-gate #include <sys/utsname.h> 607c478bd9Sstevel@tonic-gate #include <sys/zone.h> 617c478bd9Sstevel@tonic-gate #include <vm/as.h> 627c478bd9Sstevel@tonic-gate #include <vm/rm.h> 637c478bd9Sstevel@tonic-gate #include <sys/modctl.h> 647c478bd9Sstevel@tonic-gate #include <sys/systeminfo.h> 657c478bd9Sstevel@tonic-gate #include <sys/machelf.h> 6634bdffbfSGarrett D'Amore #include <sys/sunddi.h> 677c478bd9Sstevel@tonic-gate #include "elf_impl.h" 687c478bd9Sstevel@tonic-gate #if defined(__i386) || defined(__i386_COMPAT) 697c478bd9Sstevel@tonic-gate #include <sys/sysi86.h> 707c478bd9Sstevel@tonic-gate #endif 717c478bd9Sstevel@tonic-gate 727c478bd9Sstevel@tonic-gate void 737c478bd9Sstevel@tonic-gate setup_note_header(Phdr *v, proc_t *p) 747c478bd9Sstevel@tonic-gate { 757c478bd9Sstevel@tonic-gate int nlwp = p->p_lwpcnt; 767c478bd9Sstevel@tonic-gate int nzomb = p->p_zombcnt; 7734bdffbfSGarrett D'Amore int nfd; 787c478bd9Sstevel@tonic-gate size_t size; 797c478bd9Sstevel@tonic-gate prcred_t *pcrp; 8034bdffbfSGarrett D'Amore uf_info_t *fip; 8134bdffbfSGarrett D'Amore uf_entry_t *ufp; 8234bdffbfSGarrett D'Amore int fd; 8334bdffbfSGarrett D'Amore 8434bdffbfSGarrett D'Amore fip = P_FINFO(p); 8534bdffbfSGarrett D'Amore nfd = 0; 8634bdffbfSGarrett D'Amore mutex_enter(&fip->fi_lock); 8734bdffbfSGarrett D'Amore for (fd = 0; fd < fip->fi_nfiles; fd++) { 8834bdffbfSGarrett D'Amore UF_ENTER(ufp, fip, fd); 8934bdffbfSGarrett D'Amore if ((ufp->uf_file != NULL) && (ufp->uf_file->f_count > 0)) 9034bdffbfSGarrett D'Amore nfd++; 9134bdffbfSGarrett D'Amore UF_EXIT(ufp); 9234bdffbfSGarrett D'Amore } 9334bdffbfSGarrett D'Amore mutex_exit(&fip->fi_lock); 947c478bd9Sstevel@tonic-gate 957c478bd9Sstevel@tonic-gate v[0].p_type = PT_NOTE; 967c478bd9Sstevel@tonic-gate v[0].p_flags = PF_R; 9734bdffbfSGarrett D'Amore v[0].p_filesz = (sizeof (Note) * (9 + 2 * nlwp + nzomb + nfd)) 987c478bd9Sstevel@tonic-gate + roundup(sizeof (psinfo_t), sizeof (Word)) 997c478bd9Sstevel@tonic-gate + roundup(sizeof (pstatus_t), sizeof (Word)) 1007c478bd9Sstevel@tonic-gate + roundup(prgetprivsize(), sizeof (Word)) 1017c478bd9Sstevel@tonic-gate + roundup(priv_get_implinfo_size(), sizeof (Word)) 1027c478bd9Sstevel@tonic-gate + roundup(strlen(platform) + 1, sizeof (Word)) 1037c478bd9Sstevel@tonic-gate + roundup(strlen(p->p_zone->zone_name) + 1, sizeof (Word)) 1047c478bd9Sstevel@tonic-gate + roundup(__KERN_NAUXV_IMPL * sizeof (aux_entry_t), sizeof (Word)) 1057c478bd9Sstevel@tonic-gate + roundup(sizeof (utsname), sizeof (Word)) 1067c478bd9Sstevel@tonic-gate + roundup(sizeof (core_content_t), sizeof (Word)) 1077c478bd9Sstevel@tonic-gate + (nlwp + nzomb) * roundup(sizeof (lwpsinfo_t), sizeof (Word)) 10834bdffbfSGarrett D'Amore + nlwp * roundup(sizeof (lwpstatus_t), sizeof (Word)) 10934bdffbfSGarrett D'Amore + nfd * roundup(sizeof (prfdinfo_t), sizeof (Word)); 1107c478bd9Sstevel@tonic-gate 111f971a346SBryan Cantrill if (curproc->p_agenttp != NULL) { 112f971a346SBryan Cantrill v[0].p_filesz += sizeof (Note) + 113f971a346SBryan Cantrill roundup(sizeof (psinfo_t), sizeof (Word)); 114f971a346SBryan Cantrill } 115f971a346SBryan Cantrill 1167c478bd9Sstevel@tonic-gate size = sizeof (prcred_t) + sizeof (gid_t) * (ngroups_max - 1); 1177c478bd9Sstevel@tonic-gate pcrp = kmem_alloc(size, KM_SLEEP); 1187c478bd9Sstevel@tonic-gate prgetcred(p, pcrp); 1197c478bd9Sstevel@tonic-gate if (pcrp->pr_ngroups != 0) { 1207c478bd9Sstevel@tonic-gate v[0].p_filesz += sizeof (Note) + roundup(sizeof (prcred_t) + 1217c478bd9Sstevel@tonic-gate sizeof (gid_t) * (pcrp->pr_ngroups - 1), sizeof (Word)); 1227c478bd9Sstevel@tonic-gate } else { 1237c478bd9Sstevel@tonic-gate v[0].p_filesz += sizeof (Note) + 1247c478bd9Sstevel@tonic-gate roundup(sizeof (prcred_t), sizeof (Word)); 1257c478bd9Sstevel@tonic-gate } 1267c478bd9Sstevel@tonic-gate kmem_free(pcrp, size); 1277c478bd9Sstevel@tonic-gate 12834bdffbfSGarrett D'Amore 1297c478bd9Sstevel@tonic-gate #if defined(__i386) || defined(__i386_COMPAT) 1307c478bd9Sstevel@tonic-gate mutex_enter(&p->p_ldtlock); 1317c478bd9Sstevel@tonic-gate size = prnldt(p) * sizeof (struct ssd); 1327c478bd9Sstevel@tonic-gate mutex_exit(&p->p_ldtlock); 1337c478bd9Sstevel@tonic-gate if (size != 0) 1347c478bd9Sstevel@tonic-gate v[0].p_filesz += sizeof (Note) + roundup(size, sizeof (Word)); 1357c478bd9Sstevel@tonic-gate #endif /* __i386 || __i386_COMPAT */ 1367c478bd9Sstevel@tonic-gate 1377c478bd9Sstevel@tonic-gate if ((size = prhasx(p)? prgetprxregsize(p) : 0) != 0) 1387c478bd9Sstevel@tonic-gate v[0].p_filesz += nlwp * sizeof (Note) 1397c478bd9Sstevel@tonic-gate + nlwp * roundup(size, sizeof (Word)); 1407c478bd9Sstevel@tonic-gate 1417c478bd9Sstevel@tonic-gate #if defined(__sparc) 1427c478bd9Sstevel@tonic-gate /* 1437c478bd9Sstevel@tonic-gate * Figure out the number and sizes of register windows. 1447c478bd9Sstevel@tonic-gate */ 1457c478bd9Sstevel@tonic-gate { 1467c478bd9Sstevel@tonic-gate kthread_t *t = p->p_tlist; 1477c478bd9Sstevel@tonic-gate do { 1487c478bd9Sstevel@tonic-gate if ((size = prnwindows(ttolwp(t))) != 0) { 1497c478bd9Sstevel@tonic-gate size = sizeof (gwindows_t) - 1507c478bd9Sstevel@tonic-gate (SPARC_MAXREGWINDOW - size) * 1517c478bd9Sstevel@tonic-gate sizeof (struct rwindow); 1527c478bd9Sstevel@tonic-gate v[0].p_filesz += sizeof (Note) + 1537c478bd9Sstevel@tonic-gate roundup(size, sizeof (Word)); 1547c478bd9Sstevel@tonic-gate } 1557c478bd9Sstevel@tonic-gate } while ((t = t->t_forw) != p->p_tlist); 1567c478bd9Sstevel@tonic-gate } 1577c478bd9Sstevel@tonic-gate /* 1587c478bd9Sstevel@tonic-gate * Space for the Ancillary State Registers. 1597c478bd9Sstevel@tonic-gate */ 1607c478bd9Sstevel@tonic-gate if (p->p_model == DATAMODEL_LP64) 1617c478bd9Sstevel@tonic-gate v[0].p_filesz += nlwp * sizeof (Note) 1627c478bd9Sstevel@tonic-gate + nlwp * roundup(sizeof (asrset_t), sizeof (Word)); 1637c478bd9Sstevel@tonic-gate #endif /* __sparc */ 1647c478bd9Sstevel@tonic-gate } 1657c478bd9Sstevel@tonic-gate 1667c478bd9Sstevel@tonic-gate int 1677c478bd9Sstevel@tonic-gate write_elfnotes(proc_t *p, int sig, vnode_t *vp, offset_t offset, 1687c478bd9Sstevel@tonic-gate rlim64_t rlimit, cred_t *credp, core_content_t content) 1697c478bd9Sstevel@tonic-gate { 1707c478bd9Sstevel@tonic-gate union { 1717c478bd9Sstevel@tonic-gate psinfo_t psinfo; 1727c478bd9Sstevel@tonic-gate pstatus_t pstatus; 1737c478bd9Sstevel@tonic-gate lwpsinfo_t lwpsinfo; 1747c478bd9Sstevel@tonic-gate lwpstatus_t lwpstatus; 1757c478bd9Sstevel@tonic-gate #if defined(__sparc) 1767c478bd9Sstevel@tonic-gate gwindows_t gwindows; 1777c478bd9Sstevel@tonic-gate asrset_t asrset; 1787c478bd9Sstevel@tonic-gate #endif /* __sparc */ 1797c478bd9Sstevel@tonic-gate char xregs[1]; 1807c478bd9Sstevel@tonic-gate aux_entry_t auxv[__KERN_NAUXV_IMPL]; 1817c478bd9Sstevel@tonic-gate prcred_t pcred; 1827c478bd9Sstevel@tonic-gate prpriv_t ppriv; 1837c478bd9Sstevel@tonic-gate priv_impl_info_t prinfo; 1847c478bd9Sstevel@tonic-gate struct utsname uts; 1857c478bd9Sstevel@tonic-gate } *bigwad; 1867c478bd9Sstevel@tonic-gate 1877c478bd9Sstevel@tonic-gate size_t xregsize = prhasx(p)? prgetprxregsize(p) : 0; 1887c478bd9Sstevel@tonic-gate size_t crsize = sizeof (prcred_t) + sizeof (gid_t) * (ngroups_max - 1); 1897c478bd9Sstevel@tonic-gate size_t psize = prgetprivsize(); 1907c478bd9Sstevel@tonic-gate size_t bigsize = MAX(psize, MAX(sizeof (*bigwad), 1917c478bd9Sstevel@tonic-gate MAX(xregsize, crsize))); 1927c478bd9Sstevel@tonic-gate 1937c478bd9Sstevel@tonic-gate priv_impl_info_t *prii; 1947c478bd9Sstevel@tonic-gate 1957c478bd9Sstevel@tonic-gate lwpdir_t *ldp; 1967c478bd9Sstevel@tonic-gate lwpent_t *lep; 1977c478bd9Sstevel@tonic-gate kthread_t *t; 1987c478bd9Sstevel@tonic-gate klwp_t *lwp; 1997c478bd9Sstevel@tonic-gate user_t *up; 2007c478bd9Sstevel@tonic-gate int i; 2017c478bd9Sstevel@tonic-gate int nlwp; 2027c478bd9Sstevel@tonic-gate int nzomb; 2037c478bd9Sstevel@tonic-gate int error; 2047c478bd9Sstevel@tonic-gate uchar_t oldsig; 20534bdffbfSGarrett D'Amore uf_info_t *fip; 20634bdffbfSGarrett D'Amore int fd; 20734bdffbfSGarrett D'Amore vnode_t *vroot; 20834bdffbfSGarrett D'Amore 2097c478bd9Sstevel@tonic-gate #if defined(__i386) || defined(__i386_COMPAT) 2107c478bd9Sstevel@tonic-gate struct ssd *ssd; 2117c478bd9Sstevel@tonic-gate size_t ssdsize; 2127c478bd9Sstevel@tonic-gate #endif /* __i386 || __i386_COMPAT */ 2137c478bd9Sstevel@tonic-gate 2147c478bd9Sstevel@tonic-gate bigsize = MAX(bigsize, priv_get_implinfo_size()); 2157c478bd9Sstevel@tonic-gate 2167c478bd9Sstevel@tonic-gate bigwad = kmem_alloc(bigsize, KM_SLEEP); 2177c478bd9Sstevel@tonic-gate 2187c478bd9Sstevel@tonic-gate /* 2197c478bd9Sstevel@tonic-gate * The order of the elfnote entries should be same here 2207c478bd9Sstevel@tonic-gate * and in the gcore(1) command. Synchronization is 2217c478bd9Sstevel@tonic-gate * needed between the kernel and gcore(1). 2227c478bd9Sstevel@tonic-gate */ 2237c478bd9Sstevel@tonic-gate 2247c478bd9Sstevel@tonic-gate /* 2257c478bd9Sstevel@tonic-gate * Get the psinfo, and set the wait status to indicate that a core was 2267c478bd9Sstevel@tonic-gate * dumped. We have to forge this since p->p_wcode is not set yet. 2277c478bd9Sstevel@tonic-gate */ 2287c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock); 2297c478bd9Sstevel@tonic-gate prgetpsinfo(p, &bigwad->psinfo); 2307c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock); 2317c478bd9Sstevel@tonic-gate bigwad->psinfo.pr_wstat = wstat(CLD_DUMPED, sig); 2327c478bd9Sstevel@tonic-gate 2337c478bd9Sstevel@tonic-gate error = elfnote(vp, &offset, NT_PSINFO, sizeof (bigwad->psinfo), 2347c478bd9Sstevel@tonic-gate (caddr_t)&bigwad->psinfo, rlimit, credp); 2357c478bd9Sstevel@tonic-gate if (error) 2367c478bd9Sstevel@tonic-gate goto done; 2377c478bd9Sstevel@tonic-gate 2387c478bd9Sstevel@tonic-gate /* 2397c478bd9Sstevel@tonic-gate * Modify t_whystop and lwp_cursig so it appears that the current LWP 2407c478bd9Sstevel@tonic-gate * is stopped after faulting on the signal that caused the core dump. 2417c478bd9Sstevel@tonic-gate * As a result, prgetstatus() will record that signal, the saved 2427c478bd9Sstevel@tonic-gate * lwp_siginfo, and its signal handler in the core file status. We 2437c478bd9Sstevel@tonic-gate * restore lwp_cursig in case a subsequent signal was received while 2447c478bd9Sstevel@tonic-gate * dumping core. 2457c478bd9Sstevel@tonic-gate */ 2467c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock); 2477c478bd9Sstevel@tonic-gate lwp = ttolwp(curthread); 2487c478bd9Sstevel@tonic-gate 2497c478bd9Sstevel@tonic-gate oldsig = lwp->lwp_cursig; 2507c478bd9Sstevel@tonic-gate lwp->lwp_cursig = (uchar_t)sig; 2517c478bd9Sstevel@tonic-gate curthread->t_whystop = PR_FAULTED; 2527c478bd9Sstevel@tonic-gate 2537c478bd9Sstevel@tonic-gate prgetstatus(p, &bigwad->pstatus, p->p_zone); 2547c478bd9Sstevel@tonic-gate bigwad->pstatus.pr_lwp.pr_why = 0; 2557c478bd9Sstevel@tonic-gate 2567c478bd9Sstevel@tonic-gate curthread->t_whystop = 0; 2577c478bd9Sstevel@tonic-gate lwp->lwp_cursig = oldsig; 2587c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock); 2597c478bd9Sstevel@tonic-gate 2607c478bd9Sstevel@tonic-gate error = elfnote(vp, &offset, NT_PSTATUS, sizeof (bigwad->pstatus), 2617c478bd9Sstevel@tonic-gate (caddr_t)&bigwad->pstatus, rlimit, credp); 2627c478bd9Sstevel@tonic-gate if (error) 2637c478bd9Sstevel@tonic-gate goto done; 2647c478bd9Sstevel@tonic-gate 2657c478bd9Sstevel@tonic-gate error = elfnote(vp, &offset, NT_PLATFORM, strlen(platform) + 1, 2667c478bd9Sstevel@tonic-gate platform, rlimit, credp); 2677c478bd9Sstevel@tonic-gate if (error) 2687c478bd9Sstevel@tonic-gate goto done; 2697c478bd9Sstevel@tonic-gate 2707c478bd9Sstevel@tonic-gate up = PTOU(p); 2717c478bd9Sstevel@tonic-gate for (i = 0; i < __KERN_NAUXV_IMPL; i++) { 2727c478bd9Sstevel@tonic-gate bigwad->auxv[i].a_type = up->u_auxv[i].a_type; 2737c478bd9Sstevel@tonic-gate bigwad->auxv[i].a_un.a_val = up->u_auxv[i].a_un.a_val; 2747c478bd9Sstevel@tonic-gate } 2757c478bd9Sstevel@tonic-gate error = elfnote(vp, &offset, NT_AUXV, sizeof (bigwad->auxv), 2767c478bd9Sstevel@tonic-gate (caddr_t)bigwad->auxv, rlimit, credp); 2777c478bd9Sstevel@tonic-gate if (error) 2787c478bd9Sstevel@tonic-gate goto done; 2797c478bd9Sstevel@tonic-gate 2807c478bd9Sstevel@tonic-gate bcopy(&utsname, &bigwad->uts, sizeof (struct utsname)); 2817c478bd9Sstevel@tonic-gate if (!INGLOBALZONE(p)) { 2827c478bd9Sstevel@tonic-gate bcopy(p->p_zone->zone_nodename, &bigwad->uts.nodename, 2837c478bd9Sstevel@tonic-gate _SYS_NMLN); 2847c478bd9Sstevel@tonic-gate } 2857c478bd9Sstevel@tonic-gate error = elfnote(vp, &offset, NT_UTSNAME, sizeof (struct utsname), 2867c478bd9Sstevel@tonic-gate (caddr_t)&bigwad->uts, rlimit, credp); 2877c478bd9Sstevel@tonic-gate if (error) 2887c478bd9Sstevel@tonic-gate goto done; 2897c478bd9Sstevel@tonic-gate 2907c478bd9Sstevel@tonic-gate prgetcred(p, &bigwad->pcred); 2917c478bd9Sstevel@tonic-gate 2927c478bd9Sstevel@tonic-gate if (bigwad->pcred.pr_ngroups != 0) { 2937c478bd9Sstevel@tonic-gate crsize = sizeof (prcred_t) + 2947c478bd9Sstevel@tonic-gate sizeof (gid_t) * (bigwad->pcred.pr_ngroups - 1); 2957c478bd9Sstevel@tonic-gate } else 2967c478bd9Sstevel@tonic-gate crsize = sizeof (prcred_t); 2977c478bd9Sstevel@tonic-gate 2987c478bd9Sstevel@tonic-gate error = elfnote(vp, &offset, NT_PRCRED, crsize, 2997c478bd9Sstevel@tonic-gate (caddr_t)&bigwad->pcred, rlimit, credp); 3007c478bd9Sstevel@tonic-gate if (error) 3017c478bd9Sstevel@tonic-gate goto done; 3027c478bd9Sstevel@tonic-gate 3037c478bd9Sstevel@tonic-gate error = elfnote(vp, &offset, NT_CONTENT, sizeof (core_content_t), 3047c478bd9Sstevel@tonic-gate (caddr_t)&content, rlimit, credp); 3057c478bd9Sstevel@tonic-gate if (error) 3067c478bd9Sstevel@tonic-gate goto done; 3077c478bd9Sstevel@tonic-gate 3087c478bd9Sstevel@tonic-gate prgetpriv(p, &bigwad->ppriv); 3097c478bd9Sstevel@tonic-gate 3107c478bd9Sstevel@tonic-gate error = elfnote(vp, &offset, NT_PRPRIV, psize, 3117c478bd9Sstevel@tonic-gate (caddr_t)&bigwad->ppriv, rlimit, credp); 3127c478bd9Sstevel@tonic-gate if (error) 3137c478bd9Sstevel@tonic-gate goto done; 3147c478bd9Sstevel@tonic-gate 3157c478bd9Sstevel@tonic-gate prii = priv_hold_implinfo(); 3167c478bd9Sstevel@tonic-gate error = elfnote(vp, &offset, NT_PRPRIVINFO, priv_get_implinfo_size(), 3177c478bd9Sstevel@tonic-gate (caddr_t)prii, rlimit, credp); 3187c478bd9Sstevel@tonic-gate priv_release_implinfo(); 3197c478bd9Sstevel@tonic-gate if (error) 3207c478bd9Sstevel@tonic-gate goto done; 3217c478bd9Sstevel@tonic-gate 3227c478bd9Sstevel@tonic-gate /* zone can't go away as long as process exists */ 3237c478bd9Sstevel@tonic-gate error = elfnote(vp, &offset, NT_ZONENAME, 3247c478bd9Sstevel@tonic-gate strlen(p->p_zone->zone_name) + 1, p->p_zone->zone_name, 3257c478bd9Sstevel@tonic-gate rlimit, credp); 3267c478bd9Sstevel@tonic-gate if (error) 3277c478bd9Sstevel@tonic-gate goto done; 3287c478bd9Sstevel@tonic-gate 32934bdffbfSGarrett D'Amore 33034bdffbfSGarrett D'Amore /* open file table */ 33134bdffbfSGarrett D'Amore vroot = PTOU(p)->u_rdir; 33234bdffbfSGarrett D'Amore if (vroot == NULL) 33334bdffbfSGarrett D'Amore vroot = rootdir; 33434bdffbfSGarrett D'Amore 33534bdffbfSGarrett D'Amore VN_HOLD(vroot); 33634bdffbfSGarrett D'Amore 33734bdffbfSGarrett D'Amore fip = P_FINFO(p); 33834bdffbfSGarrett D'Amore 33934bdffbfSGarrett D'Amore for (fd = 0; fd < fip->fi_nfiles; fd++) { 34034bdffbfSGarrett D'Amore uf_entry_t *ufp; 34134bdffbfSGarrett D'Amore vnode_t *fvp; 34234bdffbfSGarrett D'Amore struct file *fp; 34334bdffbfSGarrett D'Amore vattr_t vattr; 34434bdffbfSGarrett D'Amore prfdinfo_t fdinfo; 34534bdffbfSGarrett D'Amore 34634bdffbfSGarrett D'Amore bzero(&fdinfo, sizeof (fdinfo)); 34734bdffbfSGarrett D'Amore 34834bdffbfSGarrett D'Amore mutex_enter(&fip->fi_lock); 34934bdffbfSGarrett D'Amore UF_ENTER(ufp, fip, fd); 35034bdffbfSGarrett D'Amore if (((fp = ufp->uf_file) == NULL) || (fp->f_count < 1)) { 35134bdffbfSGarrett D'Amore UF_EXIT(ufp); 35234bdffbfSGarrett D'Amore mutex_exit(&fip->fi_lock); 35334bdffbfSGarrett D'Amore continue; 35434bdffbfSGarrett D'Amore } 35534bdffbfSGarrett D'Amore 35634bdffbfSGarrett D'Amore fdinfo.pr_fd = fd; 35734bdffbfSGarrett D'Amore fdinfo.pr_fdflags = ufp->uf_flag; 35834bdffbfSGarrett D'Amore fdinfo.pr_fileflags = fp->f_flag2; 35934bdffbfSGarrett D'Amore fdinfo.pr_fileflags <<= 16; 36034bdffbfSGarrett D'Amore fdinfo.pr_fileflags |= fp->f_flag; 36134bdffbfSGarrett D'Amore if ((fdinfo.pr_fileflags & (FSEARCH | FEXEC)) == 0) 36234bdffbfSGarrett D'Amore fdinfo.pr_fileflags += FOPEN; 36334bdffbfSGarrett D'Amore fdinfo.pr_offset = fp->f_offset; 36434bdffbfSGarrett D'Amore 36534bdffbfSGarrett D'Amore 36634bdffbfSGarrett D'Amore fvp = fp->f_vnode; 36734bdffbfSGarrett D'Amore VN_HOLD(fvp); 36834bdffbfSGarrett D'Amore UF_EXIT(ufp); 36934bdffbfSGarrett D'Amore mutex_exit(&fip->fi_lock); 37034bdffbfSGarrett D'Amore 37134bdffbfSGarrett D'Amore /* 37234bdffbfSGarrett D'Amore * There are some vnodes that have no corresponding 37334bdffbfSGarrett D'Amore * path. Its reasonable for this to fail, in which 37434bdffbfSGarrett D'Amore * case the path will remain an empty string. 37534bdffbfSGarrett D'Amore */ 37634bdffbfSGarrett D'Amore (void) vnodetopath(vroot, fvp, fdinfo.pr_path, 37734bdffbfSGarrett D'Amore sizeof (fdinfo.pr_path), credp); 37834bdffbfSGarrett D'Amore 37933d794d1SSimon Klinkert if (VOP_GETATTR(fvp, &vattr, 0, credp, NULL) != 0) { 38033d794d1SSimon Klinkert /* 38133d794d1SSimon Klinkert * Try to write at least a subset of information 38233d794d1SSimon Klinkert */ 38333d794d1SSimon Klinkert fdinfo.pr_major = 0; 38433d794d1SSimon Klinkert fdinfo.pr_minor = 0; 38533d794d1SSimon Klinkert fdinfo.pr_ino = 0; 38633d794d1SSimon Klinkert fdinfo.pr_mode = 0; 387f2f1e742SDan McDonald fdinfo.pr_uid = (uid_t)-1; 388f2f1e742SDan McDonald fdinfo.pr_gid = (gid_t)-1; 38933d794d1SSimon Klinkert fdinfo.pr_rmajor = 0; 39033d794d1SSimon Klinkert fdinfo.pr_rminor = 0; 39133d794d1SSimon Klinkert fdinfo.pr_size = -1; 39233d794d1SSimon Klinkert 39333d794d1SSimon Klinkert error = elfnote(vp, &offset, NT_FDINFO, 39433d794d1SSimon Klinkert sizeof (fdinfo), &fdinfo, rlimit, credp); 39534bdffbfSGarrett D'Amore VN_RELE(fvp); 396*d379c830SSimon Klinkert if (error) { 39734bdffbfSGarrett D'Amore VN_RELE(vroot); 39834bdffbfSGarrett D'Amore goto done; 399*d379c830SSimon Klinkert } 40033d794d1SSimon Klinkert continue; 40134bdffbfSGarrett D'Amore } 40234bdffbfSGarrett D'Amore 40334bdffbfSGarrett D'Amore if (fvp->v_type == VSOCK) 40434bdffbfSGarrett D'Amore fdinfo.pr_fileflags |= sock_getfasync(fvp); 40534bdffbfSGarrett D'Amore 40634bdffbfSGarrett D'Amore VN_RELE(fvp); 40734bdffbfSGarrett D'Amore 40834bdffbfSGarrett D'Amore /* 40934bdffbfSGarrett D'Amore * This logic mirrors fstat(), which we cannot use 41034bdffbfSGarrett D'Amore * directly, as it calls copyout(). 41134bdffbfSGarrett D'Amore */ 41234bdffbfSGarrett D'Amore fdinfo.pr_major = getmajor(vattr.va_fsid); 41334bdffbfSGarrett D'Amore fdinfo.pr_minor = getminor(vattr.va_fsid); 41434bdffbfSGarrett D'Amore fdinfo.pr_ino = (ino64_t)vattr.va_nodeid; 41534bdffbfSGarrett D'Amore fdinfo.pr_mode = VTTOIF(vattr.va_type) | vattr.va_mode; 41634bdffbfSGarrett D'Amore fdinfo.pr_uid = vattr.va_uid; 41734bdffbfSGarrett D'Amore fdinfo.pr_gid = vattr.va_gid; 41834bdffbfSGarrett D'Amore fdinfo.pr_rmajor = getmajor(vattr.va_rdev); 41934bdffbfSGarrett D'Amore fdinfo.pr_rminor = getminor(vattr.va_rdev); 42034bdffbfSGarrett D'Amore fdinfo.pr_size = (off64_t)vattr.va_size; 42134bdffbfSGarrett D'Amore 42234bdffbfSGarrett D'Amore error = elfnote(vp, &offset, NT_FDINFO, 42334bdffbfSGarrett D'Amore sizeof (fdinfo), &fdinfo, rlimit, credp); 42434bdffbfSGarrett D'Amore if (error) { 4254b835deeSRobert Mustacchi VN_RELE(vroot); 42634bdffbfSGarrett D'Amore goto done; 42734bdffbfSGarrett D'Amore } 42834bdffbfSGarrett D'Amore } 42934bdffbfSGarrett D'Amore 4304b835deeSRobert Mustacchi VN_RELE(vroot); 4314b835deeSRobert Mustacchi 4327c478bd9Sstevel@tonic-gate #if defined(__i386) || defined(__i386_COMPAT) 4337c478bd9Sstevel@tonic-gate mutex_enter(&p->p_ldtlock); 4347c478bd9Sstevel@tonic-gate ssdsize = prnldt(p) * sizeof (struct ssd); 4357c478bd9Sstevel@tonic-gate if (ssdsize != 0) { 4367c478bd9Sstevel@tonic-gate ssd = kmem_alloc(ssdsize, KM_SLEEP); 4377c478bd9Sstevel@tonic-gate prgetldt(p, ssd); 4387c478bd9Sstevel@tonic-gate error = elfnote(vp, &offset, NT_LDT, ssdsize, 4397c478bd9Sstevel@tonic-gate (caddr_t)ssd, rlimit, credp); 4407c478bd9Sstevel@tonic-gate kmem_free(ssd, ssdsize); 4417c478bd9Sstevel@tonic-gate } 4427c478bd9Sstevel@tonic-gate mutex_exit(&p->p_ldtlock); 4437c478bd9Sstevel@tonic-gate if (error) 4447c478bd9Sstevel@tonic-gate goto done; 4457c478bd9Sstevel@tonic-gate #endif /* __i386 || defined(__i386_COMPAT) */ 4467c478bd9Sstevel@tonic-gate 4477c478bd9Sstevel@tonic-gate nlwp = p->p_lwpcnt; 4487c478bd9Sstevel@tonic-gate nzomb = p->p_zombcnt; 4497c478bd9Sstevel@tonic-gate /* for each entry in the lwp directory ... */ 4507c478bd9Sstevel@tonic-gate for (ldp = p->p_lwpdir; nlwp + nzomb != 0; ldp++) { 4517c478bd9Sstevel@tonic-gate 4527c478bd9Sstevel@tonic-gate if ((lep = ldp->ld_entry) == NULL) /* empty slot */ 4537c478bd9Sstevel@tonic-gate continue; 4547c478bd9Sstevel@tonic-gate 4557c478bd9Sstevel@tonic-gate if ((t = lep->le_thread) != NULL) { /* active lwp */ 4567c478bd9Sstevel@tonic-gate ASSERT(nlwp != 0); 4577c478bd9Sstevel@tonic-gate nlwp--; 4587c478bd9Sstevel@tonic-gate lwp = ttolwp(t); 4597c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock); 4607c478bd9Sstevel@tonic-gate prgetlwpsinfo(t, &bigwad->lwpsinfo); 4617c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock); 4627c478bd9Sstevel@tonic-gate } else { /* zombie lwp */ 4637c478bd9Sstevel@tonic-gate ASSERT(nzomb != 0); 4647c478bd9Sstevel@tonic-gate nzomb--; 4657c478bd9Sstevel@tonic-gate bzero(&bigwad->lwpsinfo, sizeof (bigwad->lwpsinfo)); 4667c478bd9Sstevel@tonic-gate bigwad->lwpsinfo.pr_lwpid = lep->le_lwpid; 4677c478bd9Sstevel@tonic-gate bigwad->lwpsinfo.pr_state = SZOMB; 4687c478bd9Sstevel@tonic-gate bigwad->lwpsinfo.pr_sname = 'Z'; 4697c478bd9Sstevel@tonic-gate bigwad->lwpsinfo.pr_start.tv_sec = lep->le_start; 4707c478bd9Sstevel@tonic-gate } 4717c478bd9Sstevel@tonic-gate error = elfnote(vp, &offset, NT_LWPSINFO, 4727c478bd9Sstevel@tonic-gate sizeof (bigwad->lwpsinfo), (caddr_t)&bigwad->lwpsinfo, 4737c478bd9Sstevel@tonic-gate rlimit, credp); 4747c478bd9Sstevel@tonic-gate if (error) 4757c478bd9Sstevel@tonic-gate goto done; 4767c478bd9Sstevel@tonic-gate if (t == NULL) /* nothing more to do for a zombie */ 4777c478bd9Sstevel@tonic-gate continue; 4787c478bd9Sstevel@tonic-gate 4797c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock); 4807c478bd9Sstevel@tonic-gate if (t == curthread) { 4817c478bd9Sstevel@tonic-gate /* 4827c478bd9Sstevel@tonic-gate * Modify t_whystop and lwp_cursig so it appears that 4837c478bd9Sstevel@tonic-gate * the current LWP is stopped after faulting on the 4847c478bd9Sstevel@tonic-gate * signal that caused the core dump. As a result, 4857c478bd9Sstevel@tonic-gate * prgetlwpstatus() will record that signal, the saved 4867c478bd9Sstevel@tonic-gate * lwp_siginfo, and its signal handler in the core file 4877c478bd9Sstevel@tonic-gate * status. We restore lwp_cursig in case a subsequent 4887c478bd9Sstevel@tonic-gate * signal was received while dumping core. 4897c478bd9Sstevel@tonic-gate */ 4907c478bd9Sstevel@tonic-gate oldsig = lwp->lwp_cursig; 4917c478bd9Sstevel@tonic-gate lwp->lwp_cursig = (uchar_t)sig; 4927c478bd9Sstevel@tonic-gate t->t_whystop = PR_FAULTED; 4937c478bd9Sstevel@tonic-gate 4947c478bd9Sstevel@tonic-gate prgetlwpstatus(t, &bigwad->lwpstatus, p->p_zone); 4957c478bd9Sstevel@tonic-gate bigwad->lwpstatus.pr_why = 0; 4967c478bd9Sstevel@tonic-gate 4977c478bd9Sstevel@tonic-gate t->t_whystop = 0; 4987c478bd9Sstevel@tonic-gate lwp->lwp_cursig = oldsig; 4997c478bd9Sstevel@tonic-gate } else { 5007c478bd9Sstevel@tonic-gate prgetlwpstatus(t, &bigwad->lwpstatus, p->p_zone); 5017c478bd9Sstevel@tonic-gate } 5027c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock); 5037c478bd9Sstevel@tonic-gate error = elfnote(vp, &offset, NT_LWPSTATUS, 5047c478bd9Sstevel@tonic-gate sizeof (bigwad->lwpstatus), (caddr_t)&bigwad->lwpstatus, 5057c478bd9Sstevel@tonic-gate rlimit, credp); 5067c478bd9Sstevel@tonic-gate if (error) 5077c478bd9Sstevel@tonic-gate goto done; 5087c478bd9Sstevel@tonic-gate 5097c478bd9Sstevel@tonic-gate #if defined(__sparc) 5107c478bd9Sstevel@tonic-gate /* 5117c478bd9Sstevel@tonic-gate * Unspilled SPARC register windows. 5127c478bd9Sstevel@tonic-gate */ 5137c478bd9Sstevel@tonic-gate { 5147c478bd9Sstevel@tonic-gate size_t size = prnwindows(lwp); 5157c478bd9Sstevel@tonic-gate 5167c478bd9Sstevel@tonic-gate if (size != 0) { 5177c478bd9Sstevel@tonic-gate size = sizeof (gwindows_t) - 5187c478bd9Sstevel@tonic-gate (SPARC_MAXREGWINDOW - size) * 5197c478bd9Sstevel@tonic-gate sizeof (struct rwindow); 5207c478bd9Sstevel@tonic-gate prgetwindows(lwp, &bigwad->gwindows); 5217c478bd9Sstevel@tonic-gate error = elfnote(vp, &offset, NT_GWINDOWS, 5227c478bd9Sstevel@tonic-gate size, (caddr_t)&bigwad->gwindows, 5237c478bd9Sstevel@tonic-gate rlimit, credp); 5247c478bd9Sstevel@tonic-gate if (error) 5257c478bd9Sstevel@tonic-gate goto done; 5267c478bd9Sstevel@tonic-gate } 5277c478bd9Sstevel@tonic-gate } 5287c478bd9Sstevel@tonic-gate /* 5297c478bd9Sstevel@tonic-gate * Ancillary State Registers. 5307c478bd9Sstevel@tonic-gate */ 5317c478bd9Sstevel@tonic-gate if (p->p_model == DATAMODEL_LP64) { 5327c478bd9Sstevel@tonic-gate prgetasregs(lwp, bigwad->asrset); 5337c478bd9Sstevel@tonic-gate error = elfnote(vp, &offset, NT_ASRS, 5347c478bd9Sstevel@tonic-gate sizeof (asrset_t), (caddr_t)bigwad->asrset, 5357c478bd9Sstevel@tonic-gate rlimit, credp); 5367c478bd9Sstevel@tonic-gate if (error) 5377c478bd9Sstevel@tonic-gate goto done; 5387c478bd9Sstevel@tonic-gate } 5397c478bd9Sstevel@tonic-gate #endif /* __sparc */ 5407c478bd9Sstevel@tonic-gate 5417c478bd9Sstevel@tonic-gate if (xregsize) { 5427c478bd9Sstevel@tonic-gate prgetprxregs(lwp, bigwad->xregs); 5437c478bd9Sstevel@tonic-gate error = elfnote(vp, &offset, NT_PRXREG, 5447c478bd9Sstevel@tonic-gate xregsize, bigwad->xregs, rlimit, credp); 5457c478bd9Sstevel@tonic-gate if (error) 5467c478bd9Sstevel@tonic-gate goto done; 5477c478bd9Sstevel@tonic-gate } 548f971a346SBryan Cantrill 549f971a346SBryan Cantrill if (t->t_lwp->lwp_spymaster != NULL) { 550f971a346SBryan Cantrill void *psaddr = t->t_lwp->lwp_spymaster; 551f971a346SBryan Cantrill #ifdef _ELF32_COMPAT 552f971a346SBryan Cantrill /* 553f971a346SBryan Cantrill * On a 64-bit kernel with 32-bit ELF compatibility, 554f971a346SBryan Cantrill * this file is compiled into two different objects: 555f971a346SBryan Cantrill * one is compiled normally, and the other is compiled 556f971a346SBryan Cantrill * with _ELF32_COMPAT set -- and therefore with a 557f971a346SBryan Cantrill * psinfo_t defined to be a psinfo32_t. However, the 558f971a346SBryan Cantrill * psinfo_t denoting our spymaster is always of the 559f971a346SBryan Cantrill * native type; if we are in the _ELF32_COMPAT case, 560f971a346SBryan Cantrill * we need to explicitly convert it. 561f971a346SBryan Cantrill */ 562f971a346SBryan Cantrill if (p->p_model == DATAMODEL_ILP32) { 563f971a346SBryan Cantrill psinfo_kto32(psaddr, &bigwad->psinfo); 564f971a346SBryan Cantrill psaddr = &bigwad->psinfo; 565f971a346SBryan Cantrill } 566f971a346SBryan Cantrill #endif 567f971a346SBryan Cantrill 568f971a346SBryan Cantrill error = elfnote(vp, &offset, NT_SPYMASTER, 569f971a346SBryan Cantrill sizeof (psinfo_t), psaddr, rlimit, credp); 570f971a346SBryan Cantrill if (error) 571f971a346SBryan Cantrill goto done; 572f971a346SBryan Cantrill } 5737c478bd9Sstevel@tonic-gate } 5747c478bd9Sstevel@tonic-gate ASSERT(nlwp == 0); 5757c478bd9Sstevel@tonic-gate 5767c478bd9Sstevel@tonic-gate done: 5777c478bd9Sstevel@tonic-gate kmem_free(bigwad, bigsize); 5787c478bd9Sstevel@tonic-gate return (error); 5797c478bd9Sstevel@tonic-gate } 580