int kt_lookup_by_name(mdb_tgt_t *t, const char *obj, const char *name, GElf_Sym *symp, mdb_syminfo_t *sip) { kt_data_t *kt = t->t_data; kt_module_t *km, kmod; mdb_var_t *v; int n; /* * To simplify the implementation, we create a fake module on the stack * which is "prepended" to k_modlist and whose symtab is kt->k_symtab. */ kmod.km_symtab = kt->k_symtab; kmod.km_list.ml_next = mdb_list_next(&kt->k_modlist); switch ((uintptr_t)obj) { case (uintptr_t)MDB_TGT_OBJ_EXEC: km = &kmod; n = 1; break; case (uintptr_t)MDB_TGT_OBJ_EVERY: km = &kmod; n = mdb_nv_size(&kt->k_modules) + 1; break; case (uintptr_t)MDB_TGT_OBJ_RTLD: obj = KT_RTLD_NAME; /*FALLTHRU*/ default: if ((v = mdb_nv_lookup(&kt->k_modules, obj)) == NULL) return (set_errno(EMDB_NOOBJ)); km = mdb_nv_get_cookie(v); n = 1; if (km->km_symtab == NULL) kt_load_module(kt, t, km); } for (; n > 0; n--, km = mdb_list_next(km)) { if (mdb_gelf_symtab_lookup_by_name(km->km_symtab, name, symp, &sip->sym_id) == 0) { sip->sym_table = MDB_TGT_SYMTAB; return (0); } } return (set_errno(EMDB_NOSYM)); }
/* * Call the current frame's mdb command. This entry point is used by the * MDB parser to actually execute a command once it has successfully parsed * a line of input. The command is waiting for us in the current frame. * We loop through each command on the list, executing its dcmd with the * appropriate argument. If the command has a successor, we know it had * a | operator after it, and so we need to create a pipe and replace * stdout with the pipe's output buffer. */ int mdb_call(uintmax_t addr, uintmax_t count, uint_t flags) { mdb_frame_t *fp = mdb.m_frame; mdb_cmd_t *cp, *ncp; mdb_iob_t *iobs[2]; int status, err = 0; jmp_buf pcb; if (mdb_iob_isapipe(mdb.m_in)) yyerror("syntax error"); mdb_intr_disable(); fp->f_cp = mdb_list_next(&fp->f_cmds); if (flags & DCMD_LOOP) flags |= DCMD_LOOPFIRST; /* set LOOPFIRST if this is a loop */ for (cp = mdb_list_next(&fp->f_cmds); cp; cp = mdb_list_next(cp)) { if (mdb_list_next(cp) != NULL) { mdb_iob_pipe(iobs, rdsvc, wrsvc); mdb_iob_stack_push(&fp->f_istk, mdb.m_in, yylineno); mdb.m_in = iobs[MDB_IOB_RDIOB]; mdb_iob_stack_push(&fp->f_ostk, mdb.m_out, 0); mdb.m_out = iobs[MDB_IOB_WRIOB]; ncp = mdb_list_next(cp); mdb_vcb_inherit(cp, ncp); bcopy(fp->f_pcb, pcb, sizeof (jmp_buf)); ASSERT(fp->f_pcmd == NULL); fp->f_pcmd = ncp; mdb_frame_set_pipe(fp); if ((err = setjmp(fp->f_pcb)) == 0) { status = mdb_call_idcmd(cp->c_dcmd, addr, count, flags | DCMD_PIPE_OUT, &cp->c_argv, &cp->c_addrv, cp->c_vcbs); ASSERT(mdb.m_in == iobs[MDB_IOB_RDIOB]); ASSERT(mdb.m_out == iobs[MDB_IOB_WRIOB]); } else { mdb_dprintf(MDB_DBG_DSTK, "frame <%u> caught " "error %s from pipeline\n", fp->f_id, mdb_err2str(err)); } if (err != 0 || DCMD_ABORTED(status)) { mdb_iob_setflags(mdb.m_in, MDB_IOB_ERR); mdb_iob_setflags(mdb.m_out, MDB_IOB_ERR); } else { mdb_iob_flush(mdb.m_out); (void) mdb_iob_ctl(mdb.m_out, I_FLUSH, (void *)FLUSHW); } mdb_frame_clear_pipe(fp); mdb_iob_destroy(mdb.m_out); mdb.m_out = mdb_iob_stack_pop(&fp->f_ostk); if (mdb.m_in != NULL) mdb_iob_destroy(mdb.m_in); mdb.m_in = mdb_iob_stack_pop(&fp->f_istk); yylineno = mdb_iob_lineno(mdb.m_in); fp->f_pcmd = NULL; bcopy(pcb, fp->f_pcb, sizeof (jmp_buf)); if (MDB_ERR_IS_FATAL(err)) longjmp(fp->f_pcb, err); if (err != 0 || DCMD_ABORTED(status) || mdb_addrvec_length(&ncp->c_addrv) == 0) break; addr = mdb_nv_get_value(mdb.m_dot); count = 1; flags = 0; } else { mdb_intr_enable(); (void) mdb_call_idcmd(cp->c_dcmd, addr, count, flags, &cp->c_argv, &cp->c_addrv, cp->c_vcbs); mdb_intr_disable(); } fp->f_cp = mdb_list_next(cp); mdb_cmd_reset(cp); } /* * If our last-command list is non-empty, destroy it. Then copy the * current frame's cmd list to the m_lastc list and reset the frame. */ while ((cp = mdb_list_next(&mdb.m_lastc)) != NULL) { mdb_list_delete(&mdb.m_lastc, cp); mdb_cmd_destroy(cp); } mdb_list_move(&fp->f_cmds, &mdb.m_lastc); mdb_frame_reset(fp); mdb_intr_enable(); return (err == 0); }
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); }