int kt_lookup_by_addr(mdb_tgt_t *t, uintptr_t addr, uint_t flags, char *buf, size_t nbytes, GElf_Sym *symp, mdb_syminfo_t *sip) { kt_data_t *kt = t->t_data; kt_module_t kmods[3], *kmods_begin = &kmods[0], *kmods_end; const char *name; kt_module_t *km = &kmods[0]; /* Point km at first fake module */ kt_module_t *sym_km = NULL; /* Module associated with best sym */ GElf_Sym sym; /* Best symbol found so far if !exact */ uint_t symid; /* ID of best symbol found so far */ /* * To simplify the implementation, we create fake modules on the stack * that are "prepended" to k_modlist and whose symtab is set to * each of three special symbol tables, in order of precedence. */ km->km_symtab = mdb.m_prsym; if (kt->k_symtab != NULL) { km->km_list.ml_next = (mdb_list_t *)(km + 1); km = mdb_list_next(km); km->km_symtab = kt->k_symtab; } if (kt->k_dynsym != NULL) { km->km_list.ml_next = (mdb_list_t *)(km + 1); km = mdb_list_next(km); km->km_symtab = kt->k_dynsym; } km->km_list.ml_next = mdb_list_next(&kt->k_modlist); kmods_end = km; /* * Now iterate over the list of fake and real modules. If the module * has no symbol table and the address is in the text section, * instantiate the module's symbol table. In exact mode, we can * jump to 'found' immediately if we match. Otherwise we continue * looking and improve our choice if we find a closer symbol. */ for (km = &kmods[0]; km != NULL; km = mdb_list_next(km)) { if (km->km_symtab == NULL && addr >= km->km_text_va && addr < km->km_text_va + km->km_text_size) kt_load_module(kt, t, km); if (mdb_gelf_symtab_lookup_by_addr(km->km_symtab, addr, flags, buf, nbytes, symp, &sip->sym_id) != 0 || symp->st_value == 0) continue; if (flags & MDB_TGT_SYM_EXACT) { sym_km = km; goto found; } if (sym_km == NULL || mdb_gelf_sym_closer(symp, &sym, addr)) { sym_km = km; sym = *symp; symid = sip->sym_id; } } if (sym_km == NULL) return (set_errno(EMDB_NOSYMADDR)); *symp = sym; /* Copy our best symbol into the caller's symbol */ sip->sym_id = symid; found: /* * Once we've found something, copy the final name into the caller's * buffer and prefix it with the load object name if appropriate. */ name = mdb_gelf_sym_name(sym_km->km_symtab, symp); if (sym_km < kmods_begin || sym_km > kmods_end) { (void) mdb_snprintf(buf, nbytes, "%s`%s", sym_km->km_name, name); } else if (nbytes > 0) { (void) strncpy(buf, name, nbytes); buf[nbytes - 1] = '\0'; } if (sym_km->km_symtab == mdb.m_prsym) sip->sym_table = MDB_TGT_PRVSYM; else sip->sym_table = MDB_TGT_SYMTAB; return (0); }
static int kp_lookup_by_addr(mdb_tgt_t *t, uintptr_t addr, uint_t flags, char *buf, size_t nbytes, GElf_Sym *symp, mdb_syminfo_t *sip) { kp_data_t *kp = t->t_data; kp_map_t *kpm = kp_addr_to_kpmap(kp, addr); kp_file_t *sym_kpf = NULL; GElf_Sym sym; uint_t symid; const char *name; kp_file_t *kpf; int n; /* * Check the user's private symbol table first; if a match is * found there, we're done or we have a first guess. */ if (mdb_gelf_symtab_lookup_by_addr(mdb.m_prsym, addr, flags, buf, nbytes, symp, &sip->sym_id) == 0) { sym_kpf = &kp->kp_prfile; if (flags & MDB_TGT_SYM_EXACT) goto found; sym = *symp; symid = sip->sym_id; } /* * If no mapping contains the address and EXACT mode is set, we're done. * Otherwise we need to search all the symbol tables in fuzzy mode. * If we find a mapping, then we only need to search that symtab. */ if (kpm == NULL || kpm->kpm_file == NULL) { if (flags & MDB_TGT_SYM_EXACT) return (set_errno(EMDB_NOSYMADDR)); kpf = kp->kp_file_head; n = kp->kp_num_files; } else { kpf = kpm->kpm_file; n = 1; } /* * Iterate through our list of load objects, scanning each one which * has a symbol table. In fuzzy mode, we continue looking and * improve our choice if we find a closer symbol. */ for (; n > 0; n--, kpf = kpf->kpf_next) { if (kpf->kpf_dynsym == NULL) continue; /* No symbols for this file */ if (mdb_gelf_symtab_lookup_by_addr(kpf->kpf_dynsym, addr - kpf->kpf_dyn_base, flags, buf, nbytes, symp, &sip->sym_id) != 0) continue; /* No symbol for this address */ symp->st_value += kpf->kpf_dyn_base; if (flags & MDB_TGT_SYM_EXACT) { sym_kpf = kpf; goto found; } if (sym_kpf == NULL || mdb_gelf_sym_closer(symp, &sym, addr)) { sym_kpf = kpf; sym = *symp; symid = sip->sym_id; } } if (sym_kpf == NULL) return (set_errno(EMDB_NOSYMADDR)); *symp = sym; /* Copy our best symbol into the caller's symbol */ sip->sym_id = symid; found: /* * Once we've found something, copy the final name into the caller's * buffer and prefix it with the load object name if appropriate. */ name = mdb_gelf_sym_name(sym_kpf->kpf_dynsym, symp); if (sym_kpf != kp->kp_map_exec->kpm_file && sym_kpf != &kp->kp_prfile) { (void) mdb_snprintf(buf, nbytes, "%s`%s", sym_kpf->kpf_basename, name); } else if (nbytes > 0) { (void) strncpy(buf, name, nbytes); buf[nbytes - 1] = '\0'; } if (sym_kpf == &kp->kp_prfile) sip->sym_table = MDB_TGT_PRVSYM; else sip->sym_table = MDB_TGT_DYNSYM; return (0); }