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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* 28 * Routines for manipulating the kmdb-specific aspects of dmods. 29 */ 30 31 #include <sys/param.h> 32 33 #include <mdb/mdb_target_impl.h> 34 #include <kmdb/kmdb_module.h> 35 #include <mdb/mdb_debug.h> 36 #include <mdb/mdb_err.h> 37 #include <mdb/mdb.h> 38 39 typedef struct kmod_symarg { 40 mdb_tgt_sym_f *sym_cb; /* Caller's callback function */ 41 void *sym_data; /* Callback function argument */ 42 uint_t sym_type; /* Symbol type/binding filter */ 43 mdb_syminfo_t sym_info; /* Symbol id and table id */ 44 const char *sym_obj; /* Containing object */ 45 } kmod_symarg_t; 46 47 void 48 kmdb_module_path_set(const char **path, size_t pathlen) 49 { 50 kmdb_wr_path_t *wr; 51 52 wr = mdb_zalloc(sizeof (kmdb_wr_path_t), UM_SLEEP); 53 wr->dpth_node.wn_task = WNTASK_DMOD_PATH_CHANGE; 54 wr->dpth_path = mdb_path_dup(path, pathlen, &wr->dpth_pathlen); 55 56 kmdb_wr_driver_notify(wr); 57 } 58 59 void 60 kmdb_module_path_ack(kmdb_wr_path_t *dpth) 61 { 62 if (dpth->dpth_path != NULL) 63 mdb_path_free(dpth->dpth_path, dpth->dpth_pathlen); 64 mdb_free(dpth, sizeof (kmdb_wr_path_t)); 65 } 66 67 static kmdb_modctl_t * 68 kmdb_module_lookup_loaded(const char *name) 69 { 70 kmdb_modctl_t *kmc; 71 mdb_var_t *v; 72 73 if ((v = mdb_nv_lookup(&mdb.m_dmodctl, name)) == NULL) 74 return (NULL); 75 76 kmc = MDB_NV_COOKIE(v); 77 if (kmc->kmc_state != KMDB_MC_STATE_LOADED) 78 return (NULL); 79 80 return (kmc); 81 } 82 83 /* 84 * Given an address, try to match it up with a dmod symbol. 85 */ 86 int 87 kmdb_module_lookup_by_addr(uintptr_t addr, uint_t flags, char *buf, 88 size_t nbytes, GElf_Sym *symp, mdb_syminfo_t *sip) 89 { 90 kmdb_modctl_t *sym_kmc = NULL; 91 GElf_Sym sym; 92 uint_t symid; 93 mdb_var_t *v; 94 const char *name; 95 96 mdb_nv_rewind(&mdb.m_dmodctl); 97 while ((v = mdb_nv_advance(&mdb.m_dmodctl)) != NULL) { 98 kmdb_modctl_t *kmc = MDB_NV_COOKIE(v); 99 100 if (kmc->kmc_state != KMDB_MC_STATE_LOADED) 101 continue; 102 103 if (mdb_gelf_symtab_lookup_by_addr(kmc->kmc_symtab, addr, flags, 104 buf, nbytes, symp, &sip->sym_id) != 0 || 105 symp->st_value == 0) 106 continue; 107 108 if (flags & MDB_TGT_SYM_EXACT) { 109 sym_kmc = kmc; 110 goto found; 111 } 112 113 /* 114 * If this is the first match we've found, or if this symbol is 115 * closer to the specified address than the last one we found, 116 * use it. 117 */ 118 if (sym_kmc == NULL || mdb_gelf_sym_closer(symp, &sym, addr)) { 119 sym_kmc = kmc; 120 sym = *symp; 121 symid = sip->sym_id; 122 } 123 } 124 125 if (sym_kmc == NULL) 126 return (set_errno(EMDB_NOSYMADDR)); 127 128 *symp = sym; 129 sip->sym_id = symid; 130 131 found: 132 /* 133 * Once we've found something, copy the final name into the caller's 134 * buffer, prefixed with a marker identifying this as a dmod symbol. 135 */ 136 if (buf != NULL) { 137 name = mdb_gelf_sym_name(sym_kmc->kmc_symtab, symp); 138 139 (void) mdb_snprintf(buf, nbytes, "DMOD`%s`%s", 140 sym_kmc->kmc_modname, name); 141 } 142 sip->sym_table = MDB_TGT_SYMTAB; 143 144 return (0); 145 } 146 147 /* 148 * Locate a given dmod symbol 149 */ 150 int 151 kmdb_module_lookup_by_name(const char *obj, const char *name, GElf_Sym *symp, 152 mdb_syminfo_t *sip) 153 { 154 kmdb_modctl_t *kmc; 155 156 if ((kmc = kmdb_module_lookup_loaded(obj)) == NULL) 157 return (set_errno(EMDB_NOSYMADDR)); 158 159 if (mdb_gelf_symtab_lookup_by_name(kmc->kmc_symtab, name, 160 symp, &sip->sym_id) == 0) { 161 sip->sym_table = MDB_TGT_SYMTAB; 162 return (0); 163 } 164 165 return (set_errno(EMDB_NOSYM)); 166 } 167 168 ctf_file_t * 169 kmdb_module_addr_to_ctf(uintptr_t addr) 170 { 171 mdb_var_t *v; 172 173 mdb_nv_rewind(&mdb.m_dmodctl); 174 while ((v = mdb_nv_advance(&mdb.m_dmodctl)) != NULL) { 175 kmdb_modctl_t *kmc = MDB_NV_COOKIE(v); 176 struct module *mp; 177 178 if (kmc->kmc_state != KMDB_MC_STATE_LOADED) 179 continue; 180 181 mp = kmc->kmc_modctl->mod_mp; 182 if (addr - (uintptr_t)mp->text < mp->text_size || 183 addr - (uintptr_t)mp->data < mp->data_size || 184 addr - mp->bss < mp->bss_size) { 185 ctf_file_t *ctfp = kmc->kmc_mod->mod_ctfp; 186 187 if (ctfp == NULL) { 188 (void) set_errno(EMDB_NOCTF); 189 return (NULL); 190 } 191 192 return (ctfp); 193 } 194 } 195 196 (void) set_errno(EMDB_NOMAP); 197 return (NULL); 198 } 199 200 ctf_file_t * 201 kmdb_module_name_to_ctf(const char *obj) 202 { 203 kmdb_modctl_t *kmc; 204 ctf_file_t *ctfp; 205 206 if ((kmc = kmdb_module_lookup_loaded(obj)) == NULL) { 207 (void) set_errno(EMDB_NOOBJ); 208 return (NULL); 209 } 210 211 if ((ctfp = kmc->kmc_mod->mod_ctfp) == NULL) { 212 (void) set_errno(EMDB_NOCTF); 213 return (NULL); 214 } 215 216 return (ctfp); 217 } 218 219 static int 220 kmdb_module_symtab_func(void *data, const GElf_Sym *sym, const char *name, 221 uint_t id) 222 { 223 kmod_symarg_t *arg = data; 224 225 if (mdb_tgt_sym_match(sym, arg->sym_type)) { 226 arg->sym_info.sym_id = id; 227 228 return (arg->sym_cb(arg->sym_data, sym, name, &arg->sym_info, 229 arg->sym_obj)); 230 } 231 232 return (0); 233 } 234 235 int 236 kmdb_module_symbol_iter(const char *obj, uint_t type, mdb_tgt_sym_f *cb, 237 void *p) 238 { 239 kmdb_modctl_t *kmc; 240 kmod_symarg_t arg; 241 mdb_var_t *v; 242 243 if ((v = mdb_nv_lookup(&mdb.m_dmodctl, obj)) == NULL) 244 return (set_errno(EMDB_NOMOD)); 245 246 kmc = MDB_NV_COOKIE(v); 247 248 if (kmc->kmc_state != KMDB_MC_STATE_LOADED) 249 return (set_errno(EMDB_NOMOD)); 250 251 arg.sym_cb = cb; 252 arg.sym_data = p; 253 arg.sym_type = type; 254 arg.sym_info.sym_table = kmc->kmc_symtab->gst_tabid; 255 arg.sym_obj = obj; 256 257 mdb_gelf_symtab_iter(kmc->kmc_symtab, kmdb_module_symtab_func, &arg); 258 259 return (0); 260 } 261