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); }
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; }
/*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); }
/* * 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); }
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); }
/* * 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); }