dt_provider_t * dt_provider_create(dtrace_hdl_t *dtp, const char *name) { dt_provider_t *pvp; if ((pvp = dt_zalloc(dtp, sizeof (dt_provider_t))) == NULL) return (NULL); (void) strlcpy(pvp->pv_desc.dtvd_name, name, DTRACE_PROVNAMELEN); pvp->pv_probes = dt_idhash_create(pvp->pv_desc.dtvd_name, NULL, 0, 0); pvp->pv_gen = dtp->dt_gen; pvp->pv_hdl = dtp; if (pvp->pv_probes == NULL) { dt_free(dtp, pvp); (void) dt_set_errno(dtp, EDT_NOMEM); return (NULL); } pvp->pv_desc.dtvd_attr.dtpa_provider = _dtrace_prvattr; pvp->pv_desc.dtvd_attr.dtpa_mod = _dtrace_prvattr; pvp->pv_desc.dtvd_attr.dtpa_func = _dtrace_prvattr; pvp->pv_desc.dtvd_attr.dtpa_name = _dtrace_prvattr; pvp->pv_desc.dtvd_attr.dtpa_args = _dtrace_prvattr; return (dt_provider_insert(dtp, pvp, dt_strtab_hash(name, NULL) % dtp->dt_provbuckets)); }
/* * The #pragma binding directive can be used to reset the version binding * on a global identifier or inline definition. If the identifier is already * defined, we can just change di_vers. If not, we insert the pragma into a * hash table of the current pcb's deferred pragmas for later processing. */ static void dt_pragma_binding(const char *prname, dt_node_t *dnp) { dtrace_hdl_t *dtp = yypcb->pcb_hdl; dt_version_t vers; const char *name; dt_ident_t *idp; if (dnp == NULL || dnp->dn_kind != DT_NODE_STRING || dnp->dn_list == NULL || dnp->dn_list->dn_kind != DT_NODE_IDENT) { xyerror(D_PRAGMA_MALFORM, "malformed #pragma %s " "\"version\" <ident>\n", prname); } if (dt_version_str2num(dnp->dn_string, &vers) == -1) { xyerror(D_PRAGMA_INVAL, "invalid version string " "specified by #pragma %s\n", prname); } name = dnp->dn_list->dn_string; idp = dt_idstack_lookup(&yypcb->pcb_globals, name); if (idp != NULL) { if (idp->di_gen != dtp->dt_gen) { xyerror(D_PRAGMA_SCOPE, "#pragma %s cannot modify " "entity defined outside program scope\n", prname); } idp->di_vers = vers; return; } if (yypcb->pcb_pragmas == NULL && (yypcb->pcb_pragmas = dt_idhash_create("pragma", NULL, 0, 0)) == NULL) longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM); idp = dt_idhash_insert(yypcb->pcb_pragmas, name, DT_IDENT_PRAGBN, 0, 0, _dtrace_defattr, vers, &dt_idops_thaw, (void *)prname, dtp->dt_gen); if (idp == NULL) longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM); if (dtp->dt_globals->dh_defer == NULL) dtp->dt_globals->dh_defer = &dt_pragma_apply; }
/* * Insert a new external symbol reference into the specified module. The new * symbol will be marked as undefined and is assigned a symbol index beyond * any existing cached symbols from this module. We use the ident's di_data * field to store a pointer to a copy of the dtrace_syminfo_t for this symbol. */ dt_ident_t * dt_module_extern(dtrace_hdl_t *dtp, dt_module_t *dmp, const char *name, const dtrace_typeinfo_t *tip) { dtrace_syminfo_t *sip; dt_ident_t *idp; uint_t id; if (dmp->dm_extern == NULL && (dmp->dm_extern = dt_idhash_create( "extern", NULL, dmp->dm_nsymelems, UINT_MAX)) == NULL) { (void) dt_set_errno(dtp, EDT_NOMEM); return (NULL); } if (dt_idhash_nextid(dmp->dm_extern, &id) == -1) { (void) dt_set_errno(dtp, EDT_SYMOFLOW); return (NULL); } if ((sip = malloc(sizeof (dtrace_syminfo_t))) == NULL) { (void) dt_set_errno(dtp, EDT_NOMEM); return (NULL); } idp = dt_idhash_insert(dmp->dm_extern, name, DT_IDENT_SYMBOL, 0, id, _dtrace_symattr, 0, &dt_idops_thaw, NULL, dtp->dt_gen); if (idp == NULL) { (void) dt_set_errno(dtp, EDT_NOMEM); free(sip); return (NULL); } sip->dts_object = dmp->dm_name; sip->dts_name = idp->di_name; sip->dts_id = idp->di_id; idp->di_data = sip; idp->di_ctfp = tip->dtt_ctfp; idp->di_type = tip->dtt_type; return (idp); }
/* * The #pragma attributes directive can be used to reset stability attributes * on a global identifier or inline definition. If the identifier is already * defined, we can just change di_attr. If not, we insert the pragma into a * hash table of the current pcb's deferred pragmas for later processing. */ static void dt_pragma_attributes(const char *prname, dt_node_t *dnp) { dtrace_hdl_t *dtp = yypcb->pcb_hdl; dtrace_attribute_t attr, *a; dt_provider_t *pvp; const char *name, *part; dt_ident_t *idp; if (dnp == NULL || dnp->dn_kind != DT_NODE_IDENT || dnp->dn_list == NULL || dnp->dn_list->dn_kind != DT_NODE_IDENT) { xyerror(D_PRAGMA_MALFORM, "malformed #pragma %s " "<attributes> <ident>\n", prname); } if (dtrace_str2attr(dnp->dn_string, &attr) == -1) { xyerror(D_PRAGMA_INVAL, "invalid attributes " "specified by #pragma %s\n", prname); } dnp = dnp->dn_list; name = dnp->dn_string; if (strcmp(name, "provider") == 0) { dnp = dnp->dn_list; name = dnp->dn_string; dnp = dnp->dn_list; part = dnp->dn_string; if ((pvp = dt_provider_lookup(dtp, name)) != NULL) { if (strcmp(part, "provider") == 0) { a = &pvp->pv_desc.dtvd_attr.dtpa_provider; } else if (strcmp(part, "module") == 0) { a = &pvp->pv_desc.dtvd_attr.dtpa_mod; } else if (strcmp(part, "function") == 0) { a = &pvp->pv_desc.dtvd_attr.dtpa_func; } else if (strcmp(part, "name") == 0) { a = &pvp->pv_desc.dtvd_attr.dtpa_name; } else if (strcmp(part, "args") == 0) { a = &pvp->pv_desc.dtvd_attr.dtpa_args; } else { xyerror(D_PRAGMA_INVAL, "invalid component " "\"%s\" in attribute #pragma " "for provider %s\n", name, part); } *a = attr; return; } } else if ((idp = dt_idstack_lookup( &yypcb->pcb_globals, name)) != NULL) { if (idp->di_gen != dtp->dt_gen) { xyerror(D_PRAGMA_SCOPE, "#pragma %s cannot modify " "entity defined outside program scope\n", prname); } idp->di_attr = attr; return; } if (yypcb->pcb_pragmas == NULL && (yypcb->pcb_pragmas = dt_idhash_create("pragma", NULL, 0, 0)) == NULL) longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM); idp = dt_idhash_insert(yypcb->pcb_pragmas, name, DT_IDENT_PRAGAT, 0, 0, attr, 0, &dt_idops_thaw, (void *)prname, dtp->dt_gen); if (idp == NULL) longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM); if (dtp->dt_globals->dh_defer == NULL) dtp->dt_globals->dh_defer = &dt_pragma_apply; }
dt_xlator_t * dt_xlator_create(dtrace_hdl_t *dtp, const dtrace_typeinfo_t *src, const dtrace_typeinfo_t *dst, const char *name, dt_node_t *members, dt_node_t *nodes) { dt_xlator_t *dxp = dt_zalloc(dtp, sizeof (dt_xlator_t)); dtrace_typeinfo_t ptr = *dst; dt_xlator_t **map; dt_node_t *dnp; uint_t kind; if (dxp == NULL) return (NULL); dxp->dx_hdl = dtp; dxp->dx_id = dtp->dt_xlatorid++; dxp->dx_gen = dtp->dt_gen; dxp->dx_arg = -1; if ((map = dt_alloc(dtp, sizeof (void *) * (dxp->dx_id + 1))) == NULL) { dt_free(dtp, dxp); return (NULL); } dt_list_append(&dtp->dt_xlators, dxp); bcopy(dtp->dt_xlatormap, map, sizeof (void *) * dxp->dx_id); dt_free(dtp, dtp->dt_xlatormap); dtp->dt_xlatormap = map; dtp->dt_xlatormap[dxp->dx_id] = dxp; if (dt_type_pointer(&ptr) == -1) { ptr.dtt_ctfp = NULL; ptr.dtt_type = CTF_ERR; } dxp->dx_ident = dt_ident_create(name ? name : "T", DT_IDENT_SCALAR, DT_IDFLG_REF | DT_IDFLG_ORPHAN, 0, _dtrace_defattr, 0, &dt_idops_thaw, NULL, dtp->dt_gen); if (dxp->dx_ident == NULL) goto err; /* no memory for identifier */ dxp->dx_ident->di_ctfp = src->dtt_ctfp; dxp->dx_ident->di_type = src->dtt_type; /* * If an input parameter name is given, this is a static translator * definition: create an idhash and identifier for the parameter. */ if (name != NULL) { dxp->dx_locals = dt_idhash_create("xlparams", NULL, 0, 0); if (dxp->dx_locals == NULL) goto err; /* no memory for identifier hash */ dt_idhash_xinsert(dxp->dx_locals, dxp->dx_ident); } dxp->dx_souid.di_name = "translator"; dxp->dx_souid.di_kind = DT_IDENT_XLSOU; dxp->dx_souid.di_flags = DT_IDFLG_REF; dxp->dx_souid.di_id = dxp->dx_id; dxp->dx_souid.di_attr = _dtrace_defattr; dxp->dx_souid.di_ops = &dt_idops_thaw; dxp->dx_souid.di_data = dxp; dxp->dx_souid.di_ctfp = dst->dtt_ctfp; dxp->dx_souid.di_type = dst->dtt_type; dxp->dx_souid.di_gen = dtp->dt_gen; dxp->dx_ptrid.di_name = "translator"; dxp->dx_ptrid.di_kind = DT_IDENT_XLPTR; dxp->dx_ptrid.di_flags = DT_IDFLG_REF; dxp->dx_ptrid.di_id = dxp->dx_id; dxp->dx_ptrid.di_attr = _dtrace_defattr; dxp->dx_ptrid.di_ops = &dt_idops_thaw; dxp->dx_ptrid.di_data = dxp; dxp->dx_ptrid.di_ctfp = ptr.dtt_ctfp; dxp->dx_ptrid.di_type = ptr.dtt_type; dxp->dx_ptrid.di_gen = dtp->dt_gen; /* * If a deferred pragma is pending on the keyword "translator", run all * the deferred pragmas on dx_souid and then copy results to dx_ptrid. * See the code in dt_pragma.c for details on deferred ident pragmas. */ if (dtp->dt_globals->dh_defer != NULL && yypcb->pcb_pragmas != NULL && dt_idhash_lookup(yypcb->pcb_pragmas, "translator") != NULL) { dtp->dt_globals->dh_defer(dtp->dt_globals, &dxp->dx_souid); dxp->dx_ptrid.di_attr = dxp->dx_souid.di_attr; dxp->dx_ptrid.di_vers = dxp->dx_souid.di_vers; } dxp->dx_src_ctfp = src->dtt_ctfp; dxp->dx_src_type = src->dtt_type; dxp->dx_src_base = ctf_type_resolve(src->dtt_ctfp, src->dtt_type); dxp->dx_dst_ctfp = dst->dtt_ctfp; dxp->dx_dst_type = dst->dtt_type; dxp->dx_dst_base = ctf_type_resolve(dst->dtt_ctfp, dst->dtt_type); kind = ctf_type_kind(dst->dtt_ctfp, dxp->dx_dst_base); assert(kind == CTF_K_STRUCT || kind == CTF_K_UNION); /* * If no input parameter is given, we're making a dynamic translator: * create member nodes for every member of the output type. Otherwise * retain the member and allocation node lists presented by the parser. */ if (name == NULL) { if (ctf_member_iter(dxp->dx_dst_ctfp, dxp->dx_dst_base, dt_xlator_create_member, dxp) != 0) goto err; } else { dxp->dx_members = members; dxp->dx_nodes = nodes; } /* * Assign member IDs to each member and allocate space for DIFOs * if and when this translator is eventually compiled. */ for (dnp = dxp->dx_members; dnp != NULL; dnp = dnp->dn_list) { dnp->dn_membxlator = dxp; dnp->dn_membid = dxp->dx_nmembers++; } dxp->dx_membdif = dt_zalloc(dtp, sizeof (dtrace_difo_t *) * dxp->dx_nmembers); if (dxp->dx_membdif == NULL) { dxp->dx_nmembers = 0; goto err; } return (dxp); err: dt_xlator_destroy(dtp, dxp); return (NULL); }