dt_dof.c

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

C
1,107
字号
/* * Copyright 2005 Sun Microsystems, Inc.  All rights reserved. * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only. * See the file usr/src/LICENSING.NOTICE in this distribution or * http://www.opensolaris.org/license/ for details. */#pragma ident	"@(#)dt_dof.c	1.6	04/11/13 SMI"#include <sys/types.h>#include <sys/sysmacros.h>#include <strings.h>#include <alloca.h>#include <assert.h>#include <stdlib.h>#include <errno.h>#include <limits.h>#include <dt_impl.h>#include <dt_strtab.h>#include <dt_provider.h>typedef struct dt_dof {	uchar_t *ddo_buf;	/* DOF data buffer base address */	dof_sec_t *ddo_secp;	/* DOF section header table pointer */	uchar_t *ddo_lptr;	/* DOF buffer pointer for loadable data */	uchar_t *ddo_uptr;	/* DOF buffer pointer for unloadable data */	size_t ddo_lsize;	/* size required for loadable DOF data */	size_t ddo_usize;	/* size required for unloadable DOF data */	size_t ddo_fsize;	/* size required for entire DOF file */	uint_t ddo_secs;	/* number of DOF sections */	size_t ddo_strs;	/* size of global string table */} dt_dof_t;/* * Add a loadable DOF section to the file using the specified data buffer and * the specified DOF section attributes.  DOF_SECF_LOAD must be set in flags. */static dof_secidx_tdof_add_lsect(dt_dof_t *ddo, const void *data, uint32_t type,    uint32_t align, uint32_t flags, uint32_t entsize, uint64_t size){	assert(flags & DOF_SECF_LOAD);	ddo->ddo_lptr = (uchar_t *)roundup((uintptr_t)ddo->ddo_lptr, align);	ddo->ddo_secp->dofs_type = type;	ddo->ddo_secp->dofs_align = align;	ddo->ddo_secp->dofs_flags = flags;	ddo->ddo_secp->dofs_entsize = entsize;	ddo->ddo_secp->dofs_offset = (size_t)(ddo->ddo_lptr - ddo->ddo_buf);	ddo->ddo_secp->dofs_size = size;	bcopy(data, ddo->ddo_lptr, size);	ddo->ddo_lptr += size;	ddo->ddo_secp++;	return (ddo->ddo_secs++);}#ifdef _when_needed/* * Add a unloadable DOF section to the file using the specified data buffer * and DOF section attributes.  DOF_SECF_LOAD must *not* be set in flags. */static dof_secidx_tdof_add_usect(dt_dof_t *ddo, const void *data, uint32_t type,    uint32_t align, uint32_t flags, uint32_t entsize, uint64_t size){	assert(!(flags & DOF_SECF_LOAD));	ddo->ddo_uptr = (uchar_t *)roundup((uintptr_t)ddo->ddo_uptr, align);	ddo->ddo_secp->dofs_type = type;	ddo->ddo_secp->dofs_align = align;	ddo->ddo_secp->dofs_flags = flags;	ddo->ddo_secp->dofs_entsize = entsize;	ddo->ddo_secp->dofs_offset = (size_t)(ddo->ddo_uptr - ddo->ddo_buf);	ddo->ddo_secp->dofs_size = size;	bcopy(data, ddo->ddo_uptr, size);	ddo->ddo_uptr += size;	ddo->ddo_secp++;	return (ddo->ddo_secs++);}#endifstatic voiddof_difo_size(dt_dof_t *ddo, const dtrace_difo_t *dp){	uint_t osecs = ddo->ddo_secs;	if (dp->dtdo_buf != NULL) {		ddo->ddo_lsize = roundup(ddo->ddo_lsize, sizeof (dif_instr_t)) +		    sizeof (dif_instr_t) * dp->dtdo_len;		ddo->ddo_secs++; /* DOF_SECT_DIF */	}	if (dp->dtdo_inttab != NULL) {		ddo->ddo_lsize = roundup(ddo->ddo_lsize, sizeof (uint64_t)) +		    sizeof (uint64_t) * dp->dtdo_intlen;		ddo->ddo_secs++; /* DOF_SECT_INTTAB */	}	if (dp->dtdo_strtab != NULL) {		ddo->ddo_lsize += dp->dtdo_strlen;		ddo->ddo_secs++; /* DOF_SECT_STRTAB */	}	if (dp->dtdo_vartab != NULL) {		ddo->ddo_lsize = roundup(ddo->ddo_lsize, sizeof (uint_t)) +		    sizeof (dtrace_difv_t) * dp->dtdo_varlen;		ddo->ddo_secs++; /* DOF_SECT_VARTAB */	}	/*	 * The DOF_SECT_DIFOHDR should have room for one dtrace_diftype_t and	 * then one dof_secidx_t for each section header reserved so far.	 */	ddo->ddo_lsize = roundup(ddo->ddo_lsize, sizeof (dof_secidx_t)) +	    sizeof (dtrace_diftype_t) +	    sizeof (dof_secidx_t) * (ddo->ddo_secs - osecs);	ddo->ddo_secs++; /* DOF_SECT_DIFOHDR */	/*	 * Now allocate space for any kernel and user relocation sections.	 * These sections refer to the DIFO, but are not mentioned in DIFOHDR.	 */	if (dp->dtdo_kreltab != NULL) {		ddo->ddo_lsize =		    roundup(ddo->ddo_lsize, sizeof (uint64_t)) +		    sizeof (dof_relodesc_t) * dp->dtdo_krelen;		ddo->ddo_secs++; /* DOF_SECT_RELTAB */		ddo->ddo_lsize = roundup(ddo->ddo_lsize,		    sizeof (dof_secidx_t)) + sizeof (dof_relohdr_t);		ddo->ddo_secs++; /* DOF_SECT_KRELHDR */	}	if (dp->dtdo_ureltab != NULL) {		ddo->ddo_lsize =		    roundup(ddo->ddo_lsize, sizeof (uint64_t)) +		    sizeof (dof_relodesc_t) * dp->dtdo_urelen;		ddo->ddo_secs++; /* DOF_SECT_RELTAB */		ddo->ddo_lsize = roundup(ddo->ddo_lsize,		    sizeof (dof_secidx_t)) + sizeof (dof_relohdr_t);		ddo->ddo_secs++; /* DOF_SECT_URELHDR */	}}static dof_secidx_tdof_difo_save(dt_dof_t *ddo, const dtrace_difo_t *dp){	dof_secidx_t dsecs[4]; /* enough for all possible DIFO sections */	uint_t nsecs = 0;	dof_difohdr_t *dofd;	dof_relohdr_t dofr;	dof_secidx_t relsec;	dof_secidx_t strsec = DOF_SECIDX_NONE;	dof_secidx_t intsec = DOF_SECIDX_NONE;	dof_secidx_t hdrsec = DOF_SECIDX_NONE;	if (dp->dtdo_buf != NULL) {		dsecs[nsecs++] = dof_add_lsect(ddo, dp->dtdo_buf,		    DOF_SECT_DIF, sizeof (dif_instr_t), DOF_SECF_LOAD,		    sizeof (dif_instr_t), sizeof (dif_instr_t) * dp->dtdo_len);	}	if (dp->dtdo_inttab != NULL) {		dsecs[nsecs++] = intsec = dof_add_lsect(ddo, dp->dtdo_inttab,		    DOF_SECT_INTTAB, sizeof (uint64_t), DOF_SECF_LOAD,		    sizeof (uint64_t), sizeof (uint64_t) * dp->dtdo_intlen);	}	if (dp->dtdo_strtab != NULL) {		dsecs[nsecs++] = strsec = dof_add_lsect(ddo, dp->dtdo_strtab,		    DOF_SECT_STRTAB, sizeof (char), DOF_SECF_LOAD,		    0, dp->dtdo_strlen);	}	if (dp->dtdo_vartab != NULL) {		dsecs[nsecs++] = dof_add_lsect(ddo, dp->dtdo_vartab,		    DOF_SECT_VARTAB, sizeof (uint_t), DOF_SECF_LOAD,		    sizeof (dtrace_difv_t),		    sizeof (dtrace_difv_t) * dp->dtdo_varlen);	}	/*	 * Copy the return type and the array of section indices that form the	 * DIFO into a single dof_difohdr_t and then add DOF_SECT_DIFOHDR.	 */	assert(nsecs <= sizeof (dsecs) / sizeof (dsecs[0]));	dofd = alloca(sizeof (dtrace_diftype_t) + sizeof (dsecs));	bcopy(&dp->dtdo_rtype, &dofd->dofd_rtype, sizeof (dtrace_diftype_t));	bcopy(dsecs, &dofd->dofd_links, sizeof (dof_secidx_t) * nsecs);	hdrsec = dof_add_lsect(ddo, dofd, DOF_SECT_DIFOHDR,	    sizeof (dof_secidx_t), DOF_SECF_LOAD, 0,	    sizeof (dtrace_diftype_t) + sizeof (dof_secidx_t) * nsecs);	/*	 * Add any other sections related to dtrace_difo_t.  These are not	 * referenced in dof_difohdr_t because they are not used by emulation.	 */	if (dp->dtdo_kreltab != NULL) {		relsec = dof_add_lsect(ddo, dp->dtdo_kreltab, DOF_SECT_RELTAB,		    sizeof (uint64_t), DOF_SECF_LOAD, sizeof (dof_relodesc_t),		    sizeof (dof_relodesc_t) * dp->dtdo_krelen);		/*		 * This code assumes the target of all relocations is the		 * integer table 'intsec' (DOF_SECT_INTTAB).  If other sections		 * need relocation in the future this will need to change.		 */		dofr.dofr_strtab = strsec;		dofr.dofr_relsec = relsec;		dofr.dofr_tgtsec = intsec;		(void) dof_add_lsect(ddo, &dofr, DOF_SECT_KRELHDR,		    sizeof (dof_secidx_t), DOF_SECF_LOAD, 0,		    sizeof (dof_relohdr_t));	}	if (dp->dtdo_ureltab != NULL) {		relsec = dof_add_lsect(ddo, dp->dtdo_ureltab, DOF_SECT_RELTAB,		    sizeof (uint64_t), DOF_SECF_LOAD, sizeof (dof_relodesc_t),		    sizeof (dof_relodesc_t) * dp->dtdo_urelen);		/*		 * This code assumes the target of all relocations is the		 * integer table 'intsec' (DOF_SECT_INTTAB).  If other sections		 * need relocation in the future this will need to change.		 */		dofr.dofr_strtab = strsec;		dofr.dofr_relsec = relsec;		dofr.dofr_tgtsec = intsec;		(void) dof_add_lsect(ddo, &dofr, DOF_SECT_URELHDR,		    sizeof (dof_secidx_t), DOF_SECF_LOAD, 0,		    sizeof (dof_relohdr_t));	}	return (hdrsec);}typedef struct dof_probe_info {	dof_probe_t *dpi_probes;	/* array of DOF probes */	size_t dpi_nprobes;		/* probe count */	uint8_t *dpi_args;		/* array of argument mappings */	size_t dpi_nargs;		/* argument count */	uint32_t *dpi_offs;		/* array of function offsets */	size_t dpi_noffs;		/* offset count */	char *dpi_strtab;		/* string table */	size_t dpi_strlen;		/* string table size */	dof_relodesc_t *dpi_rel;	/* DOF relocations */} dof_probe_info_t;/*ARGSUSED*/static voiddof_probe_size(dt_idhash_t *dhp, dt_ident_t *idp, void *data){	dof_probe_info_t *dpip = data;	dt_probe_instance_t *pip;	dt_probe_t *prp = idp->di_data;	char buf[256];	dt_node_t *dnp;	int i;	dpip->dpi_strlen += strlen(prp->pr_ident->di_name) + 1;	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));		dpip->dpi_strlen += strlen(buf) + 1;	}	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));		dpip->dpi_strlen += strlen(buf) + 1;		dpip->dpi_nargs++;	}	for (pip = prp->pr_inst; pip != NULL; pip = pip->pi_next) {		dpip->dpi_strlen += strlen(pip->pi_fname) + 1;		dpip->dpi_nprobes++;		dpip->dpi_noffs += pip->pi_noffs;	}}static voiddof_provider_size(dt_dof_t *ddo, const dt_provider_t *pvp){	dof_probe_info_t dpi;	/*	 * Ignore providers that aren't user defined.	 */	if (pvp->pv_probes == NULL)		return;	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);	ddo->ddo_lsize += dpi.dpi_strlen;	ddo->ddo_secs++; /* DOF_SECT_STRTAB */	ddo->ddo_lsize = roundup(ddo->ddo_lsize, sizeof (uint64_t));	ddo->ddo_lsize += sizeof (dof_probe_t) * dpi.dpi_nprobes;	ddo->ddo_secs++; /* DOF_SECT_PROBES */	ddo->ddo_lsize = roundup(ddo->ddo_lsize, sizeof (uint_t));	ddo->ddo_lsize += sizeof (uint8_t) * dpi.dpi_nargs;	ddo->ddo_secs++; /* DOF_SECT_PRARGS */	ddo->ddo_lsize = roundup(ddo->ddo_lsize, sizeof (uint_t));	ddo->ddo_lsize += sizeof (uint32_t) * dpi.dpi_noffs;	ddo->ddo_secs++; /* DOF_SECT_PROFFS */	ddo->ddo_lsize = roundup(ddo->ddo_lsize, sizeof (uint_t)) +	    sizeof (dof_provider_t);	ddo->ddo_secs++; /* DOF_SECT_PROVIDER */	ddo->ddo_lsize = roundup(ddo->ddo_lsize, sizeof (uint64_t));	ddo->ddo_lsize += sizeof (dof_relodesc_t) * dpi.dpi_nprobes;	ddo->ddo_secs++; /* DOF_SECT_RELTAB */	ddo->ddo_lsize = roundup(ddo->ddo_lsize, sizeof (dof_secidx_t));	ddo->ddo_lsize += sizeof (dof_relohdr_t);	ddo->ddo_secs++; /* DOF_SECT_URELHDR */}static uint8_tdof_find_arg(dt_node_t *argv, uint_t argc, const char *name){	uint8_t i = 0;	for (i = 0; i < argc; i++, argv = argv->dn_list) {		assert(argv->dn_kind == DT_NODE_TYPE);		if (strcmp(argv->dn_string, name) == 0)			return (i);	}	/* Corresponding argument not found */	assert(0);	return ((uint8_t)-1);}/*ARGSUSED*/static voiddof_probe_save(dt_idhash_t *dhp, dt_ident_t *idp, void *data)

⌨️ 快捷键说明

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