1178525Sjb/*
2178525Sjb * CDDL HEADER START
3178525Sjb *
4178525Sjb * The contents of this file are subject to the terms of the
5178525Sjb * Common Development and Distribution License, Version 1.0 only
6178525Sjb * (the "License").  You may not use this file except in compliance
7178525Sjb * with the License.
8178525Sjb *
9178525Sjb * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10178525Sjb * or http://www.opensolaris.org/os/licensing.
11178525Sjb * See the License for the specific language governing permissions
12178525Sjb * and limitations under the License.
13178525Sjb *
14178525Sjb * When distributing Covered Code, include this CDDL HEADER in each
15178525Sjb * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16178525Sjb * If applicable, add the following below this CDDL HEADER, with the
17178525Sjb * fields enclosed by brackets "[]" replaced with your own identifying
18178525Sjb * information: Portions Copyright [yyyy] [name of copyright owner]
19178525Sjb *
20178525Sjb * CDDL HEADER END
21178525Sjb */
22178525Sjb
23178525Sjb/*
24178525Sjb * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
25178525Sjb * Use is subject to license terms.
26178525Sjb */
27178525Sjb
28178525Sjb#pragma ident	"%Z%%M%	%I%	%E% SMI"
29178525Sjb
30178525Sjb#include <sys/sysmacros.h>
31178525Sjb#include <sys/param.h>
32178525Sjb#include <sys/mman.h>
33178525Sjb#include <ctf_impl.h>
34178525Sjb
35178525Sjb/*
36178525Sjb * This static string is used as the template for initially populating a
37178525Sjb * dynamic container's string table.  We always store \0 in the first byte,
38178525Sjb * and we use the generic string "PARENT" to mark this container's parent
39178525Sjb * if one is associated with the container using ctf_import().
40178525Sjb */
41178525Sjbstatic const char _CTF_STRTAB_TEMPLATE[] = "\0PARENT";
42178525Sjb
43178525Sjb/*
44178525Sjb * To create an empty CTF container, we just declare a zeroed header and call
45178525Sjb * ctf_bufopen() on it.  If ctf_bufopen succeeds, we mark the new container r/w
46178525Sjb * and initialize the dynamic members.  We set dtstrlen to 1 to reserve the
47178525Sjb * first byte of the string table for a \0 byte, and we start assigning type
48178525Sjb * IDs at 1 because type ID 0 is used as a sentinel.
49178525Sjb */
50178525Sjbctf_file_t *
51178525Sjbctf_create(int *errp)
52178525Sjb{
53178525Sjb	static const ctf_header_t hdr = { { CTF_MAGIC, CTF_VERSION, 0 } };
54178525Sjb
55178525Sjb	const ulong_t hashlen = 128;
56178525Sjb	ctf_dtdef_t **hash = ctf_alloc(hashlen * sizeof (ctf_dtdef_t *));
57178525Sjb	ctf_sect_t cts;
58178525Sjb	ctf_file_t *fp;
59178525Sjb
60178525Sjb	if (hash == NULL)
61178525Sjb		return (ctf_set_open_errno(errp, EAGAIN));
62178525Sjb
63178525Sjb	cts.cts_name = _CTF_SECTION;
64178525Sjb	cts.cts_type = SHT_PROGBITS;
65178525Sjb	cts.cts_flags = 0;
66178525Sjb	cts.cts_data = &hdr;
67178525Sjb	cts.cts_size = sizeof (hdr);
68178525Sjb	cts.cts_entsize = 1;
69178525Sjb	cts.cts_offset = 0;
70178525Sjb
71178525Sjb	if ((fp = ctf_bufopen(&cts, NULL, NULL, errp)) == NULL) {
72178525Sjb		ctf_free(hash, hashlen * sizeof (ctf_dtdef_t *));
73178525Sjb		return (NULL);
74178525Sjb	}
75178525Sjb
76178525Sjb	fp->ctf_flags |= LCTF_RDWR;
77178525Sjb	fp->ctf_dthashlen = hashlen;
78178525Sjb	bzero(hash, hashlen * sizeof (ctf_dtdef_t *));
79178525Sjb	fp->ctf_dthash = hash;
80178525Sjb	fp->ctf_dtstrlen = sizeof (_CTF_STRTAB_TEMPLATE);
81178525Sjb	fp->ctf_dtnextid = 1;
82178525Sjb	fp->ctf_dtoldid = 0;
83178525Sjb
84178525Sjb	return (fp);
85178525Sjb}
86178525Sjb
87178525Sjbstatic uchar_t *
88178525Sjbctf_copy_smembers(ctf_dtdef_t *dtd, uint_t soff, uchar_t *t)
89178525Sjb{
90178525Sjb	ctf_dmdef_t *dmd = ctf_list_next(&dtd->dtd_u.dtu_members);
91178525Sjb	ctf_member_t ctm;
92178525Sjb
93178525Sjb	for (; dmd != NULL; dmd = ctf_list_next(dmd)) {
94178525Sjb		if (dmd->dmd_name) {
95178525Sjb			ctm.ctm_name = soff;
96178525Sjb			soff += strlen(dmd->dmd_name) + 1;
97178525Sjb		} else
98178525Sjb			ctm.ctm_name = 0;
99178525Sjb
100178525Sjb		ctm.ctm_type = (ushort_t)dmd->dmd_type;
101178525Sjb		ctm.ctm_offset = (ushort_t)dmd->dmd_offset;
102178525Sjb
103178525Sjb		bcopy(&ctm, t, sizeof (ctm));
104178525Sjb		t += sizeof (ctm);
105178525Sjb	}
106178525Sjb
107178525Sjb	return (t);
108178525Sjb}
109178525Sjb
110178525Sjbstatic uchar_t *
111178525Sjbctf_copy_lmembers(ctf_dtdef_t *dtd, uint_t soff, uchar_t *t)
112178525Sjb{
113178525Sjb	ctf_dmdef_t *dmd = ctf_list_next(&dtd->dtd_u.dtu_members);
114178525Sjb	ctf_lmember_t ctlm;
115178525Sjb
116178525Sjb	for (; dmd != NULL; dmd = ctf_list_next(dmd)) {
117178525Sjb		if (dmd->dmd_name) {
118178525Sjb			ctlm.ctlm_name = soff;
119178525Sjb			soff += strlen(dmd->dmd_name) + 1;
120178525Sjb		} else
121178525Sjb			ctlm.ctlm_name = 0;
122178525Sjb
123178525Sjb		ctlm.ctlm_type = (ushort_t)dmd->dmd_type;
124178525Sjb		ctlm.ctlm_pad = 0;
125178525Sjb		ctlm.ctlm_offsethi = CTF_OFFSET_TO_LMEMHI(dmd->dmd_offset);
126178525Sjb		ctlm.ctlm_offsetlo = CTF_OFFSET_TO_LMEMLO(dmd->dmd_offset);
127178525Sjb
128178525Sjb		bcopy(&ctlm, t, sizeof (ctlm));
129178525Sjb		t += sizeof (ctlm);
130178525Sjb	}
131178525Sjb
132178525Sjb	return (t);
133178525Sjb}
134178525Sjb
135178525Sjbstatic uchar_t *
136178525Sjbctf_copy_emembers(ctf_dtdef_t *dtd, uint_t soff, uchar_t *t)
137178525Sjb{
138178525Sjb	ctf_dmdef_t *dmd = ctf_list_next(&dtd->dtd_u.dtu_members);
139178525Sjb	ctf_enum_t cte;
140178525Sjb
141178525Sjb	for (; dmd != NULL; dmd = ctf_list_next(dmd)) {
142178525Sjb		cte.cte_name = soff;
143178525Sjb		cte.cte_value = dmd->dmd_value;
144178525Sjb		soff += strlen(dmd->dmd_name) + 1;
145178525Sjb		bcopy(&cte, t, sizeof (cte));
146178525Sjb		t += sizeof (cte);
147178525Sjb	}
148178525Sjb
149178525Sjb	return (t);
150178525Sjb}
151178525Sjb
152178525Sjbstatic uchar_t *
153178525Sjbctf_copy_membnames(ctf_dtdef_t *dtd, uchar_t *s)
154178525Sjb{
155178525Sjb	ctf_dmdef_t *dmd = ctf_list_next(&dtd->dtd_u.dtu_members);
156178525Sjb	size_t len;
157178525Sjb
158178525Sjb	for (; dmd != NULL; dmd = ctf_list_next(dmd)) {
159178525Sjb		if (dmd->dmd_name == NULL)
160178525Sjb			continue; /* skip anonymous members */
161178525Sjb		len = strlen(dmd->dmd_name) + 1;
162178525Sjb		bcopy(dmd->dmd_name, s, len);
163178525Sjb		s += len;
164178525Sjb	}
165178525Sjb
166178525Sjb	return (s);
167178525Sjb}
168178525Sjb
169178525Sjb/*
170178525Sjb * If the specified CTF container is writable and has been modified, reload
171178525Sjb * this container with the updated type definitions.  In order to make this
172178525Sjb * code and the rest of libctf as simple as possible, we perform updates by
173178525Sjb * taking the dynamic type definitions and creating an in-memory CTF file
174178525Sjb * containing the definitions, and then call ctf_bufopen() on it.  This not
175178525Sjb * only leverages ctf_bufopen(), but also avoids having to bifurcate the rest
176178525Sjb * of the library code with different lookup paths for static and dynamic
177178525Sjb * type definitions.  We are therefore optimizing greatly for lookup over
178178525Sjb * update, which we assume will be an uncommon operation.  We perform one
179178525Sjb * extra trick here for the benefit of callers and to keep our code simple:
180178525Sjb * ctf_bufopen() will return a new ctf_file_t, but we want to keep the fp
181178525Sjb * constant for the caller, so after ctf_bufopen() returns, we use bcopy to
182178525Sjb * swap the interior of the old and new ctf_file_t's, and then free the old.
183178525Sjb */
184178525Sjbint
185178525Sjbctf_update(ctf_file_t *fp)
186178525Sjb{
187178525Sjb	ctf_file_t ofp, *nfp;
188178525Sjb	ctf_header_t hdr;
189178525Sjb	ctf_dtdef_t *dtd;
190178525Sjb	ctf_sect_t cts;
191178525Sjb
192178525Sjb	uchar_t *s, *s0, *t;
193178525Sjb	size_t size;
194178525Sjb	void *buf;
195178525Sjb	int err;
196178525Sjb
197178525Sjb	if (!(fp->ctf_flags & LCTF_RDWR))
198178525Sjb		return (ctf_set_errno(fp, ECTF_RDONLY));
199178525Sjb
200178525Sjb	if (!(fp->ctf_flags & LCTF_DIRTY))
201178525Sjb		return (0); /* no update required */
202178525Sjb
203178525Sjb	/*
204178525Sjb	 * Fill in an initial CTF header.  We will leave the label, object,
205178525Sjb	 * and function sections empty and only output a header, type section,
206178525Sjb	 * and string table.  The type section begins at a 4-byte aligned
207178525Sjb	 * boundary past the CTF header itself (at relative offset zero).
208178525Sjb	 */
209178525Sjb	bzero(&hdr, sizeof (hdr));
210178525Sjb	hdr.cth_magic = CTF_MAGIC;
211178525Sjb	hdr.cth_version = CTF_VERSION;
212178525Sjb
213178525Sjb	if (fp->ctf_flags & LCTF_CHILD)
214178525Sjb		hdr.cth_parname = 1; /* i.e. _CTF_STRTAB_TEMPLATE[1] */
215178525Sjb
216178525Sjb	/*
217178525Sjb	 * Iterate through the dynamic type definition list and compute the
218178525Sjb	 * size of the CTF type section we will need to generate.
219178525Sjb	 */
220178525Sjb	for (size = 0, dtd = ctf_list_next(&fp->ctf_dtdefs);
221178525Sjb	    dtd != NULL; dtd = ctf_list_next(dtd)) {
222178525Sjb
223178525Sjb		uint_t kind = CTF_INFO_KIND(dtd->dtd_data.ctt_info);
224178525Sjb		uint_t vlen = CTF_INFO_VLEN(dtd->dtd_data.ctt_info);
225178525Sjb
226178525Sjb		if (dtd->dtd_data.ctt_size != CTF_LSIZE_SENT)
227178525Sjb			size += sizeof (ctf_stype_t);
228178525Sjb		else
229178525Sjb			size += sizeof (ctf_type_t);
230178525Sjb
231178525Sjb		switch (kind) {
232178525Sjb		case CTF_K_INTEGER:
233178525Sjb		case CTF_K_FLOAT:
234178525Sjb			size += sizeof (uint_t);
235178525Sjb			break;
236178525Sjb		case CTF_K_ARRAY:
237178525Sjb			size += sizeof (ctf_array_t);
238178525Sjb			break;
239178525Sjb		case CTF_K_FUNCTION:
240178525Sjb			size += sizeof (ushort_t) * (vlen + (vlen & 1));
241178525Sjb			break;
242178525Sjb		case CTF_K_STRUCT:
243178525Sjb		case CTF_K_UNION:
244178525Sjb			if (dtd->dtd_data.ctt_size < CTF_LSTRUCT_THRESH)
245178525Sjb				size += sizeof (ctf_member_t) * vlen;
246178525Sjb			else
247178525Sjb				size += sizeof (ctf_lmember_t) * vlen;
248178525Sjb			break;
249178525Sjb		case CTF_K_ENUM:
250178525Sjb			size += sizeof (ctf_enum_t) * vlen;
251178525Sjb			break;
252178525Sjb		}
253178525Sjb	}
254178525Sjb
255178525Sjb	/*
256178525Sjb	 * Fill in the string table offset and size, compute the size of the
257178525Sjb	 * entire CTF buffer we need, and then allocate a new buffer and
258178525Sjb	 * bcopy the finished header to the start of the buffer.
259178525Sjb	 */
260178525Sjb	hdr.cth_stroff = hdr.cth_typeoff + size;
261178525Sjb	hdr.cth_strlen = fp->ctf_dtstrlen;
262178525Sjb	size = sizeof (ctf_header_t) + hdr.cth_stroff + hdr.cth_strlen;
263178525Sjb
264178525Sjb	if ((buf = ctf_data_alloc(size)) == MAP_FAILED)
265178525Sjb		return (ctf_set_errno(fp, EAGAIN));
266178525Sjb
267178525Sjb	bcopy(&hdr, buf, sizeof (ctf_header_t));
268178525Sjb	t = (uchar_t *)buf + sizeof (ctf_header_t);
269178525Sjb	s = s0 = (uchar_t *)buf + sizeof (ctf_header_t) + hdr.cth_stroff;
270178525Sjb
271178525Sjb	bcopy(_CTF_STRTAB_TEMPLATE, s, sizeof (_CTF_STRTAB_TEMPLATE));
272178525Sjb	s += sizeof (_CTF_STRTAB_TEMPLATE);
273178525Sjb
274178525Sjb	/*
275178525Sjb	 * We now take a final lap through the dynamic type definition list and
276178525Sjb	 * copy the appropriate type records and strings to the output buffer.
277178525Sjb	 */
278178525Sjb	for (dtd = ctf_list_next(&fp->ctf_dtdefs);
279178525Sjb	    dtd != NULL; dtd = ctf_list_next(dtd)) {
280178525Sjb
281178525Sjb		uint_t kind = CTF_INFO_KIND(dtd->dtd_data.ctt_info);
282178525Sjb		uint_t vlen = CTF_INFO_VLEN(dtd->dtd_data.ctt_info);
283178525Sjb
284178525Sjb		ctf_array_t cta;
285178525Sjb		uint_t encoding;
286178525Sjb		size_t len;
287178525Sjb
288178525Sjb		if (dtd->dtd_name != NULL) {
289178525Sjb			dtd->dtd_data.ctt_name = (uint_t)(s - s0);
290178525Sjb			len = strlen(dtd->dtd_name) + 1;
291178525Sjb			bcopy(dtd->dtd_name, s, len);
292178525Sjb			s += len;
293178525Sjb		} else
294178525Sjb			dtd->dtd_data.ctt_name = 0;
295178525Sjb
296178525Sjb		if (dtd->dtd_data.ctt_size != CTF_LSIZE_SENT)
297178525Sjb			len = sizeof (ctf_stype_t);
298178525Sjb		else
299178525Sjb			len = sizeof (ctf_type_t);
300178525Sjb
301178525Sjb		bcopy(&dtd->dtd_data, t, len);
302178525Sjb		t += len;
303178525Sjb
304178525Sjb		switch (kind) {
305178525Sjb		case CTF_K_INTEGER:
306178525Sjb		case CTF_K_FLOAT:
307178525Sjb			if (kind == CTF_K_INTEGER) {
308178525Sjb				encoding = CTF_INT_DATA(
309178525Sjb				    dtd->dtd_u.dtu_enc.cte_format,
310178525Sjb				    dtd->dtd_u.dtu_enc.cte_offset,
311178525Sjb				    dtd->dtd_u.dtu_enc.cte_bits);
312178525Sjb			} else {
313178525Sjb				encoding = CTF_FP_DATA(
314178525Sjb				    dtd->dtd_u.dtu_enc.cte_format,
315178525Sjb				    dtd->dtd_u.dtu_enc.cte_offset,
316178525Sjb				    dtd->dtd_u.dtu_enc.cte_bits);
317178525Sjb			}
318178525Sjb			bcopy(&encoding, t, sizeof (encoding));
319178525Sjb			t += sizeof (encoding);
320178525Sjb			break;
321178525Sjb
322178525Sjb		case CTF_K_ARRAY:
323178525Sjb			cta.cta_contents = (ushort_t)
324178525Sjb			    dtd->dtd_u.dtu_arr.ctr_contents;
325178525Sjb			cta.cta_index = (ushort_t)
326178525Sjb			    dtd->dtd_u.dtu_arr.ctr_index;
327178525Sjb			cta.cta_nelems = dtd->dtd_u.dtu_arr.ctr_nelems;
328178525Sjb			bcopy(&cta, t, sizeof (cta));
329178525Sjb			t += sizeof (cta);
330178525Sjb			break;
331178525Sjb
332178525Sjb		case CTF_K_FUNCTION: {
333178525Sjb			ushort_t *argv = (ushort_t *)(uintptr_t)t;
334178525Sjb			uint_t argc;
335178525Sjb
336178525Sjb			for (argc = 0; argc < vlen; argc++)
337178525Sjb				*argv++ = (ushort_t)dtd->dtd_u.dtu_argv[argc];
338178525Sjb
339178525Sjb			if (vlen & 1)
340178525Sjb				*argv++ = 0; /* pad to 4-byte boundary */
341178525Sjb
342178525Sjb			t = (uchar_t *)argv;
343178525Sjb			break;
344178525Sjb		}
345178525Sjb
346178525Sjb		case CTF_K_STRUCT:
347178525Sjb		case CTF_K_UNION:
348178525Sjb			if (dtd->dtd_data.ctt_size < CTF_LSTRUCT_THRESH)
349178525Sjb				t = ctf_copy_smembers(dtd, (uint_t)(s - s0), t);
350178525Sjb			else
351178525Sjb				t = ctf_copy_lmembers(dtd, (uint_t)(s - s0), t);
352178525Sjb			s = ctf_copy_membnames(dtd, s);
353178525Sjb			break;
354178525Sjb
355178525Sjb		case CTF_K_ENUM:
356178525Sjb			t = ctf_copy_emembers(dtd, (uint_t)(s - s0), t);
357178525Sjb			s = ctf_copy_membnames(dtd, s);
358178525Sjb			break;
359178525Sjb		}
360178525Sjb	}
361178525Sjb
362178525Sjb	/*
363178525Sjb	 * Finally, we are ready to ctf_bufopen() the new container.  If this
364178525Sjb	 * is successful, we then switch nfp and fp and free the old container.
365178525Sjb	 */
366178525Sjb	ctf_data_protect(buf, size);
367178525Sjb	cts.cts_name = _CTF_SECTION;
368178525Sjb	cts.cts_type = SHT_PROGBITS;
369178525Sjb	cts.cts_flags = 0;
370178525Sjb	cts.cts_data = buf;
371178525Sjb	cts.cts_size = size;
372178525Sjb	cts.cts_entsize = 1;
373178525Sjb	cts.cts_offset = 0;
374178525Sjb
375178525Sjb	if ((nfp = ctf_bufopen(&cts, NULL, NULL, &err)) == NULL) {
376178525Sjb		ctf_data_free(buf, size);
377178525Sjb		return (ctf_set_errno(fp, err));
378178525Sjb	}
379178525Sjb
380178525Sjb	(void) ctf_setmodel(nfp, ctf_getmodel(fp));
381178525Sjb	(void) ctf_import(nfp, fp->ctf_parent);
382178525Sjb
383178525Sjb	nfp->ctf_refcnt = fp->ctf_refcnt;
384178525Sjb	nfp->ctf_flags |= fp->ctf_flags & ~LCTF_DIRTY;
385178525Sjb	nfp->ctf_data.cts_data = NULL; /* force ctf_data_free() on close */
386178525Sjb	nfp->ctf_dthash = fp->ctf_dthash;
387178525Sjb	nfp->ctf_dthashlen = fp->ctf_dthashlen;
388178525Sjb	nfp->ctf_dtdefs = fp->ctf_dtdefs;
389178525Sjb	nfp->ctf_dtstrlen = fp->ctf_dtstrlen;
390178525Sjb	nfp->ctf_dtnextid = fp->ctf_dtnextid;
391178525Sjb	nfp->ctf_dtoldid = fp->ctf_dtnextid - 1;
392178525Sjb	nfp->ctf_specific = fp->ctf_specific;
393178525Sjb
394178525Sjb	fp->ctf_dthash = NULL;
395178525Sjb	fp->ctf_dthashlen = 0;
396178525Sjb	bzero(&fp->ctf_dtdefs, sizeof (ctf_list_t));
397178525Sjb
398178525Sjb	bcopy(fp, &ofp, sizeof (ctf_file_t));
399178525Sjb	bcopy(nfp, fp, sizeof (ctf_file_t));
400178525Sjb	bcopy(&ofp, nfp, sizeof (ctf_file_t));
401178525Sjb
402178525Sjb	/*
403178525Sjb	 * Initialize the ctf_lookup_by_name top-level dictionary.  We keep an
404178525Sjb	 * array of type name prefixes and the corresponding ctf_hash to use.
405178525Sjb	 * NOTE: This code must be kept in sync with the code in ctf_bufopen().
406178525Sjb	 */
407178525Sjb	fp->ctf_lookups[0].ctl_hash = &fp->ctf_structs;
408178525Sjb	fp->ctf_lookups[1].ctl_hash = &fp->ctf_unions;
409178525Sjb	fp->ctf_lookups[2].ctl_hash = &fp->ctf_enums;
410178525Sjb	fp->ctf_lookups[3].ctl_hash = &fp->ctf_names;
411178525Sjb
412178525Sjb	nfp->ctf_refcnt = 1; /* force nfp to be freed */
413178525Sjb	ctf_close(nfp);
414178525Sjb
415178525Sjb	return (0);
416178525Sjb}
417178525Sjb
418178525Sjbvoid
419178525Sjbctf_dtd_insert(ctf_file_t *fp, ctf_dtdef_t *dtd)
420178525Sjb{
421178525Sjb	ulong_t h = dtd->dtd_type & (fp->ctf_dthashlen - 1);
422178525Sjb
423178525Sjb	dtd->dtd_hash = fp->ctf_dthash[h];
424178525Sjb	fp->ctf_dthash[h] = dtd;
425178525Sjb	ctf_list_append(&fp->ctf_dtdefs, dtd);
426178525Sjb}
427178525Sjb
428178525Sjbvoid
429178525Sjbctf_dtd_delete(ctf_file_t *fp, ctf_dtdef_t *dtd)
430178525Sjb{
431178525Sjb	ulong_t h = dtd->dtd_type & (fp->ctf_dthashlen - 1);
432178525Sjb	ctf_dtdef_t *p, **q = &fp->ctf_dthash[h];
433178525Sjb	ctf_dmdef_t *dmd, *nmd;
434178525Sjb	size_t len;
435178525Sjb
436178525Sjb	for (p = *q; p != NULL; p = p->dtd_hash) {
437178525Sjb		if (p != dtd)
438178525Sjb			q = &p->dtd_hash;
439178525Sjb		else
440178525Sjb			break;
441178525Sjb	}
442178525Sjb
443178525Sjb	if (p != NULL)
444178525Sjb		*q = p->dtd_hash;
445178525Sjb
446178525Sjb	switch (CTF_INFO_KIND(dtd->dtd_data.ctt_info)) {
447178525Sjb	case CTF_K_STRUCT:
448178525Sjb	case CTF_K_UNION:
449178525Sjb	case CTF_K_ENUM:
450178525Sjb		for (dmd = ctf_list_next(&dtd->dtd_u.dtu_members);
451178525Sjb		    dmd != NULL; dmd = nmd) {
452178525Sjb			if (dmd->dmd_name != NULL) {
453178525Sjb				len = strlen(dmd->dmd_name) + 1;
454178525Sjb				ctf_free(dmd->dmd_name, len);
455178525Sjb				fp->ctf_dtstrlen -= len;
456178525Sjb			}
457178525Sjb			nmd = ctf_list_next(dmd);
458178525Sjb			ctf_free(dmd, sizeof (ctf_dmdef_t));
459178525Sjb		}
460178525Sjb		break;
461178525Sjb	case CTF_K_FUNCTION:
462178525Sjb		ctf_free(dtd->dtd_u.dtu_argv, sizeof (ctf_id_t) *
463178525Sjb		    CTF_INFO_VLEN(dtd->dtd_data.ctt_info));
464178525Sjb		break;
465178525Sjb	}
466178525Sjb
467178525Sjb	if (dtd->dtd_name) {
468178525Sjb		len = strlen(dtd->dtd_name) + 1;
469178525Sjb		ctf_free(dtd->dtd_name, len);
470178525Sjb		fp->ctf_dtstrlen -= len;
471178525Sjb	}
472178525Sjb
473178525Sjb	ctf_list_delete(&fp->ctf_dtdefs, dtd);
474178525Sjb	ctf_free(dtd, sizeof (ctf_dtdef_t));
475178525Sjb}
476178525Sjb
477178525Sjbctf_dtdef_t *
478178525Sjbctf_dtd_lookup(ctf_file_t *fp, ctf_id_t type)
479178525Sjb{
480178525Sjb	ulong_t h = type & (fp->ctf_dthashlen - 1);
481178525Sjb	ctf_dtdef_t *dtd;
482178525Sjb
483178525Sjb	if (fp->ctf_dthash == NULL)
484178525Sjb		return (NULL);
485178525Sjb
486178525Sjb	for (dtd = fp->ctf_dthash[h]; dtd != NULL; dtd = dtd->dtd_hash) {
487178525Sjb		if (dtd->dtd_type == type)
488178525Sjb			break;
489178525Sjb	}
490178525Sjb
491178525Sjb	return (dtd);
492178525Sjb}
493178525Sjb
494178525Sjb/*
495178525Sjb * Discard all of the dynamic type definitions that have been added to the
496178525Sjb * container since the last call to ctf_update().  We locate such types by
497178525Sjb * scanning the list and deleting elements that have type IDs greater than
498178525Sjb * ctf_dtoldid, which is set by ctf_update(), above.
499178525Sjb */
500178525Sjbint
501178525Sjbctf_discard(ctf_file_t *fp)
502178525Sjb{
503178525Sjb	ctf_dtdef_t *dtd, *ntd;
504178525Sjb
505178525Sjb	if (!(fp->ctf_flags & LCTF_RDWR))
506178525Sjb		return (ctf_set_errno(fp, ECTF_RDONLY));
507178525Sjb
508178525Sjb	if (!(fp->ctf_flags & LCTF_DIRTY))
509178525Sjb		return (0); /* no update required */
510178525Sjb
511178525Sjb	for (dtd = ctf_list_next(&fp->ctf_dtdefs); dtd != NULL; dtd = ntd) {
512178525Sjb		if (dtd->dtd_type <= fp->ctf_dtoldid)
513178525Sjb			continue; /* skip types that have been committed */
514178525Sjb
515178525Sjb		ntd = ctf_list_next(dtd);
516178525Sjb		ctf_dtd_delete(fp, dtd);
517178525Sjb	}
518178525Sjb
519178525Sjb	fp->ctf_dtnextid = fp->ctf_dtoldid + 1;
520178525Sjb	fp->ctf_flags &= ~LCTF_DIRTY;
521178525Sjb
522178525Sjb	return (0);
523178525Sjb}
524178525Sjb
525178525Sjbstatic ctf_id_t
526178525Sjbctf_add_generic(ctf_file_t *fp, uint_t flag, const char *name, ctf_dtdef_t **rp)
527178525Sjb{
528178525Sjb	ctf_dtdef_t *dtd;
529178525Sjb	ctf_id_t type;
530178525Sjb	char *s = NULL;
531178525Sjb
532178525Sjb	if (flag != CTF_ADD_NONROOT && flag != CTF_ADD_ROOT)
533178525Sjb		return (ctf_set_errno(fp, EINVAL));
534178525Sjb
535178525Sjb	if (!(fp->ctf_flags & LCTF_RDWR))
536178525Sjb		return (ctf_set_errno(fp, ECTF_RDONLY));
537178525Sjb
538178525Sjb	if (CTF_INDEX_TO_TYPE(fp->ctf_dtnextid, 1) > CTF_MAX_TYPE)
539178525Sjb		return (ctf_set_errno(fp, ECTF_FULL));
540178525Sjb
541178525Sjb	if ((dtd = ctf_alloc(sizeof (ctf_dtdef_t))) == NULL)
542178525Sjb		return (ctf_set_errno(fp, EAGAIN));
543178525Sjb
544178525Sjb	if (name != NULL && (s = ctf_strdup(name)) == NULL) {
545178525Sjb		ctf_free(dtd, sizeof (ctf_dtdef_t));
546178525Sjb		return (ctf_set_errno(fp, EAGAIN));
547178525Sjb	}
548178525Sjb
549178525Sjb	type = fp->ctf_dtnextid++;
550178525Sjb	type = CTF_INDEX_TO_TYPE(type, (fp->ctf_flags & LCTF_CHILD));
551178525Sjb
552178525Sjb	bzero(dtd, sizeof (ctf_dtdef_t));
553178525Sjb	dtd->dtd_name = s;
554178525Sjb	dtd->dtd_type = type;
555178525Sjb
556178525Sjb	if (s != NULL)
557178525Sjb		fp->ctf_dtstrlen += strlen(s) + 1;
558178525Sjb
559178525Sjb	ctf_dtd_insert(fp, dtd);
560178525Sjb	fp->ctf_flags |= LCTF_DIRTY;
561178525Sjb
562178525Sjb	*rp = dtd;
563178525Sjb	return (type);
564178525Sjb}
565178525Sjb
566178525Sjb/*
567178525Sjb * When encoding integer sizes, we want to convert a byte count in the range
568178525Sjb * 1-8 to the closest power of 2 (e.g. 3->4, 5->8, etc).  The clp2() function
569178525Sjb * is a clever implementation from "Hacker's Delight" by Henry Warren, Jr.
570178525Sjb */
571178525Sjbstatic size_t
572178525Sjbclp2(size_t x)
573178525Sjb{
574178525Sjb	x--;
575178525Sjb
576178525Sjb	x |= (x >> 1);
577178525Sjb	x |= (x >> 2);
578178525Sjb	x |= (x >> 4);
579178525Sjb	x |= (x >> 8);
580178525Sjb	x |= (x >> 16);
581178525Sjb
582178525Sjb	return (x + 1);
583178525Sjb}
584178525Sjb
585178525Sjbstatic ctf_id_t
586178525Sjbctf_add_encoded(ctf_file_t *fp, uint_t flag,
587178525Sjb    const char *name, const ctf_encoding_t *ep, uint_t kind)
588178525Sjb{
589178525Sjb	ctf_dtdef_t *dtd;
590178525Sjb	ctf_id_t type;
591178525Sjb
592178525Sjb	if (ep == NULL)
593178525Sjb		return (ctf_set_errno(fp, EINVAL));
594178525Sjb
595178525Sjb	if ((type = ctf_add_generic(fp, flag, name, &dtd)) == CTF_ERR)
596178525Sjb		return (CTF_ERR); /* errno is set for us */
597178525Sjb
598178525Sjb	dtd->dtd_data.ctt_info = CTF_TYPE_INFO(kind, flag, 0);
599178525Sjb	dtd->dtd_data.ctt_size = clp2(P2ROUNDUP(ep->cte_bits, NBBY) / NBBY);
600178525Sjb	dtd->dtd_u.dtu_enc = *ep;
601178525Sjb
602178525Sjb	return (type);
603178525Sjb}
604178525Sjb
605178525Sjbstatic ctf_id_t
606178525Sjbctf_add_reftype(ctf_file_t *fp, uint_t flag, ctf_id_t ref, uint_t kind)
607178525Sjb{
608178525Sjb	ctf_dtdef_t *dtd;
609178525Sjb	ctf_id_t type;
610178525Sjb
611178525Sjb	if (ref == CTF_ERR || ref < 0 || ref > CTF_MAX_TYPE)
612178525Sjb		return (ctf_set_errno(fp, EINVAL));
613178525Sjb
614178525Sjb	if ((type = ctf_add_generic(fp, flag, NULL, &dtd)) == CTF_ERR)
615178525Sjb		return (CTF_ERR); /* errno is set for us */
616178525Sjb
617178525Sjb	dtd->dtd_data.ctt_info = CTF_TYPE_INFO(kind, flag, 0);
618178525Sjb	dtd->dtd_data.ctt_type = (ushort_t)ref;
619178525Sjb
620178525Sjb	return (type);
621178525Sjb}
622178525Sjb
623178525Sjbctf_id_t
624178525Sjbctf_add_integer(ctf_file_t *fp, uint_t flag,
625178525Sjb    const char *name, const ctf_encoding_t *ep)
626178525Sjb{
627178525Sjb	return (ctf_add_encoded(fp, flag, name, ep, CTF_K_INTEGER));
628178525Sjb}
629178525Sjb
630178525Sjbctf_id_t
631178525Sjbctf_add_float(ctf_file_t *fp, uint_t flag,
632178525Sjb    const char *name, const ctf_encoding_t *ep)
633178525Sjb{
634178525Sjb	return (ctf_add_encoded(fp, flag, name, ep, CTF_K_FLOAT));
635178525Sjb}
636178525Sjb
637178525Sjbctf_id_t
638178525Sjbctf_add_pointer(ctf_file_t *fp, uint_t flag, ctf_id_t ref)
639178525Sjb{
640178525Sjb	return (ctf_add_reftype(fp, flag, ref, CTF_K_POINTER));
641178525Sjb}
642178525Sjb
643178525Sjbctf_id_t
644178525Sjbctf_add_array(ctf_file_t *fp, uint_t flag, const ctf_arinfo_t *arp)
645178525Sjb{
646178525Sjb	ctf_dtdef_t *dtd;
647178525Sjb	ctf_id_t type;
648178525Sjb
649178525Sjb	if (arp == NULL)
650178525Sjb		return (ctf_set_errno(fp, EINVAL));
651178525Sjb
652178525Sjb	if ((type = ctf_add_generic(fp, flag, NULL, &dtd)) == CTF_ERR)
653178525Sjb		return (CTF_ERR); /* errno is set for us */
654178525Sjb
655178525Sjb	dtd->dtd_data.ctt_info = CTF_TYPE_INFO(CTF_K_ARRAY, flag, 0);
656178525Sjb	dtd->dtd_data.ctt_size = 0;
657178525Sjb	dtd->dtd_u.dtu_arr = *arp;
658178525Sjb
659178525Sjb	return (type);
660178525Sjb}
661178525Sjb
662178525Sjbint
663178525Sjbctf_set_array(ctf_file_t *fp, ctf_id_t type, const ctf_arinfo_t *arp)
664178525Sjb{
665178525Sjb	ctf_dtdef_t *dtd = ctf_dtd_lookup(fp, type);
666178525Sjb
667178525Sjb	if (!(fp->ctf_flags & LCTF_RDWR))
668178525Sjb		return (ctf_set_errno(fp, ECTF_RDONLY));
669178525Sjb
670178525Sjb	if (dtd == NULL || CTF_INFO_KIND(dtd->dtd_data.ctt_info) != CTF_K_ARRAY)
671178525Sjb		return (ctf_set_errno(fp, ECTF_BADID));
672178525Sjb
673178525Sjb	fp->ctf_flags |= LCTF_DIRTY;
674178525Sjb	dtd->dtd_u.dtu_arr = *arp;
675178525Sjb
676178525Sjb	return (0);
677178525Sjb}
678178525Sjb
679178525Sjbctf_id_t
680178525Sjbctf_add_function(ctf_file_t *fp, uint_t flag,
681178525Sjb    const ctf_funcinfo_t *ctc, const ctf_id_t *argv)
682178525Sjb{
683178525Sjb	ctf_dtdef_t *dtd;
684178525Sjb	ctf_id_t type;
685178525Sjb	uint_t vlen;
686178525Sjb	ctf_id_t *vdat = NULL;
687178525Sjb
688178525Sjb	if (ctc == NULL || (ctc->ctc_flags & ~CTF_FUNC_VARARG) != 0 ||
689178525Sjb	    (ctc->ctc_argc != 0 && argv == NULL))
690178525Sjb		return (ctf_set_errno(fp, EINVAL));
691178525Sjb
692178525Sjb	vlen = ctc->ctc_argc;
693178525Sjb	if (ctc->ctc_flags & CTF_FUNC_VARARG)
694178525Sjb		vlen++; /* add trailing zero to indicate varargs (see below) */
695178525Sjb
696178525Sjb	if (vlen > CTF_MAX_VLEN)
697178525Sjb		return (ctf_set_errno(fp, EOVERFLOW));
698178525Sjb
699178525Sjb	if (vlen != 0 && (vdat = ctf_alloc(sizeof (ctf_id_t) * vlen)) == NULL)
700178525Sjb		return (ctf_set_errno(fp, EAGAIN));
701178525Sjb
702178525Sjb	if ((type = ctf_add_generic(fp, flag, NULL, &dtd)) == CTF_ERR) {
703178525Sjb		ctf_free(vdat, sizeof (ctf_id_t) * vlen);
704178525Sjb		return (CTF_ERR); /* errno is set for us */
705178525Sjb	}
706178525Sjb
707178525Sjb	dtd->dtd_data.ctt_info = CTF_TYPE_INFO(CTF_K_FUNCTION, flag, vlen);
708178525Sjb	dtd->dtd_data.ctt_type = (ushort_t)ctc->ctc_return;
709178525Sjb
710178525Sjb	bcopy(argv, vdat, sizeof (ctf_id_t) * ctc->ctc_argc);
711178525Sjb	if (ctc->ctc_flags & CTF_FUNC_VARARG)
712178525Sjb		vdat[vlen - 1] = 0; /* add trailing zero to indicate varargs */
713178525Sjb	dtd->dtd_u.dtu_argv = vdat;
714178525Sjb
715178525Sjb	return (type);
716178525Sjb}
717178525Sjb
718178525Sjbctf_id_t
719178525Sjbctf_add_struct(ctf_file_t *fp, uint_t flag, const char *name)
720178525Sjb{
721178525Sjb	ctf_hash_t *hp = &fp->ctf_structs;
722178525Sjb	ctf_helem_t *hep = NULL;
723178525Sjb	ctf_dtdef_t *dtd;
724178525Sjb	ctf_id_t type;
725178525Sjb
726178525Sjb	if (name != NULL)
727178525Sjb		hep = ctf_hash_lookup(hp, fp, name, strlen(name));
728178525Sjb
729178525Sjb	if (hep != NULL && ctf_type_kind(fp, hep->h_type) == CTF_K_FORWARD)
730178525Sjb		dtd = ctf_dtd_lookup(fp, type = hep->h_type);
731178525Sjb	else if ((type = ctf_add_generic(fp, flag, name, &dtd)) == CTF_ERR)
732178525Sjb		return (CTF_ERR); /* errno is set for us */
733178525Sjb
734178525Sjb	dtd->dtd_data.ctt_info = CTF_TYPE_INFO(CTF_K_STRUCT, flag, 0);
735178525Sjb	dtd->dtd_data.ctt_size = 0;
736178525Sjb
737178525Sjb	return (type);
738178525Sjb}
739178525Sjb
740178525Sjbctf_id_t
741178525Sjbctf_add_union(ctf_file_t *fp, uint_t flag, const char *name)
742178525Sjb{
743178525Sjb	ctf_hash_t *hp = &fp->ctf_unions;
744178525Sjb	ctf_helem_t *hep = NULL;
745178525Sjb	ctf_dtdef_t *dtd;
746178525Sjb	ctf_id_t type;
747178525Sjb
748178525Sjb	if (name != NULL)
749178525Sjb		hep = ctf_hash_lookup(hp, fp, name, strlen(name));
750178525Sjb
751178525Sjb	if (hep != NULL && ctf_type_kind(fp, hep->h_type) == CTF_K_FORWARD)
752178525Sjb		dtd = ctf_dtd_lookup(fp, type = hep->h_type);
753178525Sjb	else if ((type = ctf_add_generic(fp, flag, name, &dtd)) == CTF_ERR)
754178525Sjb		return (CTF_ERR); /* errno is set for us */
755178525Sjb
756178525Sjb	dtd->dtd_data.ctt_info = CTF_TYPE_INFO(CTF_K_UNION, flag, 0);
757178525Sjb	dtd->dtd_data.ctt_size = 0;
758178525Sjb
759178525Sjb	return (type);
760178525Sjb}
761178525Sjb
762178525Sjbctf_id_t
763178525Sjbctf_add_enum(ctf_file_t *fp, uint_t flag, const char *name)
764178525Sjb{
765178525Sjb	ctf_hash_t *hp = &fp->ctf_enums;
766178525Sjb	ctf_helem_t *hep = NULL;
767178525Sjb	ctf_dtdef_t *dtd;
768178525Sjb	ctf_id_t type;
769178525Sjb
770178525Sjb	if (name != NULL)
771178525Sjb		hep = ctf_hash_lookup(hp, fp, name, strlen(name));
772178525Sjb
773178525Sjb	if (hep != NULL && ctf_type_kind(fp, hep->h_type) == CTF_K_FORWARD)
774178525Sjb		dtd = ctf_dtd_lookup(fp, type = hep->h_type);
775178525Sjb	else if ((type = ctf_add_generic(fp, flag, name, &dtd)) == CTF_ERR)
776178525Sjb		return (CTF_ERR); /* errno is set for us */
777178525Sjb
778178525Sjb	dtd->dtd_data.ctt_info = CTF_TYPE_INFO(CTF_K_ENUM, flag, 0);
779178525Sjb	dtd->dtd_data.ctt_size = fp->ctf_dmodel->ctd_int;
780178525Sjb
781178525Sjb	return (type);
782178525Sjb}
783178525Sjb
784178525Sjbctf_id_t
785178525Sjbctf_add_forward(ctf_file_t *fp, uint_t flag, const char *name, uint_t kind)
786178525Sjb{
787178525Sjb	ctf_hash_t *hp;
788178525Sjb	ctf_helem_t *hep;
789178525Sjb	ctf_dtdef_t *dtd;
790178525Sjb	ctf_id_t type;
791178525Sjb
792178525Sjb	switch (kind) {
793178525Sjb	case CTF_K_STRUCT:
794178525Sjb		hp = &fp->ctf_structs;
795178525Sjb		break;
796178525Sjb	case CTF_K_UNION:
797178525Sjb		hp = &fp->ctf_unions;
798178525Sjb		break;
799178525Sjb	case CTF_K_ENUM:
800178525Sjb		hp = &fp->ctf_enums;
801178525Sjb		break;
802178525Sjb	default:
803178525Sjb		return (ctf_set_errno(fp, ECTF_NOTSUE));
804178525Sjb	}
805178525Sjb
806178525Sjb	/*
807178525Sjb	 * If the type is already defined or exists as a forward tag, just
808178525Sjb	 * return the ctf_id_t of the existing definition.
809178525Sjb	 */
810178525Sjb	if (name != NULL && (hep = ctf_hash_lookup(hp,
811178525Sjb	    fp, name, strlen(name))) != NULL)
812178525Sjb		return (hep->h_type);
813178525Sjb
814178525Sjb	if ((type = ctf_add_generic(fp, flag, name, &dtd)) == CTF_ERR)
815178525Sjb		return (CTF_ERR); /* errno is set for us */
816178525Sjb
817178525Sjb	dtd->dtd_data.ctt_info = CTF_TYPE_INFO(CTF_K_FORWARD, flag, 0);
818178525Sjb	dtd->dtd_data.ctt_type = kind;
819178525Sjb
820178525Sjb	return (type);
821178525Sjb}
822178525Sjb
823178525Sjbctf_id_t
824178525Sjbctf_add_typedef(ctf_file_t *fp, uint_t flag, const char *name, ctf_id_t ref)
825178525Sjb{
826178525Sjb	ctf_dtdef_t *dtd;
827178525Sjb	ctf_id_t type;
828178525Sjb
829178525Sjb	if (ref == CTF_ERR || ref < 0 || ref > CTF_MAX_TYPE)
830178525Sjb		return (ctf_set_errno(fp, EINVAL));
831178525Sjb
832178525Sjb	if ((type = ctf_add_generic(fp, flag, name, &dtd)) == CTF_ERR)
833178525Sjb		return (CTF_ERR); /* errno is set for us */
834178525Sjb
835178525Sjb	dtd->dtd_data.ctt_info = CTF_TYPE_INFO(CTF_K_TYPEDEF, flag, 0);
836178525Sjb	dtd->dtd_data.ctt_type = (ushort_t)ref;
837178525Sjb
838178525Sjb	return (type);
839178525Sjb}
840178525Sjb
841178525Sjbctf_id_t
842178525Sjbctf_add_volatile(ctf_file_t *fp, uint_t flag, ctf_id_t ref)
843178525Sjb{
844178525Sjb	return (ctf_add_reftype(fp, flag, ref, CTF_K_VOLATILE));
845178525Sjb}
846178525Sjb
847178525Sjbctf_id_t
848178525Sjbctf_add_const(ctf_file_t *fp, uint_t flag, ctf_id_t ref)
849178525Sjb{
850178525Sjb	return (ctf_add_reftype(fp, flag, ref, CTF_K_CONST));
851178525Sjb}
852178525Sjb
853178525Sjbctf_id_t
854178525Sjbctf_add_restrict(ctf_file_t *fp, uint_t flag, ctf_id_t ref)
855178525Sjb{
856178525Sjb	return (ctf_add_reftype(fp, flag, ref, CTF_K_RESTRICT));
857178525Sjb}
858178525Sjb
859178525Sjbint
860178525Sjbctf_add_enumerator(ctf_file_t *fp, ctf_id_t enid, const char *name, int value)
861178525Sjb{
862178525Sjb	ctf_dtdef_t *dtd = ctf_dtd_lookup(fp, enid);
863178525Sjb	ctf_dmdef_t *dmd;
864178525Sjb
865178525Sjb	uint_t kind, vlen, root;
866178525Sjb	char *s;
867178525Sjb
868178525Sjb	if (name == NULL)
869178525Sjb		return (ctf_set_errno(fp, EINVAL));
870178525Sjb
871178525Sjb	if (!(fp->ctf_flags & LCTF_RDWR))
872178525Sjb		return (ctf_set_errno(fp, ECTF_RDONLY));
873178525Sjb
874178525Sjb	if (dtd == NULL)
875178525Sjb		return (ctf_set_errno(fp, ECTF_BADID));
876178525Sjb
877178525Sjb	kind = CTF_INFO_KIND(dtd->dtd_data.ctt_info);
878178525Sjb	root = CTF_INFO_ISROOT(dtd->dtd_data.ctt_info);
879178525Sjb	vlen = CTF_INFO_VLEN(dtd->dtd_data.ctt_info);
880178525Sjb
881178525Sjb	if (kind != CTF_K_ENUM)
882178525Sjb		return (ctf_set_errno(fp, ECTF_NOTENUM));
883178525Sjb
884178525Sjb	if (vlen == CTF_MAX_VLEN)
885178525Sjb		return (ctf_set_errno(fp, ECTF_DTFULL));
886178525Sjb
887178525Sjb	for (dmd = ctf_list_next(&dtd->dtd_u.dtu_members);
888178525Sjb	    dmd != NULL; dmd = ctf_list_next(dmd)) {
889178525Sjb		if (strcmp(dmd->dmd_name, name) == 0)
890178525Sjb			return (ctf_set_errno(fp, ECTF_DUPMEMBER));
891178525Sjb	}
892178525Sjb
893178525Sjb	if ((dmd = ctf_alloc(sizeof (ctf_dmdef_t))) == NULL)
894178525Sjb		return (ctf_set_errno(fp, EAGAIN));
895178525Sjb
896178525Sjb	if ((s = ctf_strdup(name)) == NULL) {
897178525Sjb		ctf_free(dmd, sizeof (ctf_dmdef_t));
898178525Sjb		return (ctf_set_errno(fp, EAGAIN));
899178525Sjb	}
900178525Sjb
901178525Sjb	dmd->dmd_name = s;
902178525Sjb	dmd->dmd_type = CTF_ERR;
903178525Sjb	dmd->dmd_offset = 0;
904178525Sjb	dmd->dmd_value = value;
905178525Sjb
906178525Sjb	dtd->dtd_data.ctt_info = CTF_TYPE_INFO(kind, root, vlen + 1);
907178525Sjb	ctf_list_append(&dtd->dtd_u.dtu_members, dmd);
908178525Sjb
909178525Sjb	fp->ctf_dtstrlen += strlen(s) + 1;
910178525Sjb	fp->ctf_flags |= LCTF_DIRTY;
911178525Sjb
912178525Sjb	return (0);
913178525Sjb}
914178525Sjb
915178525Sjbint
916178525Sjbctf_add_member(ctf_file_t *fp, ctf_id_t souid, const char *name, ctf_id_t type)
917178525Sjb{
918178525Sjb	ctf_dtdef_t *dtd = ctf_dtd_lookup(fp, souid);
919178525Sjb	ctf_dmdef_t *dmd;
920178525Sjb
921178525Sjb	ssize_t msize, malign, ssize;
922178525Sjb	uint_t kind, vlen, root;
923178525Sjb	char *s = NULL;
924178525Sjb
925178525Sjb	if (!(fp->ctf_flags & LCTF_RDWR))
926178525Sjb		return (ctf_set_errno(fp, ECTF_RDONLY));
927178525Sjb
928178525Sjb	if (dtd == NULL)
929178525Sjb		return (ctf_set_errno(fp, ECTF_BADID));
930178525Sjb
931178525Sjb	kind = CTF_INFO_KIND(dtd->dtd_data.ctt_info);
932178525Sjb	root = CTF_INFO_ISROOT(dtd->dtd_data.ctt_info);
933178525Sjb	vlen = CTF_INFO_VLEN(dtd->dtd_data.ctt_info);
934178525Sjb
935178525Sjb	if (kind != CTF_K_STRUCT && kind != CTF_K_UNION)
936178525Sjb		return (ctf_set_errno(fp, ECTF_NOTSOU));
937178525Sjb
938178525Sjb	if (vlen == CTF_MAX_VLEN)
939178525Sjb		return (ctf_set_errno(fp, ECTF_DTFULL));
940178525Sjb
941178525Sjb	if (name != NULL) {
942178525Sjb		for (dmd = ctf_list_next(&dtd->dtd_u.dtu_members);
943178525Sjb		    dmd != NULL; dmd = ctf_list_next(dmd)) {
944178525Sjb			if (dmd->dmd_name != NULL &&
945178525Sjb			    strcmp(dmd->dmd_name, name) == 0)
946178525Sjb				return (ctf_set_errno(fp, ECTF_DUPMEMBER));
947178525Sjb		}
948178525Sjb	}
949178525Sjb
950178525Sjb	if ((msize = ctf_type_size(fp, type)) == CTF_ERR ||
951178525Sjb	    (malign = ctf_type_align(fp, type)) == CTF_ERR)
952178525Sjb		return (CTF_ERR); /* errno is set for us */
953178525Sjb
954178525Sjb	if ((dmd = ctf_alloc(sizeof (ctf_dmdef_t))) == NULL)
955178525Sjb		return (ctf_set_errno(fp, EAGAIN));
956178525Sjb
957178525Sjb	if (name != NULL && (s = ctf_strdup(name)) == NULL) {
958178525Sjb		ctf_free(dmd, sizeof (ctf_dmdef_t));
959178525Sjb		return (ctf_set_errno(fp, EAGAIN));
960178525Sjb	}
961178525Sjb
962178525Sjb	dmd->dmd_name = s;
963178525Sjb	dmd->dmd_type = type;
964178525Sjb	dmd->dmd_value = -1;
965178525Sjb
966178525Sjb	if (kind == CTF_K_STRUCT && vlen != 0) {
967178525Sjb		ctf_dmdef_t *lmd = ctf_list_prev(&dtd->dtd_u.dtu_members);
968178525Sjb		ctf_id_t ltype = ctf_type_resolve(fp, lmd->dmd_type);
969178525Sjb		size_t off = lmd->dmd_offset;
970178525Sjb
971178525Sjb		ctf_encoding_t linfo;
972178525Sjb		ssize_t lsize;
973178525Sjb
974178525Sjb		if (ctf_type_encoding(fp, ltype, &linfo) != CTF_ERR)
975178525Sjb			off += linfo.cte_bits;
976178525Sjb		else if ((lsize = ctf_type_size(fp, ltype)) != CTF_ERR)
977178525Sjb			off += lsize * NBBY;
978178525Sjb
979178525Sjb		/*
980178525Sjb		 * Round up the offset of the end of the last member to the
981178525Sjb		 * next byte boundary, convert 'off' to bytes, and then round
982178525Sjb		 * it up again to the next multiple of the alignment required
983178525Sjb		 * by the new member.  Finally, convert back to bits and store
984178525Sjb		 * the result in dmd_offset.  Technically we could do more
985178525Sjb		 * efficient packing if the new member is a bit-field, but
986178525Sjb		 * we're the "compiler" and ANSI says we can do as we choose.
987178525Sjb		 */
988178525Sjb		off = roundup(off, NBBY) / NBBY;
989178525Sjb		off = roundup(off, MAX(malign, 1));
990178525Sjb		dmd->dmd_offset = off * NBBY;
991178525Sjb		ssize = off + msize;
992178525Sjb	} else {
993178525Sjb		dmd->dmd_offset = 0;
994178525Sjb		ssize = ctf_get_ctt_size(fp, &dtd->dtd_data, NULL, NULL);
995178525Sjb		ssize = MAX(ssize, msize);
996178525Sjb	}
997178525Sjb
998178525Sjb	if (ssize > CTF_MAX_SIZE) {
999178525Sjb		dtd->dtd_data.ctt_size = CTF_LSIZE_SENT;
1000178525Sjb		dtd->dtd_data.ctt_lsizehi = CTF_SIZE_TO_LSIZE_HI(ssize);
1001178525Sjb		dtd->dtd_data.ctt_lsizelo = CTF_SIZE_TO_LSIZE_LO(ssize);
1002178525Sjb	} else
1003178525Sjb		dtd->dtd_data.ctt_size = (ushort_t)ssize;
1004178525Sjb
1005178525Sjb	dtd->dtd_data.ctt_info = CTF_TYPE_INFO(kind, root, vlen + 1);
1006178525Sjb	ctf_list_append(&dtd->dtd_u.dtu_members, dmd);
1007178525Sjb
1008178525Sjb	if (s != NULL)
1009178525Sjb		fp->ctf_dtstrlen += strlen(s) + 1;
1010178525Sjb
1011178525Sjb	fp->ctf_flags |= LCTF_DIRTY;
1012178525Sjb	return (0);
1013178525Sjb}
1014178525Sjb
1015178525Sjbstatic int
1016178525Sjbenumcmp(const char *name, int value, void *arg)
1017178525Sjb{
1018178525Sjb	ctf_bundle_t *ctb = arg;
1019178525Sjb	int bvalue;
1020178525Sjb
1021178525Sjb	return (ctf_enum_value(ctb->ctb_file, ctb->ctb_type,
1022178525Sjb	    name, &bvalue) == CTF_ERR || value != bvalue);
1023178525Sjb}
1024178525Sjb
1025178525Sjbstatic int
1026178525Sjbenumadd(const char *name, int value, void *arg)
1027178525Sjb{
1028178525Sjb	ctf_bundle_t *ctb = arg;
1029178525Sjb
1030178525Sjb	return (ctf_add_enumerator(ctb->ctb_file, ctb->ctb_type,
1031178525Sjb	    name, value) == CTF_ERR);
1032178525Sjb}
1033178525Sjb
1034178525Sjb/*ARGSUSED*/
1035178525Sjbstatic int
1036178525Sjbmembcmp(const char *name, ctf_id_t type, ulong_t offset, void *arg)
1037178525Sjb{
1038178525Sjb	ctf_bundle_t *ctb = arg;
1039178525Sjb	ctf_membinfo_t ctm;
1040178525Sjb
1041178525Sjb	return (ctf_member_info(ctb->ctb_file, ctb->ctb_type,
1042178525Sjb	    name, &ctm) == CTF_ERR || ctm.ctm_offset != offset);
1043178525Sjb}
1044178525Sjb
1045178525Sjbstatic int
1046178525Sjbmembadd(const char *name, ctf_id_t type, ulong_t offset, void *arg)
1047178525Sjb{
1048178525Sjb	ctf_bundle_t *ctb = arg;
1049178525Sjb	ctf_dmdef_t *dmd;
1050178525Sjb	char *s = NULL;
1051178525Sjb
1052178525Sjb	if ((dmd = ctf_alloc(sizeof (ctf_dmdef_t))) == NULL)
1053178525Sjb		return (ctf_set_errno(ctb->ctb_file, EAGAIN));
1054178525Sjb
1055178525Sjb	if (name != NULL && (s = ctf_strdup(name)) == NULL) {
1056178525Sjb		ctf_free(dmd, sizeof (ctf_dmdef_t));
1057178525Sjb		return (ctf_set_errno(ctb->ctb_file, EAGAIN));
1058178525Sjb	}
1059178525Sjb
1060178525Sjb	/*
1061178525Sjb	 * For now, dmd_type is copied as the src_fp's type; it is reset to an
1062178525Sjb	 * equivalent dst_fp type by a final loop in ctf_add_type(), below.
1063178525Sjb	 */
1064178525Sjb	dmd->dmd_name = s;
1065178525Sjb	dmd->dmd_type = type;
1066178525Sjb	dmd->dmd_offset = offset;
1067178525Sjb	dmd->dmd_value = -1;
1068178525Sjb
1069178525Sjb	ctf_list_append(&ctb->ctb_dtd->dtd_u.dtu_members, dmd);
1070178525Sjb
1071178525Sjb	if (s != NULL)
1072178525Sjb		ctb->ctb_file->ctf_dtstrlen += strlen(s) + 1;
1073178525Sjb
1074178525Sjb	ctb->ctb_file->ctf_flags |= LCTF_DIRTY;
1075178525Sjb	return (0);
1076178525Sjb}
1077178525Sjb
1078178525Sjb/*
1079178525Sjb * The ctf_add_type routine is used to copy a type from a source CTF container
1080178525Sjb * to a dynamic destination container.  This routine operates recursively by
1081178525Sjb * following the source type's links and embedded member types.  If the
1082178525Sjb * destination container already contains a named type which has the same
1083178525Sjb * attributes, then we succeed and return this type but no changes occur.
1084178525Sjb */
1085178525Sjbctf_id_t
1086178525Sjbctf_add_type(ctf_file_t *dst_fp, ctf_file_t *src_fp, ctf_id_t src_type)
1087178525Sjb{
1088178525Sjb	ctf_id_t dst_type = CTF_ERR;
1089178525Sjb	uint_t dst_kind = CTF_K_UNKNOWN;
1090178525Sjb
1091178525Sjb	const ctf_type_t *tp;
1092178525Sjb	const char *name;
1093178525Sjb	uint_t kind, flag, vlen;
1094178525Sjb
1095178525Sjb	ctf_bundle_t src, dst;
1096178525Sjb	ctf_encoding_t src_en, dst_en;
1097178525Sjb	ctf_arinfo_t src_ar, dst_ar;
1098178525Sjb
1099178525Sjb	ctf_dtdef_t *dtd;
1100178525Sjb	ctf_funcinfo_t ctc;
1101178525Sjb	ssize_t size;
1102178525Sjb
1103178525Sjb	ctf_hash_t *hp;
1104178525Sjb	ctf_helem_t *hep;
1105178525Sjb
1106178525Sjb	if (!(dst_fp->ctf_flags & LCTF_RDWR))
1107178525Sjb		return (ctf_set_errno(dst_fp, ECTF_RDONLY));
1108178525Sjb
1109178525Sjb	if ((tp = ctf_lookup_by_id(&src_fp, src_type)) == NULL)
1110178525Sjb		return (ctf_set_errno(dst_fp, ctf_errno(src_fp)));
1111178525Sjb
1112178525Sjb	name = ctf_strptr(src_fp, tp->ctt_name);
1113178525Sjb	kind = LCTF_INFO_KIND(src_fp, tp->ctt_info);
1114178525Sjb	flag = LCTF_INFO_ROOT(src_fp, tp->ctt_info);
1115178525Sjb	vlen = LCTF_INFO_VLEN(src_fp, tp->ctt_info);
1116178525Sjb
1117178525Sjb	switch (kind) {
1118178525Sjb	case CTF_K_STRUCT:
1119178525Sjb		hp = &dst_fp->ctf_structs;
1120178525Sjb		break;
1121178525Sjb	case CTF_K_UNION:
1122178525Sjb		hp = &dst_fp->ctf_unions;
1123178525Sjb		break;
1124178525Sjb	case CTF_K_ENUM:
1125178525Sjb		hp = &dst_fp->ctf_enums;
1126178525Sjb		break;
1127178525Sjb	default:
1128178525Sjb		hp = &dst_fp->ctf_names;
1129178525Sjb		break;
1130178525Sjb	}
1131178525Sjb
1132178525Sjb	/*
1133178525Sjb	 * If the source type has a name and is a root type (visible at the
1134178525Sjb	 * top-level scope), lookup the name in the destination container and
1135178525Sjb	 * verify that it is of the same kind before we do anything else.
1136178525Sjb	 */
1137178525Sjb	if ((flag & CTF_ADD_ROOT) && name[0] != '\0' &&
1138178525Sjb	    (hep = ctf_hash_lookup(hp, dst_fp, name, strlen(name))) != NULL) {
1139178525Sjb		dst_type = (ctf_id_t)hep->h_type;
1140178525Sjb		dst_kind = ctf_type_kind(dst_fp, dst_type);
1141178525Sjb	}
1142178525Sjb
1143178525Sjb	/*
1144178525Sjb	 * If an identically named dst_type exists, fail with ECTF_CONFLICT
1145178525Sjb	 * unless dst_type is a forward declaration and src_type is a struct,
1146178525Sjb	 * union, or enum (i.e. the definition of the previous forward decl).
1147178525Sjb	 */
1148178525Sjb	if (dst_type != CTF_ERR && dst_kind != kind && (
1149178525Sjb	    dst_kind != CTF_K_FORWARD || (kind != CTF_K_ENUM &&
1150178525Sjb	    kind != CTF_K_STRUCT && kind != CTF_K_UNION)))
1151178525Sjb		return (ctf_set_errno(dst_fp, ECTF_CONFLICT));
1152178525Sjb
1153178525Sjb	/*
1154178525Sjb	 * If the non-empty name was not found in the appropriate hash, search
1155178525Sjb	 * the list of pending dynamic definitions that are not yet committed.
1156178525Sjb	 * If a matching name and kind are found, assume this is the type that
1157178525Sjb	 * we are looking for.  This is necessary to permit ctf_add_type() to
1158178525Sjb	 * operate recursively on entities such as a struct that contains a
1159178525Sjb	 * pointer member that refers to the same struct type.
1160178525Sjb	 */
1161178525Sjb	if (dst_type == CTF_ERR && name[0] != '\0') {
1162178525Sjb		for (dtd = ctf_list_prev(&dst_fp->ctf_dtdefs); dtd != NULL &&
1163178525Sjb		    dtd->dtd_type > dst_fp->ctf_dtoldid;
1164178525Sjb		    dtd = ctf_list_prev(dtd)) {
1165178525Sjb			if (CTF_INFO_KIND(dtd->dtd_data.ctt_info) == kind &&
1166178525Sjb			    dtd->dtd_name != NULL &&
1167178525Sjb			    strcmp(dtd->dtd_name, name) == 0)
1168178525Sjb				return (dtd->dtd_type);
1169178525Sjb		}
1170178525Sjb	}
1171178525Sjb
1172178525Sjb	src.ctb_file = src_fp;
1173178525Sjb	src.ctb_type = src_type;
1174178525Sjb	src.ctb_dtd = NULL;
1175178525Sjb
1176178525Sjb	dst.ctb_file = dst_fp;
1177178525Sjb	dst.ctb_type = dst_type;
1178178525Sjb	dst.ctb_dtd = NULL;
1179178525Sjb
1180178525Sjb	/*
1181178525Sjb	 * Now perform kind-specific processing.  If dst_type is CTF_ERR, then
1182178525Sjb	 * we add a new type with the same properties as src_type to dst_fp.
1183178525Sjb	 * If dst_type is not CTF_ERR, then we verify that dst_type has the
1184178525Sjb	 * same attributes as src_type.  We recurse for embedded references.
1185178525Sjb	 */
1186178525Sjb	switch (kind) {
1187178525Sjb	case CTF_K_INTEGER:
1188178525Sjb	case CTF_K_FLOAT:
1189178525Sjb		if (ctf_type_encoding(src_fp, src_type, &src_en) != 0)
1190178525Sjb			return (ctf_set_errno(dst_fp, ctf_errno(src_fp)));
1191178525Sjb
1192178525Sjb		if (dst_type != CTF_ERR) {
1193178525Sjb			if (ctf_type_encoding(dst_fp, dst_type, &dst_en) != 0)
1194178525Sjb				return (CTF_ERR); /* errno is set for us */
1195178525Sjb
1196178525Sjb			if (bcmp(&src_en, &dst_en, sizeof (ctf_encoding_t)))
1197178525Sjb				return (ctf_set_errno(dst_fp, ECTF_CONFLICT));
1198178525Sjb
1199178525Sjb		} else if (kind == CTF_K_INTEGER) {
1200178525Sjb			dst_type = ctf_add_integer(dst_fp, flag, name, &src_en);
1201178525Sjb		} else
1202178525Sjb			dst_type = ctf_add_float(dst_fp, flag, name, &src_en);
1203178525Sjb		break;
1204178525Sjb
1205178525Sjb	case CTF_K_POINTER:
1206178525Sjb	case CTF_K_VOLATILE:
1207178525Sjb	case CTF_K_CONST:
1208178525Sjb	case CTF_K_RESTRICT:
1209178525Sjb		src_type = ctf_type_reference(src_fp, src_type);
1210178525Sjb		src_type = ctf_add_type(dst_fp, src_fp, src_type);
1211178525Sjb
1212178525Sjb		if (src_type == CTF_ERR)
1213178525Sjb			return (CTF_ERR); /* errno is set for us */
1214178525Sjb
1215178525Sjb		dst_type = ctf_add_reftype(dst_fp, flag, src_type, kind);
1216178525Sjb		break;
1217178525Sjb
1218178525Sjb	case CTF_K_ARRAY:
1219178525Sjb		if (ctf_array_info(src_fp, src_type, &src_ar) == CTF_ERR)
1220178525Sjb			return (ctf_set_errno(dst_fp, ctf_errno(src_fp)));
1221178525Sjb
1222178525Sjb		src_ar.ctr_contents =
1223178525Sjb		    ctf_add_type(dst_fp, src_fp, src_ar.ctr_contents);
1224178525Sjb		src_ar.ctr_index =
1225178525Sjb		    ctf_add_type(dst_fp, src_fp, src_ar.ctr_index);
1226178525Sjb		src_ar.ctr_nelems = src_ar.ctr_nelems;
1227178525Sjb
1228178525Sjb		if (src_ar.ctr_contents == CTF_ERR ||
1229178525Sjb		    src_ar.ctr_index == CTF_ERR)
1230178525Sjb			return (CTF_ERR); /* errno is set for us */
1231178525Sjb
1232178525Sjb		if (dst_type != CTF_ERR) {
1233178525Sjb			if (ctf_array_info(dst_fp, dst_type, &dst_ar) != 0)
1234178525Sjb				return (CTF_ERR); /* errno is set for us */
1235178525Sjb
1236178525Sjb			if (bcmp(&src_ar, &dst_ar, sizeof (ctf_arinfo_t)))
1237178525Sjb				return (ctf_set_errno(dst_fp, ECTF_CONFLICT));
1238178525Sjb		} else
1239178525Sjb			dst_type = ctf_add_array(dst_fp, flag, &src_ar);
1240178525Sjb		break;
1241178525Sjb
1242178525Sjb	case CTF_K_FUNCTION:
1243178525Sjb		ctc.ctc_return = ctf_add_type(dst_fp, src_fp, tp->ctt_type);
1244178525Sjb		ctc.ctc_argc = 0;
1245178525Sjb		ctc.ctc_flags = 0;
1246178525Sjb
1247178525Sjb		if (ctc.ctc_return == CTF_ERR)
1248178525Sjb			return (CTF_ERR); /* errno is set for us */
1249178525Sjb
1250178525Sjb		dst_type = ctf_add_function(dst_fp, flag, &ctc, NULL);
1251178525Sjb		break;
1252178525Sjb
1253178525Sjb	case CTF_K_STRUCT:
1254178525Sjb	case CTF_K_UNION: {
1255178525Sjb		ctf_dmdef_t *dmd;
1256178525Sjb		int errs = 0;
1257178525Sjb
1258178525Sjb		/*
1259178525Sjb		 * Technically to match a struct or union we need to check both
1260178525Sjb		 * ways (src members vs. dst, dst members vs. src) but we make
1261178525Sjb		 * this more optimal by only checking src vs. dst and comparing
1262178525Sjb		 * the total size of the structure (which we must do anyway)
1263178525Sjb		 * which covers the possibility of dst members not in src.
1264178525Sjb		 * This optimization can be defeated for unions, but is so
1265178525Sjb		 * pathological as to render it irrelevant for our purposes.
1266178525Sjb		 */
1267178525Sjb		if (dst_type != CTF_ERR && dst_kind != CTF_K_FORWARD) {
1268178525Sjb			if (ctf_type_size(src_fp, src_type) !=
1269178525Sjb			    ctf_type_size(dst_fp, dst_type))
1270178525Sjb				return (ctf_set_errno(dst_fp, ECTF_CONFLICT));
1271178525Sjb
1272178525Sjb			if (ctf_member_iter(src_fp, src_type, membcmp, &dst))
1273178525Sjb				return (ctf_set_errno(dst_fp, ECTF_CONFLICT));
1274178525Sjb
1275178525Sjb			break;
1276178525Sjb		}
1277178525Sjb
1278178525Sjb		/*
1279178525Sjb		 * Unlike the other cases, copying structs and unions is done
1280178525Sjb		 * manually so as to avoid repeated lookups in ctf_add_member
1281178525Sjb		 * and to ensure the exact same member offsets as in src_type.
1282178525Sjb		 */
1283178525Sjb		dst_type = ctf_add_generic(dst_fp, flag, name, &dtd);
1284178525Sjb		if (dst_type == CTF_ERR)
1285178525Sjb			return (CTF_ERR); /* errno is set for us */
1286178525Sjb
1287178525Sjb		dst.ctb_type = dst_type;
1288178525Sjb		dst.ctb_dtd = dtd;
1289178525Sjb
1290178525Sjb		if (ctf_member_iter(src_fp, src_type, membadd, &dst) != 0)
1291178525Sjb			errs++; /* increment errs and fail at bottom of case */
1292178525Sjb
1293178525Sjb		if ((size = ctf_type_size(src_fp, src_type)) > CTF_MAX_SIZE) {
1294178525Sjb			dtd->dtd_data.ctt_size = CTF_LSIZE_SENT;
1295178525Sjb			dtd->dtd_data.ctt_lsizehi = CTF_SIZE_TO_LSIZE_HI(size);
1296178525Sjb			dtd->dtd_data.ctt_lsizelo = CTF_SIZE_TO_LSIZE_LO(size);
1297178525Sjb		} else
1298178525Sjb			dtd->dtd_data.ctt_size = (ushort_t)size;
1299178525Sjb
1300178525Sjb		dtd->dtd_data.ctt_info = CTF_TYPE_INFO(kind, flag, vlen);
1301178525Sjb
1302178525Sjb		/*
1303178525Sjb		 * Make a final pass through the members changing each dmd_type
1304178525Sjb		 * (a src_fp type) to an equivalent type in dst_fp.  We pass
1305178525Sjb		 * through all members, leaving any that fail set to CTF_ERR.
1306178525Sjb		 */
1307178525Sjb		for (dmd = ctf_list_next(&dtd->dtd_u.dtu_members);
1308178525Sjb		    dmd != NULL; dmd = ctf_list_next(dmd)) {
1309178525Sjb			if ((dmd->dmd_type = ctf_add_type(dst_fp, src_fp,
1310178525Sjb			    dmd->dmd_type)) == CTF_ERR)
1311178525Sjb				errs++;
1312178525Sjb		}
1313178525Sjb
1314178525Sjb		if (errs)
1315178525Sjb			return (CTF_ERR); /* errno is set for us */
1316178525Sjb		break;
1317178525Sjb	}
1318178525Sjb
1319178525Sjb	case CTF_K_ENUM:
1320178525Sjb		if (dst_type != CTF_ERR && dst_kind != CTF_K_FORWARD) {
1321178525Sjb			if (ctf_enum_iter(src_fp, src_type, enumcmp, &dst) ||
1322178525Sjb			    ctf_enum_iter(dst_fp, dst_type, enumcmp, &src))
1323178525Sjb				return (ctf_set_errno(dst_fp, ECTF_CONFLICT));
1324178525Sjb		} else {
1325178525Sjb			dst_type = ctf_add_enum(dst_fp, flag, name);
1326178525Sjb			if ((dst.ctb_type = dst_type) == CTF_ERR ||
1327178525Sjb			    ctf_enum_iter(src_fp, src_type, enumadd, &dst))
1328178525Sjb				return (CTF_ERR); /* errno is set for us */
1329178525Sjb		}
1330178525Sjb		break;
1331178525Sjb
1332178525Sjb	case CTF_K_FORWARD:
1333178525Sjb		if (dst_type == CTF_ERR) {
1334178525Sjb			dst_type = ctf_add_forward(dst_fp,
1335178525Sjb			    flag, name, CTF_K_STRUCT); /* assume STRUCT */
1336178525Sjb		}
1337178525Sjb		break;
1338178525Sjb
1339178525Sjb	case CTF_K_TYPEDEF:
1340178525Sjb		src_type = ctf_type_reference(src_fp, src_type);
1341178525Sjb		src_type = ctf_add_type(dst_fp, src_fp, src_type);
1342178525Sjb
1343178525Sjb		if (src_type == CTF_ERR)
1344178525Sjb			return (CTF_ERR); /* errno is set for us */
1345178525Sjb
1346178525Sjb		/*
1347178525Sjb		 * If dst_type is not CTF_ERR at this point, we should check if
1348178525Sjb		 * ctf_type_reference(dst_fp, dst_type) != src_type and if so
1349178525Sjb		 * fail with ECTF_CONFLICT.  However, this causes problems with
1350178525Sjb		 * <sys/types.h> typedefs that vary based on things like if
1351178525Sjb		 * _ILP32x then pid_t is int otherwise long.  We therefore omit
1352178525Sjb		 * this check and assume that if the identically named typedef
1353178525Sjb		 * already exists in dst_fp, it is correct or equivalent.
1354178525Sjb		 */
1355178525Sjb		if (dst_type == CTF_ERR) {
1356178525Sjb			dst_type = ctf_add_typedef(dst_fp, flag,
1357178525Sjb			    name, src_type);
1358178525Sjb		}
1359178525Sjb		break;
1360178525Sjb
1361178525Sjb	default:
1362178525Sjb		return (ctf_set_errno(dst_fp, ECTF_CORRUPT));
1363178525Sjb	}
1364178525Sjb
1365178525Sjb	return (dst_type);
1366178525Sjb}
1367