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

📄 ctf_types.c

📁 Sun Solaris 10 中的 DTrace 组件的源代码。请参看: http://www.sun.com/software/solaris/observability.jsp
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * 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_types.c	1.6	03/09/02 SMI"#include <sys/sysmacros.h>#include <ctf_impl.h>ssize_tctf_get_ctt_size(const ctf_file_t *fp, const ctf_type_t *tp, ssize_t *sizep,    ssize_t *incrementp){	ssize_t size, increment;	if (fp->ctf_version > CTF_VERSION_1 &&	    tp->ctt_size == CTF_LSIZE_SENT) {		size = CTF_TYPE_LSIZE(tp);		increment = sizeof (ctf_type_t);	} else {		size = tp->ctt_size;		increment = sizeof (ctf_stype_t);	}	if (sizep)		*sizep = size;	if (incrementp)		*incrementp = increment;	return (size);}/* * Iterate over the members of a STRUCT or UNION.  We pass the name, member * type, and offset of each member to the specified callback function. */intctf_member_iter(ctf_file_t *fp, ctf_id_t type, ctf_member_f *func, void *arg){	ctf_file_t *ofp = fp;	const ctf_type_t *tp;	ssize_t size, increment;	uint_t kind, n;	int rc;	if ((type = ctf_type_resolve(fp, type)) == CTF_ERR)		return (CTF_ERR); /* errno is set for us */	if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)		return (CTF_ERR); /* errno is set for us */	(void) ctf_get_ctt_size(fp, tp, &size, &increment);	kind = LCTF_INFO_KIND(fp, tp->ctt_info);	if (kind != CTF_K_STRUCT && kind != CTF_K_UNION)		return (ctf_set_errno(ofp, ECTF_NOTSOU));	if (fp->ctf_version == CTF_VERSION_1 || size < CTF_LSTRUCT_THRESH) {		const ctf_member_t *mp = (const ctf_member_t *)		    ((uintptr_t)tp + increment);		for (n = LCTF_INFO_VLEN(fp, tp->ctt_info); n != 0; n--, mp++) {			const char *name = ctf_strptr(fp, mp->ctm_name);			if ((rc = func(name, mp->ctm_type, mp->ctm_offset,			    arg)) != 0)				return (rc);		}	} else {		const ctf_lmember_t *lmp = (const ctf_lmember_t *)		    ((uintptr_t)tp + increment);		for (n = LCTF_INFO_VLEN(fp, tp->ctt_info); n != 0; n--, lmp++) {			const char *name = ctf_strptr(fp, lmp->ctlm_name);			if ((rc = func(name, lmp->ctlm_type,			    (ulong_t)CTF_LMEM_OFFSET(lmp), arg)) != 0)				return (rc);		}	}	return (0);}/* * Iterate over the members of an ENUM.  We pass the string name and associated * integer value of each enum element to the specified callback function. */intctf_enum_iter(ctf_file_t *fp, ctf_id_t type, ctf_enum_f *func, void *arg){	ctf_file_t *ofp = fp;	const ctf_type_t *tp;	const ctf_enum_t *ep;	ssize_t increment;	uint_t n;	int rc;	if ((type = ctf_type_resolve(fp, type)) == CTF_ERR)		return (CTF_ERR); /* errno is set for us */	if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)		return (CTF_ERR); /* errno is set for us */	if (LCTF_INFO_KIND(fp, tp->ctt_info) != CTF_K_ENUM)		return (ctf_set_errno(ofp, ECTF_NOTENUM));	(void) ctf_get_ctt_size(fp, tp, NULL, &increment);	ep = (const ctf_enum_t *)((uintptr_t)tp + increment);	for (n = LCTF_INFO_VLEN(fp, tp->ctt_info); n != 0; n--, ep++) {		const char *name = ctf_strptr(fp, ep->cte_name);		if ((rc = func(name, ep->cte_value, arg)) != 0)			return (rc);	}	return (0);}/* * Iterate over every root (user-visible) type in the given CTF container. * We pass the type ID of each type to the specified callback function. */intctf_type_iter(ctf_file_t *fp, ctf_type_f *func, void *arg){	ctf_id_t id, max = fp->ctf_typemax;	int rc, child = (fp->ctf_flags & LCTF_CHILD);	for (id = 1; id <= max; id++) {		const ctf_type_t *tp = LCTF_INDEX_TO_TYPEPTR(fp, id);		if (CTF_INFO_ISROOT(tp->ctt_info) &&		    (rc = func(CTF_INDEX_TO_TYPE(id, child), arg)) != 0)			return (rc);	}	return (0);}/* * Follow a given type through the graph for TYPEDEF, VOLATILE, CONST, and * RESTRICT nodes until we reach a "base" type node.  This is useful when * we want to follow a type ID to a node that has members or a size.  To guard * against infinite loops, we implement simplified cycle detection and check * each link against itself, the previous node, and the topmost node. */ctf_id_tctf_type_resolve(ctf_file_t *fp, ctf_id_t type){	ctf_id_t prev = type, otype = type;	ctf_file_t *ofp = fp;	const ctf_type_t *tp;	while ((tp = ctf_lookup_by_id(&fp, type)) != NULL) {		switch (LCTF_INFO_KIND(fp, tp->ctt_info)) {		case CTF_K_TYPEDEF:		case CTF_K_VOLATILE:		case CTF_K_CONST:		case CTF_K_RESTRICT:			if (tp->ctt_type == type || tp->ctt_type == otype ||			    tp->ctt_type == prev) {				ctf_dprintf("type %ld cycle detected\n", otype);				return (ctf_set_errno(ofp, ECTF_CORRUPT));			}			prev = type;			type = tp->ctt_type;			break;		default:			return (type);		}	}	return (CTF_ERR); /* errno is set for us */}/* * Lookup the given type ID and print a string name for it into buf.  If buf * is too small, an appropriate error will be returned to the caller. */char *ctf_type_name(ctf_file_t *fp, ctf_id_t type, char *buf, size_t len){	ctf_file_t *ofp = fp;	const ctf_type_t *tp;	const ctf_array_t *ap;	const char *name;	char *p, *q;	uint_t kind;	ssize_t size, increment;	int rlen;	if (buf == NULL || len == 0) {		(void) ctf_set_errno(ofp, EINVAL);		return (NULL);	}	buf[0] = '\0'; /* start with empty string */	for (p = buf, q = buf + len; p < q; p += strlen(p)) {		if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)			return (NULL); /* errno is set for us */		len = (size_t)(q - p); /* bytes remaining in buf */		name = ctf_strptr(fp, tp->ctt_name);		kind = LCTF_INFO_KIND(fp, tp->ctt_info);		(void) ctf_get_ctt_size(fp, tp, &size, &increment);		if (name[0] != '\0' && (kind == CTF_K_FUNCTION ||		    kind == CTF_K_POINTER || kind == CTF_K_VOLATILE ||		    kind == CTF_K_CONST || kind == CTF_K_RESTRICT)) {			if (snprintf(p, len, "%s", name) >= len)				goto out;			return (buf);		}		switch (kind) {		case CTF_K_TYPEDEF:			if (name[0] == '\0') {				type = tp->ctt_type;				break;			}			/*FALLTHRU*/		case CTF_K_INTEGER:		case CTF_K_FLOAT:			if (snprintf(p, len, "%s", name) >= len)				goto out;			return (buf);		case CTF_K_ARRAY:			ap = (const ctf_array_t *)((uintptr_t)tp + increment);			if (ctf_type_name(fp, ap->cta_contents, p, len) == NULL)				return (NULL); /* errno is set for us */			p = buf + strlen(buf);			len = (size_t)(q - p);			if (snprintf(p, len, " [%u]", ap->cta_nelems) >= len)				goto out;			return (buf);		case CTF_K_FUNCTION:		case CTF_K_POINTER:			if (ctf_type_name(fp, tp->ctt_type, p, len) == NULL)				return (NULL); /* errno is set for us */			/*			 * We assume that all functions are really			 * pointers to functions.			 */			if (kind == CTF_K_POINTER &&			    ctf_type_kind(fp, tp->ctt_type) == CTF_K_FUNCTION)				return (buf);			p = buf + strlen(buf);			len = (size_t)(q - p);			if (kind == CTF_K_FUNCTION)				rlen = snprintf(p, len, " (*)()");			else if (ctf_type_kind(fp,			    tp->ctt_type) == CTF_K_POINTER)				rlen = snprintf(p, len, "*");			else				rlen = snprintf(p, len, " *");			if (rlen >= len)				goto out;			return (buf);		case CTF_K_STRUCT:		case CTF_K_FORWARD:			if (snprintf(p, len, "struct %s", name) >= len)				goto out;			return (buf);		case CTF_K_UNION:			if (snprintf(p, len, "union %s", name) >= len)				goto out;			return (buf);		case CTF_K_ENUM:			if (snprintf(p, len, "enum %s", name) >= len)				goto out;			return (buf);		case CTF_K_VOLATILE:			if (snprintf(p, len, "volatile ") >= len)				goto out;			type = tp->ctt_type;			break;		case CTF_K_CONST:			if (snprintf(p, len, "const ") >= len)				goto out;			type = tp->ctt_type;			break;		case CTF_K_RESTRICT:			if (snprintf(p, len, "restrict ") >= len)				goto out;			type = tp->ctt_type;			break;		default:			(void) ctf_set_errno(ofp, ECTF_CORRUPT);			return (NULL);		}	}out:	(void) ctf_set_errno(ofp, ECTF_NAMELEN);	buf[0] = '\0';	return (NULL);}/* * Resolve the type down to a base type node, and then return the size * of the type storage in bytes. */ssize_tctf_type_size(ctf_file_t *fp, ctf_id_t type){	const ctf_type_t *tp;	ssize_t size;	ctf_arinfo_t ar;	if ((type = ctf_type_resolve(fp, type)) == CTF_ERR)		return (-1); /* errno is set for us */	if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)		return (-1); /* errno is set for us */	switch (LCTF_INFO_KIND(fp, tp->ctt_info)) {	case CTF_K_POINTER:		return (fp->ctf_dmodel->ctd_pointer);	case CTF_K_FUNCTION:		return (0); /* function size is only known by symtab */	case CTF_K_ENUM:		return (fp->ctf_dmodel->ctd_int);	case CTF_K_ARRAY:		/*		 * Array size is not directly returned by stabs data.  Instead,		 * it defines the element type and requires the user to perform		 * the multiplication.  If ctf_get_ctt_size() returns zero, the		 * current version of ctfconvert does not compute member sizes		 * and we compute the size here on its behalf.		 */		if ((size = ctf_get_ctt_size(fp, tp, NULL, NULL)) > 0)			return (size);		if (ctf_array_info(fp, type, &ar) == CTF_ERR ||		    (size = ctf_type_size(fp, ar.ctr_contents)) == CTF_ERR)			return (-1); /* errno is set for us */		return (size * ar.ctr_nelems);	default:		return (ctf_get_ctt_size(fp, tp, NULL, NULL));	}}/* * Resolve the type down to a base type node, and then return the alignment * needed for the type storage in bytes. */ssize_tctf_type_align(ctf_file_t *fp, ctf_id_t type){	const ctf_type_t *tp;	ctf_arinfo_t r;	if ((type = ctf_type_resolve(fp, type)) == CTF_ERR)		return (-1); /* errno is set for us */	if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)		return (-1); /* errno is set for us */	switch (LCTF_INFO_KIND(fp, tp->ctt_info)) {	case CTF_K_POINTER:	case CTF_K_FUNCTION:		return (fp->ctf_dmodel->ctd_pointer);	case CTF_K_ARRAY:		if (ctf_array_info(fp, type, &r) == CTF_ERR)			return (-1); /* errno is set for us */		return (ctf_type_align(fp, r.ctr_contents));	case CTF_K_STRUCT:	case CTF_K_UNION: {		uint_t n = LCTF_INFO_VLEN(fp, tp->ctt_info);		ssize_t size, increment;		size_t align = 0;		const void *vmp;		(void) ctf_get_ctt_size(fp, tp, &size, &increment);		vmp = (uchar_t *)tp + increment;		if (LCTF_INFO_KIND(fp, tp->ctt_info) == CTF_K_STRUCT)			n = MIN(n, 1); /* only use first member for structs */		if (fp->ctf_version == CTF_VERSION_1 ||		    size < CTF_LSTRUCT_THRESH) {			const ctf_member_t *mp = vmp;			for (; n != 0; n--, mp++) {				ssize_t am = ctf_type_align(fp, mp->ctm_type);				align = MAX(align, am);			}		} else {			const ctf_lmember_t *lmp = vmp;			for (; n != 0; n--, lmp++) {				ssize_t am = ctf_type_align(fp, lmp->ctlm_type);				align = MAX(align, am);			}		}		return (align);	}

⌨️ 快捷键说明

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