1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 30*7c478bd9Sstevel@tonic-gate #include <sys/param.h> 31*7c478bd9Sstevel@tonic-gate #include <sys/thread.h> 32*7c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h> 33*7c478bd9Sstevel@tonic-gate #include <sys/signal.h> 34*7c478bd9Sstevel@tonic-gate #include <sys/cred.h> 35*7c478bd9Sstevel@tonic-gate #include <sys/user.h> 36*7c478bd9Sstevel@tonic-gate #include <sys/errno.h> 37*7c478bd9Sstevel@tonic-gate #include <sys/vnode.h> 38*7c478bd9Sstevel@tonic-gate #include <sys/mman.h> 39*7c478bd9Sstevel@tonic-gate #include <sys/kmem.h> 40*7c478bd9Sstevel@tonic-gate #include <sys/proc.h> 41*7c478bd9Sstevel@tonic-gate #include <sys/pathname.h> 42*7c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h> 43*7c478bd9Sstevel@tonic-gate #include <sys/systm.h> 44*7c478bd9Sstevel@tonic-gate #include <sys/elf.h> 45*7c478bd9Sstevel@tonic-gate #include <sys/vmsystm.h> 46*7c478bd9Sstevel@tonic-gate #include <sys/debug.h> 47*7c478bd9Sstevel@tonic-gate #include <sys/old_procfs.h> 48*7c478bd9Sstevel@tonic-gate #include <sys/auxv.h> 49*7c478bd9Sstevel@tonic-gate #include <sys/exec.h> 50*7c478bd9Sstevel@tonic-gate #include <sys/prsystm.h> 51*7c478bd9Sstevel@tonic-gate #include <vm/as.h> 52*7c478bd9Sstevel@tonic-gate #include <vm/rm.h> 53*7c478bd9Sstevel@tonic-gate #include <sys/modctl.h> 54*7c478bd9Sstevel@tonic-gate #include <sys/systeminfo.h> 55*7c478bd9Sstevel@tonic-gate #include <sys/machelf.h> 56*7c478bd9Sstevel@tonic-gate #include <sys/zone.h> 57*7c478bd9Sstevel@tonic-gate #include "elf_impl.h" 58*7c478bd9Sstevel@tonic-gate 59*7c478bd9Sstevel@tonic-gate extern void oprgetstatus(kthread_t *, prstatus_t *, zone_t *); 60*7c478bd9Sstevel@tonic-gate extern void oprgetpsinfo(proc_t *, prpsinfo_t *, kthread_t *); 61*7c478bd9Sstevel@tonic-gate 62*7c478bd9Sstevel@tonic-gate void 63*7c478bd9Sstevel@tonic-gate setup_old_note_header(Phdr *v, proc_t *p) 64*7c478bd9Sstevel@tonic-gate { 65*7c478bd9Sstevel@tonic-gate int nlwp = p->p_lwpcnt; 66*7c478bd9Sstevel@tonic-gate size_t size; 67*7c478bd9Sstevel@tonic-gate 68*7c478bd9Sstevel@tonic-gate v[0].p_type = PT_NOTE; 69*7c478bd9Sstevel@tonic-gate v[0].p_flags = PF_R; 70*7c478bd9Sstevel@tonic-gate v[0].p_filesz = (sizeof (Note) * (3 + nlwp)) 71*7c478bd9Sstevel@tonic-gate + roundup(sizeof (prpsinfo_t), sizeof (Word)) 72*7c478bd9Sstevel@tonic-gate + roundup(strlen(platform) + 1, sizeof (Word)) 73*7c478bd9Sstevel@tonic-gate + roundup(__KERN_NAUXV_IMPL * sizeof (aux_entry_t), 74*7c478bd9Sstevel@tonic-gate sizeof (Word)) 75*7c478bd9Sstevel@tonic-gate + nlwp * roundup(sizeof (prstatus_t), sizeof (Word)); 76*7c478bd9Sstevel@tonic-gate if (prhasfp()) 77*7c478bd9Sstevel@tonic-gate v[0].p_filesz += nlwp * sizeof (Note) 78*7c478bd9Sstevel@tonic-gate + nlwp*roundup(sizeof (prfpregset_t), sizeof (Word)); 79*7c478bd9Sstevel@tonic-gate if ((size = prhasx(p)? prgetprxregsize(p) : 0) != 0) 80*7c478bd9Sstevel@tonic-gate v[0].p_filesz += nlwp * sizeof (Note) 81*7c478bd9Sstevel@tonic-gate + nlwp * roundup(size, sizeof (Word)); 82*7c478bd9Sstevel@tonic-gate 83*7c478bd9Sstevel@tonic-gate #if defined(__sparc) 84*7c478bd9Sstevel@tonic-gate /* 85*7c478bd9Sstevel@tonic-gate * Figure out the number and sizes of register windows. 86*7c478bd9Sstevel@tonic-gate */ 87*7c478bd9Sstevel@tonic-gate { 88*7c478bd9Sstevel@tonic-gate kthread_t *t = p->p_tlist; 89*7c478bd9Sstevel@tonic-gate do { 90*7c478bd9Sstevel@tonic-gate if ((size = prnwindows(ttolwp(t))) != 0) { 91*7c478bd9Sstevel@tonic-gate size = sizeof (gwindows_t) - 92*7c478bd9Sstevel@tonic-gate (SPARC_MAXREGWINDOW - size) * 93*7c478bd9Sstevel@tonic-gate sizeof (struct rwindow); 94*7c478bd9Sstevel@tonic-gate v[0].p_filesz += sizeof (Note) + 95*7c478bd9Sstevel@tonic-gate roundup(size, sizeof (Word)); 96*7c478bd9Sstevel@tonic-gate } 97*7c478bd9Sstevel@tonic-gate } while ((t = t->t_forw) != p->p_tlist); 98*7c478bd9Sstevel@tonic-gate } 99*7c478bd9Sstevel@tonic-gate #endif /* __sparc */ 100*7c478bd9Sstevel@tonic-gate } 101*7c478bd9Sstevel@tonic-gate 102*7c478bd9Sstevel@tonic-gate int 103*7c478bd9Sstevel@tonic-gate write_old_elfnotes(proc_t *p, int sig, vnode_t *vp, offset_t offset, 104*7c478bd9Sstevel@tonic-gate rlim64_t rlimit, cred_t *credp) 105*7c478bd9Sstevel@tonic-gate { 106*7c478bd9Sstevel@tonic-gate union { 107*7c478bd9Sstevel@tonic-gate prpsinfo_t psinfo; 108*7c478bd9Sstevel@tonic-gate prstatus_t prstat; 109*7c478bd9Sstevel@tonic-gate prfpregset_t fpregs; 110*7c478bd9Sstevel@tonic-gate #if defined(__sparc) 111*7c478bd9Sstevel@tonic-gate gwindows_t gwindows; 112*7c478bd9Sstevel@tonic-gate #endif /* __sparc */ 113*7c478bd9Sstevel@tonic-gate char xregs[1]; 114*7c478bd9Sstevel@tonic-gate aux_entry_t auxv[__KERN_NAUXV_IMPL]; 115*7c478bd9Sstevel@tonic-gate } *bigwad; 116*7c478bd9Sstevel@tonic-gate int xregsize = prhasx(p)? prgetprxregsize(p) : 0; 117*7c478bd9Sstevel@tonic-gate size_t bigsize = MAX(sizeof (*bigwad), (size_t)xregsize); 118*7c478bd9Sstevel@tonic-gate kthread_t *t; 119*7c478bd9Sstevel@tonic-gate klwp_t *lwp; 120*7c478bd9Sstevel@tonic-gate user_t *up; 121*7c478bd9Sstevel@tonic-gate int i; 122*7c478bd9Sstevel@tonic-gate int nlwp; 123*7c478bd9Sstevel@tonic-gate int error; 124*7c478bd9Sstevel@tonic-gate 125*7c478bd9Sstevel@tonic-gate bigwad = kmem_alloc(bigsize, KM_SLEEP); 126*7c478bd9Sstevel@tonic-gate 127*7c478bd9Sstevel@tonic-gate /* 128*7c478bd9Sstevel@tonic-gate * The order of the elfnote entries should be same here and in 129*7c478bd9Sstevel@tonic-gate * the gcore(1) command. Synchronization is needed between the 130*7c478bd9Sstevel@tonic-gate * kernel and libproc's Pfgcore() function where the meat of 131*7c478bd9Sstevel@tonic-gate * the gcore(1) command lives. 132*7c478bd9Sstevel@tonic-gate */ 133*7c478bd9Sstevel@tonic-gate 134*7c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock); 135*7c478bd9Sstevel@tonic-gate oprgetpsinfo(p, &bigwad->psinfo, NULL); 136*7c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock); 137*7c478bd9Sstevel@tonic-gate error = elfnote(vp, &offset, NT_PRPSINFO, sizeof (bigwad->psinfo), 138*7c478bd9Sstevel@tonic-gate (caddr_t)&bigwad->psinfo, rlimit, credp); 139*7c478bd9Sstevel@tonic-gate if (error) 140*7c478bd9Sstevel@tonic-gate goto done; 141*7c478bd9Sstevel@tonic-gate 142*7c478bd9Sstevel@tonic-gate error = elfnote(vp, &offset, NT_PLATFORM, strlen(platform) + 1, 143*7c478bd9Sstevel@tonic-gate platform, rlimit, credp); 144*7c478bd9Sstevel@tonic-gate if (error) 145*7c478bd9Sstevel@tonic-gate goto done; 146*7c478bd9Sstevel@tonic-gate 147*7c478bd9Sstevel@tonic-gate up = PTOU(p); 148*7c478bd9Sstevel@tonic-gate for (i = 0; i < __KERN_NAUXV_IMPL; i++) { 149*7c478bd9Sstevel@tonic-gate bigwad->auxv[i].a_type = up->u_auxv[i].a_type; 150*7c478bd9Sstevel@tonic-gate bigwad->auxv[i].a_un.a_val = up->u_auxv[i].a_un.a_val; 151*7c478bd9Sstevel@tonic-gate } 152*7c478bd9Sstevel@tonic-gate error = elfnote(vp, &offset, NT_AUXV, sizeof (bigwad->auxv), 153*7c478bd9Sstevel@tonic-gate (caddr_t)bigwad->auxv, rlimit, credp); 154*7c478bd9Sstevel@tonic-gate if (error) 155*7c478bd9Sstevel@tonic-gate goto done; 156*7c478bd9Sstevel@tonic-gate 157*7c478bd9Sstevel@tonic-gate t = curthread; 158*7c478bd9Sstevel@tonic-gate nlwp = p->p_lwpcnt; 159*7c478bd9Sstevel@tonic-gate do { 160*7c478bd9Sstevel@tonic-gate ASSERT(nlwp != 0); 161*7c478bd9Sstevel@tonic-gate nlwp--; 162*7c478bd9Sstevel@tonic-gate lwp = ttolwp(t); 163*7c478bd9Sstevel@tonic-gate 164*7c478bd9Sstevel@tonic-gate mutex_enter(&p->p_lock); 165*7c478bd9Sstevel@tonic-gate if (t == curthread) { 166*7c478bd9Sstevel@tonic-gate uchar_t oldsig; 167*7c478bd9Sstevel@tonic-gate 168*7c478bd9Sstevel@tonic-gate /* 169*7c478bd9Sstevel@tonic-gate * Modify t_whystop and lwp_cursig so it appears that 170*7c478bd9Sstevel@tonic-gate * the current LWP is stopped after faulting on the 171*7c478bd9Sstevel@tonic-gate * signal that caused the core dump. As a result, 172*7c478bd9Sstevel@tonic-gate * oprgetstatus() will record that signal, the saved 173*7c478bd9Sstevel@tonic-gate * lwp_siginfo, and its signal handler in the core file 174*7c478bd9Sstevel@tonic-gate * status. We restore lwp_cursig in case a subsequent 175*7c478bd9Sstevel@tonic-gate * signal was received while dumping core. 176*7c478bd9Sstevel@tonic-gate */ 177*7c478bd9Sstevel@tonic-gate oldsig = lwp->lwp_cursig; 178*7c478bd9Sstevel@tonic-gate lwp->lwp_cursig = (uchar_t)sig; 179*7c478bd9Sstevel@tonic-gate t->t_whystop = PR_FAULTED; 180*7c478bd9Sstevel@tonic-gate 181*7c478bd9Sstevel@tonic-gate oprgetstatus(t, &bigwad->prstat, p->p_zone); 182*7c478bd9Sstevel@tonic-gate bigwad->prstat.pr_why = 0; 183*7c478bd9Sstevel@tonic-gate 184*7c478bd9Sstevel@tonic-gate t->t_whystop = 0; 185*7c478bd9Sstevel@tonic-gate lwp->lwp_cursig = oldsig; 186*7c478bd9Sstevel@tonic-gate 187*7c478bd9Sstevel@tonic-gate } else { 188*7c478bd9Sstevel@tonic-gate oprgetstatus(t, &bigwad->prstat, p->p_zone); 189*7c478bd9Sstevel@tonic-gate } 190*7c478bd9Sstevel@tonic-gate mutex_exit(&p->p_lock); 191*7c478bd9Sstevel@tonic-gate error = elfnote(vp, &offset, NT_PRSTATUS, 192*7c478bd9Sstevel@tonic-gate sizeof (bigwad->prstat), (caddr_t)&bigwad->prstat, 193*7c478bd9Sstevel@tonic-gate rlimit, credp); 194*7c478bd9Sstevel@tonic-gate if (error) 195*7c478bd9Sstevel@tonic-gate goto done; 196*7c478bd9Sstevel@tonic-gate 197*7c478bd9Sstevel@tonic-gate if (prhasfp()) { 198*7c478bd9Sstevel@tonic-gate prgetprfpregs(lwp, &bigwad->fpregs); 199*7c478bd9Sstevel@tonic-gate error = elfnote(vp, &offset, NT_PRFPREG, 200*7c478bd9Sstevel@tonic-gate sizeof (bigwad->fpregs), (caddr_t)&bigwad->fpregs, 201*7c478bd9Sstevel@tonic-gate rlimit, credp); 202*7c478bd9Sstevel@tonic-gate if (error) 203*7c478bd9Sstevel@tonic-gate goto done; 204*7c478bd9Sstevel@tonic-gate } 205*7c478bd9Sstevel@tonic-gate 206*7c478bd9Sstevel@tonic-gate #if defined(__sparc) 207*7c478bd9Sstevel@tonic-gate /* 208*7c478bd9Sstevel@tonic-gate * Unspilled SPARC register windows. 209*7c478bd9Sstevel@tonic-gate */ 210*7c478bd9Sstevel@tonic-gate { 211*7c478bd9Sstevel@tonic-gate size_t size = prnwindows(lwp); 212*7c478bd9Sstevel@tonic-gate 213*7c478bd9Sstevel@tonic-gate if (size != 0) { 214*7c478bd9Sstevel@tonic-gate size = sizeof (gwindows_t) - 215*7c478bd9Sstevel@tonic-gate (SPARC_MAXREGWINDOW - size) * 216*7c478bd9Sstevel@tonic-gate sizeof (struct rwindow); 217*7c478bd9Sstevel@tonic-gate prgetwindows(lwp, &bigwad->gwindows); 218*7c478bd9Sstevel@tonic-gate error = elfnote(vp, &offset, NT_GWINDOWS, 219*7c478bd9Sstevel@tonic-gate size, (caddr_t)&bigwad->gwindows, 220*7c478bd9Sstevel@tonic-gate rlimit, credp); 221*7c478bd9Sstevel@tonic-gate if (error) 222*7c478bd9Sstevel@tonic-gate goto done; 223*7c478bd9Sstevel@tonic-gate } 224*7c478bd9Sstevel@tonic-gate } 225*7c478bd9Sstevel@tonic-gate #endif /* __sparc */ 226*7c478bd9Sstevel@tonic-gate 227*7c478bd9Sstevel@tonic-gate if (xregsize) { 228*7c478bd9Sstevel@tonic-gate prgetprxregs(lwp, bigwad->xregs); 229*7c478bd9Sstevel@tonic-gate error = elfnote(vp, &offset, NT_PRXREG, 230*7c478bd9Sstevel@tonic-gate xregsize, bigwad->xregs, rlimit, credp); 231*7c478bd9Sstevel@tonic-gate if (error) 232*7c478bd9Sstevel@tonic-gate goto done; 233*7c478bd9Sstevel@tonic-gate } 234*7c478bd9Sstevel@tonic-gate } while ((t = t->t_forw) != curthread); 235*7c478bd9Sstevel@tonic-gate ASSERT(nlwp == 0); 236*7c478bd9Sstevel@tonic-gate 237*7c478bd9Sstevel@tonic-gate done: 238*7c478bd9Sstevel@tonic-gate kmem_free(bigwad, bigsize); 239*7c478bd9Sstevel@tonic-gate return (error); 240*7c478bd9Sstevel@tonic-gate } 241