1186f7fbfSEdward Pilatowicz /*
2186f7fbfSEdward Pilatowicz  * CDDL HEADER START
3186f7fbfSEdward Pilatowicz  *
4186f7fbfSEdward Pilatowicz  * The contents of this file are subject to the terms of the
5186f7fbfSEdward Pilatowicz  * Common Development and Distribution License (the "License").
6186f7fbfSEdward Pilatowicz  * You may not use this file except in compliance with the License.
7186f7fbfSEdward Pilatowicz  *
8186f7fbfSEdward Pilatowicz  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9186f7fbfSEdward Pilatowicz  * or http://www.opensolaris.org/os/licensing.
10186f7fbfSEdward Pilatowicz  * See the License for the specific language governing permissions
11186f7fbfSEdward Pilatowicz  * and limitations under the License.
12186f7fbfSEdward Pilatowicz  *
13186f7fbfSEdward Pilatowicz  * When distributing Covered Code, include this CDDL HEADER in each
14186f7fbfSEdward Pilatowicz  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15186f7fbfSEdward Pilatowicz  * If applicable, add the following below this CDDL HEADER, with the
16186f7fbfSEdward Pilatowicz  * fields enclosed by brackets "[]" replaced with your own identifying
17186f7fbfSEdward Pilatowicz  * information: Portions Copyright [yyyy] [name of copyright owner]
18186f7fbfSEdward Pilatowicz  *
19186f7fbfSEdward Pilatowicz  * CDDL HEADER END
20186f7fbfSEdward Pilatowicz  */
21186f7fbfSEdward Pilatowicz 
22186f7fbfSEdward Pilatowicz /*
23186f7fbfSEdward Pilatowicz  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
24186f7fbfSEdward Pilatowicz  * Use is subject to license terms.
25186f7fbfSEdward Pilatowicz  */
26*8f68126cSBryan Cantrill /*
27*8f68126cSBryan Cantrill  * Copyright (c) 2013, Joyent, Inc.  All rights reserved.
28*8f68126cSBryan Cantrill  */
29186f7fbfSEdward Pilatowicz 
30186f7fbfSEdward Pilatowicz #include <fcntl.h>
31186f7fbfSEdward Pilatowicz #include <libproc.h>
32186f7fbfSEdward Pilatowicz #include <limits.h>
33186f7fbfSEdward Pilatowicz #include <stdio.h>
34186f7fbfSEdward Pilatowicz #include <strings.h>
35186f7fbfSEdward Pilatowicz #include <sys/mkdev.h>
36186f7fbfSEdward Pilatowicz #include <sys/stat.h>
37186f7fbfSEdward Pilatowicz #include <sys/types.h>
38186f7fbfSEdward Pilatowicz 
39186f7fbfSEdward Pilatowicz #include "pmap_common.h"
40186f7fbfSEdward Pilatowicz 
41186f7fbfSEdward Pilatowicz /*
42186f7fbfSEdward Pilatowicz  * We compare the high memory addresses since stacks are faulted in from
43186f7fbfSEdward Pilatowicz  * high memory addresses to low memory addresses, and our prmap_t
44186f7fbfSEdward Pilatowicz  * structures identify only the range of addresses that have been faulted
45186f7fbfSEdward Pilatowicz  * in so far.
46186f7fbfSEdward Pilatowicz  */
47186f7fbfSEdward Pilatowicz int
cmpstacks(const void * ap,const void * bp)48186f7fbfSEdward Pilatowicz cmpstacks(const void *ap, const void *bp)
49186f7fbfSEdward Pilatowicz {
50186f7fbfSEdward Pilatowicz 	const lwpstack_t *as = ap;
51186f7fbfSEdward Pilatowicz 	const lwpstack_t *bs = bp;
52186f7fbfSEdward Pilatowicz 	uintptr_t a = (uintptr_t)as->lwps_stack.ss_sp + as->lwps_stack.ss_size;
53186f7fbfSEdward Pilatowicz 	uintptr_t b = (uintptr_t)bs->lwps_stack.ss_sp + bs->lwps_stack.ss_size;
54186f7fbfSEdward Pilatowicz 
55186f7fbfSEdward Pilatowicz 	if (a < b)
56186f7fbfSEdward Pilatowicz 		return (1);
57186f7fbfSEdward Pilatowicz 	if (a > b)
58186f7fbfSEdward Pilatowicz 		return (-1);
59186f7fbfSEdward Pilatowicz 	return (0);
60186f7fbfSEdward Pilatowicz }
61186f7fbfSEdward Pilatowicz 
62186f7fbfSEdward Pilatowicz /*
63186f7fbfSEdward Pilatowicz  * Create labels for non-anon, non-heap mappings
64186f7fbfSEdward Pilatowicz  */
65186f7fbfSEdward Pilatowicz char *
make_name(struct ps_prochandle * Pr,int lflag,uintptr_t addr,const char * mapname,char * buf,size_t bufsz)66186f7fbfSEdward Pilatowicz make_name(struct ps_prochandle *Pr, int lflag, uintptr_t addr,
67186f7fbfSEdward Pilatowicz     const char *mapname, char *buf, size_t bufsz)
68186f7fbfSEdward Pilatowicz {
69186f7fbfSEdward Pilatowicz 	const pstatus_t		*Psp = Pstatus(Pr);
70186f7fbfSEdward Pilatowicz 	struct stat		statb;
71186f7fbfSEdward Pilatowicz 	char			path[PATH_MAX];
72186f7fbfSEdward Pilatowicz 	int			len;
73186f7fbfSEdward Pilatowicz 
74*8f68126cSBryan Cantrill 	if (lflag || Pstate(Pr) == PS_DEAD) {
75186f7fbfSEdward Pilatowicz 		if (Pobjname(Pr, addr, buf, bufsz) != NULL)
76186f7fbfSEdward Pilatowicz 			return (buf);
77186f7fbfSEdward Pilatowicz 	} else {
78186f7fbfSEdward Pilatowicz 		if (Pobjname_resolved(Pr, addr, buf, bufsz) != NULL) {
79186f7fbfSEdward Pilatowicz 			/* Verify that the path exists */
80186f7fbfSEdward Pilatowicz 			if ((len = resolvepath(buf, buf, bufsz)) > 0) {
81186f7fbfSEdward Pilatowicz 				buf[len] = '\0';
82186f7fbfSEdward Pilatowicz 				return (buf);
83186f7fbfSEdward Pilatowicz 			}
84186f7fbfSEdward Pilatowicz 		}
85186f7fbfSEdward Pilatowicz 	}
86186f7fbfSEdward Pilatowicz 
87186f7fbfSEdward Pilatowicz 	if (Pstate(Pr) == PS_DEAD || *mapname == '\0')
88186f7fbfSEdward Pilatowicz 		return (NULL);
89186f7fbfSEdward Pilatowicz 
90186f7fbfSEdward Pilatowicz 	/* first see if we can find a path via /proc */
91186f7fbfSEdward Pilatowicz 	(void) snprintf(path, sizeof (path), "/proc/%d/path/%s",
92186f7fbfSEdward Pilatowicz 	    (int)Psp->pr_pid, mapname);
93186f7fbfSEdward Pilatowicz 	len = readlink(path, buf, bufsz - 1);
94186f7fbfSEdward Pilatowicz 	if (len >= 0) {
95186f7fbfSEdward Pilatowicz 		buf[len] = '\0';
96186f7fbfSEdward Pilatowicz 		return (buf);
97186f7fbfSEdward Pilatowicz 	}
98186f7fbfSEdward Pilatowicz 
99186f7fbfSEdward Pilatowicz 	/* fall back to object information reported by /proc */
100186f7fbfSEdward Pilatowicz 	(void) snprintf(path, sizeof (path),
101186f7fbfSEdward Pilatowicz 	    "/proc/%d/object/%s", (int)Psp->pr_pid, mapname);
102186f7fbfSEdward Pilatowicz 	if (stat(path, &statb) == 0) {
103186f7fbfSEdward Pilatowicz 		dev_t dev = statb.st_dev;
104186f7fbfSEdward Pilatowicz 		ino_t ino = statb.st_ino;
105186f7fbfSEdward Pilatowicz 		(void) snprintf(buf, bufsz, "dev:%lu,%lu ino:%lu",
106186f7fbfSEdward Pilatowicz 		    (ulong_t)major(dev), (ulong_t)minor(dev), ino);
107186f7fbfSEdward Pilatowicz 		return (buf);
108186f7fbfSEdward Pilatowicz 	}
109186f7fbfSEdward Pilatowicz 
110186f7fbfSEdward Pilatowicz 	return (NULL);
111186f7fbfSEdward Pilatowicz }
112186f7fbfSEdward Pilatowicz 
113186f7fbfSEdward Pilatowicz /*
114186f7fbfSEdward Pilatowicz  * Create label for anon mappings
115186f7fbfSEdward Pilatowicz  */
116186f7fbfSEdward Pilatowicz char *
anon_name(char * name,const pstatus_t * Psp,lwpstack_t * stacks,uint_t nstacks,uintptr_t vaddr,size_t size,int mflags,int shmid,int * mtypesp)117186f7fbfSEdward Pilatowicz anon_name(char *name, const pstatus_t *Psp, lwpstack_t *stacks, uint_t nstacks,
118186f7fbfSEdward Pilatowicz     uintptr_t vaddr, size_t size, int mflags, int shmid, int *mtypesp)
119186f7fbfSEdward Pilatowicz {
120186f7fbfSEdward Pilatowicz 	int mtypes = 0;
121186f7fbfSEdward Pilatowicz 
122186f7fbfSEdward Pilatowicz 	if (mflags & MA_ISM) {
123186f7fbfSEdward Pilatowicz 		if (shmid == -1)
124186f7fbfSEdward Pilatowicz 			(void) snprintf(name, PATH_MAX, "  [ %s shmid=null ]",
125186f7fbfSEdward Pilatowicz 			    (mflags & MA_NORESERVE) ? "ism" : "dism");
126186f7fbfSEdward Pilatowicz 		else
127186f7fbfSEdward Pilatowicz 			(void) snprintf(name, PATH_MAX, "  [ %s shmid=0x%x ]",
128186f7fbfSEdward Pilatowicz 			    (mflags & MA_NORESERVE) ? "ism" : "dism", shmid);
129186f7fbfSEdward Pilatowicz 		mtypes |= (1 << AT_SHARED);
130186f7fbfSEdward Pilatowicz 	} else if (mflags & MA_SHM) {
131186f7fbfSEdward Pilatowicz 		if (shmid == -1)
132186f7fbfSEdward Pilatowicz 			(void) sprintf(name, "  [ shmid=null ]");
133186f7fbfSEdward Pilatowicz 		else
134186f7fbfSEdward Pilatowicz 			(void) sprintf(name, "  [ shmid=0x%x ]", shmid);
135186f7fbfSEdward Pilatowicz 		mtypes |= (1 << AT_SHARED);
136186f7fbfSEdward Pilatowicz 	} else if (vaddr + size > Psp->pr_stkbase &&
137186f7fbfSEdward Pilatowicz 	    vaddr < Psp->pr_stkbase + Psp->pr_stksize) {
138186f7fbfSEdward Pilatowicz 		(void) strcpy(name, "  [ stack ]");
139186f7fbfSEdward Pilatowicz 		mtypes |= (1 << AT_STACK);
140186f7fbfSEdward Pilatowicz 	} else if ((mflags & MA_ANON) &&
141186f7fbfSEdward Pilatowicz 	    vaddr + size > Psp->pr_brkbase &&
142186f7fbfSEdward Pilatowicz 	    vaddr < Psp->pr_brkbase + Psp->pr_brksize) {
143186f7fbfSEdward Pilatowicz 		(void) strcpy(name, "  [ heap ]");
144186f7fbfSEdward Pilatowicz 		mtypes |= (1 << AT_HEAP);
145186f7fbfSEdward Pilatowicz 	} else {
146186f7fbfSEdward Pilatowicz 		lwpstack_t key, *stk;
147186f7fbfSEdward Pilatowicz 
148186f7fbfSEdward Pilatowicz 		key.lwps_stack.ss_sp = (void *)vaddr;
149186f7fbfSEdward Pilatowicz 		key.lwps_stack.ss_size = size;
150186f7fbfSEdward Pilatowicz 		if (nstacks > 0 &&
151186f7fbfSEdward Pilatowicz 		    (stk = bsearch(&key, stacks, nstacks, sizeof (stacks[0]),
152186f7fbfSEdward Pilatowicz 		    cmpstacks)) != NULL) {
153186f7fbfSEdward Pilatowicz 			(void) snprintf(name, PATH_MAX, "  [ %s tid=%d ]",
154186f7fbfSEdward Pilatowicz 			    (stk->lwps_stack.ss_flags & SS_ONSTACK) ?
155186f7fbfSEdward Pilatowicz 			    "altstack" : "stack",
156186f7fbfSEdward Pilatowicz 			    stk->lwps_lwpid);
157186f7fbfSEdward Pilatowicz 			mtypes |= (1 << AT_STACK);
158186f7fbfSEdward Pilatowicz 		} else {
159186f7fbfSEdward Pilatowicz 			(void) strcpy(name, "  [ anon ]");
160186f7fbfSEdward Pilatowicz 			mtypes |= (1 << AT_PRIVM);
161186f7fbfSEdward Pilatowicz 		}
162186f7fbfSEdward Pilatowicz 	}
163186f7fbfSEdward Pilatowicz 
164186f7fbfSEdward Pilatowicz 	if (mtypesp)
165186f7fbfSEdward Pilatowicz 		*mtypesp = mtypes;
166186f7fbfSEdward Pilatowicz 	return (name);
167186f7fbfSEdward Pilatowicz }
168