Пример #1
0
/*
 * Resolve the type down to a base type node, and then return the alignment
 * needed for the type storage in bytes.
 */
ssize_t
ctf_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);
	}

	case CTF_K_ENUM:
		return (fp->ctf_dmodel->ctd_int);

	default:
		return (ctf_get_ctt_size(fp, tp, NULL, NULL));
	}
}
Пример #2
0
/*
 * Convert the specified enum tag name to the corresponding value, if a
 * matching name can be found.  Otherwise CTF_ERR is returned.
 */
int
ctf_enum_value(ctf_file_t *fp, ctf_id_t type, const char *name, int *valp)
{
	ctf_file_t *ofp = fp;
	const ctf_type_t *tp;
	const ctf_enum_t *ep;
	ssize_t size, increment;
	uint_t n;

	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) {
		(void) ctf_set_errno(ofp, ECTF_NOTENUM);
		return (CTF_ERR);
	}

	(void) ctf_get_ctt_size(fp, tp, &size, &increment);

	ep = (const ctf_enum_t *)((uintptr_t)tp + increment);

	for (n = LCTF_INFO_VLEN(fp, tp->ctt_info); n != 0; n--, ep++) {
		if (strcmp(ctf_strptr(fp, ep->cte_name), name) == 0) {
			if (valp != NULL)
				*valp = ep->cte_value;
			return (0);
		}
	}

	(void) ctf_set_errno(ofp, ECTF_NOENUMNAM);
	return (CTF_ERR);
}
Пример #3
0
/*
 * Return the encoding for the specified INTEGER or FLOAT.
 */
int
ctf_type_encoding(ctf_file_t *fp, ctf_id_t type, ctf_encoding_t *ep)
{
	ctf_file_t *ofp = fp;
	const ctf_type_t *tp;
	ssize_t increment;
	uint_t data;

	if ((tp = ctf_lookup_by_id(&fp, type)) == NULL)
		return (CTF_ERR); /* errno is set for us */

	(void) ctf_get_ctt_size(fp, tp, NULL, &increment);

	switch (LCTF_INFO_KIND(fp, tp->ctt_info)) {
	case CTF_K_INTEGER:
		data = *(const uint_t *)((uintptr_t)tp + increment);
		ep->cte_format = CTF_INT_ENCODING(data);
		ep->cte_offset = CTF_INT_OFFSET(data);
		ep->cte_bits = CTF_INT_BITS(data);
		break;
	case CTF_K_FLOAT:
		data = *(const uint_t *)((uintptr_t)tp + increment);
		ep->cte_format = CTF_FP_ENCODING(data);
		ep->cte_offset = CTF_FP_OFFSET(data);
		ep->cte_bits = CTF_FP_BITS(data);
		break;
	default:
		return (ctf_set_errno(ofp, ECTF_NOTINTFP));
	}

	return (0);
}
Пример #4
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.
 */
int
ctf_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);
}
Пример #5
0
/*
 * Resolve the type down to a base type node, and then return the size
 * of the type storage in bytes.
 */
ssize_t
ctf_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));
	}
}
Пример #6
0
/*
 * Recursively visit the members of any type.  This function is used as the
 * engine for ctf_type_visit, below.  We resolve the input type, recursively
 * invoke ourself for each type member if the type is a struct or union, and
 * then invoke the callback function on the current type.  If any callback
 * returns non-zero, we abort and percolate the error code back up to the top.
 */
static int
ctf_type_rvisit(ctf_file_t *fp, ctf_id_t type, ctf_visit_f *func, void *arg,
    const char *name, ulong_t offset, int depth)
{
	ctf_id_t otype = type;
	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 */

	if ((rc = func(name, otype, offset, depth, arg)) != 0)
		return (rc);

	kind = LCTF_INFO_KIND(fp, tp->ctt_info);

	if (kind != CTF_K_STRUCT && kind != CTF_K_UNION)
		return (0);

	(void) ctf_get_ctt_size(fp, tp, &size, &increment);

	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++) {
			if ((rc = ctf_type_rvisit(fp, mp->ctm_type,
			    func, arg, ctf_strptr(fp, mp->ctm_name),
			    offset + mp->ctm_offset, depth + 1)) != 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++) {
			if ((rc = ctf_type_rvisit(fp, lmp->ctlm_type,
			    func, arg, ctf_strptr(fp, lmp->ctlm_name),
			    offset + (ulong_t)CTF_LMEM_OFFSET(lmp),
			    depth + 1)) != 0)
				return (rc);
		}
	}

	return (0);
}
Пример #7
0
/*
 * Return the type and offset for a given member of a STRUCT or UNION.
 */
int
ctf_member_info(ctf_file_t *fp, ctf_id_t type, const char *name,
    ctf_membinfo_t *mip)
{
	ctf_file_t *ofp = fp;
	const ctf_type_t *tp;
	ssize_t size, increment;
	uint_t kind, n;

	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++) {
			if (strcmp(ctf_strptr(fp, mp->ctm_name), name) == 0) {
				mip->ctm_type = mp->ctm_type;
				mip->ctm_offset = mp->ctm_offset;
				return (0);
			}
		}
	} 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++) {
			if (strcmp(ctf_strptr(fp, lmp->ctlm_name), name) == 0) {
				mip->ctm_type = lmp->ctlm_type;
				mip->ctm_offset = (ulong_t)CTF_LMEM_OFFSET(lmp);
				return (0);
			}
		}
	}

	return (ctf_set_errno(ofp, ECTF_NOMEMBNAM));
}
Пример #8
0
/*
 * Return the array type, index, and size information for the specified ARRAY.
 */
int
ctf_array_info(ctf_file_t *fp, ctf_id_t type, ctf_arinfo_t *arp)
{
	ctf_file_t *ofp = fp;
	const ctf_type_t *tp;
	const ctf_array_t *ap;
	ssize_t increment;

	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_ARRAY)
		return (ctf_set_errno(ofp, ECTF_NOTARRAY));

	(void) ctf_get_ctt_size(fp, tp, NULL, &increment);

	ap = (const ctf_array_t *)((uintptr_t)tp + increment);
	arp->ctr_contents = ap->cta_contents;
	arp->ctr_index = ap->cta_index;
	arp->ctr_nelems = ap->cta_nelems;

	return (0);
}
Пример #9
0
/*
 * Initialize the type ID translation table with the byte offset of each type,
 * and initialize the hash tables of each named type.
 */
static int
init_types(ctf_file_t *fp, const ctf_header_t *cth)
{
	/* LINTED - pointer alignment */
	const ctf_type_t *tbuf = (ctf_type_t *)(fp->ctf_buf + cth->cth_typeoff);
	/* LINTED - pointer alignment */
	const ctf_type_t *tend = (ctf_type_t *)(fp->ctf_buf + cth->cth_stroff);

	ulong_t pop[CTF_K_MAX + 1] = { 0 };
	const ctf_type_t *tp;
	ctf_hash_t *hp;
	ushort_t dst;
	ctf_id_t id;
	uint_t *xp;

	/*
	 * We initially determine whether the container is a child or a parent
	 * based on the value of cth_parname.  To support containers that pre-
	 * date cth_parname, we also scan the types themselves for references
	 * to values in the range reserved for child types in our first pass.
	 */
	int child = cth->cth_parname != 0;
	int nlstructs = 0, nlunions = 0;
	int err;

	/*
	 * We make two passes through the entire type section.  In this first
	 * pass, we count the number of each type and the total number of types.
	 */
	for (tp = tbuf; tp < tend; fp->ctf_typemax++) {
		ushort_t kind = LCTF_INFO_KIND(fp, tp->ctt_info);
		ulong_t vlen = LCTF_INFO_VLEN(fp, tp->ctt_info);
		ssize_t size, increment;

		size_t vbytes;
		uint_t n;

		(void) ctf_get_ctt_size(fp, tp, &size, &increment);

		switch (kind) {
		case CTF_K_INTEGER:
		case CTF_K_FLOAT:
			vbytes = sizeof (uint_t);
			break;
		case CTF_K_ARRAY:
			vbytes = sizeof (ctf_array_t);
			break;
		case CTF_K_FUNCTION:
			vbytes = sizeof (ushort_t) * (vlen + (vlen & 1));
			break;
		case CTF_K_STRUCT:
		case CTF_K_UNION:
			if (fp->ctf_version == CTF_VERSION_1 ||
			    size < CTF_LSTRUCT_THRESH) {
				ctf_member_t *mp = (ctf_member_t *)
				    ((uintptr_t)tp + increment);

				vbytes = sizeof (ctf_member_t) * vlen;
				for (n = vlen; n != 0; n--, mp++)
					child |= CTF_TYPE_ISCHILD(mp->ctm_type);
			} else {
				ctf_lmember_t *lmp = (ctf_lmember_t *)
				    ((uintptr_t)tp + increment);

				vbytes = sizeof (ctf_lmember_t) * vlen;
				for (n = vlen; n != 0; n--, lmp++)
					child |=
					    CTF_TYPE_ISCHILD(lmp->ctlm_type);
			}
			break;
		case CTF_K_ENUM:
			vbytes = sizeof (ctf_enum_t) * vlen;
			break;
		case CTF_K_FORWARD:
			/*
			 * For forward declarations, ctt_type is the CTF_K_*
			 * kind for the tag, so bump that population count too.
			 * If ctt_type is unknown, treat the tag as a struct.
			 */
			if (tp->ctt_type == CTF_K_UNKNOWN ||
			    tp->ctt_type >= CTF_K_MAX)
				pop[CTF_K_STRUCT]++;
			else
				pop[tp->ctt_type]++;
			/*FALLTHRU*/
		case CTF_K_UNKNOWN:
			vbytes = 0;
			break;
		case CTF_K_POINTER:
		case CTF_K_TYPEDEF:
		case CTF_K_VOLATILE:
		case CTF_K_CONST:
		case CTF_K_RESTRICT:
			child |= CTF_TYPE_ISCHILD(tp->ctt_type);
			vbytes = 0;
			break;
		default:
			ctf_dprintf("detected invalid CTF kind -- %u\n", kind);
			return (ECTF_CORRUPT);
		}
		tp = (ctf_type_t *)((uintptr_t)tp + increment + vbytes);
		pop[kind]++;
	}

	/*
	 * If we detected a reference to a child type ID, then we know this
	 * container is a child and may have a parent's types imported later.
	 */
	if (child) {
		ctf_dprintf("CTF container %p is a child\n", (void *)fp);
		fp->ctf_flags |= LCTF_CHILD;
	} else
		ctf_dprintf("CTF container %p is a parent\n", (void *)fp);

	/*
	 * Now that we've counted up the number of each type, we can allocate
	 * the hash tables, type translation table, and pointer table.
	 */
	if ((err = ctf_hash_create(&fp->ctf_structs, pop[CTF_K_STRUCT])) != 0)
		return (err);

	if ((err = ctf_hash_create(&fp->ctf_unions, pop[CTF_K_UNION])) != 0)
		return (err);

	if ((err = ctf_hash_create(&fp->ctf_enums, pop[CTF_K_ENUM])) != 0)
		return (err);

	if ((err = ctf_hash_create(&fp->ctf_names,
	    pop[CTF_K_INTEGER] + pop[CTF_K_FLOAT] + pop[CTF_K_FUNCTION] +
	    pop[CTF_K_TYPEDEF] + pop[CTF_K_POINTER] + pop[CTF_K_VOLATILE] +
	    pop[CTF_K_CONST] + pop[CTF_K_RESTRICT])) != 0)
		return (err);

	fp->ctf_txlate = ctf_alloc(sizeof (uint_t) * (fp->ctf_typemax + 1));
	fp->ctf_ptrtab = ctf_alloc(sizeof (ushort_t) * (fp->ctf_typemax + 1));

	if (fp->ctf_txlate == NULL || fp->ctf_ptrtab == NULL)
		return (EAGAIN); /* memory allocation failed */

	xp = fp->ctf_txlate;
	*xp++ = 0; /* type id 0 is used as a sentinel value */

	bzero(fp->ctf_txlate, sizeof (uint_t) * (fp->ctf_typemax + 1));
	bzero(fp->ctf_ptrtab, sizeof (ushort_t) * (fp->ctf_typemax + 1));

	/*
	 * In the second pass through the types, we fill in each entry of the
	 * type and pointer tables and add names to the appropriate hashes.
	 */
	for (id = 1, tp = tbuf; tp < tend; xp++, id++) {
		ushort_t kind = LCTF_INFO_KIND(fp, tp->ctt_info);
		ulong_t vlen = LCTF_INFO_VLEN(fp, tp->ctt_info);
		ssize_t size, increment;

		const char *name;
		size_t vbytes;
		ctf_helem_t *hep;
		ctf_encoding_t cte;

		(void) ctf_get_ctt_size(fp, tp, &size, &increment);
		name = ctf_strptr(fp, tp->ctt_name);

		switch (kind) {
		case CTF_K_INTEGER:
		case CTF_K_FLOAT:
			/*
			 * Only insert a new integer base type definition if
			 * this type name has not been defined yet.  We re-use
			 * the names with different encodings for bit-fields.
			 */
			if ((hep = ctf_hash_lookup(&fp->ctf_names, fp,
			    name, strlen(name))) == NULL) {
				err = ctf_hash_insert(&fp->ctf_names, fp,
				    CTF_INDEX_TO_TYPE(id, child), tp->ctt_name);
				if (err != 0 && err != ECTF_STRTAB)
					return (err);
			} else if (ctf_type_encoding(fp, hep->h_type,
			    &cte) == 0 && cte.cte_bits == 0) {
				/*
				 * Work-around SOS8 stabs bug: replace existing
				 * intrinsic w/ same name if it was zero bits.
				 */
				hep->h_type = CTF_INDEX_TO_TYPE(id, child);
			}
			vbytes = sizeof (uint_t);
			break;

		case CTF_K_ARRAY:
			vbytes = sizeof (ctf_array_t);
			break;

		case CTF_K_FUNCTION:
			err = ctf_hash_insert(&fp->ctf_names, fp,
			    CTF_INDEX_TO_TYPE(id, child), tp->ctt_name);
			if (err != 0 && err != ECTF_STRTAB)
				return (err);
			vbytes = sizeof (ushort_t) * (vlen + (vlen & 1));
			break;

		case CTF_K_STRUCT:
			err = ctf_hash_define(&fp->ctf_structs, fp,
			    CTF_INDEX_TO_TYPE(id, child), tp->ctt_name);

			if (err != 0 && err != ECTF_STRTAB)
				return (err);

			if (fp->ctf_version == CTF_VERSION_1 ||
			    size < CTF_LSTRUCT_THRESH)
				vbytes = sizeof (ctf_member_t) * vlen;
			else {
				vbytes = sizeof (ctf_lmember_t) * vlen;
				nlstructs++;
			}
			break;

		case CTF_K_UNION:
			err = ctf_hash_define(&fp->ctf_unions, fp,
			    CTF_INDEX_TO_TYPE(id, child), tp->ctt_name);

			if (err != 0 && err != ECTF_STRTAB)
				return (err);

			if (fp->ctf_version == CTF_VERSION_1 ||
			    size < CTF_LSTRUCT_THRESH)
				vbytes = sizeof (ctf_member_t) * vlen;
			else {
				vbytes = sizeof (ctf_lmember_t) * vlen;
				nlunions++;
			}
			break;

		case CTF_K_ENUM:
			err = ctf_hash_define(&fp->ctf_enums, fp,
			    CTF_INDEX_TO_TYPE(id, child), tp->ctt_name);

			if (err != 0 && err != ECTF_STRTAB)
				return (err);

			vbytes = sizeof (ctf_enum_t) * vlen;
			break;

		case CTF_K_TYPEDEF:
			err = ctf_hash_insert(&fp->ctf_names, fp,
			    CTF_INDEX_TO_TYPE(id, child), tp->ctt_name);
			if (err != 0 && err != ECTF_STRTAB)
				return (err);
			vbytes = 0;
			break;

		case CTF_K_FORWARD:
			/*
			 * Only insert forward tags into the given hash if the
			 * type or tag name is not already present.
			 */
			switch (tp->ctt_type) {
			case CTF_K_STRUCT:
				hp = &fp->ctf_structs;
				break;
			case CTF_K_UNION:
				hp = &fp->ctf_unions;
				break;
			case CTF_K_ENUM:
				hp = &fp->ctf_enums;
				break;
			default:
				hp = &fp->ctf_structs;
			}

			if (ctf_hash_lookup(hp, fp,
			    name, strlen(name)) == NULL) {
				err = ctf_hash_insert(hp, fp,
				    CTF_INDEX_TO_TYPE(id, child), tp->ctt_name);
				if (err != 0 && err != ECTF_STRTAB)
					return (err);
			}
			vbytes = 0;
			break;

		case CTF_K_POINTER:
			/*
			 * If the type referenced by the pointer is in this CTF
			 * container, then store the index of the pointer type
			 * in fp->ctf_ptrtab[ index of referenced type ].
			 */
			if (CTF_TYPE_ISCHILD(tp->ctt_type) == child &&
			    CTF_TYPE_TO_INDEX(tp->ctt_type) <= fp->ctf_typemax)
				fp->ctf_ptrtab[
				    CTF_TYPE_TO_INDEX(tp->ctt_type)] = id;
			/*FALLTHRU*/

		case CTF_K_VOLATILE:
		case CTF_K_CONST:
		case CTF_K_RESTRICT:
			err = ctf_hash_insert(&fp->ctf_names, fp,
			    CTF_INDEX_TO_TYPE(id, child), tp->ctt_name);
			if (err != 0 && err != ECTF_STRTAB)
				return (err);
			/*FALLTHRU*/

		default:
			vbytes = 0;
			break;
		}

		*xp = (uint_t)((uintptr_t)tp - (uintptr_t)fp->ctf_buf);
		tp = (ctf_type_t *)((uintptr_t)tp + increment + vbytes);
	}

	ctf_dprintf("%lu total types processed\n", fp->ctf_typemax);
	ctf_dprintf("%u enum names hashed\n", ctf_hash_size(&fp->ctf_enums));
	ctf_dprintf("%u struct names hashed (%d long)\n",
	    ctf_hash_size(&fp->ctf_structs), nlstructs);
	ctf_dprintf("%u union names hashed (%d long)\n",
	    ctf_hash_size(&fp->ctf_unions), nlunions);
	ctf_dprintf("%u base type names hashed\n",
	    ctf_hash_size(&fp->ctf_names));

	/*
	 * Make an additional pass through the pointer table to find pointers
	 * that point to anonymous typedef nodes.  If we find one, modify the
	 * pointer table so that the pointer is also known to point to the
	 * node that is referenced by the anonymous typedef node.
	 */
	for (id = 1; id <= fp->ctf_typemax; id++) {
		if ((dst = fp->ctf_ptrtab[id]) != 0) {
			tp = LCTF_INDEX_TO_TYPEPTR(fp, id);

			if (LCTF_INFO_KIND(fp, tp->ctt_info) == CTF_K_TYPEDEF &&
			    strcmp(ctf_strptr(fp, tp->ctt_name), "") == 0 &&
			    CTF_TYPE_ISCHILD(tp->ctt_type) == child &&
			    CTF_TYPE_TO_INDEX(tp->ctt_type) <= fp->ctf_typemax)
				fp->ctf_ptrtab[
				    CTF_TYPE_TO_INDEX(tp->ctt_type)] = dst;
		}
	}

	return (0);
}
Пример #10
0
int
ctf_add_member(ctf_file_t *fp, ctf_id_t souid, const char *name, ctf_id_t type)
{
	ctf_dtdef_t *dtd = ctf_dtd_lookup(fp, souid);
	ctf_dmdef_t *dmd;

	ssize_t msize, malign, ssize;
	uint_t kind, vlen, root;
	char *s = NULL;

	if (!(fp->ctf_flags & LCTF_RDWR))
		return (ctf_set_errno(fp, ECTF_RDONLY));

	if (dtd == NULL)
		return (ctf_set_errno(fp, ECTF_BADID));

	kind = CTF_INFO_KIND(dtd->dtd_data.ctt_info);
	root = CTF_INFO_ISROOT(dtd->dtd_data.ctt_info);
	vlen = CTF_INFO_VLEN(dtd->dtd_data.ctt_info);

	if (kind != CTF_K_STRUCT && kind != CTF_K_UNION)
		return (ctf_set_errno(fp, ECTF_NOTSOU));

	if (vlen == CTF_MAX_VLEN)
		return (ctf_set_errno(fp, ECTF_DTFULL));

	if (name != NULL) {
		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;

	ctf_ref_inc(fp, type);
	fp->ctf_flags |= LCTF_DIRTY;
	return (0);
}