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 + -
显示快捷键?