procfs_map.c revision 184652
1139776Simp/*- 216468Sdyson * Copyright (c) 1993 Jan-Simon Pendry 316468Sdyson * Copyright (c) 1993 416468Sdyson * The Regents of the University of California. All rights reserved. 516468Sdyson * 616468Sdyson * This code is derived from software contributed to Berkeley by 716468Sdyson * Jan-Simon Pendry. 816468Sdyson * 916468Sdyson * Redistribution and use in source and binary forms, with or without 1016468Sdyson * modification, are permitted provided that the following conditions 1116468Sdyson * are met: 1216468Sdyson * 1. Redistributions of source code must retain the above copyright 1316468Sdyson * notice, this list of conditions and the following disclaimer. 1416468Sdyson * 2. Redistributions in binary form must reproduce the above copyright 1516468Sdyson * notice, this list of conditions and the following disclaimer in the 1616468Sdyson * documentation and/or other materials provided with the distribution. 1716468Sdyson * 4. Neither the name of the University nor the names of its contributors 1816468Sdyson * may be used to endorse or promote products derived from this software 1916468Sdyson * without specific prior written permission. 2016468Sdyson * 2116468Sdyson * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2216468Sdyson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2316468Sdyson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2416468Sdyson * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2516468Sdyson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2616468Sdyson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2716468Sdyson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2816468Sdyson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2916468Sdyson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3016468Sdyson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3116468Sdyson * SUCH DAMAGE. 3216468Sdyson * 3316468Sdyson * @(#)procfs_status.c 8.3 (Berkeley) 2/17/94 3416468Sdyson * 3550477Speter * $FreeBSD: head/sys/fs/procfs/procfs_map.c 184652 2008-11-04 19:04:01Z jhb $ 3616468Sdyson */ 3716468Sdyson 38147692Speter#include "opt_compat.h" 39147692Speter 4016468Sdyson#include <sys/param.h> 4116468Sdyson#include <sys/systm.h> 4276166Smarkm#include <sys/lock.h> 43120583Srwatson#include <sys/filedesc.h> 44120583Srwatson#include <sys/malloc.h> 45168968Salc#include <sys/mount.h> 4676827Salfred#include <sys/mutex.h> 4716468Sdyson#include <sys/proc.h> 48183600Skib#include <sys/sbuf.h> 4987321Sdes#include <sys/uio.h> 50120583Srwatson#include <sys/vnode.h> 5176166Smarkm 5287321Sdes#include <fs/pseudofs/pseudofs.h> 5377031Sru#include <fs/procfs/procfs.h> 5416468Sdyson 5516468Sdyson#include <vm/vm.h> 5616468Sdyson#include <vm/pmap.h> 5716468Sdyson#include <vm/vm_map.h> 5816468Sdyson#include <vm/vm_page.h> 5916468Sdyson#include <vm/vm_object.h> 6016468Sdyson 61147692Speter#ifdef COMPAT_IA32 62147692Speter#include <sys/procfs.h> 63147692Speter#include <machine/fpu.h> 64147692Speter#include <compat/ia32/ia32_reg.h> 6516468Sdyson 66147692Speterextern struct sysentvec ia32_freebsd_sysvec; 67147692Speter#endif 68147692Speter 69147692Speter 7019260Sdyson#define MEBUFFERSIZE 256 7116468Sdyson 7219260Sdyson/* 7319260Sdyson * The map entries can *almost* be read with programs like cat. However, 7419260Sdyson * large maps need special programs to read. It is not easy to implement 7519260Sdyson * a program that can sense the required size of the buffer, and then 7619260Sdyson * subsequently do a read with the appropriate size. This operation cannot 7719260Sdyson * be atomic. The best that we can do is to allow the program to do a read 7819260Sdyson * with an arbitrarily large buffer, and return as much as we can. We can 7919260Sdyson * return an error code if the buffer is too small (EFBIG), then the program 8019260Sdyson * can try a bigger buffer. 8119260Sdyson */ 8216468Sdysonint 8387321Sdesprocfs_doprocmap(PFS_FILL_ARGS) 8416468Sdyson{ 85168968Salc int error, vfslocked; 8616468Sdyson vm_map_t map = &p->p_vmspace->vm_map; 87183600Skib vm_map_entry_t entry; 88168968Salc struct vnode *vp; 89120583Srwatson char *fullpath, *freepath; 90147692Speter#ifdef COMPAT_IA32 91147692Speter int wrap32 = 0; 92147692Speter#endif 9316468Sdyson 94118907Srwatson PROC_LOCK(p); 95118907Srwatson error = p_candebug(td, p); 96118907Srwatson PROC_UNLOCK(p); 97118907Srwatson if (error) 98118907Srwatson return (error); 99118907Srwatson 10016468Sdyson if (uio->uio_rw != UIO_READ) 10116468Sdyson return (EOPNOTSUPP); 10216468Sdyson 103147692Speter#ifdef COMPAT_IA32 104147692Speter if (curthread->td_proc->p_sysent == &ia32_freebsd_sysvec) { 105147692Speter if (p->p_sysent != &ia32_freebsd_sysvec) 106147692Speter return (EOPNOTSUPP); 107147692Speter wrap32 = 1; 108147692Speter } 109147692Speter#endif 110168763Sdes 111168968Salc vm_map_lock_read(map); 112183600Skib for (entry = map->header.next; entry != &map->header; 113183600Skib entry = entry->next) { 11416468Sdyson vm_object_t obj, tobj, lobj; 11542957Sdillon int ref_count, shadow_count, flags; 11616468Sdyson vm_offset_t addr; 11716468Sdyson int resident, privateresident; 11816468Sdyson char *type; 11916468Sdyson 12043748Sdillon if (entry->eflags & MAP_ENTRY_IS_SUB_MAP) 12116468Sdyson continue; 12216468Sdyson 123168968Salc privateresident = 0; 12416468Sdyson obj = entry->object.vm_object; 125168968Salc if (obj != NULL) { 126168968Salc VM_OBJECT_LOCK(obj); 127168968Salc if (obj->shadow_count == 1) 128168968Salc privateresident = obj->resident_page_count; 129168968Salc } 13016468Sdyson 13116468Sdyson resident = 0; 13216468Sdyson addr = entry->start; 13316468Sdyson while (addr < entry->end) { 134168968Salc if (pmap_extract(map->pmap, addr)) 13516468Sdyson resident++; 13616468Sdyson addr += PAGE_SIZE; 13716468Sdyson } 13816468Sdyson 139168968Salc for (lobj = tobj = obj; tobj; tobj = tobj->backing_object) { 140168968Salc if (tobj != obj) 141168968Salc VM_OBJECT_LOCK(tobj); 142168968Salc if (lobj != obj) 143168968Salc VM_OBJECT_UNLOCK(lobj); 14416468Sdyson lobj = tobj; 145168968Salc } 14616468Sdyson 147120583Srwatson freepath = NULL; 148120583Srwatson fullpath = "-"; 14935497Sdyson if (lobj) { 15035497Sdyson switch(lobj->type) { 15187321Sdes default: 15287321Sdes case OBJT_DEFAULT: 15335497Sdyson type = "default"; 154168968Salc vp = NULL; 15535497Sdyson break; 15687321Sdes case OBJT_VNODE: 15735497Sdyson type = "vnode"; 158168968Salc vp = lobj->handle; 159168968Salc vref(vp); 16035497Sdyson break; 16187321Sdes case OBJT_SWAP: 16235497Sdyson type = "swap"; 163168968Salc vp = NULL; 16435497Sdyson break; 16587321Sdes case OBJT_DEVICE: 16635497Sdyson type = "device"; 167168968Salc vp = NULL; 16835497Sdyson break; 16935497Sdyson } 170168968Salc if (lobj != obj) 171168968Salc VM_OBJECT_UNLOCK(lobj); 172123247Sdes 17335497Sdyson flags = obj->flags; 17435497Sdyson ref_count = obj->ref_count; 17535497Sdyson shadow_count = obj->shadow_count; 176168968Salc VM_OBJECT_UNLOCK(obj); 177168968Salc if (vp != NULL) { 178184652Sjhb vn_fullpath(td, vp, &fullpath, &freepath); 179168968Salc vfslocked = VFS_LOCK_GIANT(vp->v_mount); 180184652Sjhb vrele(vp); 181168968Salc VFS_UNLOCK_GIANT(vfslocked); 182168968Salc } 18317303Sdyson } else { 18417303Sdyson type = "none"; 18535497Sdyson flags = 0; 18635497Sdyson ref_count = 0; 18735497Sdyson shadow_count = 0; 18816468Sdyson } 18916468Sdyson 19016468Sdyson /* 19116468Sdyson * format: 19216468Sdyson * start, end, resident, private resident, cow, access, type. 19316468Sdyson */ 194183600Skib error = sbuf_printf(sb, 195120583Srwatson "0x%lx 0x%lx %d %d %p %s%s%s %d %d 0x%x %s %s %s %s\n", 19643634Sjdp (u_long)entry->start, (u_long)entry->end, 197147692Speter resident, privateresident, 198147692Speter#ifdef COMPAT_IA32 199147692Speter wrap32 ? NULL : obj, /* Hide 64 bit value */ 200147692Speter#else 201147692Speter obj, 202147692Speter#endif 20317306Sdyson (entry->protection & VM_PROT_READ)?"r":"-", 20417306Sdyson (entry->protection & VM_PROT_WRITE)?"w":"-", 20517306Sdyson (entry->protection & VM_PROT_EXECUTE)?"x":"-", 20635497Sdyson ref_count, shadow_count, flags, 20735497Sdyson (entry->eflags & MAP_ENTRY_COW)?"COW":"NCOW", 20835497Sdyson (entry->eflags & MAP_ENTRY_NEEDS_COPY)?"NC":"NNC", 209120583Srwatson type, fullpath); 21016468Sdyson 211120583Srwatson if (freepath != NULL) 212120583Srwatson free(freepath, M_TEMP); 213120583Srwatson 214183600Skib if (error == -1) { 215183600Skib error = 0; 21619260Sdyson break; 21716468Sdyson } 21816468Sdyson } 219168968Salc vm_map_unlock_read(map); 22087321Sdes return (error); 22116468Sdyson} 222