Ejemplo n.º 1
0
/*ARGSUSED*/
static int
dt_opt_cpp_path(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
{
	char *cpp;

	if (arg == NULL)
		return (dt_set_errno(dtp, EDT_BADOPTVAL));

	if (dtp->dt_pcb != NULL)
		return (dt_set_errno(dtp, EDT_BADOPTCTX));

	if ((cpp = strdup(arg)) == NULL)
		return (dt_set_errno(dtp, EDT_NOMEM));

#if defined(__APPLE__)
	// We use the full path to cpp
	dtp->dt_cpp_argv[0] = cpp;
#else
	dtp->dt_cpp_argv[0] = (char *)strbasename(cpp);
#endif
	free(dtp->dt_cpp_path);
	dtp->dt_cpp_path = cpp;

	return (0);
}
Ejemplo n.º 2
0
/*
 * Sends a request to the driver to load the module.  If/when the load has
 * completed successfully, kmdb_module_loaded is called.
 */
int
mdb_module_load(const char *fname, int mode)
{
    const char *modname = strbasename(fname);
    kmdb_wr_load_t *dlr;
    kmdb_modctl_t *kmc = NULL;
    const char *wformat = NULL;
    mdb_var_t *v;

    if (!mdb_module_validate_name(modname, &wformat))
        goto module_load_err;

    if ((v = mdb_nv_lookup(&mdb.m_dmodctl, modname)) != NULL) {
        kmc = MDB_NV_COOKIE(v);

        if (kmc->kmc_state == KMDB_MC_STATE_LOADING)
            wformat = "module %s is already being loaded\n";
        else
            wformat = "module %s is being unloaded\n";
        goto module_load_err;
    }

    kmc = mdb_zalloc(sizeof (kmdb_modctl_t), UM_SLEEP);
    kmc->kmc_loadmode = mode;
    kmc->kmc_modname = strdup(modname);
    kmc->kmc_state = KMDB_MC_STATE_LOADING;

    if (mdb_nv_insert(&mdb.m_dmodctl, modname, NULL, (uintptr_t)kmc, 0) ==
            NULL) {
        wformat = "module %s can't be registered for load\n";
        kmc_free(kmc);
        goto module_load_err;
    }

    dlr = mdb_zalloc(sizeof (kmdb_wr_load_t), UM_SLEEP);
    dlr->dlr_node.wn_task = WNTASK_DMOD_LOAD;
    dlr->dlr_fname = strdup(fname);

    kmdb_wr_driver_notify(dlr);

    if (!(mode & MDB_MOD_DEFER) &&
            mdb_tgt_continue(mdb.m_target, NULL) == 0)
        return (0);

    if (!(mode & MDB_MOD_SILENT))
        mdb_printf("%s load pending (:c to complete)\n", modname);

    return (0);

module_load_err:
    if (!(mode & MDB_MOD_SILENT))
        warn(wformat, modname);

    return (-1);
}
Ejemplo n.º 3
0
static void
print_frame(uintptr_t pc, int fnum)
{
	Dl_info dli;

	if (dladdr((void *)pc, &dli)) {
		mdb_iob_printf(mdb.m_err, "    [%d] %s`%s+0x%lx()\n", fnum,
		    strbasename(dli.dli_fname), dli.dli_sname,
		    pc - (uintptr_t)dli.dli_saddr);
	} else
		mdb_iob_printf(mdb.m_err, "    [%d] %p()\n", fnum, pc);
}
Ejemplo n.º 4
0
static kp_file_t *
kp_file_create(mdb_tgt_t *t, kp_map_t *kpm, GElf_Half etype)
{
	kp_file_t *kpf = mdb_zalloc(sizeof (kp_file_t), UM_SLEEP);
	kp_data_t *kp = t->t_data;
	size_t dyns_sz;
	void *dyns;

	kpf->kpf_fio = kp_io_create(t, kpm);
	kpf->kpf_map = kpm;
	kpf->kpf_basename = strbasename(kpm->kpm_map.map_name);
	kpf->kpf_file = mdb_gelf_create(kpf->kpf_fio, etype, GF_PROGRAM);
	kpf->kpf_text_base = kpm->kpm_map.map_base;

	if (kpm != kp->kp_map_exec)
		kpf->kpf_dyn_base = kpf->kpf_text_base;

	if (kpf->kpf_file == NULL)
		goto err; /* Failed to create ELF file */

	mdb_dprintf(MDB_DBG_TGT, "loading symbols for %s\n",
	    kpm->kpm_map.map_name);

	if ((kp->kp_rap != NULL) && (rd_get_dyns(kp->kp_rap,
	    kpf->kpf_text_base, &dyns, &dyns_sz) == RD_OK))
		mdb_gelf_dyns_set(kpf->kpf_file, dyns, dyns_sz);

	kpf->kpf_dynsym = mdb_gelf_symtab_create_dynamic(kpf->kpf_file,
	    MDB_TGT_DYNSYM);

	if (kpf->kpf_dynsym == NULL)
		goto err; /* Failed to create symbol table */

	kpm->kpm_file = kpf;

	if (kp->kp_file_tail != NULL)
		kp->kp_file_tail->kpf_next = kpf;
	else
		kp->kp_file_head = kpf;

	kp->kp_file_tail = kpf;
	kp->kp_num_files++;

	return (kpf);

err:
	if (kpf->kpf_file != NULL)
		mdb_gelf_destroy(kpf->kpf_file);
	else
		mdb_io_destroy(kpf->kpf_fio);
	mdb_free(kpf, sizeof (kp_file_t));
	return (NULL);
}
Ejemplo n.º 5
0
static int
kp_iter_mapping(const rd_loadobj_t *rlp, mdb_tgt_t *t)
{
	kp_data_t *kp = t->t_data;
	kp_file_t *kpf;
	kp_map_t *kpm;

	char name[MDB_TGT_MAPSZ];

	if (mdb_tgt_readstr(t, MDB_TGT_AS_VIRT, name,
	    sizeof (name), (mdb_tgt_addr_t)rlp->rl_nameaddr) <= 0) {
		mdb_dprintf(MDB_DBG_TGT, "failed to read name %p",
		    (void *)rlp->rl_nameaddr);
		return (1); /* Keep going; forget this if we can't read name */
	}

	mdb_dprintf(MDB_DBG_TGT, "rd_loadobj name = \"%s\" rl_base = %p\n",
	    name, (void *)rlp->rl_base);

	if ((kpm = kp_addr_to_kpmap(kp, rlp->rl_base)) == NULL)
		return (1); /* Keep going; no mapping at this address */

	(void) strncpy(kpm->kpm_map.map_name, name, MDB_TGT_MAPSZ);
	kpm->kpm_map.map_name[MDB_TGT_MAPSZ - 1] = '\0';

	if ((kpf = kpm->kpm_file) == NULL) {
		if (kpm == kp->kp_map_exec)
			kpf = kp_file_create(t, kpm, ET_EXEC);
		else
			kpf = kp_file_create(t, kpm, ET_DYN);

		if (kpf == NULL)
			return (1); /* Keep going; failed to build ELF file */
	} else
		kpf->kpf_basename = strbasename(kpm->kpm_map.map_name);

	if ((kpm = kp_find_data(kp, kpf, rlp)) != NULL) {
		mdb_dprintf(MDB_DBG_TGT, "found data for %s at %p\n",
		    kpf->kpf_basename, (void *)kpm->kpm_map.map_base);
		kpm->kpm_file = kpf;
	}

	return (1);
}
Ejemplo n.º 6
0
/*ARGSUSED*/
static int
dt_opt_cpp_path(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
{
	char *cpp;

	if (arg == NULL)
		return (dt_set_errno(dtp, EDT_BADOPTVAL));

	if (dtp->dt_pcb != NULL)
		return (dt_set_errno(dtp, EDT_BADOPTCTX));

	if ((cpp = strdup(arg)) == NULL)
		return (dt_set_errno(dtp, EDT_NOMEM));

	dtp->dt_cpp_argv[0] = (char *)strbasename(cpp);
	free(dtp->dt_cpp_path);
	dtp->dt_cpp_path = cpp;

	return (0);
}
Ejemplo n.º 7
0
void
mdb_create(const char *execname, const char *arg0)
{
	static const mdb_nv_disc_t psym_disc = { psym_disc_set, psym_disc_get };
	static const mdb_nv_disc_t roff_disc = { roff_disc_set, roff_disc_get };
	static const mdb_nv_disc_t thr_disc = { NULL, thr_disc_get };

	static char rootdir[MAXPATHLEN];

	const mdb_dcmd_t *dcp;
	int i;

	bzero(&mdb, sizeof (mdb_t));

	mdb.m_flags = MDB_FL_PSYM | MDB_FL_PAGER | MDB_FL_BPTNOSYMSTOP |
	    MDB_FL_READBACK;
	mdb.m_radix = MDB_DEF_RADIX;
	mdb.m_nargs = MDB_DEF_NARGS;
	mdb.m_histlen = MDB_DEF_HISTLEN;
	mdb.m_armemlim = MDB_DEF_ARRMEM;
	mdb.m_arstrlim = MDB_DEF_ARRSTR;

	mdb.m_pname = strbasename(arg0);
	if (strcmp(mdb.m_pname, "adb") == 0) {
		mdb.m_flags |= MDB_FL_NOMODS | MDB_FL_ADB | MDB_FL_REPLAST;
		mdb.m_flags &= ~MDB_FL_PAGER;
	}

	mdb.m_ipathstr = mdb_zalloc(MAXPATHLEN, UM_SLEEP);
	mdb.m_lpathstr = mdb_zalloc(MAXPATHLEN, UM_SLEEP);

	(void) strncpy(rootdir, execname, sizeof (rootdir));
	rootdir[sizeof (rootdir) - 1] = '\0';
	(void) strdirname(rootdir);

	if (strcmp(strbasename(rootdir), "sparcv9") == 0 ||
	    strcmp(strbasename(rootdir), "sparcv7") == 0 ||
	    strcmp(strbasename(rootdir), "amd64") == 0 ||
	    strcmp(strbasename(rootdir), "i86") == 0)
		(void) strdirname(rootdir);

	if (strcmp(strbasename(rootdir), "bin") == 0) {
		(void) strdirname(rootdir);
		if (strcmp(strbasename(rootdir), "usr") == 0)
			(void) strdirname(rootdir);
	} else
		(void) strcpy(rootdir, "/");

	mdb.m_root = rootdir;

	mdb.m_rminfo.mi_dvers = MDB_API_VERSION;
	mdb.m_rminfo.mi_dcmds = mdb_dcmd_builtins;
	mdb.m_rminfo.mi_walkers = NULL;

	(void) mdb_nv_create(&mdb.m_rmod.mod_walkers, UM_SLEEP);
	(void) mdb_nv_create(&mdb.m_rmod.mod_dcmds, UM_SLEEP);

	mdb.m_rmod.mod_name = mdb.m_pname;
	mdb.m_rmod.mod_info = &mdb.m_rminfo;

	(void) mdb_nv_create(&mdb.m_disasms, UM_SLEEP);
	(void) mdb_nv_create(&mdb.m_modules, UM_SLEEP);
	(void) mdb_nv_create(&mdb.m_dcmds, UM_SLEEP);
	(void) mdb_nv_create(&mdb.m_walkers, UM_SLEEP);
	(void) mdb_nv_create(&mdb.m_nv, UM_SLEEP);

	mdb.m_dot = mdb_nv_insert(&mdb.m_nv, ".", NULL, 0, MDB_NV_PERSIST);
	mdb.m_rvalue = mdb_nv_insert(&mdb.m_nv, "0", NULL, 0, MDB_NV_PERSIST);

	mdb.m_roffset =
	    mdb_nv_insert(&mdb.m_nv, "1", &roff_disc, 0, MDB_NV_PERSIST);

	mdb.m_proffset = mdb_nv_insert(&mdb.m_nv, "2", NULL, 0, MDB_NV_PERSIST);
	mdb.m_rcount = mdb_nv_insert(&mdb.m_nv, "9", NULL, 0, MDB_NV_PERSIST);

	(void) mdb_nv_insert(&mdb.m_nv, "b", NULL, 0, MDB_NV_PERSIST);
	(void) mdb_nv_insert(&mdb.m_nv, "d", NULL, 0, MDB_NV_PERSIST);
	(void) mdb_nv_insert(&mdb.m_nv, "e", NULL, 0, MDB_NV_PERSIST);
	(void) mdb_nv_insert(&mdb.m_nv, "m", NULL, 0, MDB_NV_PERSIST);
	(void) mdb_nv_insert(&mdb.m_nv, "t", NULL, 0, MDB_NV_PERSIST);
	(void) mdb_nv_insert(&mdb.m_nv, "_", &psym_disc, 0, MDB_NV_PERSIST);
	(void) mdb_nv_insert(&mdb.m_nv, "hits", NULL, 0, MDB_NV_PERSIST);

	(void) mdb_nv_insert(&mdb.m_nv, "thread", &thr_disc, 0,
	    MDB_NV_PERSIST | MDB_NV_RDONLY);

	mdb.m_prsym = mdb_gelf_symtab_create_mutable();

	(void) mdb_nv_insert(&mdb.m_modules, mdb.m_pname, NULL,
	    (uintptr_t)&mdb.m_rmod, MDB_NV_RDONLY);

	for (dcp = &mdb_dcmd_builtins[0]; dcp->dc_name != NULL; dcp++)
		(void) mdb_module_add_dcmd(&mdb.m_rmod, dcp, 0);

	for (i = 0; mdb_dis_builtins[i] != NULL; i++)
		(void) mdb_dis_create(mdb_dis_builtins[i]);

	mdb_macalias_create();

	mdb_create_builtin_tgts();

	(void) mdb_callb_add(NULL, MDB_CALLB_PROMPT, (mdb_callb_f)prompt_update,
	    NULL);

#ifdef _KMDB
	(void) mdb_nv_create(&mdb.m_dmodctl, UM_SLEEP);
#endif
	mdb_lex_state_create(&frame0);

	mdb_list_append(&mdb.m_flist, &frame0);
	mdb.m_frame = &frame0;
}
Ejemplo n.º 8
0
/*ARGSUSED*/
int
mdb_module_unload(const char *name, int mode)
{
    kmdb_modctl_t *kmc = NULL;
    const char *basename;
    mdb_var_t *v;

    /*
     * We may have been called with the name from the module itself
     * if the caller is iterating through the module list, so we need
     * to make a copy of the name.  If we don't, we can't use it after
     * the call to unload_common(), which frees the module.
     */
    name = strdup(name);
    basename = strbasename(name);

    /*
     * Make sure the module is in the proper state for unloading.  Modules
     * may only be unloaded if they have properly completed loading.
     */
    if ((v = mdb_nv_lookup(&mdb.m_dmodctl, basename)) != NULL) {
        kmc = MDB_NV_COOKIE(v);
        switch (kmc->kmc_state) {
        case KMDB_MC_STATE_LOADING:
            warn("%s is in the process of loading\n", basename);
            return (set_errno(EMDB_NOMOD));
        case KMDB_MC_STATE_UNLOADING:
            warn("%s is already being unloaded\n", basename);
            return (set_errno(EMDB_NOMOD));
        default:
            ASSERT(kmc->kmc_state == KMDB_MC_STATE_LOADED);
        }

        if (kmc->kmc_flags & KMDB_MC_FL_NOUNLOAD)
            return (set_errno(EMDB_KMODNOUNLOAD));
    }

    if (mdb_module_unload_common(name) < 0) {
        if (!(mode & MDB_MOD_SILENT)) {
            mdb_dprintf(MDB_DBG_MODULE, "unload of %s failed\n",
                        name);
        }
        return (-1); /* errno is set for us */
    }

    /*
     * Any modules legitimately not listed in dmodctl (builtins, for
     * example) will be handled by mdb_module_unload_common.  If any of
     * them get here, we've got a problem.
     */
    if (v == NULL) {
        warn("unload of unregistered module %s\n", basename);
        return (set_errno(EMDB_NOMOD));
    }

    ASSERT(kmc->kmc_dlrefcnt == 0);

    mdb_gelf_symtab_destroy(kmc->kmc_symtab);

    kmdb_module_request_unload(kmc, basename, mode);
    return (0);
}
Ejemplo n.º 9
0
int
kmdb_module_loaded(kmdb_wr_load_t *dlr)
{
    struct modctl *modp = dlr->dlr_modctl;
    const char *modname = strbasename(dlr->dlr_fname);
    struct module *mp;
    kmdb_modctl_t *kmc;
    mdb_var_t *v;

    v = mdb_nv_lookup(&mdb.m_dmodctl, modname);

    if (dlr->dlr_errno != 0) {
        /*
         * We're somewhat limited in the diagnostics that we can
         * provide in the event of a failed load.  In most load-failure
         * cases, the driver can only send up a generic errno.  We use
         * EMDB_ENOMOD to signal generic errors, and supply our own
         * message.  This twists the meaning of EMDB_NOMOD somewhat, but
         * it's better than defining a new one.
         */
        if (dlr->dlr_errno == EMDB_NOMOD) {
            mdb_warn("%s does not appear to be a kmdb dmod\n",
                     modname);
        } else {
            (void) set_errno(dlr->dlr_errno);
            mdb_warn("dmod %s failed to load", modname);
        }

        if (v != NULL)
            mdb_nv_remove(&mdb.m_dmodctl, v);
        return (0);
    }

    if ((mp = modp->mod_mp) == NULL || mp->symhdr == NULL ||
            mp->strhdr == NULL || mp->symtbl == NULL || mp->strings == NULL) {
        mdb_warn("dmod %s did not load properly\n");
        goto module_loaded_err;
    }

    if ((v = mdb_nv_lookup(&mdb.m_dmodctl, modname)) == NULL) {
        kmc = mdb_zalloc(sizeof (kmdb_modctl_t), UM_SLEEP);
        kmc->kmc_loadmode = MDB_MOD_LOCAL;
        kmc->kmc_modname = strdup(modname);
        kmc->kmc_state = KMDB_MC_STATE_LOADING;

        (void) mdb_nv_insert(&mdb.m_dmodctl, modname, NULL,
                             (uintptr_t)kmc, 0);
    } else {
        kmc = MDB_NV_COOKIE(v);
        ASSERT(kmc->kmc_symtab == NULL);
    }

    kmc->kmc_modctl = modp;
    kmc->kmc_exported = (mp->flags & KOBJ_EXPORTED) != 0;
    mdb_gelf_ehdr_to_gehdr(&mp->hdr, &kmc->kmc_ehdr);

    kmc->kmc_symtab = mdb_gelf_symtab_create_raw(&kmc->kmc_ehdr, mp->symhdr,
                      mp->symtbl, mp->strhdr, mp->strings,
                      MDB_TGT_SYMTAB);

    if (mp->flags & KOBJ_PRIM)
        kmc->kmc_flags |= KMDB_MC_FL_NOUNLOAD;

    if (mdb_module_create(modname, modp->mod_filename,
                          kmc->kmc_loadmode, &kmc->kmc_mod) < 0)
        goto module_loaded_err;

    kmc->kmc_state = KMDB_MC_STATE_LOADED;

    return (1);

module_loaded_err:
    if (kmc->kmc_symtab != NULL)
        mdb_gelf_symtab_destroy(kmc->kmc_symtab);

    kmdb_module_request_unload(kmc, kmc->kmc_modname, MDB_MOD_DEFER);
    return (0);
}
Ejemplo n.º 10
0
static int
kmdb_dbgnotify_cb(kmdb_wr_t *wn, void *arg)
{
	work_results_t *res = arg;

	switch (WR_TASK(wn)) {
	case WNTASK_DMOD_LOAD: {
		/*
		 * If this is an ack, the driver finished processing a load we
		 * requested.  We process it and free the message.  If this
		 * isn't an ack, then it's a driver-initiated load.  We process
		 * the message, and send it back as an ack so the driver can
		 * free it.
		 */
		kmdb_wr_load_t *dlr = (kmdb_wr_load_t *)wn;

		mdb_dprintf(MDB_DBG_DPI, "received module load message\n");

		if (kmdb_module_loaded(dlr) && res != NULL) {
			(void) mdb_nv_insert(&res->res_loads,
			    strbasename(dlr->dlr_fname), NULL, 0, 0);
		}

		if (WR_ISACK(dlr)) {
			kmdb_module_load_ack(dlr);
			return (0);
		}

		/* Send it back as an ack */
		mdb_dprintf(MDB_DBG_DPI, "Sending load request for %s back "
		    "as an ack\n", dlr->dlr_fname);
		WR_ACK(wn);
		kmdb_wr_driver_notify(wn);
		return (0);
	}

	case WNTASK_DMOD_LOAD_ALL:
		/*
		 * We initiated the load-all, so this must be an ack.  The
		 * individual module load messages will arrive separately -
		 * there's no need to do anything further with this message.
		 */
		ASSERT(WR_ISACK(wn));

		mdb_dprintf(MDB_DBG_DPI, "received module load all ack\n");

		kmdb_module_load_all_ack(wn);
		return (0);

	case WNTASK_DMOD_UNLOAD: {
		/*
		 * The debugger received an unload message.  The driver isn't
		 * supposed to initiate unloads, so we shouldn't see anything
		 * but acks.  We tell the dmod subsystem that the module has
		 * been unloaded, and we free the message.
		 */
		kmdb_wr_unload_t *dur = (kmdb_wr_unload_t *)wn;

		ASSERT(WR_ISACK(dur));

		mdb_dprintf(MDB_DBG_DPI, "received module unload ack\n");

		if (kmdb_module_unloaded(dur) && res != NULL) {
			(void) mdb_nv_insert(&res->res_unloads,
			    dur->dur_modname, NULL, 0, 0);
		}

		/* Done with message */
		kmdb_module_unload_ack(dur);
		return (0);
	}

	case WNTASK_DMOD_PATH_CHANGE: {
		/*
		 * The debugger received a path change message.  The driver
		 * can't initiate these, so it must be an acknowledgement.
		 * There's no processing to be done, so just free the message.
		 */
		kmdb_wr_path_t *dpth = (kmdb_wr_path_t *)wn;

		ASSERT(WR_ISACK(dpth));

		mdb_dprintf(MDB_DBG_DPI, "received path change ack\n");

		kmdb_module_path_ack(dpth);
		return (0);
	}

	default:
		mdb_warn("Received unknown message type %d from driver\n",
		    wn->wn_task);
		/* Ignore it */
		return (0);
	}
}