⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ctf_create.c

📁 Sun Solaris 10 中的 DTrace 组件的源代码。请参看: http://www.sun.com/software/solaris/observability.jsp
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * 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	"@(#)ctf_create.c	1.2	04/10/22 SMI"#include <sys/sysmacros.h>#include <sys/param.h>#include <sys/mman.h>#include <ctf_impl.h>/* * This static string is used as the template for initially populating a * dynamic container's string table.  We always store \0 in the first byte, * and we use the generic string "PARENT" to mark this container's parent * if one is associated with the container using ctf_import(). */static const char _CTF_STRTAB_TEMPLATE[] = "\0PARENT";/* * To create an empty CTF container, we just declare a zeroed header and call * ctf_bufopen() on it.  If ctf_bufopen succeeds, we mark the new container r/w * and initialize the dynamic members.  We set dtstrlen to 1 to reserve the * first byte of the string table for a \0 byte, and we start assigning type * IDs at 1 because type ID 0 is used as a sentinel. */ctf_file_t *ctf_create(int *errp){	static const ctf_header_t hdr = { { CTF_MAGIC, CTF_VERSION, 0 } };	ctf_sect_t cts;	ctf_file_t *fp;	cts.cts_name = _CTF_SECTION;	cts.cts_type = SHT_PROGBITS;	cts.cts_flags = 0;	cts.cts_data = &hdr;	cts.cts_size = sizeof (hdr);	cts.cts_entsize = 1;	cts.cts_offset = 0;	if ((fp = ctf_bufopen(&cts, NULL, NULL, errp)) != NULL) {		fp->ctf_flags |= LCTF_RDWR;		fp->ctf_dtstrlen = sizeof (_CTF_STRTAB_TEMPLATE);		fp->ctf_dtnextid = 1;		fp->ctf_dtoldid = 0;	}	return (fp);}static uchar_t *ctf_copy_smembers(ctf_dtdef_t *dtd, uint_t soff, uchar_t *t){	ctf_dmdef_t *dmd = ctf_list_next(&dtd->dtd_u.dtu_members);	ctf_member_t ctm;	for (; dmd != NULL; dmd = ctf_list_next(dmd)) {		if (dmd->dmd_name) {			ctm.ctm_name = soff;			soff += strlen(dmd->dmd_name) + 1;		} else			ctm.ctm_name = 0;		ctm.ctm_type = (ushort_t)dmd->dmd_type;		ctm.ctm_offset = (ushort_t)dmd->dmd_offset;		bcopy(&ctm, t, sizeof (ctm));		t += sizeof (ctm);	}	return (t);}static uchar_t *ctf_copy_lmembers(ctf_dtdef_t *dtd, uint_t soff, uchar_t *t){	ctf_dmdef_t *dmd = ctf_list_next(&dtd->dtd_u.dtu_members);	ctf_lmember_t ctlm;	for (; dmd != NULL; dmd = ctf_list_next(dmd)) {		if (dmd->dmd_name) {			ctlm.ctlm_name = soff;			soff += strlen(dmd->dmd_name) + 1;		} else			ctlm.ctlm_name = 0;		ctlm.ctlm_type = (ushort_t)dmd->dmd_type;		ctlm.ctlm_pad = 0;		ctlm.ctlm_offsethi = CTF_OFFSET_TO_LMEMHI(dmd->dmd_offset);		ctlm.ctlm_offsetlo = CTF_OFFSET_TO_LMEMLO(dmd->dmd_offset);		bcopy(&ctlm, t, sizeof (ctlm));		t += sizeof (ctlm);	}	return (t);}static uchar_t *ctf_copy_emembers(ctf_dtdef_t *dtd, uint_t soff, uchar_t *t){	ctf_dmdef_t *dmd = ctf_list_next(&dtd->dtd_u.dtu_members);	ctf_enum_t cte;	for (; dmd != NULL; dmd = ctf_list_next(dmd)) {		cte.cte_name = soff;		cte.cte_value = dmd->dmd_value;		soff += strlen(dmd->dmd_name) + 1;		bcopy(&cte, t, sizeof (cte));		t += sizeof (cte);	}	return (t);}static uchar_t *ctf_copy_membnames(ctf_dtdef_t *dtd, uchar_t *s){	ctf_dmdef_t *dmd = ctf_list_next(&dtd->dtd_u.dtu_members);	size_t len;	for (; dmd != NULL; dmd = ctf_list_next(dmd)) {		if (dmd->dmd_name == NULL)			continue; /* skip anonymous members */		len = strlen(dmd->dmd_name) + 1;		bcopy(dmd->dmd_name, s, len);		s += len;	}	return (s);}/* * If the specified CTF container is writable and has been modified, reload * this container with the updated type definitions.  In order to make this * code and the rest of libctf as simple as possible, we perform updates by * taking the dynamic type definitions and creating an in-memory CTF file * containing the definitions, and then call ctf_bufopen() on it.  This not * only leverages ctf_bufopen(), but also avoids having to bifurcate the rest * of the library code with different lookup paths for static and dynamic * type definitions.  We are therefore optimizing greatly for lookup over * update, which we assume will be an uncommon operation.  We perform one * extra trick here for the benefit of callers and to keep our code simple: * ctf_bufopen() will return a new ctf_file_t, but we want to keep the fp * constant for the caller, so after ctf_bufopen() returns, we use bcopy to * swap the interior of the old and new ctf_file_t's, and then free the old. */intctf_update(ctf_file_t *fp){	ctf_file_t ofp, *nfp;	ctf_header_t hdr;	ctf_dtdef_t *dtd;	ctf_sect_t cts;	uchar_t *s, *s0, *t;	size_t size;	void *buf;	int err;	if (!(fp->ctf_flags & LCTF_RDWR))		return (ctf_set_errno(fp, ECTF_RDONLY));	if (!(fp->ctf_flags & LCTF_DIRTY))		return (0); /* no update required */	/*	 * Fill in an initial CTF header.  We will leave the label, object,	 * and function sections empty and only output a header, type section,	 * and string table.  The type section begins at a 4-byte aligned	 * boundary past the CTF header itself (at relative offset zero).	 */	bzero(&hdr, sizeof (hdr));	hdr.cth_magic = CTF_MAGIC;	hdr.cth_version = CTF_VERSION;	if (fp->ctf_flags & LCTF_CHILD)		hdr.cth_parname = 1; /* i.e. _CTF_STRTAB_TEMPLATE[1] */	/*	 * Iterate through the dynamic type definition list and compute the	 * size of the CTF type section we will need to generate.	 */	for (size = 0, dtd = ctf_list_next(&fp->ctf_dtdefs);	    dtd != NULL; dtd = ctf_list_next(dtd)) {		uint_t kind = CTF_INFO_KIND(dtd->dtd_data.ctt_info);		uint_t vlen = CTF_INFO_VLEN(dtd->dtd_data.ctt_info);		if (dtd->dtd_data.ctt_size != CTF_LSIZE_SENT)			size += sizeof (ctf_stype_t);		else			size += sizeof (ctf_type_t);		switch (kind) {		case CTF_K_INTEGER:		case CTF_K_FLOAT:			size += sizeof (uint_t);			break;		case CTF_K_ARRAY:			size += sizeof (ctf_array_t);			break;		case CTF_K_FUNCTION:			size += sizeof (ushort_t) * (vlen + (vlen & 1));			break;		case CTF_K_STRUCT:		case CTF_K_UNION:			if (dtd->dtd_data.ctt_size < CTF_LSTRUCT_THRESH)				size += sizeof (ctf_member_t) * vlen;			else				size += sizeof (ctf_lmember_t) * vlen;			break;		case CTF_K_ENUM:			size += sizeof (ctf_enum_t) * vlen;			break;		}	}	/*	 * Fill in the string table offset and size, compute the size of the	 * entire CTF buffer we need, and then allocate a new buffer and	 * bcopy the finished header to the start of the buffer.	 */	hdr.cth_stroff = hdr.cth_typeoff + size;	hdr.cth_strlen = fp->ctf_dtstrlen;	size = sizeof (ctf_header_t) + hdr.cth_stroff + hdr.cth_strlen;	if ((buf = ctf_data_alloc(size)) == MAP_FAILED)		return (ctf_set_errno(fp, EAGAIN));	bcopy(&hdr, buf, sizeof (ctf_header_t));	t = (uchar_t *)buf + sizeof (ctf_header_t);	s = s0 = (uchar_t *)buf + sizeof (ctf_header_t) + hdr.cth_stroff;	bcopy(_CTF_STRTAB_TEMPLATE, s, sizeof (_CTF_STRTAB_TEMPLATE));	s += sizeof (_CTF_STRTAB_TEMPLATE);	/*	 * We now take a final lap through the dynamic type definition list and	 * copy the appropriate type records and strings to the output buffer.	 */	for (dtd = ctf_list_next(&fp->ctf_dtdefs);	    dtd != NULL; dtd = ctf_list_next(dtd)) {		uint_t kind = CTF_INFO_KIND(dtd->dtd_data.ctt_info);		uint_t vlen = CTF_INFO_VLEN(dtd->dtd_data.ctt_info);		ctf_array_t cta;		uint_t encoding;		size_t len;		if (dtd->dtd_name != NULL) {			dtd->dtd_data.ctt_name = (uint_t)(s - s0);			len = strlen(dtd->dtd_name) + 1;			bcopy(dtd->dtd_name, s, len);			s += len;		} else			dtd->dtd_data.ctt_name = 0;		if (dtd->dtd_data.ctt_size != CTF_LSIZE_SENT)			len = sizeof (ctf_stype_t);		else			len = sizeof (ctf_type_t);		bcopy(&dtd->dtd_data, t, len);		t += len;		switch (kind) {		case CTF_K_INTEGER:		case CTF_K_FLOAT:			if (kind == CTF_K_INTEGER) {				encoding = CTF_INT_DATA(				    dtd->dtd_u.dtu_enc.cte_format,				    dtd->dtd_u.dtu_enc.cte_offset,				    dtd->dtd_u.dtu_enc.cte_bits);			} else {				encoding = CTF_FP_DATA(				    dtd->dtd_u.dtu_enc.cte_format,				    dtd->dtd_u.dtu_enc.cte_offset,				    dtd->dtd_u.dtu_enc.cte_bits);			}			bcopy(&encoding, t, sizeof (encoding));			t += sizeof (encoding);			break;		case CTF_K_ARRAY:			cta.cta_contents = (ushort_t)			    dtd->dtd_u.dtu_arr.ctr_contents;			cta.cta_index = (ushort_t)			    dtd->dtd_u.dtu_arr.ctr_index;			cta.cta_nelems = dtd->dtd_u.dtu_arr.ctr_nelems;			bcopy(&cta, t, sizeof (cta));			t += sizeof (cta);			break;		case CTF_K_FUNCTION: {			ushort_t *argv = (ushort_t *)(uintptr_t)t;			uint_t argc;			for (argc = 0; argc < vlen; argc++)				*argv++ = (ushort_t)dtd->dtd_u.dtu_argv[argc];			if (vlen & 1)				*argv++ = 0; /* pad to 4-byte boundary */			t = (uchar_t *)argv;			break;		}		case CTF_K_STRUCT:		case CTF_K_UNION:			if (dtd->dtd_data.ctt_size < CTF_LSTRUCT_THRESH)				t = ctf_copy_smembers(dtd, (uint_t)(s - s0), t);			else				t = ctf_copy_lmembers(dtd, (uint_t)(s - s0), t);			s = ctf_copy_membnames(dtd, s);			break;		case CTF_K_ENUM:			t = ctf_copy_emembers(dtd, (uint_t)(s - s0), t);			s = ctf_copy_membnames(dtd, s);			break;		}	}	/*	 * Finally, we are ready to ctf_bufopen() the new container.  If this	 * is successful, we then switch nfp and fp and free the old container.	 */	ctf_data_protect(buf, size);	cts.cts_name = _CTF_SECTION;	cts.cts_type = SHT_PROGBITS;	cts.cts_flags = 0;	cts.cts_data = buf;	cts.cts_size = size;	cts.cts_entsize = 1;	cts.cts_offset = 0;	if ((nfp = ctf_bufopen(&cts, NULL, NULL, &err)) == NULL) {		ctf_data_free(buf, size);		return (ctf_set_errno(fp, err));	}	(void) ctf_setmodel(nfp, ctf_getmodel(fp));	(void) ctf_import(nfp, fp->ctf_parent);	nfp->ctf_refcnt = fp->ctf_refcnt;	nfp->ctf_flags |= fp->ctf_flags & ~LCTF_DIRTY;	nfp->ctf_data.cts_data = NULL; /* force ctf_data_free() on close */	nfp->ctf_dtdefs = fp->ctf_dtdefs;	nfp->ctf_dtstrlen = fp->ctf_dtstrlen;	nfp->ctf_dtnextid = fp->ctf_dtnextid;	nfp->ctf_dtoldid = fp->ctf_dtnextid - 1;	bzero(&fp->ctf_dtdefs, sizeof (ctf_list_t));	bcopy(fp, &ofp, sizeof (ctf_file_t));	bcopy(nfp, fp, sizeof (ctf_file_t));	bcopy(&ofp, nfp, sizeof (ctf_file_t));	/*	 * Initialize the ctf_lookup_by_name top-level dictionary.  We keep an	 * array of type name prefixes and the corresponding ctf_hash to use.	 * NOTE: This code must be kept in sync with the code in ctf_bufopen().	 */	fp->ctf_lookups[0].ctl_hash = &fp->ctf_structs;	fp->ctf_lookups[1].ctl_hash = &fp->ctf_unions;	fp->ctf_lookups[2].ctl_hash = &fp->ctf_enums;	fp->ctf_lookups[3].ctl_hash = &fp->ctf_names;	nfp->ctf_refcnt = 1; /* force nfp to be freed */	ctf_close(nfp);	return (0);}/* * Discard all of the dynamic type definitions that have been added to the * container since the last call to ctf_update().  We locate such types by * scanning the list and deleting elements that have type IDs greater than * ctf_dtoldid, which is set by ctf_update(), above. */intctf_discard(ctf_file_t *fp){	ctf_dtdef_t *dtd, *ntd;	ctf_dmdef_t *dmd, *nmd;	size_t len;	if (!(fp->ctf_flags & LCTF_RDWR))		return (ctf_set_errno(fp, ECTF_RDONLY));	if (!(fp->ctf_flags & LCTF_DIRTY))		return (0); /* no update required */	for (dtd = ctf_list_next(&fp->ctf_dtdefs); dtd != NULL; dtd = ntd) {		if (dtd->dtd_type <= fp->ctf_dtoldid)			continue; /* skip types that have been committed */		switch (CTF_INFO_KIND(dtd->dtd_data.ctt_info)) {		case CTF_K_STRUCT:		case CTF_K_UNION:		case CTF_K_ENUM:			for (dmd = ctf_list_next(&dtd->dtd_u.dtu_members);			    dmd != NULL; dmd = nmd) {				if (dmd->dmd_name != NULL) {					len = strlen(dmd->dmd_name) + 1;					ctf_free(dmd->dmd_name, len);					fp->ctf_dtstrlen -= len;

⌨️ 快捷键说明

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