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

📄 ctf_create.c

📁 Sun Solaris 10 中的 DTrace 组件的源代码。请参看: http://www.sun.com/software/solaris/observability.jsp
💻 C
📖 第 1 页 / 共 3 页
字号:
		for (dmd = ctf_list_next(&dtd->dtd_u.dtu_members);		    dmd != NULL; dmd = ctf_list_next(dmd)) {			if (dmd->dmd_name != NULL &&			    strcmp(dmd->dmd_name, name) == 0)				return (ctf_set_errno(fp, ECTF_DUPMEMBER));		}	}	if ((msize = ctf_type_size(fp, type)) == CTF_ERR ||	    (malign = ctf_type_align(fp, type)) == CTF_ERR)		return (CTF_ERR); /* errno is set for us */	if ((dmd = ctf_alloc(sizeof (ctf_dmdef_t))) == NULL)		return (ctf_set_errno(fp, EAGAIN));	if (name != NULL && (s = ctf_strdup(name)) == NULL) {		ctf_free(dmd, sizeof (ctf_dmdef_t));		return (ctf_set_errno(fp, EAGAIN));	}	dmd->dmd_name = s;	dmd->dmd_type = type;	dmd->dmd_value = -1;	if (kind == CTF_K_STRUCT && vlen != 0) {		ctf_dmdef_t *lmd = ctf_list_prev(&dtd->dtd_u.dtu_members);		ctf_id_t ltype = ctf_type_resolve(fp, lmd->dmd_type);		size_t off = lmd->dmd_offset;		ctf_encoding_t linfo;		ssize_t lsize;		if (ctf_type_encoding(fp, ltype, &linfo) != CTF_ERR)			off += linfo.cte_bits;		else if ((lsize = ctf_type_size(fp, ltype)) != CTF_ERR)			off += lsize * NBBY;		/*		 * Round up the offset of the end of the last member to the		 * next byte boundary, convert 'off' to bytes, and then round		 * it up again to the next multiple of the alignment required		 * by the new member.  Finally, convert back to bits and store		 * the result in dmd_offset.  Technically we could do more		 * efficient packing if the new member is a bit-field, but		 * we're the "compiler" and ANSI says we can do as we choose.		 */		off = roundup(off, NBBY) / NBBY;		off = roundup(off, MAX(malign, 1));		dmd->dmd_offset = off * NBBY;		ssize = off + msize;	} else {		dmd->dmd_offset = 0;		ssize = ctf_get_ctt_size(fp, &dtd->dtd_data, NULL, NULL);		ssize = MAX(ssize, msize);	}	if (ssize > CTF_MAX_SIZE) {		dtd->dtd_data.ctt_size = CTF_LSIZE_SENT;		dtd->dtd_data.ctt_lsizehi = CTF_SIZE_TO_LSIZE_HI(ssize);		dtd->dtd_data.ctt_lsizelo = CTF_SIZE_TO_LSIZE_LO(ssize);	} else		dtd->dtd_data.ctt_size = (ushort_t)ssize;	dtd->dtd_data.ctt_info = CTF_TYPE_INFO(kind, root, vlen + 1);	ctf_list_append(&dtd->dtd_u.dtu_members, dmd);	if (s != NULL)		fp->ctf_dtstrlen += strlen(s) + 1;	fp->ctf_flags |= LCTF_DIRTY;	return (0);}static intenumcmp(const char *name, int value, void *arg){	ctf_bundle_t *ctb = arg;	int bvalue;	return (ctf_enum_value(ctb->ctb_file, ctb->ctb_type,	    name, &bvalue) == CTF_ERR || value != bvalue);}static intenumadd(const char *name, int value, void *arg){	ctf_bundle_t *ctb = arg;	return (ctf_add_enumerator(ctb->ctb_file, ctb->ctb_type,	    name, value) == CTF_ERR);}/*ARGSUSED*/static intmembcmp(const char *name, ctf_id_t type, ulong_t offset, void *arg){	ctf_bundle_t *ctb = arg;	ctf_membinfo_t ctm;	return (ctf_member_info(ctb->ctb_file, ctb->ctb_type,	    name, &ctm) == CTF_ERR || ctm.ctm_offset != offset);}static intmembadd(const char *name, ctf_id_t type, ulong_t offset, void *arg){	ctf_bundle_t *ctb = arg;	ctf_dmdef_t *dmd;	char *s = NULL;	if ((dmd = ctf_alloc(sizeof (ctf_dmdef_t))) == NULL)		return (ctf_set_errno(ctb->ctb_file, EAGAIN));	if (name != NULL && (s = ctf_strdup(name)) == NULL) {		ctf_free(dmd, sizeof (ctf_dmdef_t));		return (ctf_set_errno(ctb->ctb_file, EAGAIN));	}	/*	 * For now, dmd_type is copied as the src_fp's type; it is reset to an	 * equivalent dst_fp type by a final loop in ctf_add_type(), below.	 */	dmd->dmd_name = s;	dmd->dmd_type = type;	dmd->dmd_offset = offset;	dmd->dmd_value = -1;	ctf_list_append(&ctb->ctb_dtd->dtd_u.dtu_members, dmd);	if (s != NULL)		ctb->ctb_file->ctf_dtstrlen += strlen(s) + 1;	ctb->ctb_file->ctf_flags |= LCTF_DIRTY;	return (0);}/* * The ctf_add_type routine is used to copy a type from a source CTF container * to a dynamic destination container.  This routine operates recursively by * following the source type's links and embedded member types.  If the * destination container already contains a named type which has the same * attributes, then we succeed and return this type but no changes occur. */ctf_id_tctf_add_type(ctf_file_t *dst_fp, ctf_file_t *src_fp, ctf_id_t src_type){	ctf_id_t dst_type = CTF_ERR;	const ctf_type_t *tp;	const char *name;	uint_t kind, flag, vlen;	ctf_bundle_t src, dst;	ctf_encoding_t src_en, dst_en;	ctf_arinfo_t src_ar, dst_ar;	ctf_dtdef_t *dtd;	ctf_funcinfo_t ctc;	ssize_t size;	ctf_hash_t *hp;	ctf_helem_t *hep;	if (!(dst_fp->ctf_flags & LCTF_RDWR))		return (ctf_set_errno(dst_fp, ECTF_RDONLY));	if ((tp = ctf_lookup_by_id(&src_fp, src_type)) == NULL)		return (ctf_set_errno(dst_fp, ctf_errno(src_fp)));	name = ctf_strptr(src_fp, tp->ctt_name);	kind = LCTF_INFO_KIND(src_fp, tp->ctt_info);	flag = LCTF_INFO_ROOT(src_fp, tp->ctt_info);	vlen = LCTF_INFO_VLEN(src_fp, tp->ctt_info);	switch (kind) {	case CTF_K_STRUCT:		hp = &dst_fp->ctf_structs;		break;	case CTF_K_UNION:		hp = &dst_fp->ctf_unions;		break;	case CTF_K_ENUM:		hp = &dst_fp->ctf_enums;		break;	default:		hp = &dst_fp->ctf_names;		break;	}	/*	 * If the source type has a name and is a root type (visible at the	 * top-level scope), lookup the name in the destination container and	 * verify that it is of the same kind before we do anything else.	 */	if ((flag & CTF_ADD_ROOT) && name[0] != '\0' &&	    (hep = ctf_hash_lookup(hp, dst_fp, name, strlen(name))) != NULL)		dst_type = (ctf_id_t)hep->h_type;	if (dst_type != CTF_ERR && ctf_type_kind(dst_fp, dst_type) != kind)		return (ctf_set_errno(dst_fp, ECTF_CONFLICT));	/*	 * If the non-empty name was not found in the appropriate hash, search	 * the list of pending dynamic definitions that are not yet committed.	 * If a matching name and kind are found, assume this is the type that	 * we are looking for.  This is necessary to permit ctf_add_type() to	 * operate recursively on entities such as a struct that contains a	 * pointer member that refers to the same struct type.	 */	if (dst_type == CTF_ERR && name[0] != '\0') {		for (dtd = ctf_list_prev(&dst_fp->ctf_dtdefs); dtd != NULL &&		    dtd->dtd_type > dst_fp->ctf_dtoldid;		    dtd = ctf_list_prev(dtd)) {			if (CTF_INFO_KIND(dtd->dtd_data.ctt_info) == kind &&			    dtd->dtd_name != NULL &&			    strcmp(dtd->dtd_name, name) == 0)				return (dtd->dtd_type);		}	}	src.ctb_file = src_fp;	src.ctb_type = src_type;	src.ctb_dtd = NULL;	dst.ctb_file = dst_fp;	dst.ctb_type = dst_type;	dst.ctb_dtd = NULL;	/*	 * Now perform kind-specific processing.  If dst_type is CTF_ERR, then	 * we add a new type with the same properties as src_type to dst_fp.	 * If dst_type is not CTF_ERR, then we verify that dst_type has the	 * same attributes as src_type.  We recurse for embedded references.	 */	switch (kind) {	case CTF_K_INTEGER:	case CTF_K_FLOAT:		if (ctf_type_encoding(src_fp, src_type, &src_en) != 0)			return (ctf_set_errno(dst_fp, ctf_errno(src_fp)));		if (dst_type != CTF_ERR) {			if (ctf_type_encoding(dst_fp, dst_type, &dst_en) != 0)				return (CTF_ERR); /* errno is set for us */			if (bcmp(&src_en, &dst_en, sizeof (ctf_encoding_t)))				return (ctf_set_errno(dst_fp, ECTF_CONFLICT));		} else if (kind == CTF_K_INTEGER) {			dst_type = ctf_add_integer(dst_fp, flag, name, &src_en);		} else			dst_type = ctf_add_float(dst_fp, flag, name, &src_en);		break;	case CTF_K_POINTER:	case CTF_K_VOLATILE:	case CTF_K_CONST:	case CTF_K_RESTRICT:		src_type = ctf_type_reference(src_fp, src_type);		src_type = ctf_add_type(dst_fp, src_fp, src_type);		if (src_type == CTF_ERR)			return (CTF_ERR); /* errno is set for us */		dst_type = ctf_add_reftype(dst_fp, flag, src_type, kind);		break;	case CTF_K_ARRAY:		if (ctf_array_info(src_fp, src_type, &src_ar) == CTF_ERR)			return (ctf_set_errno(dst_fp, ctf_errno(src_fp)));		src_ar.ctr_contents =		    ctf_add_type(dst_fp, src_fp, src_ar.ctr_contents);		src_ar.ctr_index =		    ctf_add_type(dst_fp, src_fp, src_ar.ctr_index);		src_ar.ctr_nelems = src_ar.ctr_nelems;		if (src_ar.ctr_contents == CTF_ERR ||		    src_ar.ctr_index == CTF_ERR)			return (CTF_ERR); /* errno is set for us */		if (dst_type != CTF_ERR) {			if (ctf_array_info(dst_fp, dst_type, &dst_ar) != 0)				return (CTF_ERR); /* errno is set for us */			if (bcmp(&src_ar, &dst_ar, sizeof (ctf_arinfo_t)))				return (ctf_set_errno(dst_fp, ECTF_CONFLICT));		} else			dst_type = ctf_add_array(dst_fp, flag, &src_ar);		break;	case CTF_K_FUNCTION:		ctc.ctc_return = ctf_add_type(dst_fp, src_fp, tp->ctt_type);		ctc.ctc_argc = 0;		ctc.ctc_flags = 0;		if (ctc.ctc_return == CTF_ERR)			return (CTF_ERR); /* errno is set for us */		dst_type = ctf_add_function(dst_fp, flag, &ctc, NULL);		break;	case CTF_K_STRUCT:	case CTF_K_UNION: {		ctf_dmdef_t *dmd;		int errs = 0;		/*		 * Technically to match a struct or union we need to check both		 * ways (src members vs. dst, dst members vs. src) but we make		 * this more optimal by only checking src vs. dst and comparing		 * the total size of the structure (which we must do anyway)		 * which covers the possibility of dst members not in src.		 * This optimization can be defeated for unions, but is so		 * pathological as to render it irrelevant for our purposes.		 */		if (dst_type != CTF_ERR) {			if (ctf_type_size(src_fp, src_type) !=			    ctf_type_size(dst_fp, dst_type))				return (ctf_set_errno(dst_fp, ECTF_CONFLICT));			if (ctf_member_iter(src_fp, src_type, membcmp, &dst))				return (ctf_set_errno(dst_fp, ECTF_CONFLICT));			break;		}		/*		 * Unlike the other cases, copying structs and unions is done		 * manually so as to avoid repeated lookups in ctf_add_member		 * and to ensure the exact same member offsets as in src_type.		 */		dst_type = ctf_add_generic(dst_fp, flag, name, &dtd);		if (dst_type == CTF_ERR)			return (CTF_ERR); /* errno is set for us */		dst.ctb_type = dst_type;		dst.ctb_dtd = dtd;		if (ctf_member_iter(src_fp, src_type, membadd, &dst) != 0)			errs++; /* increment errs and fail at bottom of case */		if ((size = ctf_type_size(src_fp, src_type)) > CTF_MAX_SIZE) {			dtd->dtd_data.ctt_size = CTF_LSIZE_SENT;			dtd->dtd_data.ctt_lsizehi = CTF_SIZE_TO_LSIZE_HI(size);			dtd->dtd_data.ctt_lsizelo = CTF_SIZE_TO_LSIZE_LO(size);		} else			dtd->dtd_data.ctt_size = (ushort_t)size;		dtd->dtd_data.ctt_info = CTF_TYPE_INFO(kind, flag, vlen);		/*		 * Make a final pass through the members changing each dmd_type		 * (a src_fp type) to an equivalent type in dst_fp.  We pass		 * through all members, leaving any that fail set to CTF_ERR.		 */		for (dmd = ctf_list_next(&dtd->dtd_u.dtu_members);		    dmd != NULL; dmd = ctf_list_next(dmd)) {			if ((dmd->dmd_type = ctf_add_type(dst_fp, src_fp,			    dmd->dmd_type)) == CTF_ERR)				errs++;		}		if (errs)			return (CTF_ERR); /* errno is set for us */		break;	}	case CTF_K_ENUM:		if (dst_type != CTF_ERR) {			if (ctf_enum_iter(src_fp, src_type, enumcmp, &dst) ||			    ctf_enum_iter(dst_fp, dst_type, enumcmp, &src))				return (ctf_set_errno(dst_fp, ECTF_CONFLICT));		} else {			dst_type = ctf_add_enum(dst_fp, flag, name);			if ((dst.ctb_type = dst_type) == CTF_ERR ||			    ctf_enum_iter(src_fp, src_type, enumadd, &dst))				return (CTF_ERR); /* errno is set for us */		}		break;	case CTF_K_FORWARD:		if (dst_type == CTF_ERR) {			dst_type = ctf_add_forward(dst_fp,			    flag, name, CTF_K_STRUCT); /* assume STRUCT */		}		break;	case CTF_K_TYPEDEF:		src_type = ctf_type_reference(src_fp, src_type);		src_type = ctf_add_type(dst_fp, src_fp, src_type);		if (src_type == CTF_ERR)			return (CTF_ERR); /* errno is set for us */		/*		 * If dst_type is not CTF_ERR at this point, we should check if		 * ctf_type_reference(dst_fp, dst_type) != src_type and if so		 * fail with ECTF_CONFLICT.  However, this causes problems with		 * <sys/types.h> typedefs that vary based on things like if		 * _ILP32x then pid_t is int otherwise long.  We therefore omit		 * this check and assume that if the identically named typedef		 * already exists in dst_fp, it is correct or equivalent.		 */		if (dst_type == CTF_ERR) {			dst_type = ctf_add_typedef(dst_fp, flag,			    name, src_type);		}		break;	default:		return (ctf_set_errno(dst_fp, ECTF_CORRUPT));	}	return (dst_type);}

⌨️ 快捷键说明

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