mdb_ks.c revision f4da9be01648d6afa604495d9b9956dddeb92a8c
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail/*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * CDDL HEADER START
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail *
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * The contents of this file are subject to the terms of the
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * Common Development and Distribution License (the "License").
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * You may not use this file except in compliance with the License.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail *
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * or http://www.opensolaris.org/os/licensing.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * See the License for the specific language governing permissions
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * and limitations under the License.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail *
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * When distributing Covered Code, include this CDDL HEADER in each
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * If applicable, add the following below this CDDL HEADER, with the
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * fields enclosed by brackets "[]" replaced with your own identifying
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * information: Portions Copyright [yyyy] [name of copyright owner]
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail *
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * CDDL HEADER END
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail/*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * Use is subject to license terms.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail#pragma ident "%Z%%M% %I% %E% SMI"
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail/*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * Mdb kernel support module. This module is loaded automatically when the
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * kvm target is initialized. Any global functions declared here are exported
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * for the resolution of symbols in subsequently loaded modules.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail *
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * WARNING: Do not assume that static variables in mdb_ks will be initialized
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * to zero.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail#include <mdb/mdb_target.h>
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail#include <mdb/mdb_param.h>
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail#include <mdb/mdb_modapi.h>
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail#include <mdb/mdb_ks.h>
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail#include <sys/types.h>
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail#include <sys/procfs.h>
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail#include <sys/proc.h>
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail#include <sys/dnlc.h>
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail#include <sys/autoconf.h>
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail#include <sys/machelf.h>
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail#include <sys/modctl.h>
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail#include <sys/hwconf.h>
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail#include <sys/kobj.h>
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail#include <sys/fs/autofs.h>
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail#include <sys/ddi_impldefs.h>
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail#include <sys/refstr_impl.h>
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail#include <sys/cpuvar.h>
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail#include <sys/dlpi.h>
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail#include <errno.h>
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail#include <vm/seg_vn.h>
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail#include <vm/page.h>
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail#define MDB_PATH_NELEM 256 /* Maximum path components */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailtypedef struct mdb_path {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail size_t mdp_nelem; /* Number of components */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail uint_t mdp_complete; /* Path completely resolved? */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail uintptr_t mdp_vnode[MDB_PATH_NELEM]; /* Array of vnode_t addresses */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail char *mdp_name[MDB_PATH_NELEM]; /* Array of name components */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail} mdb_path_t;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailstatic int mdb_autonode2path(uintptr_t, mdb_path_t *);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailstatic int mdb_sprintpath(char *, size_t, mdb_path_t *);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail/*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * Kernel parameters from <sys/param.h> which we keep in-core:
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailunsigned long _mdb_ks_pagesize;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailunsigned int _mdb_ks_pageshift;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailunsigned long _mdb_ks_pageoffset;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailunsigned long long _mdb_ks_pagemask;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailunsigned long _mdb_ks_mmu_pagesize;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailunsigned int _mdb_ks_mmu_pageshift;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailunsigned long _mdb_ks_mmu_pageoffset;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailunsigned long _mdb_ks_mmu_pagemask;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailuintptr_t _mdb_ks_kernelbase;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailuintptr_t _mdb_ks_userlimit;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailuintptr_t _mdb_ks_userlimit32;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailuintptr_t _mdb_ks_argsbase;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailunsigned long _mdb_ks_msg_bsize;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailunsigned long _mdb_ks_defaultstksz;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailint _mdb_ks_ncpu;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail/*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * In-core copy of DNLC information:
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail#define MDB_DNLC_HSIZE 1024
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail#define MDB_DNLC_HASH(vp) (((uintptr_t)(vp) >> 3) & (MDB_DNLC_HSIZE - 1))
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail#define MDB_DNLC_NCACHE_SZ(ncp) (sizeof (ncache_t) + (ncp)->namlen)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail#define MDB_DNLC_MAX_RETRY 4
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailstatic ncache_t **dnlc_hash; /* mdbs hash array of dnlc entries */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail/*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * This will be the location of the vnodeops pointer for "autofs_vnodeops"
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * The pointer still needs to be read with mdb_vread() to get the location
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * of the vnodeops structure for autofs.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailstatic struct vnodeops *autofs_vnops_ptr;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail/*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * STREAMS queue registrations:
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailtypedef struct mdb_qinfo {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail const mdb_qops_t *qi_ops; /* Address of ops vector */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail uintptr_t qi_addr; /* Address of qinit structure (key) */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail struct mdb_qinfo *qi_next; /* Next qinfo in list */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail} mdb_qinfo_t;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailstatic mdb_qinfo_t *qi_head; /* Head of qinfo chain */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail/*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * Device naming callback structure:
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailtypedef struct nm_query {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail const char *nm_name; /* Device driver name [in/out] */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail major_t nm_major; /* Device major number [in/out] */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ushort_t nm_found; /* Did we find a match? [out] */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail} nm_query_t;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail/*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * Address-to-modctl callback structure:
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailtypedef struct a2m_query {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail uintptr_t a2m_addr; /* Virtual address [in] */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail uintptr_t a2m_where; /* Modctl address [out] */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail} a2m_query_t;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail/*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * Segment-to-mdb_map callback structure:
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailtypedef struct {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail struct seg_ops *asm_segvn_ops; /* Address of segvn ops [in] */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail void (*asm_callback)(const struct mdb_map *, void *); /* Callb [in] */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail void *asm_cbdata; /* Callback data [in] */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail} asmap_arg_t;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailstatic void
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbaildnlc_free(void)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail{
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ncache_t *ncp, *next;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail int i;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (dnlc_hash == NULL) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail /*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * Free up current dnlc entries
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail for (i = 0; i < MDB_DNLC_HSIZE; i++) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail for (ncp = dnlc_hash[i]; ncp; ncp = next) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail next = ncp->hash_next;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail mdb_free(ncp, MDB_DNLC_NCACHE_SZ(ncp));
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail mdb_free(dnlc_hash, MDB_DNLC_HSIZE * sizeof (ncache_t *));
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail dnlc_hash = NULL;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail}
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailchar bad_dnlc[] = "inconsistent dnlc chain: %d, ncache va: %p"
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail " - continuing with the rest\n";
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailstatic int
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbaildnlc_load(void)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail{
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail int i; /* hash index */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail int retry_cnt = 0;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail int skip_bad_chains = 0;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail int nc_hashsz; /* kernel hash array size */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail uintptr_t nc_hash_addr; /* kernel va of ncache hash array */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail uintptr_t head; /* kernel va of head of hash chain */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail /*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * If we've already cached the DNLC and we're looking at a dump,
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * our cache is good forever, so don't bother re-loading.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (dnlc_hash && mdb_prop_postmortem) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (0);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail /*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * For a core dump, retries wont help.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * Just print and skip any bad chains.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (mdb_prop_postmortem) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail skip_bad_chains = 1;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailretry:
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (retry_cnt++ >= MDB_DNLC_MAX_RETRY) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail /*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * Give up retrying the rapidly changing dnlc.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * Just print and skip any bad chains
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail skip_bad_chains = 1;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail dnlc_free(); /* Free up the mdb hashed dnlc - if any */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail /*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * Although nc_hashsz and the location of nc_hash doesn't currently
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * change, it may do in the future with a more dynamic dnlc.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * So always read these values afresh.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (mdb_readvar(&nc_hashsz, "nc_hashsz") == -1) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail mdb_warn("failed to read nc_hashsz");
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (-1);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (mdb_readvar(&nc_hash_addr, "nc_hash") == -1) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail mdb_warn("failed to read nc_hash");
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (-1);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail /*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * Allocate the mdb dnlc hash array
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail dnlc_hash = mdb_zalloc(MDB_DNLC_HSIZE * sizeof (ncache_t *), UM_SLEEP);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail /* for each kernel hash chain */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail for (i = 0, head = nc_hash_addr; i < nc_hashsz;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail i++, head += sizeof (nc_hash_t)) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail nc_hash_t nch; /* kernel hash chain header */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ncache_t *ncp; /* name cache pointer */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail int hash; /* mdb hash value */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail uintptr_t nc_va; /* kernel va of next ncache */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail uintptr_t ncprev_va; /* kernel va of previous ncache */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail int khash; /* kernel dnlc hash value */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail uchar_t namelen; /* name length */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ncache_t nc; /* name cache entry */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail int nc_size; /* size of a name cache entry */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail /*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * We read each element of the nc_hash array individually
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * just before we process the entries in its chain. This is
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * because the chain can change so rapidly on a running system.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (mdb_vread(&nch, sizeof (nc_hash_t), head) == -1) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail mdb_warn("failed to read nc_hash chain header %d", i);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail dnlc_free();
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (-1);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ncprev_va = head;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail nc_va = (uintptr_t)(nch.hash_next);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail /* for each entry in the chain */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail while (nc_va != head) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail /*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * The size of the ncache entries varies
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * because the name is appended to the structure.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * So we read in the structure then re-read
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * for the structure plus name.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (mdb_vread(&nc, sizeof (ncache_t), nc_va) == -1) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (skip_bad_chains) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail mdb_warn(bad_dnlc, i, nc_va);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail break;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail goto retry;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail nc_size = MDB_DNLC_NCACHE_SZ(&nc);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ncp = mdb_alloc(nc_size, UM_SLEEP);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (mdb_vread(ncp, nc_size - 1, nc_va) == -1) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail mdb_free(ncp, nc_size);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (skip_bad_chains) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail mdb_warn(bad_dnlc, i, nc_va);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail break;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail goto retry;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail /*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * Check for chain consistency
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if ((uintptr_t)ncp->hash_prev != ncprev_va) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail mdb_free(ncp, nc_size);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (skip_bad_chains) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail mdb_warn(bad_dnlc, i, nc_va);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail break;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail goto retry;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail /*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * Terminate the new name with a null.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * Note, we allowed space for this null when
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * allocating space for the entry.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ncp->name[ncp->namlen] = '\0';
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail /*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * Validate new entry by re-hashing using the
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * kernel dnlc hash function and comparing the hash
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail DNLCHASH(ncp->name, ncp->dp, khash, namelen);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if ((namelen != ncp->namlen) ||
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail (khash != ncp->hash)) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail mdb_free(ncp, nc_size);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (skip_bad_chains) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail mdb_warn(bad_dnlc, i, nc_va);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail break;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail goto retry;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail /*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * Finally put the validated entry into the mdb
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * hash chains. Reuse the kernel next hash field
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * for the mdb hash chain pointer.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail hash = MDB_DNLC_HASH(ncp->vp);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ncprev_va = nc_va;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail nc_va = (uintptr_t)(ncp->hash_next);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ncp->hash_next = dnlc_hash[hash];
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail dnlc_hash[hash] = ncp;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (0);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail}
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail/*ARGSUSED*/
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailint
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbaildnlcdump(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail{
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ncache_t *ent;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail int i;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if ((flags & DCMD_ADDRSPEC) || argc != 0)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (DCMD_USAGE);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (dnlc_load() == -1)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (DCMD_ERR);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail mdb_printf("%<u>%-?s %-?s %-32s%</u>\n", "VP", "DVP", "NAME");
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail for (i = 0; i < MDB_DNLC_HSIZE; i++) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail for (ent = dnlc_hash[i]; ent != NULL; ent = ent->hash_next) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail mdb_printf("%0?p %0?p %s\n",
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ent->vp, ent->dp, ent->name);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (DCMD_OK);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail}
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailstatic int
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailmdb_sprintpath(char *buf, size_t len, mdb_path_t *path)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail{
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail char *s = buf;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail int i;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (len < sizeof ("/..."))
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (-1);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (!path->mdp_complete) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail (void) strcpy(s, "??");
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail s += 2;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (path->mdp_nelem == 0)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (-1);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (path->mdp_nelem == 0) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail (void) strcpy(s, "/");
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (0);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail for (i = path->mdp_nelem - 1; i >= 0; i--) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail /*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * Number of bytes left is the distance from where we
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * are to the end, minus 2 for '/' and '\0'
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ssize_t left = (ssize_t)(&buf[len] - s) - 2;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (left <= 0)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail break;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail *s++ = '/';
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail (void) strncpy(s, path->mdp_name[i], left);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail s[left - 1] = '\0';
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail s += strlen(s);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (left < strlen(path->mdp_name[i]))
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail break;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (i >= 0)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail (void) strcpy(&buf[len - 4], "...");
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (0);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail}
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailstatic int
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailmdb_autonode2path(uintptr_t addr, mdb_path_t *path)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail{
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail fninfo_t fni;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail fnnode_t fn;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail vnode_t vn;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail vfs_t vfs;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail struct vnodeops *autofs_vnops = NULL;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail /*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * "autofs_vnops_ptr" is the address of the pointer to the vnodeops
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * structure for autofs. We want to read it each time we access
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * it since autofs could (in theory) be unloaded and reloaded.
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (mdb_vread(&autofs_vnops, sizeof (autofs_vnops),
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail (uintptr_t)autofs_vnops_ptr) == -1)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (-1);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (mdb_vread(&vn, sizeof (vn), addr) == -1)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (-1);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (autofs_vnops == NULL || vn.v_op != autofs_vnops)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (-1);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail addr = (uintptr_t)vn.v_data;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (mdb_vread(&vfs, sizeof (vfs), (uintptr_t)vn.v_vfsp) == -1 ||
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail mdb_vread(&fni, sizeof (fni), (uintptr_t)vfs.vfs_data) == -1 ||
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail mdb_vread(&vn, sizeof (vn), (uintptr_t)fni.fi_rootvp) == -1)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (-1);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail for (;;) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail size_t elem = path->mdp_nelem++;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail char elemstr[MAXNAMELEN];
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail char *c, *p;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (elem == MDB_PATH_NELEM) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail path->mdp_nelem--;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (-1);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (mdb_vread(&fn, sizeof (fn), addr) != sizeof (fn)) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail path->mdp_nelem--;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (-1);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (mdb_readstr(elemstr, sizeof (elemstr),
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail (uintptr_t)fn.fn_name) <= 0) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail (void) strcpy(elemstr, "?");
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail c = mdb_alloc(strlen(elemstr) + 1, UM_SLEEP | UM_GC);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail (void) strcpy(c, elemstr);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail path->mdp_vnode[elem] = (uintptr_t)fn.fn_vnode;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (addr == (uintptr_t)fn.fn_parent) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail path->mdp_name[elem] = &c[1];
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail path->mdp_complete = TRUE;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail break;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if ((p = strrchr(c, '/')) != NULL)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail path->mdp_name[elem] = p + 1;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail else
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail path->mdp_name[elem] = c;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail addr = (uintptr_t)fn.fn_parent;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (0);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail}
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailint
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailmdb_vnode2path(uintptr_t addr, char *buf, size_t buflen)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail{
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail uintptr_t rootdir;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ncache_t *ent;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail vnode_t vp;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail mdb_path_t path;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail /*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * Check to see if we have a cached value for this vnode
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (mdb_vread(&vp, sizeof (vp), addr) != -1 &&
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail vp.v_path != NULL &&
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail mdb_readstr(buf, buflen, (uintptr_t)vp.v_path) != -1)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (0);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (dnlc_load() == -1)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (-1);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (mdb_readvar(&rootdir, "rootdir") == -1) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail mdb_warn("failed to read 'rootdir'");
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (-1);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail bzero(&path, sizeof (mdb_path_t));
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailagain:
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if ((addr == NULL) && (path.mdp_nelem == 0)) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail /*
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail * 0 elems && complete tells sprintpath to just print "/"
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail path.mdp_complete = TRUE;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail goto out;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (addr == rootdir) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail path.mdp_complete = TRUE;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail goto out;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail for (ent = dnlc_hash[MDB_DNLC_HASH(addr)]; ent; ent = ent->hash_next) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if ((uintptr_t)ent->vp == addr) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (strcmp(ent->name, "..") == 0 ||
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail strcmp(ent->name, ".") == 0)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail continue;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail path.mdp_vnode[path.mdp_nelem] = (uintptr_t)ent->vp;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail path.mdp_name[path.mdp_nelem] = ent->name;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail path.mdp_nelem++;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (path.mdp_nelem == MDB_PATH_NELEM) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail path.mdp_nelem--;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail mdb_warn("path exceeded maximum expected "
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail "elements\n");
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (-1);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail addr = (uintptr_t)ent->dp;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail goto again;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail (void) mdb_autonode2path(addr, &path);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailout:
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (mdb_sprintpath(buf, buflen, &path));
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail}
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailuintptr_t
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailmdb_pid2proc(pid_t pid, proc_t *proc)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail{
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail int pid_hashsz, hash;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail uintptr_t paddr, pidhash, procdir;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail struct pid pidp;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (mdb_readvar(&pidhash, "pidhash") == -1)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (NULL);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (mdb_readvar(&pid_hashsz, "pid_hashsz") == -1)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (NULL);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (mdb_readvar(&procdir, "procdir") == -1)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (NULL);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail hash = pid & (pid_hashsz - 1);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (mdb_vread(&paddr, sizeof (paddr),
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail pidhash + (hash * sizeof (paddr))) == -1)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (NULL);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail while (paddr != 0) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (mdb_vread(&pidp, sizeof (pidp), paddr) == -1)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (NULL);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (pidp.pid_id == pid) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail uintptr_t procp;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (mdb_vread(&procp, sizeof (procp), procdir +
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail (pidp.pid_prslot * sizeof (procp))) == -1)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (NULL);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (proc != NULL)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail (void) mdb_vread(proc, sizeof (proc_t), procp);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (procp);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail paddr = (uintptr_t)pidp.pid_link;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (NULL);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail}
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailint
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailmdb_cpu2cpuid(uintptr_t cpup)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail{
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail cpu_t cpu;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (mdb_vread(&cpu, sizeof (cpu_t), cpup) != sizeof (cpu_t))
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (-1);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (cpu.cpu_id);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail}
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailint
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailmdb_cpuset_find(uintptr_t cpusetp)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail{
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ulong_t *cpuset;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail size_t nr_words = BT_BITOUL(NCPU);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail size_t sz = nr_words * sizeof (ulong_t);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail size_t i;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail int cpu = -1;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail cpuset = mdb_alloc(sz, UM_SLEEP);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (mdb_vread(cpuset, sz, cpusetp) != sz)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail goto out;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail for (i = 0; i < nr_words; i++) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail size_t j;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ulong_t m;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail for (j = 0, m = 1; j < BT_NBIPUL; j++, m <<= 1) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (cpuset[i] & m) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail cpu = i * BT_NBIPUL + j;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail goto out;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailout:
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail mdb_free(cpuset, sz);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (cpu);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail}
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailuintptr_t
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailmdb_vnode2page(uintptr_t vp, uintptr_t offset)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail{
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail long page_hashsz, ndx;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail uintptr_t page_hash, pp;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (mdb_readvar(&page_hashsz, "page_hashsz") == -1 ||
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail mdb_readvar(&page_hash, "page_hash") == -1)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (NULL);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ndx = PAGE_HASH_FUNC(vp, offset);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail page_hash += ndx * sizeof (uintptr_t);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail mdb_vread(&pp, sizeof (pp), page_hash);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail while (pp != NULL) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail page_t page;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail mdb_vread(&page, sizeof (page), pp);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if ((uintptr_t)page.p_vnode == vp &&
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail (uintptr_t)page.p_offset == offset)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (pp);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail pp = (uintptr_t)page.p_hash;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (NULL);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail}
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailchar
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailmdb_vtype2chr(vtype_t type, mode_t mode)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail{
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail static const char vttab[] = {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ' ', /* VNON */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ' ', /* VREG */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail '/', /* VDIR */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ' ', /* VBLK */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ' ', /* VCHR */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail '@', /* VLNK */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail '|', /* VFIFO */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail '>', /* VDOOR */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ' ', /* VPROC */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail '=', /* VSOCK */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail ' ', /* VBAD */
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail };
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (type < 0 || type >= sizeof (vttab) / sizeof (vttab[0]))
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return ('?');
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (type == VREG && (mode & 0111) != 0)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return ('*');
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (vttab[type]);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail}
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailstatic int
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbaila2m_walk_modctl(uintptr_t addr, const struct modctl *m, a2m_query_t *a2m)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail{
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail struct module mod;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (m->mod_mp == NULL)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (0);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (mdb_vread(&mod, sizeof (mod), (uintptr_t)m->mod_mp) == -1) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail mdb_warn("couldn't read modctl %p's module", addr);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (0);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (a2m->a2m_addr >= (uintptr_t)mod.text &&
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail a2m->a2m_addr < (uintptr_t)mod.text + mod.text_size)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail goto found;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (a2m->a2m_addr >= (uintptr_t)mod.data &&
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail a2m->a2m_addr < (uintptr_t)mod.data + mod.data_size)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail goto found;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (0);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailfound:
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail a2m->a2m_where = addr;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (-1);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail}
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailuintptr_t
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailmdb_addr2modctl(uintptr_t addr)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail{
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail a2m_query_t a2m;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail a2m.a2m_addr = addr;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail a2m.a2m_where = NULL;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail (void) mdb_walk("modctl", (mdb_walk_cb_t)a2m_walk_modctl, &a2m);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (a2m.a2m_where);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail}
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailstatic mdb_qinfo_t *
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailqi_lookup(uintptr_t qinit_addr)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail{
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail mdb_qinfo_t *qip;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail for (qip = qi_head; qip != NULL; qip = qip->qi_next) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (qip->qi_addr == qinit_addr)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (qip);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (NULL);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail}
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailvoid
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailmdb_qops_install(const mdb_qops_t *qops, uintptr_t qinit_addr)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail{
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail mdb_qinfo_t *qip = qi_lookup(qinit_addr);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (qip != NULL) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail qip->qi_ops = qops;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail qip = mdb_alloc(sizeof (mdb_qinfo_t), UM_SLEEP);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail qip->qi_ops = qops;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail qip->qi_addr = qinit_addr;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail qip->qi_next = qi_head;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail qi_head = qip;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail}
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailvoid
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailmdb_qops_remove(const mdb_qops_t *qops, uintptr_t qinit_addr)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail{
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail mdb_qinfo_t *qip, *p = NULL;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail for (qip = qi_head; qip != NULL; p = qip, qip = qip->qi_next) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (qip->qi_addr == qinit_addr && qip->qi_ops == qops) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (qi_head == qip)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail qi_head = qip->qi_next;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail else
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail p->qi_next = qip->qi_next;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail mdb_free(qip, sizeof (mdb_qinfo_t));
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail}
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailchar *
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailmdb_qname(const queue_t *q, char *buf, size_t nbytes)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail{
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail struct module_info mi;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail struct qinit qi;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (mdb_vread(&qi, sizeof (qi), (uintptr_t)q->q_qinfo) == -1) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail mdb_warn("failed to read qinit at %p", q->q_qinfo);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail goto err;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (mdb_vread(&mi, sizeof (mi), (uintptr_t)qi.qi_minfo) == -1) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail mdb_warn("failed to read module_info at %p", qi.qi_minfo);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail goto err;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (mdb_readstr(buf, nbytes, (uintptr_t)mi.mi_idname) <= 0) {
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail mdb_warn("failed to read mi_idname at %p", mi.mi_idname);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail goto err;
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail }
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (buf);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailerr:
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail (void) mdb_snprintf(buf, nbytes, "???");
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (buf);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail}
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailvoid
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailmdb_qinfo(const queue_t *q, char *buf, size_t nbytes)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail{
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail mdb_qinfo_t *qip = qi_lookup((uintptr_t)q->q_qinfo);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail buf[0] = '\0';
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (qip != NULL)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail qip->qi_ops->q_info(q, buf, nbytes);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail}
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailuintptr_t
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbailmdb_qrnext(const queue_t *q)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail{
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail mdb_qinfo_t *qip = qi_lookup((uintptr_t)q->q_qinfo);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail if (qip != NULL)
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (qip->qi_ops->q_rnext(q));
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail return (NULL);
6e91bba0d6c6bdabbba62cefae583715a4a58e2aGirish Moodalbail}
uintptr_t
mdb_qwnext(const queue_t *q)
{
mdb_qinfo_t *qip = qi_lookup((uintptr_t)q->q_qinfo);
if (qip != NULL)
return (qip->qi_ops->q_wnext(q));
return (NULL);
}
uintptr_t
mdb_qrnext_default(const queue_t *q)
{
return ((uintptr_t)q->q_next);
}
uintptr_t
mdb_qwnext_default(const queue_t *q)
{
return ((uintptr_t)q->q_next);
}
/*
* The following three routines borrowed from modsubr.c
*/
static int
nm_hash(const char *name)
{
char c;
int hash = 0;
for (c = *name++; c; c = *name++)
hash ^= c;
return (hash & MOD_BIND_HASHMASK);
}
static uintptr_t
find_mbind(const char *name, uintptr_t *hashtab)
{
int hashndx;
uintptr_t mb;
struct bind mb_local;
char node_name[MAXPATHLEN + 1];
hashndx = nm_hash(name);
mb = hashtab[hashndx];
while (mb) {
if (mdb_vread(&mb_local, sizeof (mb_local), mb) == -1) {
mdb_warn("failed to read struct bind at %p", mb);
return (NULL);
}
if (mdb_readstr(node_name, sizeof (node_name),
(uintptr_t)mb_local.b_name) == -1) {
mdb_warn("failed to read node name string at %p",
mb_local.b_name);
return (NULL);
}
if (strcmp(name, node_name) == 0)
break;
mb = (uintptr_t)mb_local.b_next;
}
return (mb);
}
int
mdb_name_to_major(const char *name, major_t *major)
{
uintptr_t mbind;
uintptr_t mb_hashtab[MOD_BIND_HASHSIZE];
struct bind mbind_local;
if (mdb_readsym(mb_hashtab, sizeof (mb_hashtab), "mb_hashtab") == -1) {
mdb_warn("failed to read symbol 'mb_hashtab'");
return (-1);
}
if ((mbind = find_mbind(name, mb_hashtab)) != NULL) {
if (mdb_vread(&mbind_local, sizeof (mbind_local), mbind) ==
-1) {
mdb_warn("failed to read mbind struct at %p", mbind);
return (-1);
}
*major = (major_t)mbind_local.b_num;
return (0);
}
return (-1);
}
const char *
mdb_major_to_name(major_t major)
{
static char name[MODMAXNAMELEN + 1];
uintptr_t devnamesp;
struct devnames dn;
uint_t devcnt;
if (mdb_readvar(&devcnt, "devcnt") == -1 || major >= devcnt ||
mdb_readvar(&devnamesp, "devnamesp") == -1)
return (NULL);
if (mdb_vread(&dn, sizeof (struct devnames), devnamesp +
major * sizeof (struct devnames)) != sizeof (struct devnames))
return (NULL);
if (mdb_readstr(name, MODMAXNAMELEN + 1, (uintptr_t)dn.dn_name) == -1)
return (NULL);
return ((const char *)name);
}
/*
* Return the name of the driver attached to the dip in drivername.
*/
int
mdb_devinfo2driver(uintptr_t dip_addr, char *drivername, size_t namebufsize)
{
struct dev_info devinfo;
char bind_name[MAXPATHLEN + 1];
major_t major;
const char *namestr;
if (mdb_vread(&devinfo, sizeof (devinfo), dip_addr) == -1) {
mdb_warn("failed to read devinfo at %p", dip_addr);
return (-1);
}
if (mdb_readstr(bind_name, sizeof (bind_name),
(uintptr_t)devinfo.devi_binding_name) == -1) {
mdb_warn("failed to read binding name at %p",
devinfo.devi_binding_name);
return (-1);
}
/*
* Many->one relation: various names to one major number
*/
if (mdb_name_to_major(bind_name, &major) == -1) {
mdb_warn("failed to translate bind name to major number\n");
return (-1);
}
/*
* One->one relation: one major number corresponds to one driver
*/
if ((namestr = mdb_major_to_name(major)) == NULL) {
(void) strncpy(drivername, "???", namebufsize);
return (-1);
}
(void) strncpy(drivername, namestr, namebufsize);
return (0);
}
/*
* Find the name of the driver attached to this dip (if any), given:
* - the address of a dip (in core)
* - the NAME of the global pointer to the driver's i_ddi_soft_state struct
* - pointer to a pointer to receive the address
*/
int
mdb_devinfo2statep(uintptr_t dip_addr, char *soft_statep_name,
uintptr_t *statep)
{
struct dev_info dev_info;
if (mdb_vread(&dev_info, sizeof (dev_info), dip_addr) == -1) {
mdb_warn("failed to read devinfo at %p", dip_addr);
return (-1);
}
return (mdb_get_soft_state_byname(soft_statep_name,
dev_info.devi_instance, statep, NULL, 0));
}
/*
* Returns a pointer to the top of the soft state struct for the instance
* specified (in state_addr), given the address of the global soft state
* pointer and size of the struct. Also fills in the buffer pointed to by
* state_buf_p (if non-NULL) with the contents of the state struct.
*/
int
mdb_get_soft_state_byaddr(uintptr_t ssaddr, uint_t instance,
uintptr_t *state_addr, void *state_buf_p, size_t sizeof_state)
{
struct i_ddi_soft_state ss;
void *statep;
if (mdb_vread(&ss, sizeof (ss), ssaddr) == -1)
return (-1);
if (instance >= ss.n_items)
return (-1);
if (mdb_vread(&statep, sizeof (statep), (uintptr_t)ss.array +
(sizeof (statep) * instance)) == -1)
return (-1);
if (state_addr != NULL)
*state_addr = (uintptr_t)statep;
if (statep == NULL) {
errno = ENOENT;
return (-1);
}
if (state_buf_p != NULL) {
/* Read the state struct into the buffer in local space. */
if (mdb_vread(state_buf_p, sizeof_state,
(uintptr_t)statep) == -1)
return (-1);
}
return (0);
}
/*
* Returns a pointer to the top of the soft state struct for the instance
* specified (in state_addr), given the name of the global soft state pointer
* and size of the struct. Also fills in the buffer pointed to by
* state_buf_p (if non-NULL) with the contents of the state struct.
*/
int
mdb_get_soft_state_byname(char *softstatep_name, uint_t instance,
uintptr_t *state_addr, void *state_buf_p, size_t sizeof_state)
{
uintptr_t ssaddr;
if (mdb_readvar((void *)&ssaddr, softstatep_name) == -1)
return (-1);
return (mdb_get_soft_state_byaddr(ssaddr, instance, state_addr,
state_buf_p, sizeof_state));
}
static const mdb_dcmd_t dcmds[] = {
{ "dnlc", NULL, "print DNLC contents", dnlcdump },
{ NULL }
};
static const mdb_modinfo_t modinfo = { MDB_API_VERSION, dcmds };
/*ARGSUSED*/
static void
update_vars(void *arg)
{
GElf_Sym sym;
if (mdb_lookup_by_name("auto_vnodeops", &sym) == 0)
autofs_vnops_ptr = (struct vnodeops *)(uintptr_t)sym.st_value;
else
autofs_vnops_ptr = NULL;
(void) mdb_readvar(&_mdb_ks_pagesize, "_pagesize");
(void) mdb_readvar(&_mdb_ks_pageshift, "_pageshift");
(void) mdb_readvar(&_mdb_ks_pageoffset, "_pageoffset");
(void) mdb_readvar(&_mdb_ks_pagemask, "_pagemask");
(void) mdb_readvar(&_mdb_ks_mmu_pagesize, "_mmu_pagesize");
(void) mdb_readvar(&_mdb_ks_mmu_pageshift, "_mmu_pageshift");
(void) mdb_readvar(&_mdb_ks_mmu_pageoffset, "_mmu_pageoffset");
(void) mdb_readvar(&_mdb_ks_mmu_pagemask, "_mmu_pagemask");
(void) mdb_readvar(&_mdb_ks_kernelbase, "_kernelbase");
(void) mdb_readvar(&_mdb_ks_userlimit, "_userlimit");
(void) mdb_readvar(&_mdb_ks_userlimit32, "_userlimit32");
(void) mdb_readvar(&_mdb_ks_argsbase, "_argsbase");
(void) mdb_readvar(&_mdb_ks_msg_bsize, "_msg_bsize");
(void) mdb_readvar(&_mdb_ks_defaultstksz, "_defaultstksz");
(void) mdb_readvar(&_mdb_ks_ncpu, "_ncpu");
}
const mdb_modinfo_t *
_mdb_init(void)
{
/*
* When used with mdb, mdb_ks is a separate dmod. With kmdb, however,
* mdb_ks is compiled into the debugger module. kmdb cannot
* automatically modunload itself when it exits. If it restarts after
* debugger fault, static variables may not be initialized to zero.
* They must be manually reinitialized here.
*/
dnlc_hash = NULL;
qi_head = NULL;
mdb_callback_add(MDB_CALLBACK_STCHG, update_vars, NULL);
update_vars(NULL);
return (&modinfo);
}
void
_mdb_fini(void)
{
dnlc_free();
while (qi_head != NULL) {
mdb_qinfo_t *qip = qi_head;
qi_head = qip->qi_next;
mdb_free(qip, sizeof (mdb_qinfo_t));
}
}
/*
* Interface between MDB kproc target and mdb_ks. The kproc target relies
* on looking up and invoking these functions in mdb_ks so that dependencies
* on the current kernel implementation are isolated in mdb_ks.
*/
/*
* Given the address of a proc_t, return the p.p_as pointer; return NULL
* if we were unable to read a proc structure from the given address.
*/
uintptr_t
mdb_kproc_as(uintptr_t proc_addr)
{
proc_t p;
if (mdb_vread(&p, sizeof (p), proc_addr) == sizeof (p))
return ((uintptr_t)p.p_as);
return (NULL);
}
/*
* Given the address of a proc_t, return the p.p_model value; return
* PR_MODEL_UNKNOWN if we were unable to read a proc structure or if
* the model value does not match one of the two known values.
*/
uint_t
mdb_kproc_model(uintptr_t proc_addr)
{
proc_t p;
if (mdb_vread(&p, sizeof (p), proc_addr) == sizeof (p)) {
switch (p.p_model) {
case DATAMODEL_ILP32:
return (PR_MODEL_ILP32);
case DATAMODEL_LP64:
return (PR_MODEL_LP64);
}
}
return (PR_MODEL_UNKNOWN);
}
/*
* Callback function for walking process's segment list. For each segment,
* we fill in an mdb_map_t describing its properties, and then invoke
* the callback function provided by the kproc target.
*/
static int
asmap_step(uintptr_t addr, const struct seg *seg, asmap_arg_t *asmp)
{
struct segvn_data svd;
mdb_map_t map;
if (seg->s_ops == asmp->asm_segvn_ops && mdb_vread(&svd,
sizeof (svd), (uintptr_t)seg->s_data) == sizeof (svd)) {
if (svd.vp != NULL) {
if (mdb_vnode2path((uintptr_t)svd.vp, map.map_name,
MDB_TGT_MAPSZ) != 0) {
(void) mdb_snprintf(map.map_name,
MDB_TGT_MAPSZ, "[ vnode %p ]", svd.vp);
}
} else
(void) strcpy(map.map_name, "[ anon ]");
} else {
(void) mdb_snprintf(map.map_name, MDB_TGT_MAPSZ,
"[ seg %p ]", addr);
}
map.map_base = (uintptr_t)seg->s_base;
map.map_size = seg->s_size;
map.map_flags = 0;
asmp->asm_callback((const struct mdb_map *)&map, asmp->asm_cbdata);
return (WALK_NEXT);
}
/*
* Given a process address space, walk its segment list using the seg walker,
* convert the segment data to an mdb_map_t, and pass this information
* back to the kproc target via the given callback function.
*/
int
mdb_kproc_asiter(uintptr_t as,
void (*func)(const struct mdb_map *, void *), void *p)
{
asmap_arg_t arg;
GElf_Sym sym;
arg.asm_segvn_ops = NULL;
arg.asm_callback = func;
arg.asm_cbdata = p;
if (mdb_lookup_by_name("segvn_ops", &sym) == 0)
arg.asm_segvn_ops = (struct seg_ops *)(uintptr_t)sym.st_value;
return (mdb_pwalk("seg", (mdb_walk_cb_t)asmap_step, &arg, as));
}
/*
* Copy the auxv array from the given process's u-area into the provided
* buffer. If the buffer is NULL, only return the size of the auxv array
* so the caller knows how much space will be required.
*/
int
mdb_kproc_auxv(uintptr_t proc, auxv_t *auxv)
{
if (auxv != NULL) {
proc_t p;
if (mdb_vread(&p, sizeof (p), proc) != sizeof (p))
return (-1);
bcopy(p.p_user.u_auxv, auxv,
sizeof (auxv_t) * __KERN_NAUXV_IMPL);
}
return (__KERN_NAUXV_IMPL);
}
/*
* Given a process address, return the PID.
*/
pid_t
mdb_kproc_pid(uintptr_t proc_addr)
{
struct pid pid;
proc_t p;
if (mdb_vread(&p, sizeof (p), proc_addr) == sizeof (p) &&
mdb_vread(&pid, sizeof (pid), (uintptr_t)p.p_pidp) == sizeof (pid))
return (pid.pid_id);
return (-1);
}
/*
* Interface between the MDB kvm target and mdb_ks. The kvm target relies
* on looking up and invoking these functions in mdb_ks so that dependencies
* on the current kernel implementation are isolated in mdb_ks.
*/
/*
* Determine whether or not the thread that panicked the given kernel was a
* kernel thread (panic_thread->t_procp == &p0).
*/
void
mdb_dump_print_content(dumphdr_t *dh, pid_t content)
{
GElf_Sym sym;
uintptr_t pt;
uintptr_t procp;
int expcont = 0;
int actcont;
(void) mdb_readvar(&expcont, "dump_conflags");
actcont = dh->dump_flags & DF_CONTENT;
if (actcont == DF_ALL) {
mdb_printf("dump content: all kernel and user pages\n");
return;
} else if (actcont == DF_CURPROC) {
mdb_printf("dump content: kernel pages and pages from "
"PID %d", content);
return;
}
mdb_printf("dump content: kernel pages only\n");
if (!(expcont & DF_CURPROC))
return;
if (mdb_readvar(&pt, "panic_thread") != sizeof (pt) || pt == NULL)
goto kthreadpanic_err;
if (mdb_vread(&procp, sizeof (procp), pt + OFFSETOF(kthread_t,
t_procp)) == -1 || procp == NULL)
goto kthreadpanic_err;
if (mdb_lookup_by_name("p0", &sym) != 0)
goto kthreadpanic_err;
if (procp == (uintptr_t)sym.st_value) {
mdb_printf(" (curproc requested, but a kernel thread "
"panicked)\n");
} else {
mdb_printf(" (curproc requested, but the process that "
"panicked could not be dumped)\n");
}
return;
kthreadpanic_err:
mdb_printf(" (curproc requested, but the process that panicked could "
"not be found)\n");
}
/*
* Determine the process that was saved in a `curproc' dump. This process will
* be recorded as the first element in dump_pids[].
*/
int
mdb_dump_find_curproc(void)
{
uintptr_t pidp;
pid_t pid = -1;
if (mdb_readvar(&pidp, "dump_pids") == sizeof (pidp) &&
mdb_vread(&pid, sizeof (pid), pidp) == sizeof (pid) &&
pid > 0)
return (pid);
else
return (-1);
}
/*
* Following three funcs extracted from sunddi.c
*/
/*
* Return core address of root node of devinfo tree
*/
static uintptr_t
mdb_ddi_root_node(void)
{
uintptr_t top_devinfo_addr;
/* return (top_devinfo); */
if (mdb_readvar(&top_devinfo_addr, "top_devinfo") == -1) {
mdb_warn("failed to read top_devinfo");
return (NULL);
}
return (top_devinfo_addr);
}
/*
* Return the name of the devinfo node pointed at by 'dip_addr' in the buffer
* pointed at by 'name.'
*
* - dip_addr is a pointer to a dev_info struct in core.
*/
static char *
mdb_ddi_deviname(uintptr_t dip_addr, char *name, size_t name_size)
{
uintptr_t addrname;
ssize_t length;
char *local_namep = name;
size_t local_name_size = name_size;
struct dev_info local_dip;
if (dip_addr == mdb_ddi_root_node()) {
if (name_size < 1) {
mdb_warn("failed to get node name: buf too small\n");
return (NULL);
}
*name = '\0';
return (name);
}
if (name_size < 2) {
mdb_warn("failed to get node name: buf too small\n");
return (NULL);
}
local_namep = name;
*local_namep++ = '/';
*local_namep = '\0';
local_name_size--;
if (mdb_vread(&local_dip, sizeof (struct dev_info), dip_addr) == -1) {
mdb_warn("failed to read devinfo struct");
}
length = mdb_readstr(local_namep, local_name_size,
(uintptr_t)local_dip.devi_node_name);
if (length == -1) {
mdb_warn("failed to read node name");
return (NULL);
}
local_namep += length;
local_name_size -= length;
addrname = (uintptr_t)local_dip.devi_addr;
if (addrname != NULL) {
if (local_name_size < 2) {
mdb_warn("not enough room for node address string");
return (name);
}
*local_namep++ = '@';
*local_namep = '\0';
local_name_size--;
length = mdb_readstr(local_namep, local_name_size, addrname);
if (length == -1) {
mdb_warn("failed to read name");
return (NULL);
}
}
return (name);
}
/*
* Generate the full path under the /devices dir to the device entry.
*
* dip is a pointer to a devinfo struct in core (not in local memory).
*/
char *
mdb_ddi_pathname(uintptr_t dip_addr, char *path, size_t pathlen)
{
struct dev_info local_dip;
uintptr_t parent_dip;
char *bp;
size_t buf_left;
if (dip_addr == mdb_ddi_root_node()) {
*path = '\0';
return (path);
}
if (mdb_vread(&local_dip, sizeof (struct dev_info), dip_addr) == -1) {
mdb_warn("failed to read devinfo struct");
}
parent_dip = (uintptr_t)local_dip.devi_parent;
(void) mdb_ddi_pathname(parent_dip, path, pathlen);
bp = path + strlen(path);
buf_left = pathlen - strlen(path);
(void) mdb_ddi_deviname(dip_addr, bp, buf_left);
return (path);
}
/*
* Read in the string value of a refstr, which is appended to the end of
* the structure.
*/
ssize_t
mdb_read_refstr(uintptr_t refstr_addr, char *str, size_t nbytes)
{
struct refstr *r = (struct refstr *)refstr_addr;
return (mdb_readstr(str, nbytes, (uintptr_t)r->rs_string));
}
/*
* Chase an mblk list by b_next and return the length.
*/
int
mdb_mblk_count(const mblk_t *mb)
{
int count;
mblk_t mblk;
if (mb == NULL)
return (0);
count = 1;
while (mb->b_next != NULL) {
count++;
if (mdb_vread(&mblk, sizeof (mblk), (uintptr_t)mb->b_next) ==
-1)
break;
mb = &mblk;
}
return (count);
}
/*
* Write the given MAC address as a printable string in the usual colon-
* separated format. Assumes that buflen is at least 2.
*/
void
mdb_mac_addr(const uint8_t *addr, size_t alen, char *buf, size_t buflen)
{
int slen;
if (alen == 0 || buflen < 4) {
(void) strcpy(buf, "?");
return;
}
for (;;) {
/*
* If there are more MAC address bytes available, but we won't
* have any room to print them, then add "..." to the string
* instead. See below for the 'magic number' explanation.
*/
if ((alen == 2 && buflen < 6) || (alen > 2 && buflen < 7)) {
(void) strcpy(buf, "...");
break;
}
slen = mdb_snprintf(buf, buflen, "%02x", *addr++);
buf += slen;
if (--alen == 0)
break;
*buf++ = ':';
buflen -= slen + 1;
/*
* At this point, based on the first 'if' statement above,
* either alen == 1 and buflen >= 3, or alen > 1 and
* buflen >= 4. The first case leaves room for the final "xx"
* number and trailing NUL byte. The second leaves room for at
* least "...". Thus the apparently 'magic' numbers chosen for
* that statement.
*/
}
}
/*
* Produce a string that represents a DLPI primitive, or NULL if no such string
* is possible.
*/
const char *
mdb_dlpi_prim(int prim)
{
switch (prim) {
case DL_INFO_REQ: return ("DL_INFO_REQ");
case DL_INFO_ACK: return ("DL_INFO_ACK");
case DL_ATTACH_REQ: return ("DL_ATTACH_REQ");
case DL_DETACH_REQ: return ("DL_DETACH_REQ");
case DL_BIND_REQ: return ("DL_BIND_REQ");
case DL_BIND_ACK: return ("DL_BIND_ACK");
case DL_UNBIND_REQ: return ("DL_UNBIND_REQ");
case DL_OK_ACK: return ("DL_OK_ACK");
case DL_ERROR_ACK: return ("DL_ERROR_ACK");
case DL_ENABMULTI_REQ: return ("DL_ENABMULTI_REQ");
case DL_DISABMULTI_REQ: return ("DL_DISABMULTI_REQ");
case DL_PROMISCON_REQ: return ("DL_PROMISCON_REQ");
case DL_PROMISCOFF_REQ: return ("DL_PROMISCOFF_REQ");
case DL_UNITDATA_REQ: return ("DL_UNITDATA_REQ");
case DL_UNITDATA_IND: return ("DL_UNITDATA_IND");
case DL_UDERROR_IND: return ("DL_UDERROR_IND");
case DL_PHYS_ADDR_REQ: return ("DL_PHYS_ADDR_REQ");
case DL_PHYS_ADDR_ACK: return ("DL_PHYS_ADDR_ACK");
case DL_SET_PHYS_ADDR_REQ: return ("DL_SET_PHYS_ADDR_REQ");
case DL_NOTIFY_REQ: return ("DL_NOTIFY_REQ");
case DL_NOTIFY_ACK: return ("DL_NOTIFY_ACK");
case DL_NOTIFY_IND: return ("DL_NOTIFY_IND");
case DL_CAPABILITY_REQ: return ("DL_CAPABILITY_REQ");
case DL_CAPABILITY_ACK: return ("DL_CAPABILITY_ACK");
case DL_CONTROL_REQ: return ("DL_CONTROL_REQ");
case DL_CONTROL_ACK: return ("DL_CONTROL_ACK");
case DL_PASSIVE_REQ: return ("DL_PASSIVE_REQ");
default: return (NULL);
}
}