Exemplo n.º 1
0
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));
}
Exemplo n.º 2
0
/*
 * 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);
}
Exemplo n.º 3
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);
}