Пример #1
0
int
mdb_ctf_module_lookup(const char *name, mdb_ctf_id_t *p)
{
	ctf_file_t *fp;
	ctf_id_t id;
	mdb_module_t *mod;

	if ((mod = mdb_get_module()) == NULL)
		return (set_errno(EMDB_CTX));

	if ((fp = mod->mod_ctfp) == NULL)
		return (set_errno(EMDB_NOCTF));

	if ((id = ctf_lookup_by_name(fp, name)) == CTF_ERR)
		return (set_errno(ctf_to_errno(ctf_errno(fp))));

	set_ctf_id(p, fp, id);

	return (0);
}
Пример #2
0
RTR0DECL(int) RTR0DbgKrnlInfoQueryMember(RTDBGKRNLINFO hKrnlInfo, const char *pszStructure,
                                         const char *pszMember, size_t *poffMember)
{
    PRTDBGKRNLINFOINT pThis = hKrnlInfo;
    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
    AssertMsgReturn(pThis->u32Magic == RTDBGKRNLINFO_MAGIC, ("%p: u32Magic=%RX32\n", pThis, pThis->u32Magic), VERR_INVALID_HANDLE);
    AssertPtrReturn(pszMember, VERR_INVALID_PARAMETER);
    AssertPtrReturn(pszStructure, VERR_INVALID_PARAMETER);
    AssertPtrReturn(poffMember, VERR_INVALID_PARAMETER);
    RT_ASSERT_PREEMPTIBLE();

    int rc = VERR_NOT_FOUND;
    ctf_id_t TypeIdent = ctf_lookup_by_name(pThis->pGenUnixCTF, pszStructure);
    if (TypeIdent != CTF_ERR)
    {
        ctf_membinfo_t MemberInfo;
        RT_ZERO(MemberInfo);
        if (ctf_member_info(pThis->pGenUnixCTF, TypeIdent, pszMember, &MemberInfo) != CTF_ERR)
        {
            *poffMember = (MemberInfo.ctm_offset >> 3);
            return VINF_SUCCESS;
        }
RTR0DECL(int) RTR0DbgKrnlInfoQueryMember(RTDBGKRNLINFO hKrnlInfo, const char *pszModule, const char *pszStructure,
                                         const char *pszMember, size_t *poffMember)
{
    PRTDBGKRNLINFOINT pThis = hKrnlInfo;
    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
    AssertMsgReturn(pThis->u32Magic == RTDBGKRNLINFO_MAGIC, ("%p: u32Magic=%RX32\n", pThis, pThis->u32Magic), VERR_INVALID_HANDLE);
    AssertPtrReturn(pszMember, VERR_INVALID_PARAMETER);
    AssertPtrReturn(pszStructure, VERR_INVALID_PARAMETER);
    AssertPtrReturn(poffMember, VERR_INVALID_PARAMETER);
    if (g_frtSolInitDone)
        RT_ASSERT_PREEMPTIBLE();

    ctf_file_t *pCtf = NULL;
    modctl_t   *pMod = NULL;
    if (!pszModule)
    {
        pCtf = pThis->pGenUnixCTF;
        pMod = pThis->pGenUnixMod;
    }
    else
    {
        int rc2 = rtR0DbgKrnlInfoModRetainEx(pszModule, &pMod, &pCtf);
        if (RT_FAILURE(rc2))
            return rc2;
        Assert(pMod);
        Assert(pCtf);
    }

    int rc = VERR_NOT_FOUND;
    ctf_id_t TypeIdent = ctf_lookup_by_name(pCtf, pszStructure);
    if (TypeIdent != CTF_ERR)
    {
        ctf_membinfo_t MemberInfo;
        RT_ZERO(MemberInfo);
        if (ctf_member_info(pCtf, TypeIdent, pszMember, &MemberInfo) != CTF_ERR)
        {
            *poffMember = (MemberInfo.ctm_offset >> 3);
            rc = VINF_SUCCESS;
        }
Пример #4
0
/*ARGSUSED*/
static int
obj_lookup(void *data, const mdb_map_t *mp, const char *name)
{
	tnarg_t *tnp = data;
	ctf_file_t *fp;
	ctf_id_t id;

	if ((fp = mdb_tgt_name_to_ctf(tnp->tn_tgt, name)) != NULL &&
	    (id = ctf_lookup_by_name(fp, tnp->tn_name)) != CTF_ERR) {
		tnp->tn_fp = fp;
		tnp->tn_id = id;

		/*
		 * We may have found a forward declaration.  If we did, we'll
		 * note the ID and file pointer, but we'll keep searching in
		 * an attempt to find the real thing.  If we found something
		 * real (i.e. not a forward), we stop the iteration.
		 */
		return (ctf_type_kind(fp, id) == CTF_K_FORWARD ? 0 : -1);
	}

	return (0);
}
Пример #5
0
/*
 * Attempt to convert the given C type name into the corresponding CTF type ID.
 * It is not possible to do complete and proper conversion of type names
 * without implementing a more full-fledged parser, which is necessary to
 * handle things like types that are function pointers to functions that
 * have arguments that are function pointers, and fun stuff like that.
 * Instead, this function implements a very simple conversion algorithm that
 * finds the things that we actually care about: structs, unions, enums,
 * integers, floats, typedefs, and pointers to any of these named types.
 */
ctf_id_t
ctf_lookup_by_name(ctf_file_t *fp, const char *name)
{
	static const char delimiters[] = " \t\n\r\v\f*";

	const ctf_lookup_t *lp;
	const ctf_helem_t *hp;
	const char *p, *q, *end;
	ctf_id_t type = 0;
	ctf_id_t ntype, ptype;

	if (name == NULL)
		return (ctf_set_errno(fp, EINVAL));

	for (p = name, end = name + strlen(name); *p != '\0'; p = q) {
		while (isspace((unsigned char)*p))
			p++; /* skip leading ws */

		if (p == end)
			break;

		if ((q = strpbrk(p + 1, delimiters)) == NULL)
			q = end; /* compare until end */

		if (*p == '*') {
			/*
			 * Find a pointer to type by looking in fp->ctf_ptrtab.
			 * If we can't find a pointer to the given type, see if
			 * we can compute a pointer to the type resulting from
			 * resolving the type down to its base type and use
			 * that instead.  This helps with cases where the CTF
			 * data includes "struct foo *" but not "foo_t *" and
			 * the user tries to access "foo_t *" in the debugger.
			 */
			ntype = fp->ctf_ptrtab[CTF_TYPE_TO_INDEX(type)];
			if (ntype == 0) {
				ntype = ctf_type_resolve(fp, type);
				if (ntype == CTF_ERR || (ntype = fp->ctf_ptrtab[
				    CTF_TYPE_TO_INDEX(ntype)]) == 0) {
					(void) ctf_set_errno(fp, ECTF_NOTYPE);
					goto err;
				}
			}

			type = CTF_INDEX_TO_TYPE(ntype,
			    (fp->ctf_flags & LCTF_CHILD));

			q = p + 1;
			continue;
		}

		if (isqualifier(p, (size_t)(q - p)))
			continue; /* skip qualifier keyword */

		for (lp = fp->ctf_lookups; lp->ctl_prefix != NULL; lp++) {
			if (lp->ctl_prefix[0] == '\0' ||
			    strncmp(p, lp->ctl_prefix, (size_t)(q - p)) == 0) {
				for (p += lp->ctl_len; isspace((unsigned char)*p); p++)
					continue; /* skip prefix and next ws */

				if ((q = strchr(p, '*')) == NULL)
					q = end;  /* compare until end */

				while (isspace((unsigned char)q[-1]))
					q--;	  /* exclude trailing ws */

				if ((hp = ctf_hash_lookup(lp->ctl_hash, fp, p,
				    (size_t)(q - p))) == NULL) {
					(void) ctf_set_errno(fp, ECTF_NOTYPE);
					goto err;
				}

				type = hp->h_type;
				break;
			}
		}

		if (lp->ctl_prefix == NULL) {
			(void) ctf_set_errno(fp, ECTF_NOTYPE);
			goto err;
		}
	}

	if (*p != '\0' || type == 0)
		return (ctf_set_errno(fp, ECTF_SYNTAX));

	return (type);

err:
	if (fp->ctf_parent != NULL &&
	    (ptype = ctf_lookup_by_name(fp->ctf_parent, name)) != CTF_ERR)
		return (ptype);

	return (CTF_ERR);
}
Пример #6
0
int
dtrace_lookup_by_type(dtrace_hdl_t *dtp, const char *object, const char *name,
    dtrace_typeinfo_t *tip)
{
	dtrace_typeinfo_t ti;
	dt_module_t *dmp;
	int found = 0;
	ctf_id_t id;
	uint_t n, i;
	int justone;
	ctf_file_t *fp;
	char *buf, *p, *q;

	uint_t mask = 0; /* mask of dt_module flags to match */
	uint_t bits = 0; /* flag bits that must be present */

	if (object != DTRACE_OBJ_EVERY &&
	    object != DTRACE_OBJ_KMODS &&
	    object != DTRACE_OBJ_UMODS) {
		if ((dmp = dt_module_from_object(dtp, object)) == NULL)
			return (-1); /* dt_errno is set for us */

		if (dt_module_load(dtp, dmp) == -1)
			return (-1); /* dt_errno is set for us */
		n = 1;
		justone = 1;
	} else {
		if (object == DTRACE_OBJ_KMODS)
			mask = bits = DT_DM_KERNEL;
		else if (object == DTRACE_OBJ_UMODS)
			mask = DT_DM_KERNEL;

		dmp = dt_list_next(&dtp->dt_modlist);
		n = dtp->dt_nmods;
		justone = 0;
	}

	if (tip == NULL)
		tip = &ti;

	for (; n > 0; n--, dmp = dt_list_next(dmp)) {
		if ((dmp->dm_flags & mask) != bits)
			continue; /* failed to match required attributes */

		/*
		 * If we can't load the CTF container, continue on to the next
		 * module.  If our search was scoped to only one module then
		 * return immediately leaving dt_errno unmodified.
		 */
		if (dt_module_hasctf(dtp, dmp) == 0) {
			if (justone)
				return (-1);
			continue;
		}

		/*
		 * Look up the type in the module's CTF container.  If our
		 * match is a forward declaration tag, save this choice in
		 * 'tip' and keep going in the hope that we will locate the
		 * underlying structure definition.  Otherwise just return.
		 */
		if (dmp->dm_pid == 0) {
			id = ctf_lookup_by_name(dmp->dm_ctfp, name);
			fp = dmp->dm_ctfp;
		} else {
			if ((p = strchr(name, '`')) != NULL) {
				buf = strdup(name);
				if (buf == NULL)
					return (dt_set_errno(dtp, EDT_NOMEM));
				p = strchr(buf, '`');
				if ((q = strchr(p + 1, '`')) != NULL)
					p = q;
				*p = '\0';
				fp = dt_module_getctflib(dtp, dmp, buf);
				if (fp == NULL || (id = ctf_lookup_by_name(fp,
				    p + 1)) == CTF_ERR)
					id = CTF_ERR;
				free(buf);
			} else {
				for (i = 0; i < dmp->dm_nctflibs; i++) {
					fp = dmp->dm_libctfp[i];
					id = ctf_lookup_by_name(fp, name);
					if (id != CTF_ERR)
						break;
				}
			}
		}
		if (id != CTF_ERR) {
			tip->dtt_object = dmp->dm_name;
			tip->dtt_ctfp = fp;
			tip->dtt_type = id;
			if (ctf_type_kind(fp, ctf_type_resolve(fp, id)) !=
			    CTF_K_FORWARD)
				return (0);

			found++;
		}
	}

	if (found == 0)
		return (dt_set_errno(dtp, EDT_NOTYPE));

	return (0);
}
Пример #7
0
/*
 * Convert a string type name with an optional leading object specifier into
 * the corresponding CTF file container and type ID.  If an error occurs, we
 * print an appropriate message and return NULL.
 */
static ctf_file_t *
name_to_type(mdb_tgt_t *t, const char *cname, ctf_id_t *idp)
{
	const char *object = MDB_TGT_OBJ_EXEC;
	ctf_file_t *fp = NULL;
	ctf_id_t id;
	tnarg_t arg;
	char *p, *s;
	char buf[MDB_SYM_NAMLEN];
	char *name = &buf[0];

	(void) mdb_snprintf(buf, sizeof (buf), "%s", cname);

	if ((p = strrsplit(name, '`')) != NULL) {
		/*
		 * We need to shuffle things around a little to support
		 * type names of the form "struct module`name".
		 */
		if ((s = strsplit(name, ' ')) != NULL) {
			bcopy(cname + (s - name), name, (p - s) - 1);
			name[(p - s) - 1] = '\0';
			bcopy(cname, name + (p - s), s - name);
			p = name + (p - s);
		}
		if (*name != '\0')
			object = name;
		name = p;
	}

	/*
	 * Attempt to look up the name in the primary object file.  If this
	 * fails and the name was unscoped, search all remaining object files.
	 * Finally, search the synthetic types.
	 */
	if (((fp = mdb_tgt_name_to_ctf(t, object)) == NULL ||
	    (id = ctf_lookup_by_name(fp, name)) == CTF_ERR ||
	    ctf_type_kind(fp, id) == CTF_K_FORWARD) &&
	    object == MDB_TGT_OBJ_EXEC) {

		arg.tn_tgt = t;
		arg.tn_name = name;
		arg.tn_fp = NULL;
		arg.tn_id = CTF_ERR;

		(void) mdb_tgt_object_iter(t, obj_lookup, &arg);

		if (arg.tn_id != CTF_ERR) {
			fp = arg.tn_fp;
			id = arg.tn_id;
		} else if (mdb.m_synth != NULL) {
			if ((id = ctf_lookup_by_name(mdb.m_synth,
			    name)) != CTF_ERR)
				fp = mdb.m_synth;
		}
	}

	if (fp == NULL)
		return (NULL); /* errno is set for us */

	if (id == CTF_ERR) {
		(void) set_errno(ctf_to_errno(ctf_errno(fp)));
		return (NULL);
	}

	*idp = id;
	return (fp);
}