1*b00559d0Schristos /* $NetBSD: procfs_map.c,v 1.36 2008/07/25 18:36:50 christos Exp $ */ 2aad01611Sagc 3aad01611Sagc /* 4aad01611Sagc * Copyright (c) 1993 5aad01611Sagc * The Regents of the University of California. All rights reserved. 6aad01611Sagc * 7aad01611Sagc * This code is derived from software contributed to Berkeley by 8aad01611Sagc * Jan-Simon Pendry. 9aad01611Sagc * 10aad01611Sagc * Redistribution and use in source and binary forms, with or without 11aad01611Sagc * modification, are permitted provided that the following conditions 12aad01611Sagc * are met: 13aad01611Sagc * 1. Redistributions of source code must retain the above copyright 14aad01611Sagc * notice, this list of conditions and the following disclaimer. 15aad01611Sagc * 2. Redistributions in binary form must reproduce the above copyright 16aad01611Sagc * notice, this list of conditions and the following disclaimer in the 17aad01611Sagc * documentation and/or other materials provided with the distribution. 18aad01611Sagc * 3. Neither the name of the University nor the names of its contributors 19aad01611Sagc * may be used to endorse or promote products derived from this software 20aad01611Sagc * without specific prior written permission. 21aad01611Sagc * 22aad01611Sagc * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23aad01611Sagc * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24aad01611Sagc * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25aad01611Sagc * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26aad01611Sagc * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27aad01611Sagc * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28aad01611Sagc * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29aad01611Sagc * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30aad01611Sagc * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31aad01611Sagc * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32aad01611Sagc * SUCH DAMAGE. 33aad01611Sagc * 34aad01611Sagc * @(#)procfs_status.c 8.3 (Berkeley) 2/17/94 35aad01611Sagc * 36aad01611Sagc * $FreeBSD: procfs_map.c,v 1.18 1998/12/04 22:54:51 archie Exp $ 37aad01611Sagc */ 38ea669760Smsaitoh 39ea669760Smsaitoh /* 40ea669760Smsaitoh * Copyright (c) 1993 Jan-Simon Pendry 41ea669760Smsaitoh * 42ea669760Smsaitoh * This code is derived from software contributed to Berkeley by 43ea669760Smsaitoh * Jan-Simon Pendry. 44ea669760Smsaitoh * 45ea669760Smsaitoh * Redistribution and use in source and binary forms, with or without 46ea669760Smsaitoh * modification, are permitted provided that the following conditions 47ea669760Smsaitoh * are met: 48ea669760Smsaitoh * 1. Redistributions of source code must retain the above copyright 49ea669760Smsaitoh * notice, this list of conditions and the following disclaimer. 50ea669760Smsaitoh * 2. Redistributions in binary form must reproduce the above copyright 51ea669760Smsaitoh * notice, this list of conditions and the following disclaimer in the 52ea669760Smsaitoh * documentation and/or other materials provided with the distribution. 53ea669760Smsaitoh * 3. All advertising materials mentioning features or use of this software 54ea669760Smsaitoh * must display the following acknowledgement: 55ea669760Smsaitoh * This product includes software developed by the University of 56ea669760Smsaitoh * California, Berkeley and its contributors. 57ea669760Smsaitoh * 4. Neither the name of the University nor the names of its contributors 58ea669760Smsaitoh * may be used to endorse or promote products derived from this software 59ea669760Smsaitoh * without specific prior written permission. 60ea669760Smsaitoh * 61ea669760Smsaitoh * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 62ea669760Smsaitoh * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 63ea669760Smsaitoh * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 64ea669760Smsaitoh * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 65ea669760Smsaitoh * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 66ea669760Smsaitoh * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 67ea669760Smsaitoh * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 68ea669760Smsaitoh * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 69ea669760Smsaitoh * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 70ea669760Smsaitoh * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 71ea669760Smsaitoh * SUCH DAMAGE. 72ea669760Smsaitoh * 73ea669760Smsaitoh * @(#)procfs_status.c 8.3 (Berkeley) 2/17/94 74ea669760Smsaitoh * 75ea669760Smsaitoh * $FreeBSD: procfs_map.c,v 1.18 1998/12/04 22:54:51 archie Exp $ 76ea669760Smsaitoh */ 77ea669760Smsaitoh 78e4b00f43Slukem #include <sys/cdefs.h> 79*b00559d0Schristos __KERNEL_RCSID(0, "$NetBSD: procfs_map.c,v 1.36 2008/07/25 18:36:50 christos Exp $"); 80e4b00f43Slukem 81ea669760Smsaitoh #include <sys/param.h> 82ea669760Smsaitoh #include <sys/systm.h> 83ea669760Smsaitoh #include <sys/proc.h> 84ea669760Smsaitoh #include <sys/vnode.h> 852e64bebdSfvdl #include <sys/malloc.h> 862e64bebdSfvdl #include <sys/namei.h> 87a97de7b9Spooka #include <sys/filedesc.h> 88ea669760Smsaitoh #include <miscfs/procfs/procfs.h> 89ea669760Smsaitoh 90ea669760Smsaitoh #include <sys/lock.h> 91ea669760Smsaitoh 92ea669760Smsaitoh #include <uvm/uvm.h> 93ea669760Smsaitoh 94a7761fd2Schristos #define BUFFERSIZE (64 * 1024) 953bccc0f7Schristos #define MAXBUFFERSIZE (256 * 1024) 96ea669760Smsaitoh 97ea669760Smsaitoh /* 98ea669760Smsaitoh * The map entries can *almost* be read with programs like cat. However, 99ea669760Smsaitoh * large maps need special programs to read. It is not easy to implement 100ea669760Smsaitoh * a program that can sense the required size of the buffer, and then 101ea669760Smsaitoh * subsequently do a read with the appropriate size. This operation cannot 102ea669760Smsaitoh * be atomic. The best that we can do is to allow the program to do a read 103ea669760Smsaitoh * with an arbitrarily large buffer, and return as much as we can. We can 104ea669760Smsaitoh * return an error code if the buffer is too small (EFBIG), then the program 105ea669760Smsaitoh * can try a bigger buffer. 106ea669760Smsaitoh */ 107ea669760Smsaitoh int 10895e1ffb1Schristos procfs_domap(struct lwp *curl, struct proc *p, struct pfsnode *pfs, 1092e64bebdSfvdl struct uio *uio, int linuxmode) 110ea669760Smsaitoh { 111a7761fd2Schristos int error; 112b07ec3fcSad struct vmspace *vm; 113b07ec3fcSad struct vm_map *map; 114821ec03eSchs struct vm_map_entry *entry; 1153bccc0f7Schristos char *buffer = NULL; 1163bccc0f7Schristos size_t bufsize = BUFFERSIZE; 1172e64bebdSfvdl char *path; 1182e64bebdSfvdl struct vnode *vp; 1192e64bebdSfvdl struct vattr va; 1202e64bebdSfvdl dev_t dev; 1212e64bebdSfvdl long fileid; 122a7761fd2Schristos size_t pos; 123ea669760Smsaitoh 124ea669760Smsaitoh if (uio->uio_rw != UIO_READ) 125a7761fd2Schristos return EOPNOTSUPP; 126ea669760Smsaitoh 127a7761fd2Schristos if (uio->uio_offset != 0) { 128a7761fd2Schristos /* 129a7761fd2Schristos * we return 0 here, so that the second read returns EOF 130a7761fd2Schristos * we don't support reading from an offset because the 131a7761fd2Schristos * map could have changed between the two reads. 132a7761fd2Schristos */ 133a7761fd2Schristos return 0; 134a7761fd2Schristos } 135ea669760Smsaitoh 136ea669760Smsaitoh error = 0; 137a7761fd2Schristos 138a7761fd2Schristos if (linuxmode != 0) 139a7761fd2Schristos path = malloc(MAXPATHLEN * 4, M_TEMP, M_WAITOK); 140a7761fd2Schristos else 141b07ec3fcSad path = NULL; 142b07ec3fcSad 143a7761fd2Schristos if ((error = proc_vmspace_getref(p, &vm)) != 0) 144a7761fd2Schristos goto out; 145b07ec3fcSad 146b07ec3fcSad map = &vm->vm_map; 147ea669760Smsaitoh vm_map_lock_read(map); 148b07ec3fcSad 1493bccc0f7Schristos again: 1503bccc0f7Schristos buffer = malloc(bufsize, M_TEMP, M_WAITOK); 151a7761fd2Schristos pos = 0; 152a7761fd2Schristos for (entry = map->header.next; entry != &map->header; 153ea669760Smsaitoh entry = entry->next) { 154ea669760Smsaitoh 155ea669760Smsaitoh if (UVM_ET_ISSUBMAP(entry)) 156ea669760Smsaitoh continue; 157ea669760Smsaitoh 1582e64bebdSfvdl if (linuxmode != 0) { 1592e64bebdSfvdl *path = 0; 1602e64bebdSfvdl dev = (dev_t)0; 1612e64bebdSfvdl fileid = 0; 1622e64bebdSfvdl if (UVM_ET_ISOBJ(entry) && 1632e64bebdSfvdl UVM_OBJ_IS_VNODE(entry->object.uvm_obj)) { 1642e64bebdSfvdl vp = (struct vnode *)entry->object.uvm_obj; 16561e8303eSpooka error = VOP_GETATTR(vp, &va, curl->l_cred); 1662e64bebdSfvdl if (error == 0 && vp != pfs->pfs_vnode) { 1672e64bebdSfvdl fileid = va.va_fileid; 1682e64bebdSfvdl dev = va.va_fsid; 169177940c7Schristos error = vnode_to_path(path, 170177940c7Schristos MAXPATHLEN * 4, vp, curl, p); 1712e64bebdSfvdl } 1722e64bebdSfvdl } 173*b00559d0Schristos pos += snprintf(buffer + pos, bufsize - pos, 1742e64bebdSfvdl "%0*lx-%0*lx %c%c%c%c %0*lx %02x:%02x %ld %s\n", 1753c425b68Spk (int)sizeof(void *) * 2,(unsigned long)entry->start, 1763c425b68Spk (int)sizeof(void *) * 2,(unsigned long)entry->end, 1772e64bebdSfvdl (entry->protection & VM_PROT_READ) ? 'r' : '-', 1782e64bebdSfvdl (entry->protection & VM_PROT_WRITE) ? 'w' : '-', 1792e64bebdSfvdl (entry->protection & VM_PROT_EXECUTE) ? 'x' : '-', 1802e64bebdSfvdl (entry->etype & UVM_ET_COPYONWRITE) ? 'p' : 's', 1813c425b68Spk (int)sizeof(void *) * 2, 1822e64bebdSfvdl (unsigned long)entry->offset, 1832e64bebdSfvdl major(dev), minor(dev), fileid, path); 1842e64bebdSfvdl } else { 185*b00559d0Schristos pos += snprintf(buffer + pos, bufsize - pos, 1861f5b9b4dSmsaitoh "0x%lx 0x%lx %c%c%c %c%c%c %s %s %d %d %d\n", 187ea669760Smsaitoh entry->start, entry->end, 1881f5b9b4dSmsaitoh (entry->protection & VM_PROT_READ) ? 'r' : '-', 1891f5b9b4dSmsaitoh (entry->protection & VM_PROT_WRITE) ? 'w' : '-', 1901f5b9b4dSmsaitoh (entry->protection & VM_PROT_EXECUTE) ? 'x' : '-', 1911f5b9b4dSmsaitoh (entry->max_protection & VM_PROT_READ) ? 'r' : '-', 1921f5b9b4dSmsaitoh (entry->max_protection & VM_PROT_WRITE) ? 'w' : '-', 1932e64bebdSfvdl (entry->max_protection & VM_PROT_EXECUTE) ? 1942e64bebdSfvdl 'x' : '-', 1952e64bebdSfvdl (entry->etype & UVM_ET_COPYONWRITE) ? 1962e64bebdSfvdl "COW" : "NCOW", 197ea669760Smsaitoh (entry->etype & UVM_ET_NEEDSCOPY) ? "NC" : "NNC", 1982e64bebdSfvdl entry->inheritance, entry->wired_count, 1992e64bebdSfvdl entry->advice); 2002e64bebdSfvdl } 2013bccc0f7Schristos if (pos >= bufsize) { 2023bccc0f7Schristos bufsize <<= 1; 2033bccc0f7Schristos if (bufsize > MAXBUFFERSIZE) { 2043bccc0f7Schristos error = ENOMEM; 2053bccc0f7Schristos goto out; 2063bccc0f7Schristos } 2073bccc0f7Schristos free(buffer, M_TEMP); 2083bccc0f7Schristos goto again; 2093bccc0f7Schristos } 210ea669760Smsaitoh } 211b07ec3fcSad 212ea669760Smsaitoh vm_map_unlock_read(map); 213b07ec3fcSad uvmspace_free(vm); 214a7761fd2Schristos 215a7761fd2Schristos error = uiomove(buffer, pos, uio); 216a7761fd2Schristos out: 217b07ec3fcSad if (path != NULL) 218b07ec3fcSad free(path, M_TEMP); 219a7761fd2Schristos if (buffer != NULL) 220a7761fd2Schristos free(buffer, M_TEMP); 221b07ec3fcSad 222ea669760Smsaitoh return error; 223ea669760Smsaitoh } 224ea669760Smsaitoh 225ea669760Smsaitoh int 226168cd830Schristos procfs_validmap(struct lwp *l, struct mount *mp) 227ea669760Smsaitoh { 228934634a1Spavel return ((l->l_flag & LW_SYSTEM) == 0); 229ea669760Smsaitoh } 230