dt_dof.c

来自「Sun Solaris 10 中的 DTrace 组件的源代码。请参看: htt」· C语言 代码 · 共 1,107 行 · 第 1/3 页

C
1,107
字号
{	dof_probe_info_t *dpip = data;	dt_probe_instance_t *pip;	dt_probe_t *prp = idp->di_data;	dof_stridx_t name, nargv, xargv;	uint32_t argidx;	dt_node_t *dnp;	char buf[256];	int i;	name = dpip->dpi_strlen;	(void) strcpy(dpip->dpi_strtab + dpip->dpi_strlen,	    prp->pr_ident->di_name);	dpip->dpi_strlen += strlen(prp->pr_ident->di_name) + 1;	nargv = dpip->dpi_strlen;	for (i = 0, dnp = prp->pr_nargs; i < prp->pr_nargc;	    i++, dnp = dnp->dn_list) {		assert(dnp->dn_kind == DT_NODE_TYPE);		(void) ctf_type_name(dnp->dn_ctfp, dnp->dn_type, buf,		    sizeof (buf));		(void) strcpy(dpip->dpi_strtab + dpip->dpi_strlen, buf);		dpip->dpi_strlen += strlen(buf) + 1;	}	xargv = dpip->dpi_strlen;	argidx = dpip->dpi_nargs;	for (i = 0, dnp = prp->pr_xargs; i < prp->pr_xargc;	    i++, dnp = dnp->dn_list) {		assert(dnp->dn_kind == DT_NODE_TYPE);		(void) ctf_type_name(dnp->dn_ctfp, dnp->dn_type, buf,		    sizeof (buf));		(void) strcpy(dpip->dpi_strtab + dpip->dpi_strlen, buf);		dpip->dpi_strlen += strlen(buf) + 1;		dpip->dpi_args[dpip->dpi_nargs++] = (dnp->dn_string == NULL) ?		    i : dof_find_arg(prp->pr_nargs, prp->pr_nargc,		    dnp->dn_string);	}	for (pip = prp->pr_inst; pip != NULL; pip = pip->pi_next) {		dof_probe_t *dofprp = &dpip->dpi_probes[dpip->dpi_nprobes];		dof_relodesc_t *dofrp = &dpip->dpi_rel[dpip->dpi_nprobes];		int i;		dpip->dpi_nprobes++;		dofprp->dofpr_addr = 0;		dofprp->dofpr_func = dpip->dpi_strlen;		(void) strcpy(dpip->dpi_strtab + dpip->dpi_strlen,		    pip->pi_fname);		dpip->dpi_strlen += strlen(pip->pi_fname) + 1;		dofprp->dofpr_name = name;		dofprp->dofpr_nargv = nargv;		dofprp->dofpr_xargv = xargv;		dofprp->dofpr_argidx = argidx;		dofprp->dofpr_nargc = prp->pr_nargc;		dofprp->dofpr_xargc = prp->pr_xargc;		dofprp->dofpr_offidx = dpip->dpi_noffs;		dofprp->dofpr_noffs = pip->pi_noffs;		for (i = 0; i < dofprp->dofpr_noffs; i++) {			dpip->dpi_offs[dpip->dpi_noffs++] = pip->pi_offs[i];		}		dofrp->dofr_name = dofprp->dofpr_func;		dofrp->dofr_type = DOF_RELO_SETX;		dofrp->dofr_offset = (char *)&dofprp->dofpr_addr -		    (char *)dpip->dpi_probes;	}}static dof_attr_tdof_attr(const dtrace_attribute_t *ap){	return (DOF_ATTR(ap->dtat_name, ap->dtat_data, ap->dtat_class));}static intdof_provider_save(dtrace_hdl_t *dtp, dt_dof_t *ddo, const dt_provider_t *pvp){	dof_provider_t dofpv;	dof_probe_info_t dpi;	dof_relohdr_t dofr;	/*	 * Ignore providers that aren't user defined.	 */	if (pvp->pv_probes == NULL)		return (0);	dofpv.dofpv_provattr = dof_attr(&pvp->pv_desc.dtvd_attr.dtpa_provider);	dofpv.dofpv_modattr = dof_attr(&pvp->pv_desc.dtvd_attr.dtpa_mod);	dofpv.dofpv_funcattr = dof_attr(&pvp->pv_desc.dtvd_attr.dtpa_func);	dofpv.dofpv_nameattr = dof_attr(&pvp->pv_desc.dtvd_attr.dtpa_name);	dofpv.dofpv_argsattr = dof_attr(&pvp->pv_desc.dtvd_attr.dtpa_args);	dpi.dpi_nprobes = 0;	dpi.dpi_nargs = 0;	dpi.dpi_noffs = 0;	dpi.dpi_strlen = 1; /* leading '\0' */	dpi.dpi_strlen += strlen(pvp->pv_desc.dtvd_name) + 1;	(void) dt_idhash_iter(pvp->pv_probes, dof_probe_size, &dpi);	if ((dpi.dpi_probes = calloc(dpi.dpi_nprobes,	    sizeof (dof_probe_t))) == NULL) {		return (dt_set_errno(dtp, EDT_NOMEM));	}	if ((dpi.dpi_args = calloc(dpi.dpi_nargs, sizeof (uint8_t))) == NULL) {		free(dpi.dpi_probes);		return (dt_set_errno(dtp, EDT_NOMEM));	}	if ((dpi.dpi_offs = calloc(dpi.dpi_noffs, sizeof (uint32_t))) == NULL) {		free(dpi.dpi_probes);		free(dpi.dpi_args);		return (dt_set_errno(dtp, EDT_NOMEM));	}	if ((dpi.dpi_strtab = malloc(dpi.dpi_strlen)) == NULL) {		free(dpi.dpi_probes);		free(dpi.dpi_args);		free(dpi.dpi_offs);		return (dt_set_errno(dtp, EDT_NOMEM));	}	if ((dpi.dpi_rel = calloc(dpi.dpi_nprobes,	    sizeof (dof_relodesc_t))) == NULL) {		free(dpi.dpi_probes);		free(dpi.dpi_args);		free(dpi.dpi_offs);		free(dpi.dpi_strtab);		return (dt_set_errno(dtp, EDT_NOMEM));	}	dpi.dpi_nprobes = 0;	dpi.dpi_nargs = 0;	dpi.dpi_noffs = 0;	dpi.dpi_strtab[0] = '\0';	dpi.dpi_strlen = 1;	dofpv.dofpv_name = dpi.dpi_strlen;	(void) strcpy(dpi.dpi_strtab + dpi.dpi_strlen, pvp->pv_desc.dtvd_name);	dpi.dpi_strlen += strlen(pvp->pv_desc.dtvd_name) + 1;	(void) dt_idhash_iter(pvp->pv_probes, dof_probe_save, &dpi);	dofpv.dofpv_strtab = dof_add_lsect(ddo, dpi.dpi_strtab,	    DOF_SECT_STRTAB, sizeof (char), DOF_SECF_LOAD, 0, dpi.dpi_strlen);	dofpv.dofpv_probes = dof_add_lsect(ddo, dpi.dpi_probes,	    DOF_SECT_PROBES, sizeof (uint64_t), DOF_SECF_LOAD,	    sizeof (dof_probe_t), sizeof (dof_probe_t) * dpi.dpi_nprobes);	dofpv.dofpv_prargs = dof_add_lsect(ddo, dpi.dpi_args,	    DOF_SECT_PRARGS, sizeof (uint_t), DOF_SECF_LOAD,	    sizeof (uint8_t), sizeof (uint8_t) * dpi.dpi_nargs);	dofpv.dofpv_proffs = dof_add_lsect(ddo, dpi.dpi_offs,	    DOF_SECT_PROFFS, sizeof (uint_t), DOF_SECF_LOAD,	    sizeof (uint32_t), sizeof (uint32_t) * dpi.dpi_noffs);	(void) dof_add_lsect(ddo, &dofpv, DOF_SECT_PROVIDER, sizeof (uint_t),	    DOF_SECF_LOAD, 0, sizeof (dof_provider_t));	dofr.dofr_strtab = dofpv.dofpv_strtab;	dofr.dofr_relsec = dof_add_lsect(ddo, dpi.dpi_rel, DOF_SECT_RELTAB,	    sizeof (uint64_t), DOF_SECF_LOAD, sizeof (dof_relodesc_t),	    sizeof (dof_relodesc_t) * dpi.dpi_nprobes);	dofr.dofr_tgtsec = dofpv.dofpv_probes;	(void) dof_add_lsect(ddo, &dofr, DOF_SECT_URELHDR,	    sizeof (dof_secidx_t), DOF_SECF_LOAD, 0, sizeof (dof_relohdr_t));	free(dpi.dpi_probes);	free(dpi.dpi_args);	free(dpi.dpi_offs);	free(dpi.dpi_strtab);	free(dpi.dpi_rel);	return (0);}static intdtrace_dof_hdr(dtrace_hdl_t *dtp, dof_hdr_t *hp){	/*	 * If our config values cannot fit in a uint8_t, we can't generate a	 * DOF header since the values won't fit.  This can only happen if the	 * user forcibly compiles a program with an artificial configuration.	 */	if (dtp->dt_conf.dtc_difversion > UINT8_MAX ||	    dtp->dt_conf.dtc_difintregs > UINT8_MAX ||	    dtp->dt_conf.dtc_diftupregs > UINT8_MAX) {		return (dt_set_errno(dtp, EOVERFLOW));	}	bzero(hp, sizeof (dof_hdr_t));	hp->dofh_ident[DOF_ID_MAG0] = DOF_MAG_MAG0;	hp->dofh_ident[DOF_ID_MAG1] = DOF_MAG_MAG1;	hp->dofh_ident[DOF_ID_MAG2] = DOF_MAG_MAG2;	hp->dofh_ident[DOF_ID_MAG3] = DOF_MAG_MAG3;	if (dtp->dt_conf.dtc_ctfmodel == CTF_MODEL_LP64)		hp->dofh_ident[DOF_ID_MODEL] = DOF_MODEL_LP64;	else		hp->dofh_ident[DOF_ID_MODEL] = DOF_MODEL_ILP32;	hp->dofh_ident[DOF_ID_ENCODING] = DOF_ENCODE_NATIVE;	hp->dofh_ident[DOF_ID_VERSION] = DOF_VERSION_1;	hp->dofh_ident[DOF_ID_DIFVERS] = dtp->dt_conf.dtc_difversion;	hp->dofh_ident[DOF_ID_DIFIREG] = dtp->dt_conf.dtc_difintregs;	hp->dofh_ident[DOF_ID_DIFTREG] = dtp->dt_conf.dtc_diftupregs;	hp->dofh_flags = 0;	hp->dofh_hdrsize = sizeof (dof_hdr_t);	hp->dofh_secsize = sizeof (dof_sec_t);	hp->dofh_secoff = sizeof (dof_hdr_t);	hp->dofh_pad = 0;	return (0);}void *dtrace_dof_create(dtrace_hdl_t *dtp, dtrace_prog_t *pgp, uint_t flags){	const dtrace_ecbdesc_t *edp, *last;	const dtrace_probedesc_t *pdp;	const dtrace_actdesc_t *ap;	const dt_stmt_t *stp, *next;	dof_secidx_t strsec;	char *strtab, *strp;	size_t stroff;	dof_hdr_t *hp;	dof_sec_t *secbase;	dt_dof_t ddo;	dof_stridx_t strndx;	dof_secidx_t *actsecs;	uint_t maxacts = 0;	if (flags & ~DTRACE_D_MASK) {		(void) dt_set_errno(dtp, EINVAL);		return (NULL);	}	bzero(&ddo, sizeof (dt_dof_t));	ddo.ddo_lsize = sizeof (dof_hdr_t);	/*	 * First, iterate through the statements and compute the total size of	 * the DOF file we will need to create.  We use the statements to find	 * the unique set of ECB descriptions associated with the program,	 * each of which results in a set of sections in the DOF file.  To that	 * we must add a file header, section header table, and string table.	 */	stp = dt_list_next(&pgp->dp_stmts);	last = NULL;	for (; stp != NULL; stp = dt_list_next(stp)) {		uint_t nacts = 0;		dtrace_stmtdesc_t *sdp = stp->ds_desc;		dtrace_actdesc_t *ap = sdp->dtsd_action;		/*		 * If the action associated with this statement has format		 * data, we must allocate space for it in the string table.		 */		if (ap != NULL && sdp->dtsd_fmtdata != NULL) {			ddo.ddo_strs += dtrace_printf_format(dtp,			    sdp->dtsd_fmtdata, NULL, 0) + 1;		}		if ((edp = sdp->dtsd_ecbdesc) == last)			continue; /* same ecb as previous statement */		pdp = &edp->dted_probe;		last = edp;		ddo.ddo_lsize = roundup(ddo.ddo_lsize, sizeof (dof_secidx_t)) +		    sizeof (dof_probedesc_t);		ddo.ddo_secs++; /* DOF_SECT_PROBEDESC */		if (pdp->dtpd_provider[0] != '\0')			ddo.ddo_strs += strlen(pdp->dtpd_provider) + 1;		if (pdp->dtpd_mod[0] != '\0')			ddo.ddo_strs += strlen(pdp->dtpd_mod) + 1;		if (pdp->dtpd_func[0] != '\0')			ddo.ddo_strs += strlen(pdp->dtpd_func) + 1;		if (pdp->dtpd_name[0] != '\0')			ddo.ddo_strs += strlen(pdp->dtpd_name) + 1;		if (edp->dted_pred.dtpdd_difo != NULL)			dof_difo_size(&ddo, edp->dted_pred.dtpdd_difo);		for (ap = edp->dted_action; ap != NULL; ap = ap->dtad_next) {			if (ap->dtad_difo != NULL)				dof_difo_size(&ddo, ap->dtad_difo);			nacts++;		}		maxacts = MAX(maxacts, nacts); /* track biggest ecbdesc */		if (nacts != 0) {			ddo.ddo_lsize = roundup(ddo.ddo_lsize,			    sizeof (uint64_t)) + sizeof (dof_actdesc_t) * nacts;			ddo.ddo_secs++; /* DOF_SECT_ACTDESC */		}		ddo.ddo_lsize = roundup(ddo.ddo_lsize, sizeof (uint64_t)) +		    sizeof (dof_ecbdesc_t);		ddo.ddo_secs++; /* DOF_SECT_ECBDESC */	}	if (flags & DTRACE_D_PROBES) {		uint_t h;		dt_provider_t *pvp;		for (h = 0; h < dtp->dt_provbuckets; h++) {			for (pvp = dtp->dt_provs[h]; pvp != NULL;			    pvp = pvp->pv_next) {				dof_provider_size(&ddo, pvp);			}		}	}	ddo.ddo_lsize += ddo.ddo_strs + 1;	ddo.ddo_secs++; /* DOF_SECT_STRTAB */	/*	 * Now that we've added up all the sections, add in the size of the	 * section header table.  We know that the dof_hdr_t is aligned so that	 * that dof_sec_t's can follow it, and that dof_sec_t is aligned so	 * that the first section (PROBEDESC) can follow it.  As a result,	 * no extra padding bytes are required between either of these things.	 */	ddo.ddo_lsize += sizeof (dof_sec_t) * ddo.ddo_secs;	stroff = ddo.ddo_lsize - (ddo.ddo_strs + 1);	/*	 * If our DOF file has unloadable data (ddo_usize), then round up	 * the loadable size to a 64-byte boundary and include it in the	 * final file size.  Otherwise the file size is the loadable size.	 */	if (ddo.ddo_usize != 0)		ddo.ddo_fsize = roundup(ddo.ddo_lsize, 64) + ddo.ddo_usize;	else		ddo.ddo_fsize = ddo.ddo_lsize;	/*	 * Allocate a buffer for the entire DOF file, bzero it so padding does	 * not "leak" uninitialized memory values, and then fill in the header.	 */	if ((ddo.ddo_buf = malloc(ddo.ddo_fsize)) == NULL) {		(void) dt_set_errno(dtp, EDT_NOMEM);		return (NULL);	}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?