xref: /freebsd/cddl/contrib/opensolaris/common/ctf/ctf_create.c (revision a6fb86917362e3f6d24e95e940e80845c2cfde8a)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 
23 /*
24  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
25  * Use is subject to license terms.
26  */
27 /*
28  * Copyright (c) 2013, Joyent, Inc.  All rights reserved.
29  */
30 
31 #include <sys/sysmacros.h>
32 #include <sys/param.h>
33 #include <sys/mman.h>
34 #include <ctf_impl.h>
35 #include <sys/debug.h>
36 
37 /*
38  * This static string is used as the template for initially populating a
39  * dynamic container's string table.  We always store \0 in the first byte,
40  * and we use the generic string "PARENT" to mark this container's parent
41  * if one is associated with the container using ctf_import().
42  */
43 static const char _CTF_STRTAB_TEMPLATE[] = "\0PARENT";
44 
45 /*
46  * To create an empty CTF container, we just declare a zeroed header and call
47  * ctf_bufopen() on it.  If ctf_bufopen succeeds, we mark the new container r/w
48  * and initialize the dynamic members.  We set dtstrlen to 1 to reserve the
49  * first byte of the string table for a \0 byte, and we start assigning type
50  * IDs at 1 because type ID 0 is used as a sentinel.
51  */
52 ctf_file_t *
ctf_create(int * errp)53 ctf_create(int *errp)
54 {
55 	static const ctf_header_t hdr = { { CTF_MAGIC, CTF_VERSION, 0 } };
56 
57 	const ulong_t hashlen = 128;
58 	ctf_dtdef_t **hash = ctf_alloc(hashlen * sizeof (ctf_dtdef_t *));
59 	ctf_sect_t cts;
60 	ctf_file_t *fp;
61 
62 	if (hash == NULL)
63 		return (ctf_set_open_errno(errp, EAGAIN));
64 
65 	cts.cts_name = _CTF_SECTION;
66 	cts.cts_type = SHT_PROGBITS;
67 	cts.cts_flags = 0;
68 	cts.cts_data = (void *)&hdr;
69 	cts.cts_size = sizeof (hdr);
70 	cts.cts_entsize = 1;
71 	cts.cts_offset = 0;
72 
73 	if ((fp = ctf_bufopen(&cts, NULL, NULL, errp)) == NULL) {
74 		ctf_free(hash, hashlen * sizeof (ctf_dtdef_t *));
75 		return (NULL);
76 	}
77 
78 	fp->ctf_flags |= LCTF_RDWR;
79 	fp->ctf_dthashlen = hashlen;
80 	bzero(hash, hashlen * sizeof (ctf_dtdef_t *));
81 	fp->ctf_dthash = hash;
82 	fp->ctf_dtstrlen = sizeof (_CTF_STRTAB_TEMPLATE);
83 	fp->ctf_dtnextid = 1;
84 	fp->ctf_dtoldid = 0;
85 
86 	return (fp);
87 }
88 
89 static uchar_t *
ctf_copy_smembers(const ctf_file_t * fp,ctf_dtdef_t * dtd,uint_t soff,uchar_t * t)90 ctf_copy_smembers(const ctf_file_t *fp, ctf_dtdef_t *dtd, uint_t soff,
91     uchar_t *t)
92 {
93 	ctf_dmdef_t *dmd = ctf_list_next(&dtd->dtd_u.dtu_members);
94 	size_t sz;
95 	uint_t name;
96 
97 	for (; dmd != NULL; dmd = ctf_list_next(dmd)) {
98 		if (dmd->dmd_name) {
99 			name = soff;
100 			soff += strlen(dmd->dmd_name) + 1;
101 		} else
102 			name = 0;
103 
104 		if (fp->ctf_version == CTF_VERSION_2) {
105 			struct ctf_member_v2 ctm;
106 
107 			ctm.ctm_name = name;
108 			ctm.ctm_type = (ushort_t)dmd->dmd_type;
109 			ctm.ctm_offset = (ushort_t)dmd->dmd_offset;
110 
111 			sz = sizeof (ctm);
112 			bcopy(&ctm, t, sz);
113 			t += sz;
114 		} else {
115 			struct ctf_member_v3 ctm;
116 
117 			ctm.ctm_name = name;
118 			ctm.ctm_type = dmd->dmd_type;
119 			ctm.ctm_offset = dmd->dmd_offset;
120 
121 			sz = sizeof (ctm);
122 			bcopy(&ctm, t, sz);
123 			t += sz;
124 		}
125 	}
126 
127 	return (t);
128 }
129 
130 static uchar_t *
ctf_copy_lmembers(const ctf_file_t * fp,ctf_dtdef_t * dtd,uint_t soff,uchar_t * t)131 ctf_copy_lmembers(const ctf_file_t *fp, ctf_dtdef_t *dtd, uint_t soff,
132     uchar_t *t)
133 {
134 	ctf_dmdef_t *dmd = ctf_list_next(&dtd->dtd_u.dtu_members);
135 	size_t sz;
136 	uint_t name;
137 
138 	for (; dmd != NULL; dmd = ctf_list_next(dmd)) {
139 		if (dmd->dmd_name) {
140 			name = soff;
141 			soff += strlen(dmd->dmd_name) + 1;
142 		} else
143 			name = 0;
144 
145 		if (fp->ctf_version == CTF_VERSION_2) {
146 			struct ctf_lmember_v2 ctlm;
147 
148 			ctlm.ctlm_name = name;
149 			ctlm.ctlm_type = (ushort_t)dmd->dmd_type;
150 			ctlm.ctlm_pad = 0;
151 			ctlm.ctlm_offsethi = CTF_OFFSET_TO_LMEMHI(dmd->dmd_offset);
152 			ctlm.ctlm_offsetlo = CTF_OFFSET_TO_LMEMLO(dmd->dmd_offset);
153 
154 			sz = sizeof (ctlm);
155 			bcopy(&ctlm, t, sz);
156 			t += sz;
157 		} else {
158 			struct ctf_lmember_v3 ctlm;
159 
160 			ctlm.ctlm_name = name;
161 			ctlm.ctlm_type = dmd->dmd_type;
162 			ctlm.ctlm_offsethi = CTF_OFFSET_TO_LMEMHI(dmd->dmd_offset);
163 			ctlm.ctlm_offsetlo = CTF_OFFSET_TO_LMEMLO(dmd->dmd_offset);
164 
165 			sz = sizeof (ctlm);
166 			bcopy(&ctlm, t, sz);
167 			t += sz;
168 		}
169 	}
170 
171 	return (t);
172 }
173 
174 static uchar_t *
ctf_copy_emembers(ctf_dtdef_t * dtd,uint_t soff,uchar_t * t)175 ctf_copy_emembers(ctf_dtdef_t *dtd, uint_t soff, uchar_t *t)
176 {
177 	ctf_dmdef_t *dmd = ctf_list_next(&dtd->dtd_u.dtu_members);
178 	ctf_enum_t cte;
179 
180 	for (; dmd != NULL; dmd = ctf_list_next(dmd)) {
181 		cte.cte_name = soff;
182 		cte.cte_value = dmd->dmd_value;
183 		soff += strlen(dmd->dmd_name) + 1;
184 		bcopy(&cte, t, sizeof (cte));
185 		t += sizeof (cte);
186 	}
187 
188 	return (t);
189 }
190 
191 static uchar_t *
ctf_copy_membnames(ctf_dtdef_t * dtd,uchar_t * s)192 ctf_copy_membnames(ctf_dtdef_t *dtd, uchar_t *s)
193 {
194 	ctf_dmdef_t *dmd = ctf_list_next(&dtd->dtd_u.dtu_members);
195 	size_t len;
196 
197 	for (; dmd != NULL; dmd = ctf_list_next(dmd)) {
198 		if (dmd->dmd_name == NULL)
199 			continue; /* skip anonymous members */
200 		len = strlen(dmd->dmd_name) + 1;
201 		bcopy(dmd->dmd_name, s, len);
202 		s += len;
203 	}
204 
205 	return (s);
206 }
207 
208 /*
209  * Only types of dyanmic CTF containers contain reference counts. These
210  * containers are marked RD/WR. Because of that we basically make this a no-op
211  * for compatability with non-dynamic CTF sections. This is also a no-op for
212  * types which are not dynamic types. It is the responsibility of the caller to
213  * make sure it is a valid type. We help that caller out on debug builds.
214  *
215  * Note that the reference counts are not maintained for types that are not
216  * within this container. In other words if we have a type in a parent, that
217  * will not have its reference count increased. On the flip side, the parent
218  * will not be allowed to remove dynamic types if it has children.
219  */
220 static void
ctf_ref_inc(ctf_file_t * fp,ctf_id_t tid)221 ctf_ref_inc(ctf_file_t *fp, ctf_id_t tid)
222 {
223 	ctf_dtdef_t *dtd = ctf_dtd_lookup(fp, tid);
224 
225 	if (dtd == NULL)
226 		return;
227 
228 	if (!(fp->ctf_flags & LCTF_RDWR))
229 		return;
230 
231 	dtd->dtd_ref++;
232 }
233 
234 /*
235  * Just as with ctf_ref_inc, this is a no-op on non-writeable containers and the
236  * caller should ensure that this is already a valid type.
237  */
238 static void
ctf_ref_dec(ctf_file_t * fp,ctf_id_t tid)239 ctf_ref_dec(ctf_file_t *fp, ctf_id_t tid)
240 {
241 	ctf_dtdef_t *dtd = ctf_dtd_lookup(fp, tid);
242 
243 	if (dtd == NULL)
244 		return;
245 
246 	if (!(fp->ctf_flags & LCTF_RDWR))
247 		return;
248 
249 	ASSERT(dtd->dtd_ref >= 1);
250 	dtd->dtd_ref--;
251 }
252 
253 /*
254  * If the specified CTF container is writable and has been modified, reload
255  * this container with the updated type definitions.  In order to make this
256  * code and the rest of libctf as simple as possible, we perform updates by
257  * taking the dynamic type definitions and creating an in-memory CTF file
258  * containing the definitions, and then call ctf_bufopen() on it.  This not
259  * only leverages ctf_bufopen(), but also avoids having to bifurcate the rest
260  * of the library code with different lookup paths for static and dynamic
261  * type definitions.  We are therefore optimizing greatly for lookup over
262  * update, which we assume will be an uncommon operation.  We perform one
263  * extra trick here for the benefit of callers and to keep our code simple:
264  * ctf_bufopen() will return a new ctf_file_t, but we want to keep the fp
265  * constant for the caller, so after ctf_bufopen() returns, we use bcopy to
266  * swap the interior of the old and new ctf_file_t's, and then free the old.
267  *
268  * Note that the lists of dynamic types stays around and the resulting container
269  * is still writeable. Furthermore, the reference counts that are on the dtd's
270  * are still valid.
271  */
272 int
ctf_update(ctf_file_t * fp)273 ctf_update(ctf_file_t *fp)
274 {
275 	ctf_file_t ofp, *nfp;
276 	ctf_header_t hdr;
277 	ctf_dtdef_t *dtd;
278 	ctf_sect_t cts;
279 
280 	uchar_t *s, *s0, *t;
281 	size_t size;
282 	void *buf;
283 	int err;
284 
285 	if (!(fp->ctf_flags & LCTF_RDWR))
286 		return (ctf_set_errno(fp, ECTF_RDONLY));
287 
288 	if (!(fp->ctf_flags & LCTF_DIRTY))
289 		return (0); /* no update required */
290 
291 	/*
292 	 * Fill in an initial CTF header.  We will leave the label, object,
293 	 * and function sections empty and only output a header, type section,
294 	 * and string table.  The type section begins at a 4-byte aligned
295 	 * boundary past the CTF header itself (at relative offset zero).
296 	 */
297 	bzero(&hdr, sizeof (hdr));
298 	hdr.cth_magic = CTF_MAGIC;
299 	hdr.cth_version = fp->ctf_version;
300 
301 	if (fp->ctf_flags & LCTF_CHILD)
302 		hdr.cth_parname = 1; /* i.e. _CTF_STRTAB_TEMPLATE[1] */
303 
304 	/*
305 	 * Iterate through the dynamic type definition list and compute the
306 	 * size of the CTF type section we will need to generate.
307 	 */
308 	for (size = 0, dtd = ctf_list_next(&fp->ctf_dtdefs);
309 	    dtd != NULL; dtd = ctf_list_next(dtd)) {
310 
311 		uint_t kind = LCTF_INFO_KIND(fp, dtd->dtd_data.ctt_info);
312 		uint_t vlen = LCTF_INFO_VLEN(fp, dtd->dtd_data.ctt_info);
313 
314 		if (fp->ctf_version == CTF_VERSION_2) {
315 			if (dtd->dtd_data.ctt_size != CTF_V2_LSIZE_SENT)
316 				size += sizeof (struct ctf_stype_v2);
317 			else
318 				size += sizeof (struct ctf_type_v2);
319 		} else {
320 			if (dtd->dtd_data.ctt_size != LCTF_LSIZE_SENT(fp))
321 				size += sizeof (struct ctf_stype_v3);
322 			else
323 				size += sizeof (struct ctf_type_v3);
324 		}
325 
326 		switch (kind) {
327 		case CTF_K_INTEGER:
328 		case CTF_K_FLOAT:
329 			size += sizeof (uint_t);
330 			break;
331 		case CTF_K_ARRAY:
332 			size += fp->ctf_version == CTF_VERSION_2 ?
333 			    sizeof (struct ctf_array_v2) :
334 			    sizeof (struct ctf_array_v3);
335 			break;
336 		case CTF_K_FUNCTION:
337 			size += roundup2(fp->ctf_idwidth * vlen, 4);
338 			break;
339 		case CTF_K_STRUCT:
340 		case CTF_K_UNION:
341 			if (fp->ctf_version == CTF_VERSION_2) {
342 				if (dtd->dtd_data.ctt_size <
343 				    LCTF_LSTRUCT_THRESH(fp))
344 					size += sizeof (struct ctf_member_v2) *
345 					    vlen;
346 				else
347 					size += sizeof (struct ctf_lmember_v2) *
348 					    vlen;
349 			} else {
350 				if (dtd->dtd_data.ctt_size <
351 				    LCTF_LSTRUCT_THRESH(fp))
352 					size += sizeof (struct ctf_member_v3) *
353 					    vlen;
354 				else
355 					size += sizeof (struct ctf_lmember_v3) *
356 					    vlen;
357 			}
358 			break;
359 		case CTF_K_ENUM:
360 			size += sizeof (ctf_enum_t) * vlen;
361 			break;
362 		}
363 	}
364 
365 	/*
366 	 * Fill in the string table offset and size, compute the size of the
367 	 * entire CTF buffer we need, and then allocate a new buffer and
368 	 * bcopy the finished header to the start of the buffer.
369 	 */
370 	hdr.cth_stroff = hdr.cth_typeoff + size;
371 	hdr.cth_strlen = fp->ctf_dtstrlen;
372 	size = sizeof (ctf_header_t) + hdr.cth_stroff + hdr.cth_strlen;
373 
374 	if ((buf = ctf_data_alloc(size)) == MAP_FAILED)
375 		return (ctf_set_errno(fp, EAGAIN));
376 
377 	bcopy(&hdr, buf, sizeof (ctf_header_t));
378 	t = (uchar_t *)buf + sizeof (ctf_header_t);
379 	s = s0 = (uchar_t *)buf + sizeof (ctf_header_t) + hdr.cth_stroff;
380 
381 	bcopy(_CTF_STRTAB_TEMPLATE, s, sizeof (_CTF_STRTAB_TEMPLATE));
382 	s += sizeof (_CTF_STRTAB_TEMPLATE);
383 
384 	/*
385 	 * We now take a final lap through the dynamic type definition list and
386 	 * copy the appropriate type records and strings to the output buffer.
387 	 */
388 	for (dtd = ctf_list_next(&fp->ctf_dtdefs);
389 	    dtd != NULL; dtd = ctf_list_next(dtd)) {
390 		void *tp;
391 		uint_t kind = LCTF_INFO_KIND(fp, dtd->dtd_data.ctt_info);
392 		uint_t vlen = LCTF_INFO_VLEN(fp, dtd->dtd_data.ctt_info);
393 		struct ctf_type_v2 ctt;
394 
395 		uint_t encoding;
396 		size_t len;
397 
398 		if (dtd->dtd_name != NULL) {
399 			dtd->dtd_data.ctt_name = (uint_t)(s - s0);
400 			len = strlen(dtd->dtd_name) + 1;
401 			bcopy(dtd->dtd_name, s, len);
402 			s += len;
403 		} else
404 			dtd->dtd_data.ctt_name = 0;
405 
406 		if (fp->ctf_version == CTF_VERSION_2) {
407 			ctt.ctt_name = dtd->dtd_data.ctt_name;
408 			ctt.ctt_info = (ushort_t)dtd->dtd_data.ctt_info;
409 			ctt.ctt_size = (ushort_t)dtd->dtd_data.ctt_size;
410 			if (dtd->dtd_data.ctt_size != CTF_V2_LSIZE_SENT)
411 				len = sizeof (struct ctf_stype_v2);
412 			else {
413 				len = sizeof (struct ctf_type_v2);
414 				ctt.ctt_lsizehi = dtd->dtd_data.ctt_lsizehi;
415 				ctt.ctt_lsizelo = dtd->dtd_data.ctt_lsizelo;
416 			}
417 			tp = &ctt;
418 		} else {
419 			if (dtd->dtd_data.ctt_size != LCTF_LSIZE_SENT(fp))
420 				len = sizeof (struct ctf_stype_v3);
421 			else
422 				len = sizeof (struct ctf_type_v3);
423 			tp = &dtd->dtd_data;
424 		}
425 
426 		bcopy(tp, t, len);
427 		t += len;
428 
429 		switch (kind) {
430 		case CTF_K_INTEGER:
431 		case CTF_K_FLOAT:
432 			if (kind == CTF_K_INTEGER) {
433 				encoding = CTF_INT_DATA(
434 				    dtd->dtd_u.dtu_enc.cte_format,
435 				    dtd->dtd_u.dtu_enc.cte_offset,
436 				    dtd->dtd_u.dtu_enc.cte_bits);
437 			} else {
438 				encoding = CTF_FP_DATA(
439 				    dtd->dtd_u.dtu_enc.cte_format,
440 				    dtd->dtd_u.dtu_enc.cte_offset,
441 				    dtd->dtd_u.dtu_enc.cte_bits);
442 			}
443 			bcopy(&encoding, t, sizeof (encoding));
444 			t += sizeof (encoding);
445 			break;
446 
447 		case CTF_K_ARRAY:
448 			if (fp->ctf_version == CTF_VERSION_2) {
449 				struct ctf_array_v2 cta;
450 
451 				cta.cta_contents =
452 				    (uint16_t)dtd->dtd_u.dtu_arr.ctr_contents;
453 				cta.cta_index =
454 				    (uint16_t)dtd->dtd_u.dtu_arr.ctr_index;
455 				cta.cta_nelems = dtd->dtd_u.dtu_arr.ctr_nelems;
456 
457 				bcopy(&cta, t, sizeof (cta));
458 				t += sizeof (cta);
459 			} else {
460 				struct ctf_array_v3 cta;
461 
462 				cta.cta_contents =
463 				    dtd->dtd_u.dtu_arr.ctr_contents;
464 				cta.cta_index = dtd->dtd_u.dtu_arr.ctr_index;
465 				cta.cta_nelems = dtd->dtd_u.dtu_arr.ctr_nelems;
466 
467 				bcopy(&cta, t, sizeof (cta));
468 				t += sizeof (cta);
469 			}
470 			break;
471 
472 		case CTF_K_FUNCTION: {
473 			char *argv = (char *)(uintptr_t)t;
474 			uint_t argc;
475 
476 			if (fp->ctf_version == CTF_VERSION_2) {
477 				ushort_t arg;
478 
479 				for (argc = 0; argc < vlen;
480 				    argc++, argv += sizeof(arg)) {
481 					arg =
482 					    (ushort_t)dtd->dtd_u.dtu_argv[argc];
483 					memcpy(argv, &arg, sizeof(arg));
484 				}
485 			} else {
486 				uint_t arg;
487 
488 				for (argc = 0; argc < vlen;
489 				    argc++, argv += sizeof(arg)) {
490 					arg = (uint_t)dtd->dtd_u.dtu_argv[argc];
491 					memcpy(argv, &arg, sizeof(arg));
492 				}
493 			}
494 
495 			t = (uchar_t *)argv;
496 			break;
497 		}
498 
499 		case CTF_K_STRUCT:
500 		case CTF_K_UNION:
501 			if (dtd->dtd_data.ctt_size < LCTF_LSTRUCT_THRESH(fp))
502 				t = ctf_copy_smembers(fp, dtd, (uint_t)(s - s0),
503 				    t);
504 			else
505 				t = ctf_copy_lmembers(fp, dtd, (uint_t)(s - s0),
506 				    t);
507 			s = ctf_copy_membnames(dtd, s);
508 			break;
509 
510 		case CTF_K_ENUM:
511 			t = ctf_copy_emembers(dtd, (uint_t)(s - s0), t);
512 			s = ctf_copy_membnames(dtd, s);
513 			break;
514 		}
515 	}
516 
517 	/*
518 	 * Finally, we are ready to ctf_bufopen() the new container.  If this
519 	 * is successful, we then switch nfp and fp and free the old container.
520 	 */
521 	ctf_data_protect(buf, size);
522 	cts.cts_name = _CTF_SECTION;
523 	cts.cts_type = SHT_PROGBITS;
524 	cts.cts_flags = 0;
525 	cts.cts_data = buf;
526 	cts.cts_size = size;
527 	cts.cts_entsize = 1;
528 	cts.cts_offset = 0;
529 
530 	if ((nfp = ctf_bufopen(&cts, NULL, NULL, &err)) == NULL) {
531 		ctf_data_free(buf, size);
532 		return (ctf_set_errno(fp, err));
533 	}
534 
535 	(void) ctf_setmodel(nfp, ctf_getmodel(fp));
536 	(void) ctf_import(nfp, fp->ctf_parent);
537 
538 	nfp->ctf_refcnt = fp->ctf_refcnt;
539 	nfp->ctf_flags |= fp->ctf_flags & ~LCTF_DIRTY;
540 	nfp->ctf_data.cts_data = NULL; /* force ctf_data_free() on close */
541 	nfp->ctf_dthash = fp->ctf_dthash;
542 	nfp->ctf_dthashlen = fp->ctf_dthashlen;
543 	nfp->ctf_dtdefs = fp->ctf_dtdefs;
544 	nfp->ctf_dtstrlen = fp->ctf_dtstrlen;
545 	nfp->ctf_dtnextid = fp->ctf_dtnextid;
546 	nfp->ctf_dtoldid = fp->ctf_dtnextid - 1;
547 	nfp->ctf_specific = fp->ctf_specific;
548 
549 	fp->ctf_dthash = NULL;
550 	fp->ctf_dthashlen = 0;
551 	bzero(&fp->ctf_dtdefs, sizeof (ctf_list_t));
552 
553 	bcopy(fp, &ofp, sizeof (ctf_file_t));
554 	bcopy(nfp, fp, sizeof (ctf_file_t));
555 	bcopy(&ofp, nfp, sizeof (ctf_file_t));
556 
557 	/*
558 	 * Initialize the ctf_lookup_by_name top-level dictionary.  We keep an
559 	 * array of type name prefixes and the corresponding ctf_hash to use.
560 	 * NOTE: This code must be kept in sync with the code in ctf_bufopen().
561 	 */
562 	fp->ctf_lookups[0].ctl_hash = &fp->ctf_structs;
563 	fp->ctf_lookups[1].ctl_hash = &fp->ctf_unions;
564 	fp->ctf_lookups[2].ctl_hash = &fp->ctf_enums;
565 	fp->ctf_lookups[3].ctl_hash = &fp->ctf_names;
566 
567 	nfp->ctf_refcnt = 1; /* force nfp to be freed */
568 	ctf_close(nfp);
569 
570 	return (0);
571 }
572 
573 void
ctf_dtd_insert(ctf_file_t * fp,ctf_dtdef_t * dtd)574 ctf_dtd_insert(ctf_file_t *fp, ctf_dtdef_t *dtd)
575 {
576 	ulong_t h = dtd->dtd_type & (fp->ctf_dthashlen - 1);
577 
578 	dtd->dtd_hash = fp->ctf_dthash[h];
579 	fp->ctf_dthash[h] = dtd;
580 	ctf_list_append(&fp->ctf_dtdefs, dtd);
581 }
582 
583 void
ctf_dtd_delete(ctf_file_t * fp,ctf_dtdef_t * dtd)584 ctf_dtd_delete(ctf_file_t *fp, ctf_dtdef_t *dtd)
585 {
586 	ulong_t h = dtd->dtd_type & (fp->ctf_dthashlen - 1);
587 	ctf_dtdef_t *p, **q = &fp->ctf_dthash[h];
588 	ctf_dmdef_t *dmd, *nmd;
589 	size_t len;
590 	int kind, i;
591 
592 	for (p = *q; p != NULL; p = p->dtd_hash) {
593 		if (p != dtd)
594 			q = &p->dtd_hash;
595 		else
596 			break;
597 	}
598 
599 	if (p != NULL)
600 		*q = p->dtd_hash;
601 
602 	kind = LCTF_INFO_KIND(fp, dtd->dtd_data.ctt_info);
603 	switch (kind) {
604 	case CTF_K_STRUCT:
605 	case CTF_K_UNION:
606 	case CTF_K_ENUM:
607 		for (dmd = ctf_list_next(&dtd->dtd_u.dtu_members);
608 		    dmd != NULL; dmd = nmd) {
609 			if (dmd->dmd_name != NULL) {
610 				len = strlen(dmd->dmd_name) + 1;
611 				ctf_free(dmd->dmd_name, len);
612 				fp->ctf_dtstrlen -= len;
613 			}
614 			if (kind != CTF_K_ENUM)
615 				ctf_ref_dec(fp, dmd->dmd_type);
616 			nmd = ctf_list_next(dmd);
617 			ctf_free(dmd, sizeof (ctf_dmdef_t));
618 		}
619 		break;
620 	case CTF_K_FUNCTION:
621 		ctf_ref_dec(fp, dtd->dtd_data.ctt_type);
622 		for (i = 0; i < LCTF_INFO_VLEN(fp, dtd->dtd_data.ctt_info); i++)
623 			if (dtd->dtd_u.dtu_argv[i] != 0)
624 				ctf_ref_dec(fp, dtd->dtd_u.dtu_argv[i]);
625 		ctf_free(dtd->dtd_u.dtu_argv, sizeof (ctf_id_t) *
626 		    LCTF_INFO_VLEN(fp, dtd->dtd_data.ctt_info));
627 		break;
628 	case CTF_K_ARRAY:
629 		ctf_ref_dec(fp, dtd->dtd_u.dtu_arr.ctr_contents);
630 		ctf_ref_dec(fp, dtd->dtd_u.dtu_arr.ctr_index);
631 		break;
632 	case CTF_K_TYPEDEF:
633 		ctf_ref_dec(fp, dtd->dtd_data.ctt_type);
634 		break;
635 	case CTF_K_POINTER:
636 	case CTF_K_VOLATILE:
637 	case CTF_K_CONST:
638 	case CTF_K_RESTRICT:
639 		ctf_ref_dec(fp, dtd->dtd_data.ctt_type);
640 		break;
641 	}
642 
643 	if (dtd->dtd_name) {
644 		len = strlen(dtd->dtd_name) + 1;
645 		ctf_free(dtd->dtd_name, len);
646 		fp->ctf_dtstrlen -= len;
647 	}
648 
649 	ctf_list_delete(&fp->ctf_dtdefs, dtd);
650 	ctf_free(dtd, sizeof (ctf_dtdef_t));
651 }
652 
653 ctf_dtdef_t *
ctf_dtd_lookup(ctf_file_t * fp,ctf_id_t type)654 ctf_dtd_lookup(ctf_file_t *fp, ctf_id_t type)
655 {
656 	ulong_t h = type & (fp->ctf_dthashlen - 1);
657 	ctf_dtdef_t *dtd;
658 
659 	if (fp->ctf_dthash == NULL)
660 		return (NULL);
661 
662 	for (dtd = fp->ctf_dthash[h]; dtd != NULL; dtd = dtd->dtd_hash) {
663 		if (dtd->dtd_type == type)
664 			break;
665 	}
666 
667 	return (dtd);
668 }
669 
670 /*
671  * Discard all of the dynamic type definitions that have been added to the
672  * container since the last call to ctf_update().  We locate such types by
673  * scanning the list and deleting elements that have type IDs greater than
674  * ctf_dtoldid, which is set by ctf_update(), above. Note that to work properly
675  * with our reference counting schemes, we must delete the dynamic list in
676  * reverse.
677  */
678 int
ctf_discard(ctf_file_t * fp)679 ctf_discard(ctf_file_t *fp)
680 {
681 	ctf_dtdef_t *dtd, *ntd;
682 
683 	if (!(fp->ctf_flags & LCTF_RDWR))
684 		return (ctf_set_errno(fp, ECTF_RDONLY));
685 
686 	if (!(fp->ctf_flags & LCTF_DIRTY))
687 		return (0); /* no update required */
688 
689 	for (dtd = ctf_list_prev(&fp->ctf_dtdefs); dtd != NULL; dtd = ntd) {
690 		ntd = ctf_list_prev(dtd);
691 		if (LCTF_TYPE_TO_INDEX(fp, dtd->dtd_type) <= fp->ctf_dtoldid)
692 			continue; /* skip types that have been committed */
693 
694 		ctf_dtd_delete(fp, dtd);
695 	}
696 
697 	fp->ctf_dtnextid = fp->ctf_dtoldid + 1;
698 	fp->ctf_flags &= ~LCTF_DIRTY;
699 
700 	return (0);
701 }
702 
703 static ctf_id_t
ctf_add_generic(ctf_file_t * fp,uint_t flag,const char * name,ctf_dtdef_t ** rp)704 ctf_add_generic(ctf_file_t *fp, uint_t flag, const char *name, ctf_dtdef_t **rp)
705 {
706 	ctf_dtdef_t *dtd;
707 	ctf_id_t type;
708 	char *s = NULL;
709 
710 	if (flag != CTF_ADD_NONROOT && flag != CTF_ADD_ROOT)
711 		return (ctf_set_errno(fp, EINVAL));
712 
713 	if (!(fp->ctf_flags & LCTF_RDWR))
714 		return (ctf_set_errno(fp, ECTF_RDONLY));
715 
716 	if (LCTF_INDEX_TO_TYPE(fp, fp->ctf_dtnextid, 1) > LCTF_MAX_TYPE(fp))
717 		return (ctf_set_errno(fp, ECTF_FULL));
718 
719 	if ((dtd = ctf_alloc(sizeof (ctf_dtdef_t))) == NULL)
720 		return (ctf_set_errno(fp, EAGAIN));
721 
722 	if (name != NULL && *name != '\0' && (s = ctf_strdup(name)) == NULL) {
723 		ctf_free(dtd, sizeof (ctf_dtdef_t));
724 		return (ctf_set_errno(fp, EAGAIN));
725 	}
726 
727 	type = fp->ctf_dtnextid++;
728 	type = LCTF_INDEX_TO_TYPE(fp, type, (fp->ctf_flags & LCTF_CHILD));
729 
730 	bzero(dtd, sizeof (ctf_dtdef_t));
731 	dtd->dtd_name = s;
732 	dtd->dtd_type = type;
733 
734 	if (s != NULL)
735 		fp->ctf_dtstrlen += strlen(s) + 1;
736 
737 	ctf_dtd_insert(fp, dtd);
738 	fp->ctf_flags |= LCTF_DIRTY;
739 
740 	*rp = dtd;
741 	return (type);
742 }
743 
744 /*
745  * When encoding integer sizes, we want to convert a byte count in the range
746  * 1-8 to the closest power of 2 (e.g. 3->4, 5->8, etc).  The clp2() function
747  * is a clever implementation from "Hacker's Delight" by Henry Warren, Jr.
748  */
749 static size_t
clp2(size_t x)750 clp2(size_t x)
751 {
752 	x--;
753 
754 	x |= (x >> 1);
755 	x |= (x >> 2);
756 	x |= (x >> 4);
757 	x |= (x >> 8);
758 	x |= (x >> 16);
759 
760 	return (x + 1);
761 }
762 
763 static ctf_id_t
ctf_add_encoded(ctf_file_t * fp,uint_t flag,const char * name,const ctf_encoding_t * ep,uint_t kind)764 ctf_add_encoded(ctf_file_t *fp, uint_t flag,
765     const char *name, const ctf_encoding_t *ep, uint_t kind)
766 {
767 	ctf_dtdef_t *dtd;
768 	ctf_id_t type;
769 
770 	if (ep == NULL)
771 		return (ctf_set_errno(fp, EINVAL));
772 
773 	if ((type = ctf_add_generic(fp, flag, name, &dtd)) == CTF_ERR)
774 		return (CTF_ERR); /* errno is set for us */
775 
776 	dtd->dtd_data.ctt_info = LCTF_TYPE_INFO(fp, kind, flag, 0);
777 	dtd->dtd_data.ctt_size = clp2(P2ROUNDUP(ep->cte_bits, NBBY) / NBBY);
778 	dtd->dtd_u.dtu_enc = *ep;
779 
780 	return (type);
781 }
782 
783 static ctf_id_t
ctf_add_reftype(ctf_file_t * fp,uint_t flag,ctf_id_t ref,uint_t kind)784 ctf_add_reftype(ctf_file_t *fp, uint_t flag, ctf_id_t ref, uint_t kind)
785 {
786 	ctf_dtdef_t *dtd;
787 	ctf_id_t type;
788 
789 	if (ref == CTF_ERR || ref > LCTF_MAX_TYPE(fp))
790 		return (ctf_set_errno(fp, EINVAL));
791 
792 	if ((type = ctf_add_generic(fp, flag, NULL, &dtd)) == CTF_ERR)
793 		return (CTF_ERR); /* errno is set for us */
794 
795 	ctf_ref_inc(fp, ref);
796 
797 	dtd->dtd_data.ctt_info = LCTF_TYPE_INFO(fp, kind, flag, 0);
798 	dtd->dtd_data.ctt_type = (uint_t)ref;
799 
800 	return (type);
801 }
802 
803 ctf_id_t
ctf_add_integer(ctf_file_t * fp,uint_t flag,const char * name,const ctf_encoding_t * ep)804 ctf_add_integer(ctf_file_t *fp, uint_t flag,
805     const char *name, const ctf_encoding_t *ep)
806 {
807 	return (ctf_add_encoded(fp, flag, name, ep, CTF_K_INTEGER));
808 }
809 
810 ctf_id_t
ctf_add_float(ctf_file_t * fp,uint_t flag,const char * name,const ctf_encoding_t * ep)811 ctf_add_float(ctf_file_t *fp, uint_t flag,
812     const char *name, const ctf_encoding_t *ep)
813 {
814 	return (ctf_add_encoded(fp, flag, name, ep, CTF_K_FLOAT));
815 }
816 
817 ctf_id_t
ctf_add_pointer(ctf_file_t * fp,uint_t flag,ctf_id_t ref)818 ctf_add_pointer(ctf_file_t *fp, uint_t flag, ctf_id_t ref)
819 {
820 	return (ctf_add_reftype(fp, flag, ref, CTF_K_POINTER));
821 }
822 
823 ctf_id_t
ctf_add_array(ctf_file_t * fp,uint_t flag,const ctf_arinfo_t * arp)824 ctf_add_array(ctf_file_t *fp, uint_t flag, const ctf_arinfo_t *arp)
825 {
826 	ctf_dtdef_t *dtd;
827 	ctf_id_t type;
828 	ctf_file_t *fpd;
829 
830 	if (arp == NULL)
831 		return (ctf_set_errno(fp, EINVAL));
832 
833 	fpd = fp;
834 	if (ctf_lookup_by_id(&fpd, arp->ctr_contents) == NULL &&
835 	    ctf_dtd_lookup(fp, arp->ctr_contents) == NULL)
836 		return (ctf_set_errno(fp, ECTF_BADID));
837 
838 	fpd = fp;
839 	if (ctf_lookup_by_id(&fpd, arp->ctr_index) == NULL &&
840 	    ctf_dtd_lookup(fp, arp->ctr_index) == NULL)
841 		return (ctf_set_errno(fp, ECTF_BADID));
842 
843 	if ((type = ctf_add_generic(fp, flag, NULL, &dtd)) == CTF_ERR)
844 		return (CTF_ERR); /* errno is set for us */
845 
846 	dtd->dtd_data.ctt_info = LCTF_TYPE_INFO(fp, CTF_K_ARRAY, flag, 0);
847 	dtd->dtd_data.ctt_size = 0;
848 	dtd->dtd_u.dtu_arr = *arp;
849 	ctf_ref_inc(fp, arp->ctr_contents);
850 	ctf_ref_inc(fp, arp->ctr_index);
851 
852 	return (type);
853 }
854 
855 int
ctf_set_array(ctf_file_t * fp,ctf_id_t type,const ctf_arinfo_t * arp)856 ctf_set_array(ctf_file_t *fp, ctf_id_t type, const ctf_arinfo_t *arp)
857 {
858 	ctf_file_t *fpd;
859 	ctf_dtdef_t *dtd = ctf_dtd_lookup(fp, type);
860 
861 	if (!(fp->ctf_flags & LCTF_RDWR))
862 		return (ctf_set_errno(fp, ECTF_RDONLY));
863 
864 	if (dtd == NULL ||
865 	    LCTF_INFO_KIND(fp, dtd->dtd_data.ctt_info) != CTF_K_ARRAY)
866 		return (ctf_set_errno(fp, ECTF_BADID));
867 
868 	fpd = fp;
869 	if (ctf_lookup_by_id(&fpd, arp->ctr_contents) == NULL &&
870 	    ctf_dtd_lookup(fp, arp->ctr_contents) == NULL)
871 		return (ctf_set_errno(fp, ECTF_BADID));
872 
873 	fpd = fp;
874 	if (ctf_lookup_by_id(&fpd, arp->ctr_index) == NULL &&
875 	    ctf_dtd_lookup(fp, arp->ctr_index) == NULL)
876 		return (ctf_set_errno(fp, ECTF_BADID));
877 
878 	ctf_ref_dec(fp, dtd->dtd_u.dtu_arr.ctr_contents);
879 	ctf_ref_dec(fp, dtd->dtd_u.dtu_arr.ctr_index);
880 	fp->ctf_flags |= LCTF_DIRTY;
881 	dtd->dtd_u.dtu_arr = *arp;
882 	ctf_ref_inc(fp, arp->ctr_contents);
883 	ctf_ref_inc(fp, arp->ctr_index);
884 
885 	return (0);
886 }
887 
888 ctf_id_t
ctf_add_function(ctf_file_t * fp,uint_t flag,const ctf_funcinfo_t * ctc,const ctf_id_t * argv)889 ctf_add_function(ctf_file_t *fp, uint_t flag,
890     const ctf_funcinfo_t *ctc, const ctf_id_t *argv)
891 {
892 	ctf_dtdef_t *dtd;
893 	ctf_id_t type;
894 	uint_t vlen;
895 	int i;
896 	ctf_id_t *vdat = NULL;
897 	ctf_file_t *fpd;
898 
899 	if (ctc == NULL || (ctc->ctc_flags & ~CTF_FUNC_VARARG) != 0 ||
900 	    (ctc->ctc_argc != 0 && argv == NULL))
901 		return (ctf_set_errno(fp, EINVAL));
902 
903 	vlen = ctc->ctc_argc;
904 	if (ctc->ctc_flags & CTF_FUNC_VARARG)
905 		vlen++; /* add trailing zero to indicate varargs (see below) */
906 
907 	if (vlen > LCTF_MAX_VLEN(fp))
908 		return (ctf_set_errno(fp, EOVERFLOW));
909 
910 	fpd = fp;
911 	if (ctf_lookup_by_id(&fpd, ctc->ctc_return) == NULL &&
912 	    ctf_dtd_lookup(fp, ctc->ctc_return) == NULL)
913 		return (ctf_set_errno(fp, ECTF_BADID));
914 
915 	for (i = 0; i < ctc->ctc_argc; i++) {
916 		fpd = fp;
917 		if (ctf_lookup_by_id(&fpd, argv[i]) == NULL &&
918 		    ctf_dtd_lookup(fp, argv[i]) == NULL)
919 			return (ctf_set_errno(fp, ECTF_BADID));
920 	}
921 
922 	if (vlen != 0 && (vdat = ctf_alloc(sizeof (ctf_id_t) * vlen)) == NULL)
923 		return (ctf_set_errno(fp, EAGAIN));
924 
925 	if ((type = ctf_add_generic(fp, flag, NULL, &dtd)) == CTF_ERR) {
926 		ctf_free(vdat, sizeof (ctf_id_t) * vlen);
927 		return (CTF_ERR); /* errno is set for us */
928 	}
929 
930 	dtd->dtd_data.ctt_info = LCTF_TYPE_INFO(fp, CTF_K_FUNCTION, flag, vlen);
931 	dtd->dtd_data.ctt_type = ctc->ctc_return;
932 
933 	ctf_ref_inc(fp, ctc->ctc_return);
934 	for (i = 0; i < ctc->ctc_argc; i++)
935 		ctf_ref_inc(fp, argv[i]);
936 
937 	bcopy(argv, vdat, sizeof (ctf_id_t) * ctc->ctc_argc);
938 	if (ctc->ctc_flags & CTF_FUNC_VARARG)
939 		vdat[vlen - 1] = 0; /* add trailing zero to indicate varargs */
940 	dtd->dtd_u.dtu_argv = vdat;
941 
942 	return (type);
943 }
944 
945 ctf_id_t
ctf_add_struct(ctf_file_t * fp,uint_t flag,const char * name)946 ctf_add_struct(ctf_file_t *fp, uint_t flag, const char *name)
947 {
948 	ctf_hash_t *hp = &fp->ctf_structs;
949 	ctf_helem_t *hep = NULL;
950 	ctf_dtdef_t *dtd;
951 	ctf_id_t type;
952 
953 	if (name != NULL)
954 		hep = ctf_hash_lookup(hp, fp, name, strlen(name));
955 
956 	if (hep != NULL && ctf_type_kind(fp, hep->h_type) == CTF_K_FORWARD)
957 		dtd = ctf_dtd_lookup(fp, type = hep->h_type);
958 	else if ((type = ctf_add_generic(fp, flag, name, &dtd)) == CTF_ERR)
959 		return (CTF_ERR); /* errno is set for us */
960 
961 	dtd->dtd_data.ctt_info = LCTF_TYPE_INFO(fp, CTF_K_STRUCT, flag, 0);
962 	dtd->dtd_data.ctt_size = 0;
963 
964 	return (type);
965 }
966 
967 ctf_id_t
ctf_add_union(ctf_file_t * fp,uint_t flag,const char * name)968 ctf_add_union(ctf_file_t *fp, uint_t flag, const char *name)
969 {
970 	ctf_hash_t *hp = &fp->ctf_unions;
971 	ctf_helem_t *hep = NULL;
972 	ctf_dtdef_t *dtd;
973 	ctf_id_t type;
974 
975 	if (name != NULL)
976 		hep = ctf_hash_lookup(hp, fp, name, strlen(name));
977 
978 	if (hep != NULL && ctf_type_kind(fp, hep->h_type) == CTF_K_FORWARD)
979 		dtd = ctf_dtd_lookup(fp, type = hep->h_type);
980 	else if ((type = ctf_add_generic(fp, flag, name, &dtd)) == CTF_ERR)
981 		return (CTF_ERR); /* errno is set for us */
982 
983 	dtd->dtd_data.ctt_info = LCTF_TYPE_INFO(fp, CTF_K_UNION, flag, 0);
984 	dtd->dtd_data.ctt_size = 0;
985 
986 	return (type);
987 }
988 
989 ctf_id_t
ctf_add_enum(ctf_file_t * fp,uint_t flag,const char * name)990 ctf_add_enum(ctf_file_t *fp, uint_t flag, const char *name)
991 {
992 	ctf_hash_t *hp = &fp->ctf_enums;
993 	ctf_helem_t *hep = NULL;
994 	ctf_dtdef_t *dtd;
995 	ctf_id_t type;
996 
997 	if (name != NULL)
998 		hep = ctf_hash_lookup(hp, fp, name, strlen(name));
999 
1000 	if (hep != NULL && ctf_type_kind(fp, hep->h_type) == CTF_K_FORWARD)
1001 		dtd = ctf_dtd_lookup(fp, type = hep->h_type);
1002 	else if ((type = ctf_add_generic(fp, flag, name, &dtd)) == CTF_ERR)
1003 		return (CTF_ERR); /* errno is set for us */
1004 
1005 	dtd->dtd_data.ctt_info = LCTF_TYPE_INFO(fp, CTF_K_ENUM, flag, 0);
1006 	dtd->dtd_data.ctt_size = fp->ctf_dmodel->ctd_int;
1007 
1008 	return (type);
1009 }
1010 
1011 ctf_id_t
ctf_add_forward(ctf_file_t * fp,uint_t flag,const char * name,uint_t kind)1012 ctf_add_forward(ctf_file_t *fp, uint_t flag, const char *name, uint_t kind)
1013 {
1014 	ctf_hash_t *hp;
1015 	ctf_helem_t *hep;
1016 	ctf_dtdef_t *dtd;
1017 	ctf_id_t type;
1018 
1019 	switch (kind) {
1020 	case CTF_K_STRUCT:
1021 		hp = &fp->ctf_structs;
1022 		break;
1023 	case CTF_K_UNION:
1024 		hp = &fp->ctf_unions;
1025 		break;
1026 	case CTF_K_ENUM:
1027 		hp = &fp->ctf_enums;
1028 		break;
1029 	default:
1030 		return (ctf_set_errno(fp, ECTF_NOTSUE));
1031 	}
1032 
1033 	/*
1034 	 * If the type is already defined or exists as a forward tag, just
1035 	 * return the ctf_id_t of the existing definition.
1036 	 */
1037 	if (name != NULL && (hep = ctf_hash_lookup(hp,
1038 	    fp, name, strlen(name))) != NULL)
1039 		return (hep->h_type);
1040 
1041 	if ((type = ctf_add_generic(fp, flag, name, &dtd)) == CTF_ERR)
1042 		return (CTF_ERR); /* errno is set for us */
1043 
1044 	dtd->dtd_data.ctt_info = LCTF_TYPE_INFO(fp, CTF_K_FORWARD, flag, 0);
1045 	dtd->dtd_data.ctt_type = kind;
1046 
1047 	return (type);
1048 }
1049 
1050 ctf_id_t
ctf_add_typedef(ctf_file_t * fp,uint_t flag,const char * name,ctf_id_t ref)1051 ctf_add_typedef(ctf_file_t *fp, uint_t flag, const char *name, ctf_id_t ref)
1052 {
1053 	ctf_dtdef_t *dtd;
1054 	ctf_id_t type;
1055 	ctf_file_t *fpd;
1056 
1057 	fpd = fp;
1058 	if (ref == CTF_ERR || (ctf_lookup_by_id(&fpd, ref) == NULL &&
1059 	    ctf_dtd_lookup(fp, ref) == NULL))
1060 		return (ctf_set_errno(fp, EINVAL));
1061 
1062 	if ((type = ctf_add_generic(fp, flag, name, &dtd)) == CTF_ERR)
1063 		return (CTF_ERR); /* errno is set for us */
1064 
1065 	dtd->dtd_data.ctt_info = LCTF_TYPE_INFO(fp, CTF_K_TYPEDEF, flag, 0);
1066 	dtd->dtd_data.ctt_type = ref;
1067 	ctf_ref_inc(fp, ref);
1068 
1069 	return (type);
1070 }
1071 
1072 ctf_id_t
ctf_add_volatile(ctf_file_t * fp,uint_t flag,ctf_id_t ref)1073 ctf_add_volatile(ctf_file_t *fp, uint_t flag, ctf_id_t ref)
1074 {
1075 	return (ctf_add_reftype(fp, flag, ref, CTF_K_VOLATILE));
1076 }
1077 
1078 ctf_id_t
ctf_add_const(ctf_file_t * fp,uint_t flag,ctf_id_t ref)1079 ctf_add_const(ctf_file_t *fp, uint_t flag, ctf_id_t ref)
1080 {
1081 	return (ctf_add_reftype(fp, flag, ref, CTF_K_CONST));
1082 }
1083 
1084 ctf_id_t
ctf_add_restrict(ctf_file_t * fp,uint_t flag,ctf_id_t ref)1085 ctf_add_restrict(ctf_file_t *fp, uint_t flag, ctf_id_t ref)
1086 {
1087 	return (ctf_add_reftype(fp, flag, ref, CTF_K_RESTRICT));
1088 }
1089 
1090 int
ctf_add_enumerator(ctf_file_t * fp,ctf_id_t enid,const char * name,int value)1091 ctf_add_enumerator(ctf_file_t *fp, ctf_id_t enid, const char *name, int value)
1092 {
1093 	ctf_dtdef_t *dtd = ctf_dtd_lookup(fp, enid);
1094 	ctf_dmdef_t *dmd;
1095 
1096 	uint_t kind, vlen, root;
1097 	char *s;
1098 
1099 	if (name == NULL)
1100 		return (ctf_set_errno(fp, EINVAL));
1101 
1102 	if (!(fp->ctf_flags & LCTF_RDWR))
1103 		return (ctf_set_errno(fp, ECTF_RDONLY));
1104 
1105 	if (dtd == NULL)
1106 		return (ctf_set_errno(fp, ECTF_BADID));
1107 
1108 	kind = LCTF_INFO_KIND(fp, dtd->dtd_data.ctt_info);
1109 	root = LCTF_INFO_ROOT(fp, dtd->dtd_data.ctt_info);
1110 	vlen = LCTF_INFO_VLEN(fp, dtd->dtd_data.ctt_info);
1111 
1112 	if (kind != CTF_K_ENUM)
1113 		return (ctf_set_errno(fp, ECTF_NOTENUM));
1114 
1115 	if (vlen > LCTF_MAX_VLEN(fp))
1116 		return (ctf_set_errno(fp, ECTF_DTFULL));
1117 
1118 	for (dmd = ctf_list_next(&dtd->dtd_u.dtu_members);
1119 	    dmd != NULL; dmd = ctf_list_next(dmd)) {
1120 		if (strcmp(dmd->dmd_name, name) == 0)
1121 			return (ctf_set_errno(fp, ECTF_DUPMEMBER));
1122 	}
1123 
1124 	if ((dmd = ctf_alloc(sizeof (ctf_dmdef_t))) == NULL)
1125 		return (ctf_set_errno(fp, EAGAIN));
1126 
1127 	if ((s = ctf_strdup(name)) == NULL) {
1128 		ctf_free(dmd, sizeof (ctf_dmdef_t));
1129 		return (ctf_set_errno(fp, EAGAIN));
1130 	}
1131 
1132 	dmd->dmd_name = s;
1133 	dmd->dmd_type = CTF_ERR;
1134 	dmd->dmd_offset = 0;
1135 	dmd->dmd_value = value;
1136 
1137 	dtd->dtd_data.ctt_info = LCTF_TYPE_INFO(fp, kind, root, vlen + 1);
1138 	ctf_list_append(&dtd->dtd_u.dtu_members, dmd);
1139 
1140 	fp->ctf_dtstrlen += strlen(s) + 1;
1141 	fp->ctf_flags |= LCTF_DIRTY;
1142 
1143 	return (0);
1144 }
1145 
1146 int
ctf_add_member(ctf_file_t * fp,ctf_id_t souid,const char * name,ctf_id_t type)1147 ctf_add_member(ctf_file_t *fp, ctf_id_t souid, const char *name, ctf_id_t type)
1148 {
1149 	ctf_dtdef_t *dtd = ctf_dtd_lookup(fp, souid);
1150 	ctf_dmdef_t *dmd;
1151 
1152 	ssize_t msize, malign, ssize;
1153 	uint_t kind, vlen, root;
1154 	char *s = NULL;
1155 
1156 	if (!(fp->ctf_flags & LCTF_RDWR))
1157 		return (ctf_set_errno(fp, ECTF_RDONLY));
1158 
1159 	if (dtd == NULL)
1160 		return (ctf_set_errno(fp, ECTF_BADID));
1161 
1162 	kind = LCTF_INFO_KIND(fp, dtd->dtd_data.ctt_info);
1163 	root = LCTF_INFO_ROOT(fp, dtd->dtd_data.ctt_info);
1164 	vlen = LCTF_INFO_VLEN(fp, dtd->dtd_data.ctt_info);
1165 
1166 	if (kind != CTF_K_STRUCT && kind != CTF_K_UNION)
1167 		return (ctf_set_errno(fp, ECTF_NOTSOU));
1168 
1169 	if (vlen > LCTF_MAX_VLEN(fp))
1170 		return (ctf_set_errno(fp, ECTF_DTFULL));
1171 
1172 	if (name != NULL) {
1173 		for (dmd = ctf_list_next(&dtd->dtd_u.dtu_members);
1174 		    dmd != NULL; dmd = ctf_list_next(dmd)) {
1175 			if (dmd->dmd_name != NULL &&
1176 			    strcmp(dmd->dmd_name, name) == 0)
1177 				return (ctf_set_errno(fp, ECTF_DUPMEMBER));
1178 		}
1179 	}
1180 
1181 	if ((msize = ctf_type_size(fp, type)) == CTF_ERR ||
1182 	    (malign = ctf_type_align(fp, type)) == CTF_ERR)
1183 		return (CTF_ERR); /* errno is set for us */
1184 
1185 	if ((dmd = ctf_alloc(sizeof (ctf_dmdef_t))) == NULL)
1186 		return (ctf_set_errno(fp, EAGAIN));
1187 
1188 	if (name != NULL && (s = ctf_strdup(name)) == NULL) {
1189 		ctf_free(dmd, sizeof (ctf_dmdef_t));
1190 		return (ctf_set_errno(fp, EAGAIN));
1191 	}
1192 
1193 	dmd->dmd_name = s;
1194 	dmd->dmd_type = type;
1195 	dmd->dmd_value = -1;
1196 
1197 	if (kind == CTF_K_STRUCT && vlen != 0) {
1198 		ctf_dmdef_t *lmd = ctf_list_prev(&dtd->dtd_u.dtu_members);
1199 		ctf_id_t ltype = ctf_type_resolve(fp, lmd->dmd_type);
1200 		size_t off = lmd->dmd_offset;
1201 
1202 		ctf_encoding_t linfo;
1203 		ssize_t lsize;
1204 
1205 		if (ctf_type_encoding(fp, ltype, &linfo) != CTF_ERR)
1206 			off += linfo.cte_bits;
1207 		else if ((lsize = ctf_type_size(fp, ltype)) != CTF_ERR)
1208 			off += lsize * NBBY;
1209 
1210 		/*
1211 		 * Round up the offset of the end of the last member to the
1212 		 * next byte boundary, convert 'off' to bytes, and then round
1213 		 * it up again to the next multiple of the alignment required
1214 		 * by the new member.  Finally, convert back to bits and store
1215 		 * the result in dmd_offset.  Technically we could do more
1216 		 * efficient packing if the new member is a bit-field, but
1217 		 * we're the "compiler" and ANSI says we can do as we choose.
1218 		 */
1219 		off = roundup(off, NBBY) / NBBY;
1220 		off = roundup(off, MAX(malign, 1));
1221 		dmd->dmd_offset = off * NBBY;
1222 		ssize = off + msize;
1223 	} else {
1224 		dmd->dmd_offset = 0;
1225 		ssize = ctf_get_ctt_size(fp, &dtd->dtd_data, NULL, NULL);
1226 		ssize = MAX(ssize, msize);
1227 	}
1228 
1229 	if (ssize > LCTF_MAX_SIZE(fp)) {
1230 		dtd->dtd_data.ctt_size = LCTF_LSIZE_SENT(fp);
1231 		dtd->dtd_data.ctt_lsizehi = CTF_SIZE_TO_LSIZE_HI(ssize);
1232 		dtd->dtd_data.ctt_lsizelo = CTF_SIZE_TO_LSIZE_LO(ssize);
1233 	} else
1234 		dtd->dtd_data.ctt_size = ssize;
1235 
1236 	dtd->dtd_data.ctt_info = LCTF_TYPE_INFO(fp, kind, root, vlen + 1);
1237 	ctf_list_append(&dtd->dtd_u.dtu_members, dmd);
1238 
1239 	if (s != NULL)
1240 		fp->ctf_dtstrlen += strlen(s) + 1;
1241 
1242 	ctf_ref_inc(fp, type);
1243 	fp->ctf_flags |= LCTF_DIRTY;
1244 	return (0);
1245 }
1246 
1247 /*
1248  * This removes a type from the dynamic section. This will fail if the type is
1249  * referenced by another type. Note that the CTF ID is never reused currently by
1250  * CTF. Note that if this container is a parent container then we just outright
1251  * refuse to remove the type. There currently is no notion of searching for the
1252  * ctf_dtdef_t in parent containers. If there is, then this constraint could
1253  * become finer grained.
1254  */
1255 int
ctf_delete_type(ctf_file_t * fp,ctf_id_t type)1256 ctf_delete_type(ctf_file_t *fp, ctf_id_t type)
1257 {
1258 	ctf_file_t *fpd;
1259 	ctf_dtdef_t *dtd = ctf_dtd_lookup(fp, type);
1260 
1261 	if (!(fp->ctf_flags & LCTF_RDWR))
1262 		return (ctf_set_errno(fp, ECTF_RDONLY));
1263 
1264 	/*
1265 	 * We want to give as useful an errno as possible. That means that we
1266 	 * want to distinguish between a type which does not exist and one for
1267 	 * which the type is not dynamic.
1268 	 */
1269 	fpd = fp;
1270 	if (ctf_lookup_by_id(&fpd, type) == NULL &&
1271 	    ctf_dtd_lookup(fp, type) == NULL)
1272 		return (CTF_ERR); /* errno is set for us */
1273 
1274 	if (dtd == NULL)
1275 		return (ctf_set_errno(fp, ECTF_NOTDYN));
1276 
1277 	if (dtd->dtd_ref != 0 || fp->ctf_refcnt > 1)
1278 		return (ctf_set_errno(fp, ECTF_REFERENCED));
1279 
1280 	ctf_dtd_delete(fp, dtd);
1281 	fp->ctf_flags |= LCTF_DIRTY;
1282 	return (0);
1283 }
1284 
1285 static int
enumcmp(const char * name,int value,void * arg)1286 enumcmp(const char *name, int value, void *arg)
1287 {
1288 	ctf_bundle_t *ctb = arg;
1289 	int bvalue;
1290 
1291 	return (ctf_enum_value(ctb->ctb_file, ctb->ctb_type,
1292 	    name, &bvalue) == CTF_ERR || value != bvalue);
1293 }
1294 
1295 static int
enumadd(const char * name,int value,void * arg)1296 enumadd(const char *name, int value, void *arg)
1297 {
1298 	ctf_bundle_t *ctb = arg;
1299 
1300 	return (ctf_add_enumerator(ctb->ctb_file, ctb->ctb_type,
1301 	    name, value) == CTF_ERR);
1302 }
1303 
1304 static int
membadd(const char * name,ctf_id_t type,ulong_t offset,void * arg)1305 membadd(const char *name, ctf_id_t type, ulong_t offset, void *arg)
1306 {
1307 	ctf_bundle_t *ctb = arg;
1308 	ctf_dmdef_t *dmd;
1309 	char *s = NULL;
1310 
1311 	if ((dmd = ctf_alloc(sizeof (ctf_dmdef_t))) == NULL)
1312 		return (ctf_set_errno(ctb->ctb_file, EAGAIN));
1313 
1314 	if (name != NULL && *name != '\0' && (s = ctf_strdup(name)) == NULL) {
1315 		ctf_free(dmd, sizeof (ctf_dmdef_t));
1316 		return (ctf_set_errno(ctb->ctb_file, EAGAIN));
1317 	}
1318 
1319 	/*
1320 	 * For now, dmd_type is copied as the src_fp's type; it is reset to an
1321 	 * equivalent dst_fp type by a final loop in ctf_add_type(), below.
1322 	 */
1323 	dmd->dmd_name = s;
1324 	dmd->dmd_type = type;
1325 	dmd->dmd_offset = offset;
1326 	dmd->dmd_value = -1;
1327 
1328 	ctf_list_append(&ctb->ctb_dtd->dtd_u.dtu_members, dmd);
1329 
1330 	if (s != NULL)
1331 		ctb->ctb_file->ctf_dtstrlen += strlen(s) + 1;
1332 
1333 	ctb->ctb_file->ctf_flags |= LCTF_DIRTY;
1334 	return (0);
1335 }
1336 
1337 static long
soucmp(ctf_file_t * src_fp,ctf_id_t src_type,ctf_file_t * dst_fp,ctf_id_t dst_type)1338 soucmp(ctf_file_t *src_fp, ctf_id_t src_type, ctf_file_t *dst_fp,
1339     ctf_id_t dst_type)
1340 {
1341 	const void *src_tp, *dst_tp;
1342 	const char *src_name, *dst_name;
1343 	ssize_t src_sz, dst_sz, src_inc, dst_inc;
1344 	uint_t dst_kind, dst_vlen, src_kind, src_vlen, n;
1345 
1346 	if ((src_type = ctf_type_resolve(src_fp, src_type)) == CTF_ERR)
1347 		return (CTF_ERR);
1348 	if ((dst_type = ctf_type_resolve(dst_fp, dst_type)) == CTF_ERR)
1349 		return (CTF_ERR);
1350 
1351 	if ((src_tp = ctf_lookup_by_id(&src_fp, src_type)) == NULL)
1352 		return (CTF_ERR);
1353 	if ((dst_tp = ctf_lookup_by_id(&dst_fp, dst_type)) == NULL)
1354 		return (CTF_ERR);
1355 
1356 	ctf_get_ctt_info(src_fp, src_tp, &src_kind, &src_vlen, NULL);
1357 	ctf_get_ctt_info(dst_fp, dst_tp, &dst_kind, &dst_vlen, NULL);
1358 
1359 	if (src_kind != dst_kind)
1360 		return (ctf_set_errno(dst_fp, ECTF_CONFLICT));
1361 	if (src_kind != CTF_K_STRUCT && src_kind != CTF_K_UNION)
1362 		return (ctf_set_errno(dst_fp, ECTF_CONFLICT));
1363 	if (src_vlen != dst_vlen)
1364 		return (ctf_set_errno(dst_fp, ECTF_CONFLICT));
1365 
1366 	(void) ctf_get_ctt_size(src_fp, src_tp, &src_sz, &src_inc);
1367 	(void) ctf_get_ctt_size(dst_fp, dst_tp, &dst_sz, &dst_inc);
1368 	if (src_sz != dst_sz)
1369 		return (ctf_set_errno(dst_fp, ECTF_CONFLICT));
1370 
1371 	const char *src_mp, *dst_mp;
1372 	ulong_t src_offset, dst_offset;
1373 
1374 	src_mp = (const char *)src_tp + src_inc;
1375 	dst_mp = (const char *)dst_tp + dst_inc;
1376 	for (n = src_vlen; n != 0;
1377 	    n--, src_mp += src_inc, dst_mp += dst_inc) {
1378 		ctf_get_ctm_info(src_fp, src_mp, src_sz, &src_inc, NULL,
1379 		    &src_offset, &src_name);
1380 		ctf_get_ctm_info(dst_fp, dst_mp, dst_sz, &dst_inc, NULL,
1381 		    &dst_offset, &dst_name);
1382 
1383 		if (src_offset != dst_offset)
1384 			return (ctf_set_errno(dst_fp, ECTF_CONFLICT));
1385 		if (strcmp(src_name, dst_name) != 0)
1386 			return (ctf_set_errno(dst_fp, ECTF_CONFLICT));
1387 	}
1388 
1389 	return (0);
1390 }
1391 
1392 /*
1393  * The ctf_add_type routine is used to copy a type from a source CTF container
1394  * to a dynamic destination container.  This routine operates recursively by
1395  * following the source type's links and embedded member types.  If the
1396  * destination container already contains a named type which has the same
1397  * attributes, then we succeed and return this type but no changes occur.
1398  */
1399 ctf_id_t
ctf_add_type(ctf_file_t * dst_fp,ctf_file_t * src_fp,ctf_id_t src_type)1400 ctf_add_type(ctf_file_t *dst_fp, ctf_file_t *src_fp, ctf_id_t src_type)
1401 {
1402 	ctf_id_t dst_type = CTF_ERR;
1403 	uint_t dst_kind = CTF_K_UNKNOWN;
1404 
1405 	const void *tp;
1406 	const char *name;
1407 	uint_t type, kind, flag, vlen;
1408 
1409 	ctf_bundle_t src, dst;
1410 	ctf_encoding_t src_en, main_en, dst_en;
1411 	ctf_arinfo_t src_ar, dst_ar;
1412 
1413 	ctf_dtdef_t *dtd;
1414 	ctf_funcinfo_t ctc;
1415 	ssize_t size;
1416 
1417 	ctf_hash_t *hp;
1418 	ctf_helem_t *hep;
1419 
1420 	if (dst_fp == src_fp)
1421 		return (src_type);
1422 
1423 	if (!(dst_fp->ctf_flags & LCTF_RDWR))
1424 		return (ctf_set_errno(dst_fp, ECTF_RDONLY));
1425 
1426 	if ((tp = ctf_lookup_by_id(&src_fp, src_type)) == NULL)
1427 		return (ctf_set_errno(dst_fp, ctf_errno(src_fp)));
1428 
1429 	name = ctf_type_rname(src_fp, tp);
1430 
1431 	ctf_get_ctt_info(src_fp, tp, &kind, &vlen, &flag);
1432 
1433 	switch (kind) {
1434 	case CTF_K_STRUCT:
1435 		hp = &dst_fp->ctf_structs;
1436 		break;
1437 	case CTF_K_UNION:
1438 		hp = &dst_fp->ctf_unions;
1439 		break;
1440 	case CTF_K_ENUM:
1441 		hp = &dst_fp->ctf_enums;
1442 		break;
1443 	default:
1444 		hp = &dst_fp->ctf_names;
1445 		break;
1446 	}
1447 
1448 	/*
1449 	 * If the source type has a name and is a root type (visible at the
1450 	 * top-level scope), lookup the name in the destination container and
1451 	 * verify that it is of the same kind before we do anything else.
1452 	 */
1453 	if ((flag & CTF_ADD_ROOT) && name[0] != '\0' &&
1454 	    (hep = ctf_hash_lookup(hp, dst_fp, name, strlen(name))) != NULL) {
1455 		dst_type = (ctf_id_t)hep->h_type;
1456 		dst_kind = ctf_type_kind(dst_fp, dst_type);
1457 	}
1458 
1459 	/*
1460 	 * If an identically named dst_type exists, fail with ECTF_CONFLICT
1461 	 * unless dst_type is a forward declaration and src_type is a struct,
1462 	 * union, or enum (i.e. the definition of the previous forward decl).
1463 	 */
1464 	if (dst_type != CTF_ERR && dst_kind != kind) {
1465 		if (dst_kind != CTF_K_FORWARD || (kind != CTF_K_ENUM &&
1466 		    kind != CTF_K_STRUCT && kind != CTF_K_UNION))
1467 			return (ctf_set_errno(dst_fp, ECTF_CONFLICT));
1468 		else
1469 			dst_type = CTF_ERR;
1470 	}
1471 
1472 	/*
1473 	 * If the non-empty name was not found in the appropriate hash, search
1474 	 * the list of pending dynamic definitions that are not yet committed.
1475 	 * If a matching name and kind are found, assume this is the type that
1476 	 * we are looking for.  This is necessary to permit ctf_add_type() to
1477 	 * operate recursively on entities such as a struct that contains a
1478 	 * pointer member that refers to the same struct type.
1479 	 *
1480 	 * In the case of integer and floating point types, we match using the
1481 	 * type encoding as well - else we may incorrectly return a bitfield
1482 	 * type, for instance.
1483 	 */
1484 	if (dst_type == CTF_ERR && name[0] != '\0') {
1485 		for (dtd = ctf_list_prev(&dst_fp->ctf_dtdefs); dtd != NULL &&
1486 		    LCTF_TYPE_TO_INDEX(dst_fp, dtd->dtd_type) >
1487 		    dst_fp->ctf_dtoldid; dtd = ctf_list_prev(dtd)) {
1488 			if (LCTF_INFO_KIND(dst_fp, dtd->dtd_data.ctt_info) !=
1489 			    kind || dtd->dtd_name == NULL ||
1490 			    strcmp(dtd->dtd_name, name) != 0)
1491 				continue;
1492 			if (kind == CTF_K_INTEGER || kind == CTF_K_FLOAT) {
1493 				if (ctf_type_encoding(src_fp, src_type,
1494 				    &src_en) != 0)
1495 					continue;
1496 				if (bcmp(&src_en, &dtd->dtd_u.dtu_enc,
1497 				    sizeof (ctf_encoding_t)) != 0)
1498 					continue;
1499 			}
1500 			return (dtd->dtd_type);
1501 		}
1502 	}
1503 
1504 	src.ctb_file = src_fp;
1505 	src.ctb_type = src_type;
1506 	src.ctb_dtd = NULL;
1507 
1508 	dst.ctb_file = dst_fp;
1509 	dst.ctb_type = dst_type;
1510 	dst.ctb_dtd = NULL;
1511 
1512 	/*
1513 	 * Now perform kind-specific processing.  If dst_type is CTF_ERR, then
1514 	 * we add a new type with the same properties as src_type to dst_fp.
1515 	 * If dst_type is not CTF_ERR, then we verify that dst_type has the
1516 	 * same attributes as src_type.  We recurse for embedded references.
1517 	 */
1518 	switch (kind) {
1519 	case CTF_K_INTEGER:
1520 	case CTF_K_FLOAT:
1521 		if (ctf_type_encoding(src_fp, src_type, &src_en) != 0)
1522 			return (ctf_set_errno(dst_fp, ctf_errno(src_fp)));
1523 
1524 		/*
1525 		 * This could be a bitfield, and the CTF library assumes
1526 		 * intrinsics will appear before bitfields. Therefore,
1527 		 * try to copy over the intrinsic prior to copying the
1528 		 * bitfield.
1529 		 */
1530 		if (dst_type == CTF_ERR && name[0] != '\0' &&
1531 		    (hep = ctf_hash_lookup(&src_fp->ctf_names, src_fp, name,
1532 		    strlen(name))) != NULL &&
1533 		    src_type != (ctf_id_t)hep->h_type) {
1534 			if (ctf_type_encoding(src_fp, (ctf_id_t)hep->h_type,
1535 			    &main_en) != 0) {
1536 				return (ctf_set_errno(dst_fp,
1537 				    ctf_errno(src_fp)));
1538 			}
1539 			if (bcmp(&src_en, &main_en, sizeof (ctf_encoding_t)) &&
1540 			    ctf_add_type(dst_fp, src_fp,
1541 			    (ctf_id_t)hep->h_type) == CTF_ERR)
1542 				return (CTF_ERR); /* errno is set for us */
1543 		}
1544 
1545 		if (dst_type != CTF_ERR) {
1546 			if (ctf_type_encoding(dst_fp, dst_type, &dst_en) != 0)
1547 				return (CTF_ERR); /* errno is set for us */
1548 
1549 			if (bcmp(&src_en, &dst_en, sizeof (ctf_encoding_t)))
1550 				return (ctf_set_errno(dst_fp, ECTF_CONFLICT));
1551 
1552 		} else if (kind == CTF_K_INTEGER) {
1553 			dst_type = ctf_add_integer(dst_fp, flag, name, &src_en);
1554 		} else
1555 			dst_type = ctf_add_float(dst_fp, flag, name, &src_en);
1556 		break;
1557 
1558 	case CTF_K_POINTER:
1559 	case CTF_K_VOLATILE:
1560 	case CTF_K_CONST:
1561 	case CTF_K_RESTRICT:
1562 		src_type = ctf_type_reference(src_fp, src_type);
1563 		src_type = ctf_add_type(dst_fp, src_fp, src_type);
1564 
1565 		if (src_type == CTF_ERR)
1566 			return (CTF_ERR); /* errno is set for us */
1567 
1568 		dst_type = ctf_add_reftype(dst_fp, flag, src_type, kind);
1569 		break;
1570 
1571 	case CTF_K_ARRAY:
1572 		if (ctf_array_info(src_fp, src_type, &src_ar) == CTF_ERR)
1573 			return (ctf_set_errno(dst_fp, ctf_errno(src_fp)));
1574 
1575 		src_ar.ctr_contents =
1576 		    ctf_add_type(dst_fp, src_fp, src_ar.ctr_contents);
1577 		src_ar.ctr_index =
1578 		    ctf_add_type(dst_fp, src_fp, src_ar.ctr_index);
1579 		src_ar.ctr_nelems = src_ar.ctr_nelems;
1580 
1581 		if (src_ar.ctr_contents == CTF_ERR ||
1582 		    src_ar.ctr_index == CTF_ERR)
1583 			return (CTF_ERR); /* errno is set for us */
1584 
1585 		if (dst_type != CTF_ERR) {
1586 			if (ctf_array_info(dst_fp, dst_type, &dst_ar) != 0)
1587 				return (CTF_ERR); /* errno is set for us */
1588 
1589 			if (bcmp(&src_ar, &dst_ar, sizeof (ctf_arinfo_t)))
1590 				return (ctf_set_errno(dst_fp, ECTF_CONFLICT));
1591 		} else
1592 			dst_type = ctf_add_array(dst_fp, flag, &src_ar);
1593 		break;
1594 
1595 	case CTF_K_FUNCTION:
1596 		ctf_get_ctt_index(src_fp, tp, NULL, &type, NULL);
1597 		ctc.ctc_return = ctf_add_type(dst_fp, src_fp, type);
1598 		ctc.ctc_argc = 0;
1599 		ctc.ctc_flags = 0;
1600 
1601 		if (ctc.ctc_return == CTF_ERR)
1602 			return (CTF_ERR); /* errno is set for us */
1603 
1604 		dst_type = ctf_add_function(dst_fp, flag, &ctc, NULL);
1605 		break;
1606 
1607 	case CTF_K_STRUCT:
1608 	case CTF_K_UNION: {
1609 		ctf_dmdef_t *dmd;
1610 		int errs = 0;
1611 
1612 		if (dst_type != CTF_ERR && dst_kind != CTF_K_FORWARD) {
1613 			/*
1614 			 * Compare the sizes and fields of the two types.
1615 			 * The field comparisons only check the names and
1616 			 * offsets, so this is not perfect but is good enough
1617 			 * for scenarios that we care about.
1618 			 */
1619 			if (soucmp(src_fp, src_type, dst_fp, dst_type) != 0)
1620 				return (CTF_ERR); /* errno is set for us */
1621 			break;
1622 		}
1623 
1624 		/*
1625 		 * Unlike the other cases, copying structs and unions is done
1626 		 * manually so as to avoid repeated lookups in ctf_add_member
1627 		 * and to ensure the exact same member offsets as in src_type.
1628 		 */
1629 		dst_type = ctf_add_generic(dst_fp, flag, name, &dtd);
1630 		if (dst_type == CTF_ERR)
1631 			return (CTF_ERR); /* errno is set for us */
1632 
1633 		dst.ctb_type = dst_type;
1634 		dst.ctb_dtd = dtd;
1635 
1636 		if (ctf_member_iter(src_fp, src_type, membadd, &dst) != 0)
1637 			errs++; /* increment errs and fail at bottom of case */
1638 
1639 		if ((size = ctf_type_size(src_fp, src_type)) >
1640 		    LCTF_MAX_SIZE(src_fp)) {
1641 			dtd->dtd_data.ctt_size = LCTF_LSIZE_SENT(dst_fp);
1642 			dtd->dtd_data.ctt_lsizehi = CTF_SIZE_TO_LSIZE_HI(size);
1643 			dtd->dtd_data.ctt_lsizelo = CTF_SIZE_TO_LSIZE_LO(size);
1644 		} else
1645 			dtd->dtd_data.ctt_size = size;
1646 
1647 		dtd->dtd_data.ctt_info = LCTF_TYPE_INFO(dst_fp, kind, flag,
1648 		    vlen);
1649 
1650 		/*
1651 		 * Make a final pass through the members changing each dmd_type
1652 		 * (a src_fp type) to an equivalent type in dst_fp.  We pass
1653 		 * through all members, leaving any that fail set to CTF_ERR.
1654 		 */
1655 		for (dmd = ctf_list_next(&dtd->dtd_u.dtu_members);
1656 		    dmd != NULL; dmd = ctf_list_next(dmd)) {
1657 			if ((dmd->dmd_type = ctf_add_type(dst_fp, src_fp,
1658 			    dmd->dmd_type)) == CTF_ERR)
1659 				errs++;
1660 		}
1661 
1662 		if (errs)
1663 			return (CTF_ERR); /* errno is set for us */
1664 
1665 		/*
1666 		 * Now that we know that we can't fail, we go through and bump
1667 		 * all the reference counts on the member types.
1668 		 */
1669 		for (dmd = ctf_list_next(&dtd->dtd_u.dtu_members);
1670 		    dmd != NULL; dmd = ctf_list_next(dmd))
1671 			ctf_ref_inc(dst_fp, dmd->dmd_type);
1672 		break;
1673 	}
1674 
1675 	case CTF_K_ENUM:
1676 		if (dst_type != CTF_ERR && dst_kind != CTF_K_FORWARD) {
1677 			if (ctf_enum_iter(src_fp, src_type, enumcmp, &dst) ||
1678 			    ctf_enum_iter(dst_fp, dst_type, enumcmp, &src))
1679 				return (ctf_set_errno(dst_fp, ECTF_CONFLICT));
1680 		} else {
1681 			dst_type = ctf_add_enum(dst_fp, flag, name);
1682 			if ((dst.ctb_type = dst_type) == CTF_ERR ||
1683 			    ctf_enum_iter(src_fp, src_type, enumadd, &dst))
1684 				return (CTF_ERR); /* errno is set for us */
1685 		}
1686 		break;
1687 
1688 	case CTF_K_FORWARD:
1689 		if (dst_type == CTF_ERR) {
1690 			dst_type = ctf_add_forward(dst_fp,
1691 			    flag, name, CTF_K_STRUCT); /* assume STRUCT */
1692 		}
1693 		break;
1694 
1695 	case CTF_K_TYPEDEF:
1696 		src_type = ctf_type_reference(src_fp, src_type);
1697 		src_type = ctf_add_type(dst_fp, src_fp, src_type);
1698 
1699 		if (src_type == CTF_ERR)
1700 			return (CTF_ERR); /* errno is set for us */
1701 
1702 		/*
1703 		 * If dst_type is not CTF_ERR at this point, we should check if
1704 		 * ctf_type_reference(dst_fp, dst_type) != src_type and if so
1705 		 * fail with ECTF_CONFLICT.  However, this causes problems with
1706 		 * <sys/types.h> typedefs that vary based on things like if
1707 		 * _ILP32x then pid_t is int otherwise long.  We therefore omit
1708 		 * this check and assume that if the identically named typedef
1709 		 * already exists in dst_fp, it is correct or equivalent.
1710 		 */
1711 		if (dst_type == CTF_ERR) {
1712 			dst_type = ctf_add_typedef(dst_fp, flag,
1713 			    name, src_type);
1714 		}
1715 		break;
1716 
1717 	default:
1718 		return (ctf_set_errno(dst_fp, ECTF_CORRUPT));
1719 	}
1720 
1721 	return (dst_type);
1722 }
1723