186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz/*
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * CDDL HEADER START
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz *
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * The contents of this file are subject to the terms of the
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * Common Development and Distribution License (the "License").
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * You may not use this file except in compliance with the License.
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz *
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * or http://www.opensolaris.org/os/licensing.
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * See the License for the specific language governing permissions
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * and limitations under the License.
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz *
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * When distributing Covered Code, include this CDDL HEADER in each
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * If applicable, add the following below this CDDL HEADER, with the
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * fields enclosed by brackets "[]" replaced with your own identifying
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * information: Portions Copyright [yyyy] [name of copyright owner]
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz *
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * CDDL HEADER END
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz */
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz/*
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * Use is subject to license terms.
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz */
8f68126c6dc4f2178929233f0c7ccce877e973caBryan Cantrill/*
8f68126c6dc4f2178929233f0c7ccce877e973caBryan Cantrill * Copyright (c) 2013, Joyent, Inc. All rights reserved.
8f68126c6dc4f2178929233f0c7ccce877e973caBryan Cantrill */
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz#include <fcntl.h>
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz#include <libproc.h>
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz#include <limits.h>
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz#include <stdio.h>
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz#include <strings.h>
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz#include <sys/mkdev.h>
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz#include <sys/stat.h>
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz#include <sys/types.h>
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz#include "pmap_common.h"
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz/*
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * We compare the high memory addresses since stacks are faulted in from
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * high memory addresses to low memory addresses, and our prmap_t
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * structures identify only the range of addresses that have been faulted
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * in so far.
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz */
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowiczint
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowiczcmpstacks(const void *ap, const void *bp)
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz{
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz const lwpstack_t *as = ap;
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz const lwpstack_t *bs = bp;
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz uintptr_t a = (uintptr_t)as->lwps_stack.ss_sp + as->lwps_stack.ss_size;
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz uintptr_t b = (uintptr_t)bs->lwps_stack.ss_sp + bs->lwps_stack.ss_size;
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz if (a < b)
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz return (1);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz if (a > b)
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz return (-1);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz return (0);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz}
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz/*
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * Create labels for non-anon, non-heap mappings
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz */
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowiczchar *
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowiczmake_name(struct ps_prochandle *Pr, int lflag, uintptr_t addr,
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz const char *mapname, char *buf, size_t bufsz)
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz{
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz const pstatus_t *Psp = Pstatus(Pr);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz struct stat statb;
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz char path[PATH_MAX];
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz int len;
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz
8f68126c6dc4f2178929233f0c7ccce877e973caBryan Cantrill if (lflag || Pstate(Pr) == PS_DEAD) {
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz if (Pobjname(Pr, addr, buf, bufsz) != NULL)
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz return (buf);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz } else {
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz if (Pobjname_resolved(Pr, addr, buf, bufsz) != NULL) {
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz /* Verify that the path exists */
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz if ((len = resolvepath(buf, buf, bufsz)) > 0) {
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz buf[len] = '\0';
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz return (buf);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz }
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz }
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz }
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz if (Pstate(Pr) == PS_DEAD || *mapname == '\0')
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz return (NULL);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz /* first see if we can find a path via /proc */
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz (void) snprintf(path, sizeof (path), "/proc/%d/path/%s",
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz (int)Psp->pr_pid, mapname);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz len = readlink(path, buf, bufsz - 1);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz if (len >= 0) {
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz buf[len] = '\0';
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz return (buf);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz }
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz /* fall back to object information reported by /proc */
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz (void) snprintf(path, sizeof (path),
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz "/proc/%d/object/%s", (int)Psp->pr_pid, mapname);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz if (stat(path, &statb) == 0) {
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz dev_t dev = statb.st_dev;
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz ino_t ino = statb.st_ino;
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz (void) snprintf(buf, bufsz, "dev:%lu,%lu ino:%lu",
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz (ulong_t)major(dev), (ulong_t)minor(dev), ino);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz return (buf);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz }
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz return (NULL);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz}
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz/*
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz * Create label for anon mappings
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz */
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowiczchar *
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowiczanon_name(char *name, const pstatus_t *Psp, lwpstack_t *stacks, uint_t nstacks,
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz uintptr_t vaddr, size_t size, int mflags, int shmid, int *mtypesp)
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz{
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz int mtypes = 0;
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz if (mflags & MA_ISM) {
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz if (shmid == -1)
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz (void) snprintf(name, PATH_MAX, " [ %s shmid=null ]",
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz (mflags & MA_NORESERVE) ? "ism" : "dism");
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz else
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz (void) snprintf(name, PATH_MAX, " [ %s shmid=0x%x ]",
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz (mflags & MA_NORESERVE) ? "ism" : "dism", shmid);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz mtypes |= (1 << AT_SHARED);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz } else if (mflags & MA_SHM) {
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz if (shmid == -1)
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz (void) sprintf(name, " [ shmid=null ]");
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz else
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz (void) sprintf(name, " [ shmid=0x%x ]", shmid);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz mtypes |= (1 << AT_SHARED);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz } else if (vaddr + size > Psp->pr_stkbase &&
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz vaddr < Psp->pr_stkbase + Psp->pr_stksize) {
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz (void) strcpy(name, " [ stack ]");
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz mtypes |= (1 << AT_STACK);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz } else if ((mflags & MA_ANON) &&
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz vaddr + size > Psp->pr_brkbase &&
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz vaddr < Psp->pr_brkbase + Psp->pr_brksize) {
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz (void) strcpy(name, " [ heap ]");
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz mtypes |= (1 << AT_HEAP);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz } else {
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz lwpstack_t key, *stk;
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz key.lwps_stack.ss_sp = (void *)vaddr;
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz key.lwps_stack.ss_size = size;
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz if (nstacks > 0 &&
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz (stk = bsearch(&key, stacks, nstacks, sizeof (stacks[0]),
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz cmpstacks)) != NULL) {
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz (void) snprintf(name, PATH_MAX, " [ %s tid=%d ]",
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz (stk->lwps_stack.ss_flags & SS_ONSTACK) ?
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz "altstack" : "stack",
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz stk->lwps_lwpid);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz mtypes |= (1 << AT_STACK);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz } else {
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz (void) strcpy(name, " [ anon ]");
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz mtypes |= (1 << AT_PRIVM);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz }
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz }
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz if (mtypesp)
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz *mtypesp = mtypes;
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz return (name);
186f7fbf5e07d046b50e4e15c32b21f109b76c80Edward Pilatowicz}