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 (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #include <fcntl.h> 28 #include <libproc.h> 29 #include <limits.h> 30 #include <stdio.h> 31 #include <strings.h> 32 #include <sys/mkdev.h> 33 #include <sys/stat.h> 34 #include <sys/types.h> 35 36 #include "pmap_common.h" 37 38 /* 39 * We compare the high memory addresses since stacks are faulted in from 40 * high memory addresses to low memory addresses, and our prmap_t 41 * structures identify only the range of addresses that have been faulted 42 * in so far. 43 */ 44 int 45 cmpstacks(const void *ap, const void *bp) 46 { 47 const lwpstack_t *as = ap; 48 const lwpstack_t *bs = bp; 49 uintptr_t a = (uintptr_t)as->lwps_stack.ss_sp + as->lwps_stack.ss_size; 50 uintptr_t b = (uintptr_t)bs->lwps_stack.ss_sp + bs->lwps_stack.ss_size; 51 52 if (a < b) 53 return (1); 54 if (a > b) 55 return (-1); 56 return (0); 57 } 58 59 /* 60 * Create labels for non-anon, non-heap mappings 61 */ 62 char * 63 make_name(struct ps_prochandle *Pr, int lflag, uintptr_t addr, 64 const char *mapname, char *buf, size_t bufsz) 65 { 66 const pstatus_t *Psp = Pstatus(Pr); 67 struct stat statb; 68 char path[PATH_MAX]; 69 int len; 70 71 if (lflag) { 72 if (Pobjname(Pr, addr, buf, bufsz) != NULL) 73 return (buf); 74 } else { 75 if (Pobjname_resolved(Pr, addr, buf, bufsz) != NULL) { 76 /* Verify that the path exists */ 77 if ((len = resolvepath(buf, buf, bufsz)) > 0) { 78 buf[len] = '\0'; 79 return (buf); 80 } 81 } 82 } 83 84 if (Pstate(Pr) == PS_DEAD || *mapname == '\0') 85 return (NULL); 86 87 /* first see if we can find a path via /proc */ 88 (void) snprintf(path, sizeof (path), "/proc/%d/path/%s", 89 (int)Psp->pr_pid, mapname); 90 len = readlink(path, buf, bufsz - 1); 91 if (len >= 0) { 92 buf[len] = '\0'; 93 return (buf); 94 } 95 96 /* fall back to object information reported by /proc */ 97 (void) snprintf(path, sizeof (path), 98 "/proc/%d/object/%s", (int)Psp->pr_pid, mapname); 99 if (stat(path, &statb) == 0) { 100 dev_t dev = statb.st_dev; 101 ino_t ino = statb.st_ino; 102 (void) snprintf(buf, bufsz, "dev:%lu,%lu ino:%lu", 103 (ulong_t)major(dev), (ulong_t)minor(dev), ino); 104 return (buf); 105 } 106 107 return (NULL); 108 } 109 110 /* 111 * Create label for anon mappings 112 */ 113 char * 114 anon_name(char *name, const pstatus_t *Psp, lwpstack_t *stacks, uint_t nstacks, 115 uintptr_t vaddr, size_t size, int mflags, int shmid, int *mtypesp) 116 { 117 int mtypes = 0; 118 119 if (mflags & MA_ISM) { 120 if (shmid == -1) 121 (void) snprintf(name, PATH_MAX, " [ %s shmid=null ]", 122 (mflags & MA_NORESERVE) ? "ism" : "dism"); 123 else 124 (void) snprintf(name, PATH_MAX, " [ %s shmid=0x%x ]", 125 (mflags & MA_NORESERVE) ? "ism" : "dism", shmid); 126 mtypes |= (1 << AT_SHARED); 127 } else if (mflags & MA_SHM) { 128 if (shmid == -1) 129 (void) sprintf(name, " [ shmid=null ]"); 130 else 131 (void) sprintf(name, " [ shmid=0x%x ]", shmid); 132 mtypes |= (1 << AT_SHARED); 133 } else if (vaddr + size > Psp->pr_stkbase && 134 vaddr < Psp->pr_stkbase + Psp->pr_stksize) { 135 (void) strcpy(name, " [ stack ]"); 136 mtypes |= (1 << AT_STACK); 137 } else if ((mflags & MA_ANON) && 138 vaddr + size > Psp->pr_brkbase && 139 vaddr < Psp->pr_brkbase + Psp->pr_brksize) { 140 (void) strcpy(name, " [ heap ]"); 141 mtypes |= (1 << AT_HEAP); 142 } else { 143 lwpstack_t key, *stk; 144 145 key.lwps_stack.ss_sp = (void *)vaddr; 146 key.lwps_stack.ss_size = size; 147 if (nstacks > 0 && 148 (stk = bsearch(&key, stacks, nstacks, sizeof (stacks[0]), 149 cmpstacks)) != NULL) { 150 (void) snprintf(name, PATH_MAX, " [ %s tid=%d ]", 151 (stk->lwps_stack.ss_flags & SS_ONSTACK) ? 152 "altstack" : "stack", 153 stk->lwps_lwpid); 154 mtypes |= (1 << AT_STACK); 155 } else { 156 (void) strcpy(name, " [ anon ]"); 157 mtypes |= (1 << AT_PRIVM); 158 } 159 } 160 161 if (mtypesp) 162 *mtypesp = mtypes; 163 return (name); 164 } 165