1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 /* 27 * Tracking of kernel module loads and unloads 28 */ 29 30 #include <kmdb/kmdb_kdi.h> 31 #include <kmdb/kctl/kctl.h> 32 #include <sys/kobj.h> 33 #include <sys/kobj_impl.h> 34 #include <sys/ctf_api.h> 35 36 static kobj_notify_list_t kctl_mod_notifiers[] = { 37 { kctl_mod_changed, KOBJ_NOTIFY_MODLOADED }, 38 { kctl_mod_changed, KOBJ_NOTIFY_MODUNLOADING }, 39 { NULL, 0 } 40 }; 41 42 int 43 kctl_mod_decompress(struct modctl *modp) 44 { 45 ctf_file_t *fp; 46 struct module *mp = modp->mod_mp; 47 int rc; 48 49 if ((kmdb_kdi_get_flags() & KMDB_KDI_FL_NOCTF) || mp->ctfdata == NULL) 50 return (0); 51 52 if ((fp = ctf_modopen(mp, &rc)) == NULL) 53 return (rc); 54 55 ctf_close(fp); 56 57 return (0); 58 } 59 60 void 61 kctl_mod_loaded(struct modctl *modp) 62 { 63 int rc; 64 65 mutex_enter(&mod_lock); 66 if (modp->mod_mp == NULL) { 67 mutex_exit(&mod_lock); 68 return; 69 } 70 71 if ((rc = kctl_mod_decompress(modp)) != 0) { 72 cmn_err(CE_WARN, "failed to decompress CTF data for %s: %s\n", 73 modp->mod_modname, ctf_errmsg(rc)); 74 } 75 mutex_exit(&mod_lock); 76 77 if (!(kmdb_kdi_get_flags() & KMDB_KDI_FL_NOMODS)) 78 kctl_dmod_autoload(modp->mod_modname); 79 } 80 81 /*ARGSUSED*/ 82 void 83 kctl_mod_changed(uint_t why, struct modctl *what) 84 { 85 if (why == KOBJ_NOTIFY_MODLOADED) 86 kctl_mod_loaded(what); 87 } 88 89 /* 90 * Tell krtld to notify kmdb when modules have been loaded and unloaded 91 */ 92 void 93 kctl_mod_notify_reg(void) 94 { 95 kobj_notify_list_t *kn; 96 97 for (kn = kctl_mod_notifiers; kn->kn_func != NULL; kn++) 98 (void) kobj_notify_add(kn); 99 } 100 101 void 102 kctl_mod_notify_unreg(void) 103 { 104 kobj_notify_list_t *kn; 105 106 for (kn = kctl_mod_notifiers; kn->kn_func != NULL; kn++) 107 (void) kobj_notify_remove(kn); 108 } 109