VirtualBox

source: vbox/trunk/src/VBox/ExtPacks/VBoxDTrace/onnv/common/ctf/ctf_create.c@ 86250

Last change on this file since 86250 was 63129, checked in by vboxsync, 8 years ago

dtrace: warnings

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 36.6 KB
Line 
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#ifndef VBOX
29#pragma ident "%Z%%M% %I% %E% SMI"
30
31#include <sys/sysmacros.h>
32#include <sys/param.h>
33#include <sys/mman.h>
34#else /* VBOX */
35#endif /* VBOX */
36#include <ctf_impl.h>
37
38/*
39 * This static string is used as the template for initially populating a
40 * dynamic container's string table. We always store \0 in the first byte,
41 * and we use the generic string "PARENT" to mark this container's parent
42 * if one is associated with the container using ctf_import().
43 */
44static const char _CTF_STRTAB_TEMPLATE[] = "\0PARENT";
45
46/*
47 * To create an empty CTF container, we just declare a zeroed header and call
48 * ctf_bufopen() on it. If ctf_bufopen succeeds, we mark the new container r/w
49 * and initialize the dynamic members. We set dtstrlen to 1 to reserve the
50 * first byte of the string table for a \0 byte, and we start assigning type
51 * IDs at 1 because type ID 0 is used as a sentinel.
52 */
53ctf_file_t *
54ctf_create(int *errp)
55{
56 static const ctf_header_t hdr = { { CTF_MAGIC, CTF_VERSION, 0 } };
57
58 const ulong_t hashlen = 128;
59 ctf_dtdef_t **hash = ctf_alloc(hashlen * sizeof (ctf_dtdef_t *));
60 ctf_sect_t cts;
61 ctf_file_t *fp;
62
63 if (hash == NULL)
64 return (ctf_set_open_errno(errp, EAGAIN));
65
66 cts.cts_name = _CTF_SECTION;
67 cts.cts_type = SHT_PROGBITS;
68 cts.cts_flags = 0;
69 cts.cts_data = &hdr;
70 cts.cts_size = sizeof (hdr);
71 cts.cts_entsize = 1;
72 cts.cts_offset = 0;
73
74 if ((fp = ctf_bufopen(&cts, NULL, NULL, errp)) == NULL) {
75 ctf_free(hash, hashlen * sizeof (ctf_dtdef_t *));
76 return (NULL);
77 }
78
79 fp->ctf_flags |= LCTF_RDWR;
80 fp->ctf_dthashlen = hashlen;
81 bzero(hash, hashlen * sizeof (ctf_dtdef_t *));
82 fp->ctf_dthash = hash;
83 fp->ctf_dtstrlen = sizeof (_CTF_STRTAB_TEMPLATE);
84 fp->ctf_dtnextid = 1;
85 fp->ctf_dtoldid = 0;
86
87 return (fp);
88}
89
90static uchar_t *
91ctf_copy_smembers(ctf_dtdef_t *dtd, uint_t soff, uchar_t *t)
92{
93 ctf_dmdef_t *dmd = ctf_list_next(&dtd->dtd_u.dtu_members);
94 ctf_member_t ctm;
95
96 for (; dmd != NULL; dmd = ctf_list_next(dmd)) {
97 if (dmd->dmd_name) {
98 ctm.ctm_name = soff;
99 soff += VBDTCAST(uint_t)strlen(dmd->dmd_name) + 1;
100 } else
101 ctm.ctm_name = 0;
102
103 ctm.ctm_type = (ushort_t)dmd->dmd_type;
104 ctm.ctm_offset = (ushort_t)dmd->dmd_offset;
105
106 bcopy(&ctm, t, sizeof (ctm));
107 t += sizeof (ctm);
108 }
109
110 return (t);
111}
112
113static uchar_t *
114ctf_copy_lmembers(ctf_dtdef_t *dtd, uint_t soff, uchar_t *t)
115{
116 ctf_dmdef_t *dmd = ctf_list_next(&dtd->dtd_u.dtu_members);
117 ctf_lmember_t ctlm;
118
119 for (; dmd != NULL; dmd = ctf_list_next(dmd)) {
120 if (dmd->dmd_name) {
121 ctlm.ctlm_name = soff;
122 soff += VBDTCAST(uint_t)strlen(dmd->dmd_name) + 1;
123 } else
124 ctlm.ctlm_name = 0;
125
126 ctlm.ctlm_type = (ushort_t)dmd->dmd_type;
127 ctlm.ctlm_pad = 0;
128 ctlm.ctlm_offsethi = CTF_OFFSET_TO_LMEMHI(dmd->dmd_offset);
129 ctlm.ctlm_offsetlo = CTF_OFFSET_TO_LMEMLO(dmd->dmd_offset);
130
131 bcopy(&ctlm, t, sizeof (ctlm));
132 t += sizeof (ctlm);
133 }
134
135 return (t);
136}
137
138static uchar_t *
139ctf_copy_emembers(ctf_dtdef_t *dtd, uint_t soff, uchar_t *t)
140{
141 ctf_dmdef_t *dmd = ctf_list_next(&dtd->dtd_u.dtu_members);
142 ctf_enum_t cte;
143
144 for (; dmd != NULL; dmd = ctf_list_next(dmd)) {
145 cte.cte_name = soff;
146 cte.cte_value = dmd->dmd_value;
147 soff += VBDTCAST(uint_t)strlen(dmd->dmd_name) + 1;
148 bcopy(&cte, t, sizeof (cte));
149 t += sizeof (cte);
150 }
151
152 return (t);
153}
154
155static uchar_t *
156ctf_copy_membnames(ctf_dtdef_t *dtd, uchar_t *s)
157{
158 ctf_dmdef_t *dmd = ctf_list_next(&dtd->dtd_u.dtu_members);
159 size_t len;
160
161 for (; dmd != NULL; dmd = ctf_list_next(dmd)) {
162 if (dmd->dmd_name == NULL)
163 continue; /* skip anonymous members */
164 len = strlen(dmd->dmd_name) + 1;
165 bcopy(dmd->dmd_name, s, len);
166 s += len;
167 }
168
169 return (s);
170}
171
172/*
173 * If the specified CTF container is writable and has been modified, reload
174 * this container with the updated type definitions. In order to make this
175 * code and the rest of libctf as simple as possible, we perform updates by
176 * taking the dynamic type definitions and creating an in-memory CTF file
177 * containing the definitions, and then call ctf_bufopen() on it. This not
178 * only leverages ctf_bufopen(), but also avoids having to bifurcate the rest
179 * of the library code with different lookup paths for static and dynamic
180 * type definitions. We are therefore optimizing greatly for lookup over
181 * update, which we assume will be an uncommon operation. We perform one
182 * extra trick here for the benefit of callers and to keep our code simple:
183 * ctf_bufopen() will return a new ctf_file_t, but we want to keep the fp
184 * constant for the caller, so after ctf_bufopen() returns, we use bcopy to
185 * swap the interior of the old and new ctf_file_t's, and then free the old.
186 */
187int
188ctf_update(ctf_file_t *fp)
189{
190 ctf_file_t ofp, *nfp;
191 ctf_header_t hdr;
192 ctf_dtdef_t *dtd;
193 ctf_sect_t cts;
194
195 uchar_t *s, *s0, *t;
196 size_t size;
197 void *buf;
198 int err;
199
200 if (!(fp->ctf_flags & LCTF_RDWR))
201 return (ctf_set_errno(fp, ECTF_RDONLY));
202
203 if (!(fp->ctf_flags & LCTF_DIRTY))
204 return (0); /* no update required */
205
206 /*
207 * Fill in an initial CTF header. We will leave the label, object,
208 * and function sections empty and only output a header, type section,
209 * and string table. The type section begins at a 4-byte aligned
210 * boundary past the CTF header itself (at relative offset zero).
211 */
212 bzero(&hdr, sizeof (hdr));
213 hdr.cth_magic = CTF_MAGIC;
214 hdr.cth_version = CTF_VERSION;
215
216 if (fp->ctf_flags & LCTF_CHILD)
217 hdr.cth_parname = 1; /* i.e. _CTF_STRTAB_TEMPLATE[1] */
218
219 /*
220 * Iterate through the dynamic type definition list and compute the
221 * size of the CTF type section we will need to generate.
222 */
223 for (size = 0, dtd = ctf_list_next(&fp->ctf_dtdefs);
224 dtd != NULL; dtd = ctf_list_next(dtd)) {
225
226 uint_t kind = CTF_INFO_KIND(dtd->dtd_data.ctt_info);
227 uint_t vlen = CTF_INFO_VLEN(dtd->dtd_data.ctt_info);
228
229 if (dtd->dtd_data.ctt_size != CTF_LSIZE_SENT)
230 size += sizeof (ctf_stype_t);
231 else
232 size += sizeof (ctf_type_t);
233
234 switch (kind) {
235 case CTF_K_INTEGER:
236 case CTF_K_FLOAT:
237 size += sizeof (uint_t);
238 break;
239 case CTF_K_ARRAY:
240 size += sizeof (ctf_array_t);
241 break;
242 case CTF_K_FUNCTION:
243 size += sizeof (ushort_t) * (vlen + (vlen & 1));
244 break;
245 case CTF_K_STRUCT:
246 case CTF_K_UNION:
247 if (dtd->dtd_data.ctt_size < CTF_LSTRUCT_THRESH)
248 size += sizeof (ctf_member_t) * vlen;
249 else
250 size += sizeof (ctf_lmember_t) * vlen;
251 break;
252 case CTF_K_ENUM:
253 size += sizeof (ctf_enum_t) * vlen;
254 break;
255 }
256 }
257
258 /*
259 * Fill in the string table offset and size, compute the size of the
260 * entire CTF buffer we need, and then allocate a new buffer and
261 * bcopy the finished header to the start of the buffer.
262 */
263 hdr.cth_stroff = hdr.cth_typeoff + VBDTCAST(uint_t)size;
264 hdr.cth_strlen = VBDTCAST(uint_t)fp->ctf_dtstrlen;
265 size = sizeof (ctf_header_t) + hdr.cth_stroff + hdr.cth_strlen;
266
267 if ((buf = ctf_data_alloc(size)) == MAP_FAILED)
268 return (ctf_set_errno(fp, EAGAIN));
269
270 bcopy(&hdr, buf, sizeof (ctf_header_t));
271 t = (uchar_t *)buf + sizeof (ctf_header_t);
272 s = s0 = (uchar_t *)buf + sizeof (ctf_header_t) + hdr.cth_stroff;
273
274 bcopy(_CTF_STRTAB_TEMPLATE, s, sizeof (_CTF_STRTAB_TEMPLATE));
275 s += sizeof (_CTF_STRTAB_TEMPLATE);
276
277 /*
278 * We now take a final lap through the dynamic type definition list and
279 * copy the appropriate type records and strings to the output buffer.
280 */
281 for (dtd = ctf_list_next(&fp->ctf_dtdefs);
282 dtd != NULL; dtd = ctf_list_next(dtd)) {
283
284 uint_t kind = CTF_INFO_KIND(dtd->dtd_data.ctt_info);
285 uint_t vlen = CTF_INFO_VLEN(dtd->dtd_data.ctt_info);
286
287 ctf_array_t cta;
288 uint_t encoding;
289 size_t len;
290
291 if (dtd->dtd_name != NULL) {
292 dtd->dtd_data.ctt_name = (uint_t)(s - s0);
293 len = strlen(dtd->dtd_name) + 1;
294 bcopy(dtd->dtd_name, s, len);
295 s += len;
296 } else
297 dtd->dtd_data.ctt_name = 0;
298
299 if (dtd->dtd_data.ctt_size != CTF_LSIZE_SENT)
300 len = sizeof (ctf_stype_t);
301 else
302 len = sizeof (ctf_type_t);
303
304 bcopy(&dtd->dtd_data, t, len);
305 t += len;
306
307 switch (kind) {
308 case CTF_K_INTEGER:
309 case CTF_K_FLOAT:
310 if (kind == CTF_K_INTEGER) {
311 encoding = CTF_INT_DATA(
312 dtd->dtd_u.dtu_enc.cte_format,
313 dtd->dtd_u.dtu_enc.cte_offset,
314 dtd->dtd_u.dtu_enc.cte_bits);
315 } else {
316 encoding = CTF_FP_DATA(
317 dtd->dtd_u.dtu_enc.cte_format,
318 dtd->dtd_u.dtu_enc.cte_offset,
319 dtd->dtd_u.dtu_enc.cte_bits);
320 }
321 bcopy(&encoding, t, sizeof (encoding));
322 t += sizeof (encoding);
323 break;
324
325 case CTF_K_ARRAY:
326 cta.cta_contents = (ushort_t)
327 dtd->dtd_u.dtu_arr.ctr_contents;
328 cta.cta_index = (ushort_t)
329 dtd->dtd_u.dtu_arr.ctr_index;
330 cta.cta_nelems = dtd->dtd_u.dtu_arr.ctr_nelems;
331 bcopy(&cta, t, sizeof (cta));
332 t += sizeof (cta);
333 break;
334
335 case CTF_K_FUNCTION: {
336 ushort_t *argv = (ushort_t *)(uintptr_t)t;
337 uint_t argc;
338
339 for (argc = 0; argc < vlen; argc++)
340 *argv++ = (ushort_t)dtd->dtd_u.dtu_argv[argc];
341
342 if (vlen & 1)
343 *argv++ = 0; /* pad to 4-byte boundary */
344
345 t = (uchar_t *)argv;
346 break;
347 }
348
349 case CTF_K_STRUCT:
350 case CTF_K_UNION:
351 if (dtd->dtd_data.ctt_size < CTF_LSTRUCT_THRESH)
352 t = ctf_copy_smembers(dtd, (uint_t)(s - s0), t);
353 else
354 t = ctf_copy_lmembers(dtd, (uint_t)(s - s0), t);
355 s = ctf_copy_membnames(dtd, s);
356 break;
357
358 case CTF_K_ENUM:
359 t = ctf_copy_emembers(dtd, (uint_t)(s - s0), t);
360 s = ctf_copy_membnames(dtd, s);
361 break;
362 }
363 }
364
365 /*
366 * Finally, we are ready to ctf_bufopen() the new container. If this
367 * is successful, we then switch nfp and fp and free the old container.
368 */
369 ctf_data_protect(buf, size);
370 cts.cts_name = _CTF_SECTION;
371 cts.cts_type = SHT_PROGBITS;
372 cts.cts_flags = 0;
373 cts.cts_data = buf;
374 cts.cts_size = size;
375 cts.cts_entsize = 1;
376 cts.cts_offset = 0;
377
378 if ((nfp = ctf_bufopen(&cts, NULL, NULL, &err)) == NULL) {
379 ctf_data_free(buf, size);
380 return (ctf_set_errno(fp, err));
381 }
382
383 (void) ctf_setmodel(nfp, ctf_getmodel(fp));
384 (void) ctf_import(nfp, fp->ctf_parent);
385
386 nfp->ctf_refcnt = fp->ctf_refcnt;
387 nfp->ctf_flags |= fp->ctf_flags & ~LCTF_DIRTY;
388 nfp->ctf_data.cts_data = NULL; /* force ctf_data_free() on close */
389 nfp->ctf_dthash = fp->ctf_dthash;
390 nfp->ctf_dthashlen = fp->ctf_dthashlen;
391 nfp->ctf_dtdefs = fp->ctf_dtdefs;
392 nfp->ctf_dtstrlen = fp->ctf_dtstrlen;
393 nfp->ctf_dtnextid = fp->ctf_dtnextid;
394 nfp->ctf_dtoldid = fp->ctf_dtnextid - 1;
395 nfp->ctf_specific = fp->ctf_specific;
396
397 fp->ctf_dthash = NULL;
398 fp->ctf_dthashlen = 0;
399 bzero(&fp->ctf_dtdefs, sizeof (ctf_list_t));
400
401 bcopy(fp, &ofp, sizeof (ctf_file_t));
402 bcopy(nfp, fp, sizeof (ctf_file_t));
403 bcopy(&ofp, nfp, sizeof (ctf_file_t));
404
405 /*
406 * Initialize the ctf_lookup_by_name top-level dictionary. We keep an
407 * array of type name prefixes and the corresponding ctf_hash to use.
408 * NOTE: This code must be kept in sync with the code in ctf_bufopen().
409 */
410 fp->ctf_lookups[0].ctl_hash = &fp->ctf_structs;
411 fp->ctf_lookups[1].ctl_hash = &fp->ctf_unions;
412 fp->ctf_lookups[2].ctl_hash = &fp->ctf_enums;
413 fp->ctf_lookups[3].ctl_hash = &fp->ctf_names;
414
415 nfp->ctf_refcnt = 1; /* force nfp to be freed */
416 ctf_close(nfp);
417
418 return (0);
419}
420
421void
422ctf_dtd_insert(ctf_file_t *fp, ctf_dtdef_t *dtd)
423{
424 ulong_t h = dtd->dtd_type & (fp->ctf_dthashlen - 1);
425
426 dtd->dtd_hash = fp->ctf_dthash[h];
427 fp->ctf_dthash[h] = dtd;
428 ctf_list_append(&fp->ctf_dtdefs, dtd);
429}
430
431void
432ctf_dtd_delete(ctf_file_t *fp, ctf_dtdef_t *dtd)
433{
434 ulong_t h = dtd->dtd_type & (fp->ctf_dthashlen - 1);
435 ctf_dtdef_t *p, **q = &fp->ctf_dthash[h];
436 ctf_dmdef_t *dmd, *nmd;
437 size_t len;
438
439 for (p = *q; p != NULL; p = p->dtd_hash) {
440 if (p != dtd)
441 q = &p->dtd_hash;
442 else
443 break;
444 }
445
446 if (p != NULL)
447 *q = p->dtd_hash;
448
449 switch (CTF_INFO_KIND(dtd->dtd_data.ctt_info)) {
450 case CTF_K_STRUCT:
451 case CTF_K_UNION:
452 case CTF_K_ENUM:
453 for (dmd = ctf_list_next(&dtd->dtd_u.dtu_members);
454 dmd != NULL; dmd = nmd) {
455 if (dmd->dmd_name != NULL) {
456 len = strlen(dmd->dmd_name) + 1;
457 ctf_free(dmd->dmd_name, len);
458 fp->ctf_dtstrlen -= len;
459 }
460 nmd = ctf_list_next(dmd);
461 ctf_free(dmd, sizeof (ctf_dmdef_t));
462 }
463 break;
464 case CTF_K_FUNCTION:
465 ctf_free(dtd->dtd_u.dtu_argv, sizeof (ctf_id_t) *
466 CTF_INFO_VLEN(dtd->dtd_data.ctt_info));
467 break;
468 }
469
470 if (dtd->dtd_name) {
471 len = strlen(dtd->dtd_name) + 1;
472 ctf_free(dtd->dtd_name, len);
473 fp->ctf_dtstrlen -= len;
474 }
475
476 ctf_list_delete(&fp->ctf_dtdefs, dtd);
477 ctf_free(dtd, sizeof (ctf_dtdef_t));
478}
479
480ctf_dtdef_t *
481ctf_dtd_lookup(ctf_file_t *fp, ctf_id_t type)
482{
483 ulong_t h = type & (fp->ctf_dthashlen - 1);
484 ctf_dtdef_t *dtd;
485
486 if (fp->ctf_dthash == NULL)
487 return (NULL);
488
489 for (dtd = fp->ctf_dthash[h]; dtd != NULL; dtd = dtd->dtd_hash) {
490 if (dtd->dtd_type == type)
491 break;
492 }
493
494 return (dtd);
495}
496
497/*
498 * Discard all of the dynamic type definitions that have been added to the
499 * container since the last call to ctf_update(). We locate such types by
500 * scanning the list and deleting elements that have type IDs greater than
501 * ctf_dtoldid, which is set by ctf_update(), above.
502 */
503int
504ctf_discard(ctf_file_t *fp)
505{
506 ctf_dtdef_t *dtd, *ntd VBDTMSC(NULL);
507
508 if (!(fp->ctf_flags & LCTF_RDWR))
509 return (ctf_set_errno(fp, ECTF_RDONLY));
510
511 if (!(fp->ctf_flags & LCTF_DIRTY))
512 return (0); /* no update required */
513
514 for (dtd = ctf_list_next(&fp->ctf_dtdefs); dtd != NULL; dtd = ntd) {
515 if (dtd->dtd_type <= (intptr_t /*vbox*/)fp->ctf_dtoldid)
516 continue; /* skip types that have been committed */
517
518 ntd = ctf_list_next(dtd);
519 ctf_dtd_delete(fp, dtd);
520 }
521
522 fp->ctf_dtnextid = fp->ctf_dtoldid + 1;
523 fp->ctf_flags &= ~LCTF_DIRTY;
524
525 return (0);
526}
527
528static ctf_id_t
529ctf_add_generic(ctf_file_t *fp, uint_t flag, const char *name, ctf_dtdef_t **rp)
530{
531 ctf_dtdef_t *dtd;
532 ctf_id_t type;
533 char *s = NULL;
534
535 if (flag != CTF_ADD_NONROOT && flag != CTF_ADD_ROOT)
536 return (ctf_set_errno(fp, EINVAL));
537
538 if (!(fp->ctf_flags & LCTF_RDWR))
539 return (ctf_set_errno(fp, ECTF_RDONLY));
540
541 if (CTF_INDEX_TO_TYPE(fp->ctf_dtnextid, 1) > CTF_MAX_TYPE)
542 return (ctf_set_errno(fp, ECTF_FULL));
543
544 if ((dtd = ctf_alloc(sizeof (ctf_dtdef_t))) == NULL)
545 return (ctf_set_errno(fp, EAGAIN));
546
547 if (name != NULL && (s = ctf_strdup(name)) == NULL) {
548 ctf_free(dtd, sizeof (ctf_dtdef_t));
549 return (ctf_set_errno(fp, EAGAIN));
550 }
551
552 type = fp->ctf_dtnextid++;
553 type = CTF_INDEX_TO_TYPE(type, (fp->ctf_flags & LCTF_CHILD));
554
555 bzero(dtd, sizeof (ctf_dtdef_t));
556 dtd->dtd_name = s;
557 dtd->dtd_type = type;
558
559 if (s != NULL)
560 fp->ctf_dtstrlen += strlen(s) + 1;
561
562 ctf_dtd_insert(fp, dtd);
563 fp->ctf_flags |= LCTF_DIRTY;
564
565 *rp = dtd;
566 return (type);
567}
568
569/*
570 * When encoding integer sizes, we want to convert a byte count in the range
571 * 1-8 to the closest power of 2 (e.g. 3->4, 5->8, etc). The clp2() function
572 * is a clever implementation from "Hacker's Delight" by Henry Warren, Jr.
573 */
574static size_t
575clp2(size_t x)
576{
577 x--;
578
579 x |= (x >> 1);
580 x |= (x >> 2);
581 x |= (x >> 4);
582 x |= (x >> 8);
583 x |= (x >> 16);
584
585 return (x + 1);
586}
587
588static ctf_id_t
589ctf_add_encoded(ctf_file_t *fp, uint_t flag,
590 const char *name, const ctf_encoding_t *ep, uint_t kind)
591{
592 ctf_dtdef_t *dtd;
593 ctf_id_t type;
594
595 if (ep == NULL)
596 return (ctf_set_errno(fp, EINVAL));
597
598 if ((type = ctf_add_generic(fp, flag, name, &dtd)) == CTF_ERR)
599 return (CTF_ERR); /* errno is set for us */
600
601 dtd->dtd_data.ctt_info = CTF_TYPE_INFO(kind, flag, 0);
602 dtd->dtd_data.ctt_size = VBDTCAST(ushort_t)clp2(P2ROUNDUP(ep->cte_bits, NBBY) / NBBY);
603 dtd->dtd_u.dtu_enc = *ep;
604
605 return (type);
606}
607
608static ctf_id_t
609ctf_add_reftype(ctf_file_t *fp, uint_t flag, ctf_id_t ref, uint_t kind)
610{
611 ctf_dtdef_t *dtd;
612 ctf_id_t type;
613
614 if (ref == CTF_ERR || ref < 0 || ref > CTF_MAX_TYPE)
615 return (ctf_set_errno(fp, EINVAL));
616
617 if ((type = ctf_add_generic(fp, flag, NULL, &dtd)) == CTF_ERR)
618 return (CTF_ERR); /* errno is set for us */
619
620 dtd->dtd_data.ctt_info = CTF_TYPE_INFO(kind, flag, 0);
621 dtd->dtd_data.ctt_type = (ushort_t)ref;
622
623 return (type);
624}
625
626ctf_id_t
627ctf_add_integer(ctf_file_t *fp, uint_t flag,
628 const char *name, const ctf_encoding_t *ep)
629{
630 return (ctf_add_encoded(fp, flag, name, ep, CTF_K_INTEGER));
631}
632
633ctf_id_t
634ctf_add_float(ctf_file_t *fp, uint_t flag,
635 const char *name, const ctf_encoding_t *ep)
636{
637 return (ctf_add_encoded(fp, flag, name, ep, CTF_K_FLOAT));
638}
639
640ctf_id_t
641ctf_add_pointer(ctf_file_t *fp, uint_t flag, ctf_id_t ref)
642{
643 return (ctf_add_reftype(fp, flag, ref, CTF_K_POINTER));
644}
645
646ctf_id_t
647ctf_add_array(ctf_file_t *fp, uint_t flag, const ctf_arinfo_t *arp)
648{
649 ctf_dtdef_t *dtd;
650 ctf_id_t type;
651
652 if (arp == NULL)
653 return (ctf_set_errno(fp, EINVAL));
654
655 if ((type = ctf_add_generic(fp, flag, NULL, &dtd)) == CTF_ERR)
656 return (CTF_ERR); /* errno is set for us */
657
658 dtd->dtd_data.ctt_info = CTF_TYPE_INFO(CTF_K_ARRAY, flag, 0);
659 dtd->dtd_data.ctt_size = 0;
660 dtd->dtd_u.dtu_arr = *arp;
661
662 return (type);
663}
664
665int
666ctf_set_array(ctf_file_t *fp, ctf_id_t type, const ctf_arinfo_t *arp)
667{
668 ctf_dtdef_t *dtd = ctf_dtd_lookup(fp, type);
669
670 if (!(fp->ctf_flags & LCTF_RDWR))
671 return (ctf_set_errno(fp, ECTF_RDONLY));
672
673 if (dtd == NULL || CTF_INFO_KIND(dtd->dtd_data.ctt_info) != CTF_K_ARRAY)
674 return (ctf_set_errno(fp, ECTF_BADID));
675
676 fp->ctf_flags |= LCTF_DIRTY;
677 dtd->dtd_u.dtu_arr = *arp;
678
679 return (0);
680}
681
682ctf_id_t
683ctf_add_function(ctf_file_t *fp, uint_t flag,
684 const ctf_funcinfo_t *ctc, const ctf_id_t *argv)
685{
686 ctf_dtdef_t *dtd;
687 ctf_id_t type;
688 uint_t vlen;
689 ctf_id_t *vdat = NULL;
690
691 if (ctc == NULL || (ctc->ctc_flags & ~CTF_FUNC_VARARG) != 0 ||
692 (ctc->ctc_argc != 0 && argv == NULL))
693 return (ctf_set_errno(fp, EINVAL));
694
695 vlen = ctc->ctc_argc;
696 if (ctc->ctc_flags & CTF_FUNC_VARARG)
697 vlen++; /* add trailing zero to indicate varargs (see below) */
698
699 if (vlen > CTF_MAX_VLEN)
700 return (ctf_set_errno(fp, EOVERFLOW));
701
702 if (vlen != 0 && (vdat = ctf_alloc(sizeof (ctf_id_t) * vlen)) == NULL)
703 return (ctf_set_errno(fp, EAGAIN));
704
705 if ((type = ctf_add_generic(fp, flag, NULL, &dtd)) == CTF_ERR) {
706 ctf_free(vdat, sizeof (ctf_id_t) * vlen);
707 return (CTF_ERR); /* errno is set for us */
708 }
709
710 dtd->dtd_data.ctt_info = CTF_TYPE_INFO(CTF_K_FUNCTION, flag, vlen);
711 dtd->dtd_data.ctt_type = (ushort_t)ctc->ctc_return;
712
713 bcopy(argv, vdat, sizeof (ctf_id_t) * ctc->ctc_argc);
714 if (ctc->ctc_flags & CTF_FUNC_VARARG)
715 vdat[vlen - 1] = 0; /* add trailing zero to indicate varargs */
716 dtd->dtd_u.dtu_argv = vdat;
717
718 return (type);
719}
720
721ctf_id_t
722ctf_add_struct(ctf_file_t *fp, uint_t flag, const char *name)
723{
724 ctf_hash_t *hp = &fp->ctf_structs;
725 ctf_helem_t *hep = NULL;
726 ctf_dtdef_t *dtd;
727 ctf_id_t type;
728
729 if (name != NULL)
730 hep = ctf_hash_lookup(hp, fp, name, strlen(name));
731
732 if (hep != NULL && ctf_type_kind(fp, hep->h_type) == CTF_K_FORWARD)
733 dtd = ctf_dtd_lookup(fp, type = hep->h_type);
734 else if ((type = ctf_add_generic(fp, flag, name, &dtd)) == CTF_ERR)
735 return (CTF_ERR); /* errno is set for us */
736
737 dtd->dtd_data.ctt_info = CTF_TYPE_INFO(CTF_K_STRUCT, flag, 0);
738 dtd->dtd_data.ctt_size = 0;
739
740 return (type);
741}
742
743ctf_id_t
744ctf_add_union(ctf_file_t *fp, uint_t flag, const char *name)
745{
746 ctf_hash_t *hp = &fp->ctf_unions;
747 ctf_helem_t *hep = NULL;
748 ctf_dtdef_t *dtd;
749 ctf_id_t type;
750
751 if (name != NULL)
752 hep = ctf_hash_lookup(hp, fp, name, strlen(name));
753
754 if (hep != NULL && ctf_type_kind(fp, hep->h_type) == CTF_K_FORWARD)
755 dtd = ctf_dtd_lookup(fp, type = hep->h_type);
756 else if ((type = ctf_add_generic(fp, flag, name, &dtd)) == CTF_ERR)
757 return (CTF_ERR); /* errno is set for us */
758
759 dtd->dtd_data.ctt_info = CTF_TYPE_INFO(CTF_K_UNION, flag, 0);
760 dtd->dtd_data.ctt_size = 0;
761
762 return (type);
763}
764
765ctf_id_t
766ctf_add_enum(ctf_file_t *fp, uint_t flag, const char *name)
767{
768 ctf_hash_t *hp = &fp->ctf_enums;
769 ctf_helem_t *hep = NULL;
770 ctf_dtdef_t *dtd;
771 ctf_id_t type;
772
773 if (name != NULL)
774 hep = ctf_hash_lookup(hp, fp, name, strlen(name));
775
776 if (hep != NULL && ctf_type_kind(fp, hep->h_type) == CTF_K_FORWARD)
777 dtd = ctf_dtd_lookup(fp, type = hep->h_type);
778 else if ((type = ctf_add_generic(fp, flag, name, &dtd)) == CTF_ERR)
779 return (CTF_ERR); /* errno is set for us */
780
781 dtd->dtd_data.ctt_info = CTF_TYPE_INFO(CTF_K_ENUM, flag, 0);
782 dtd->dtd_data.ctt_size = VBDTCAST(ushort_t)fp->ctf_dmodel->ctd_int;
783
784 return (type);
785}
786
787ctf_id_t
788ctf_add_forward(ctf_file_t *fp, uint_t flag, const char *name, uint_t kind)
789{
790 ctf_hash_t *hp;
791 ctf_helem_t *hep;
792 ctf_dtdef_t *dtd;
793 ctf_id_t type;
794
795 switch (kind) {
796 case CTF_K_STRUCT:
797 hp = &fp->ctf_structs;
798 break;
799 case CTF_K_UNION:
800 hp = &fp->ctf_unions;
801 break;
802 case CTF_K_ENUM:
803 hp = &fp->ctf_enums;
804 break;
805 default:
806 return (ctf_set_errno(fp, ECTF_NOTSUE));
807 }
808
809 /*
810 * If the type is already defined or exists as a forward tag, just
811 * return the ctf_id_t of the existing definition.
812 */
813 if (name != NULL && (hep = ctf_hash_lookup(hp,
814 fp, name, strlen(name))) != NULL)
815 return (hep->h_type);
816
817 if ((type = ctf_add_generic(fp, flag, name, &dtd)) == CTF_ERR)
818 return (CTF_ERR); /* errno is set for us */
819
820 dtd->dtd_data.ctt_info = CTF_TYPE_INFO(CTF_K_FORWARD, flag, 0);
821 dtd->dtd_data.ctt_type = kind;
822
823 return (type);
824}
825
826ctf_id_t
827ctf_add_typedef(ctf_file_t *fp, uint_t flag, const char *name, ctf_id_t ref)
828{
829 ctf_dtdef_t *dtd;
830 ctf_id_t type;
831
832 if (ref == CTF_ERR || ref < 0 || ref > CTF_MAX_TYPE)
833 return (ctf_set_errno(fp, EINVAL));
834
835 if ((type = ctf_add_generic(fp, flag, name, &dtd)) == CTF_ERR)
836 return (CTF_ERR); /* errno is set for us */
837
838 dtd->dtd_data.ctt_info = CTF_TYPE_INFO(CTF_K_TYPEDEF, flag, 0);
839 dtd->dtd_data.ctt_type = (ushort_t)ref;
840
841 return (type);
842}
843
844ctf_id_t
845ctf_add_volatile(ctf_file_t *fp, uint_t flag, ctf_id_t ref)
846{
847 return (ctf_add_reftype(fp, flag, ref, CTF_K_VOLATILE));
848}
849
850ctf_id_t
851ctf_add_const(ctf_file_t *fp, uint_t flag, ctf_id_t ref)
852{
853 return (ctf_add_reftype(fp, flag, ref, CTF_K_CONST));
854}
855
856ctf_id_t
857ctf_add_restrict(ctf_file_t *fp, uint_t flag, ctf_id_t ref)
858{
859 return (ctf_add_reftype(fp, flag, ref, CTF_K_RESTRICT));
860}
861
862int
863ctf_add_enumerator(ctf_file_t *fp, ctf_id_t enid, const char *name, int value)
864{
865 ctf_dtdef_t *dtd = ctf_dtd_lookup(fp, enid);
866 ctf_dmdef_t *dmd;
867
868 uint_t kind, vlen, root;
869 char *s;
870
871 if (name == NULL)
872 return (ctf_set_errno(fp, EINVAL));
873
874 if (!(fp->ctf_flags & LCTF_RDWR))
875 return (ctf_set_errno(fp, ECTF_RDONLY));
876
877 if (dtd == NULL)
878 return (ctf_set_errno(fp, ECTF_BADID));
879
880 kind = CTF_INFO_KIND(dtd->dtd_data.ctt_info);
881 root = CTF_INFO_ISROOT(dtd->dtd_data.ctt_info);
882 vlen = CTF_INFO_VLEN(dtd->dtd_data.ctt_info);
883
884 if (kind != CTF_K_ENUM)
885 return (ctf_set_errno(fp, ECTF_NOTENUM));
886
887 if (vlen == CTF_MAX_VLEN)
888 return (ctf_set_errno(fp, ECTF_DTFULL));
889
890 for (dmd = ctf_list_next(&dtd->dtd_u.dtu_members);
891 dmd != NULL; dmd = ctf_list_next(dmd)) {
892 if (strcmp(dmd->dmd_name, name) == 0)
893 return (ctf_set_errno(fp, ECTF_DUPMEMBER));
894 }
895
896 if ((dmd = ctf_alloc(sizeof (ctf_dmdef_t))) == NULL)
897 return (ctf_set_errno(fp, EAGAIN));
898
899 if ((s = ctf_strdup(name)) == NULL) {
900 ctf_free(dmd, sizeof (ctf_dmdef_t));
901 return (ctf_set_errno(fp, EAGAIN));
902 }
903
904 dmd->dmd_name = s;
905 dmd->dmd_type = CTF_ERR;
906 dmd->dmd_offset = 0;
907 dmd->dmd_value = value;
908
909 dtd->dtd_data.ctt_info = CTF_TYPE_INFO(kind, root, vlen + 1);
910 ctf_list_append(&dtd->dtd_u.dtu_members, dmd);
911
912 fp->ctf_dtstrlen += strlen(s) + 1;
913 fp->ctf_flags |= LCTF_DIRTY;
914
915 return (0);
916}
917
918int
919ctf_add_member(ctf_file_t *fp, ctf_id_t souid, const char *name, ctf_id_t type)
920{
921 ctf_dtdef_t *dtd = ctf_dtd_lookup(fp, souid);
922 ctf_dmdef_t *dmd;
923
924 ssize_t msize, malign, ssize;
925 uint_t kind, vlen, root;
926 char *s = NULL;
927
928 if (!(fp->ctf_flags & LCTF_RDWR))
929 return (ctf_set_errno(fp, ECTF_RDONLY));
930
931 if (dtd == NULL)
932 return (ctf_set_errno(fp, ECTF_BADID));
933
934 kind = CTF_INFO_KIND(dtd->dtd_data.ctt_info);
935 root = CTF_INFO_ISROOT(dtd->dtd_data.ctt_info);
936 vlen = CTF_INFO_VLEN(dtd->dtd_data.ctt_info);
937
938 if (kind != CTF_K_STRUCT && kind != CTF_K_UNION)
939 return (ctf_set_errno(fp, ECTF_NOTSOU));
940
941 if (vlen == CTF_MAX_VLEN)
942 return (ctf_set_errno(fp, ECTF_DTFULL));
943
944 if (name != NULL) {
945 for (dmd = ctf_list_next(&dtd->dtd_u.dtu_members);
946 dmd != NULL; dmd = ctf_list_next(dmd)) {
947 if (dmd->dmd_name != NULL &&
948 strcmp(dmd->dmd_name, name) == 0)
949 return (ctf_set_errno(fp, ECTF_DUPMEMBER));
950 }
951 }
952
953 if ((msize = ctf_type_size(fp, type)) == CTF_ERR ||
954 (malign = ctf_type_align(fp, type)) == CTF_ERR)
955 return (CTF_ERR); /* errno is set for us */
956
957 if ((dmd = ctf_alloc(sizeof (ctf_dmdef_t))) == NULL)
958 return (ctf_set_errno(fp, EAGAIN));
959
960 if (name != NULL && (s = ctf_strdup(name)) == NULL) {
961 ctf_free(dmd, sizeof (ctf_dmdef_t));
962 return (ctf_set_errno(fp, EAGAIN));
963 }
964
965 dmd->dmd_name = s;
966 dmd->dmd_type = type;
967 dmd->dmd_value = -1;
968
969 if (kind == CTF_K_STRUCT && vlen != 0) {
970 ctf_dmdef_t *lmd = ctf_list_prev(&dtd->dtd_u.dtu_members);
971 ctf_id_t ltype = ctf_type_resolve(fp, lmd->dmd_type);
972 size_t off = lmd->dmd_offset;
973
974 ctf_encoding_t linfo;
975 ssize_t lsize;
976
977 if (ctf_type_encoding(fp, ltype, &linfo) != CTF_ERR)
978 off += linfo.cte_bits;
979 else if ((lsize = ctf_type_size(fp, ltype)) != CTF_ERR)
980 off += lsize * NBBY;
981
982 /*
983 * Round up the offset of the end of the last member to the
984 * next byte boundary, convert 'off' to bytes, and then round
985 * it up again to the next multiple of the alignment required
986 * by the new member. Finally, convert back to bits and store
987 * the result in dmd_offset. Technically we could do more
988 * efficient packing if the new member is a bit-field, but
989 * we're the "compiler" and ANSI says we can do as we choose.
990 */
991 off = roundup(off, NBBY) / NBBY;
992 off = roundup(off, MAX(malign, 1));
993 dmd->dmd_offset = off * NBBY;
994 ssize = off + msize;
995 } else {
996 dmd->dmd_offset = 0;
997 ssize = ctf_get_ctt_size(fp, &dtd->dtd_data, NULL, NULL);
998 ssize = MAX(ssize, msize);
999 }
1000
1001 if (ssize > CTF_MAX_SIZE) {
1002 dtd->dtd_data.ctt_size = CTF_LSIZE_SENT;
1003 dtd->dtd_data.ctt_lsizehi = CTF_SIZE_TO_LSIZE_HI(ssize);
1004 dtd->dtd_data.ctt_lsizelo = CTF_SIZE_TO_LSIZE_LO(ssize);
1005 } else
1006 dtd->dtd_data.ctt_size = (ushort_t)ssize;
1007
1008 dtd->dtd_data.ctt_info = CTF_TYPE_INFO(kind, root, vlen + 1);
1009 ctf_list_append(&dtd->dtd_u.dtu_members, dmd);
1010
1011 if (s != NULL)
1012 fp->ctf_dtstrlen += strlen(s) + 1;
1013
1014 fp->ctf_flags |= LCTF_DIRTY;
1015 return (0);
1016}
1017
1018static int
1019enumcmp(const char *name, int value, void *arg)
1020{
1021 ctf_bundle_t *ctb = arg;
1022 int bvalue;
1023
1024 return (ctf_enum_value(ctb->ctb_file, ctb->ctb_type,
1025 name, &bvalue) == CTF_ERR || value != bvalue);
1026}
1027
1028static int
1029enumadd(const char *name, int value, void *arg)
1030{
1031 ctf_bundle_t *ctb = arg;
1032
1033 return (ctf_add_enumerator(ctb->ctb_file, ctb->ctb_type,
1034 name, value) == CTF_ERR);
1035}
1036
1037/*ARGSUSED*/
1038static int
1039membcmp(const char *name, ctf_id_t type, ulong_t offset, void *arg)
1040{
1041 ctf_bundle_t *ctb = arg;
1042 ctf_membinfo_t ctm;
1043 RT_NOREF1(type);
1044
1045 return (ctf_member_info(ctb->ctb_file, ctb->ctb_type,
1046 name, &ctm) == CTF_ERR || ctm.ctm_offset != offset);
1047}
1048
1049static int
1050membadd(const char *name, ctf_id_t type, ulong_t offset, void *arg)
1051{
1052 ctf_bundle_t *ctb = arg;
1053 ctf_dmdef_t *dmd;
1054 char *s = NULL;
1055
1056 if ((dmd = ctf_alloc(sizeof (ctf_dmdef_t))) == NULL)
1057 return (ctf_set_errno(ctb->ctb_file, EAGAIN));
1058
1059 if (name != NULL && (s = ctf_strdup(name)) == NULL) {
1060 ctf_free(dmd, sizeof (ctf_dmdef_t));
1061 return (ctf_set_errno(ctb->ctb_file, EAGAIN));
1062 }
1063
1064 /*
1065 * For now, dmd_type is copied as the src_fp's type; it is reset to an
1066 * equivalent dst_fp type by a final loop in ctf_add_type(), below.
1067 */
1068 dmd->dmd_name = s;
1069 dmd->dmd_type = type;
1070 dmd->dmd_offset = offset;
1071 dmd->dmd_value = -1;
1072
1073 ctf_list_append(&ctb->ctb_dtd->dtd_u.dtu_members, dmd);
1074
1075 if (s != NULL)
1076 ctb->ctb_file->ctf_dtstrlen += strlen(s) + 1;
1077
1078 ctb->ctb_file->ctf_flags |= LCTF_DIRTY;
1079 return (0);
1080}
1081
1082/*
1083 * The ctf_add_type routine is used to copy a type from a source CTF container
1084 * to a dynamic destination container. This routine operates recursively by
1085 * following the source type's links and embedded member types. If the
1086 * destination container already contains a named type which has the same
1087 * attributes, then we succeed and return this type but no changes occur.
1088 */
1089ctf_id_t
1090ctf_add_type(ctf_file_t *dst_fp, ctf_file_t *src_fp, ctf_id_t src_type)
1091{
1092 ctf_id_t dst_type = CTF_ERR;
1093 uint_t dst_kind = CTF_K_UNKNOWN;
1094
1095 const ctf_type_t *tp;
1096 const char *name;
1097 uint_t kind, flag, vlen;
1098
1099 ctf_bundle_t src, dst;
1100 ctf_encoding_t src_en, dst_en;
1101 ctf_arinfo_t src_ar, dst_ar;
1102
1103 ctf_dtdef_t *dtd;
1104 ctf_funcinfo_t ctc;
1105 ssize_t size;
1106
1107 ctf_hash_t *hp;
1108 ctf_helem_t *hep;
1109
1110 if (!(dst_fp->ctf_flags & LCTF_RDWR))
1111 return (ctf_set_errno(dst_fp, ECTF_RDONLY));
1112
1113 if ((tp = ctf_lookup_by_id(&src_fp, src_type)) == NULL)
1114 return (ctf_set_errno(dst_fp, ctf_errno(src_fp)));
1115
1116 name = ctf_strptr(src_fp, tp->ctt_name);
1117 kind = LCTF_INFO_KIND(src_fp, tp->ctt_info);
1118 flag = LCTF_INFO_ROOT(src_fp, tp->ctt_info);
1119 vlen = LCTF_INFO_VLEN(src_fp, tp->ctt_info);
1120
1121 switch (kind) {
1122 case CTF_K_STRUCT:
1123 hp = &dst_fp->ctf_structs;
1124 break;
1125 case CTF_K_UNION:
1126 hp = &dst_fp->ctf_unions;
1127 break;
1128 case CTF_K_ENUM:
1129 hp = &dst_fp->ctf_enums;
1130 break;
1131 default:
1132 hp = &dst_fp->ctf_names;
1133 break;
1134 }
1135
1136 /*
1137 * If the source type has a name and is a root type (visible at the
1138 * top-level scope), lookup the name in the destination container and
1139 * verify that it is of the same kind before we do anything else.
1140 */
1141 if ((flag & CTF_ADD_ROOT) && name[0] != '\0' &&
1142 (hep = ctf_hash_lookup(hp, dst_fp, name, strlen(name))) != NULL) {
1143 dst_type = (ctf_id_t)hep->h_type;
1144 dst_kind = ctf_type_kind(dst_fp, dst_type);
1145 }
1146
1147 /*
1148 * If an identically named dst_type exists, fail with ECTF_CONFLICT
1149 * unless dst_type is a forward declaration and src_type is a struct,
1150 * union, or enum (i.e. the definition of the previous forward decl).
1151 */
1152 if (dst_type != CTF_ERR && dst_kind != kind && (
1153 dst_kind != CTF_K_FORWARD || (kind != CTF_K_ENUM &&
1154 kind != CTF_K_STRUCT && kind != CTF_K_UNION)))
1155 return (ctf_set_errno(dst_fp, ECTF_CONFLICT));
1156
1157 /*
1158 * If the non-empty name was not found in the appropriate hash, search
1159 * the list of pending dynamic definitions that are not yet committed.
1160 * If a matching name and kind are found, assume this is the type that
1161 * we are looking for. This is necessary to permit ctf_add_type() to
1162 * operate recursively on entities such as a struct that contains a
1163 * pointer member that refers to the same struct type.
1164 */
1165 if (dst_type == CTF_ERR && name[0] != '\0') {
1166 for (dtd = ctf_list_prev(&dst_fp->ctf_dtdefs); dtd != NULL &&
1167 dtd->dtd_type > (intptr_t /*vbox*/)dst_fp->ctf_dtoldid;
1168 dtd = ctf_list_prev(dtd)) {
1169 if ((uint_t)CTF_INFO_KIND(dtd->dtd_data.ctt_info) == kind &&
1170 dtd->dtd_name != NULL &&
1171 strcmp(dtd->dtd_name, name) == 0)
1172 return (dtd->dtd_type);
1173 }
1174 }
1175
1176 src.ctb_file = src_fp;
1177 src.ctb_type = src_type;
1178 src.ctb_dtd = NULL;
1179
1180 dst.ctb_file = dst_fp;
1181 dst.ctb_type = dst_type;
1182 dst.ctb_dtd = NULL;
1183
1184 /*
1185 * Now perform kind-specific processing. If dst_type is CTF_ERR, then
1186 * we add a new type with the same properties as src_type to dst_fp.
1187 * If dst_type is not CTF_ERR, then we verify that dst_type has the
1188 * same attributes as src_type. We recurse for embedded references.
1189 */
1190 switch (kind) {
1191 case CTF_K_INTEGER:
1192 case CTF_K_FLOAT:
1193 if (ctf_type_encoding(src_fp, src_type, &src_en) != 0)
1194 return (ctf_set_errno(dst_fp, ctf_errno(src_fp)));
1195
1196 if (dst_type != CTF_ERR) {
1197 if (ctf_type_encoding(dst_fp, dst_type, &dst_en) != 0)
1198 return (CTF_ERR); /* errno is set for us */
1199
1200 if (bcmp(&src_en, &dst_en, sizeof (ctf_encoding_t)))
1201 return (ctf_set_errno(dst_fp, ECTF_CONFLICT));
1202
1203 } else if (kind == CTF_K_INTEGER) {
1204 dst_type = ctf_add_integer(dst_fp, flag, name, &src_en);
1205 } else
1206 dst_type = ctf_add_float(dst_fp, flag, name, &src_en);
1207 break;
1208
1209 case CTF_K_POINTER:
1210 case CTF_K_VOLATILE:
1211 case CTF_K_CONST:
1212 case CTF_K_RESTRICT:
1213 src_type = ctf_type_reference(src_fp, src_type);
1214 src_type = ctf_add_type(dst_fp, src_fp, src_type);
1215
1216 if (src_type == CTF_ERR)
1217 return (CTF_ERR); /* errno is set for us */
1218
1219 dst_type = ctf_add_reftype(dst_fp, flag, src_type, kind);
1220 break;
1221
1222 case CTF_K_ARRAY:
1223 if (ctf_array_info(src_fp, src_type, &src_ar) == CTF_ERR)
1224 return (ctf_set_errno(dst_fp, ctf_errno(src_fp)));
1225
1226 src_ar.ctr_contents =
1227 ctf_add_type(dst_fp, src_fp, src_ar.ctr_contents);
1228 src_ar.ctr_index =
1229 ctf_add_type(dst_fp, src_fp, src_ar.ctr_index);
1230 src_ar.ctr_nelems = src_ar.ctr_nelems;
1231
1232 if (src_ar.ctr_contents == CTF_ERR ||
1233 src_ar.ctr_index == CTF_ERR)
1234 return (CTF_ERR); /* errno is set for us */
1235
1236 if (dst_type != CTF_ERR) {
1237 if (ctf_array_info(dst_fp, dst_type, &dst_ar) != 0)
1238 return (CTF_ERR); /* errno is set for us */
1239
1240 if (bcmp(&src_ar, &dst_ar, sizeof (ctf_arinfo_t)))
1241 return (ctf_set_errno(dst_fp, ECTF_CONFLICT));
1242 } else
1243 dst_type = ctf_add_array(dst_fp, flag, &src_ar);
1244 break;
1245
1246 case CTF_K_FUNCTION:
1247 ctc.ctc_return = ctf_add_type(dst_fp, src_fp, tp->ctt_type);
1248 ctc.ctc_argc = 0;
1249 ctc.ctc_flags = 0;
1250
1251 if (ctc.ctc_return == CTF_ERR)
1252 return (CTF_ERR); /* errno is set for us */
1253
1254 dst_type = ctf_add_function(dst_fp, flag, &ctc, NULL);
1255 break;
1256
1257 case CTF_K_STRUCT:
1258 case CTF_K_UNION: {
1259 ctf_dmdef_t *dmd;
1260 int errs = 0;
1261
1262 /*
1263 * Technically to match a struct or union we need to check both
1264 * ways (src members vs. dst, dst members vs. src) but we make
1265 * this more optimal by only checking src vs. dst and comparing
1266 * the total size of the structure (which we must do anyway)
1267 * which covers the possibility of dst members not in src.
1268 * This optimization can be defeated for unions, but is so
1269 * pathological as to render it irrelevant for our purposes.
1270 */
1271 if (dst_type != CTF_ERR && dst_kind != CTF_K_FORWARD) {
1272 if (ctf_type_size(src_fp, src_type) !=
1273 ctf_type_size(dst_fp, dst_type))
1274 return (ctf_set_errno(dst_fp, ECTF_CONFLICT));
1275
1276 if (ctf_member_iter(src_fp, src_type, membcmp, &dst))
1277 return (ctf_set_errno(dst_fp, ECTF_CONFLICT));
1278
1279 break;
1280 }
1281
1282 /*
1283 * Unlike the other cases, copying structs and unions is done
1284 * manually so as to avoid repeated lookups in ctf_add_member
1285 * and to ensure the exact same member offsets as in src_type.
1286 */
1287 dst_type = ctf_add_generic(dst_fp, flag, name, &dtd);
1288 if (dst_type == CTF_ERR)
1289 return (CTF_ERR); /* errno is set for us */
1290
1291 dst.ctb_type = dst_type;
1292 dst.ctb_dtd = dtd;
1293
1294 if (ctf_member_iter(src_fp, src_type, membadd, &dst) != 0)
1295 errs++; /* increment errs and fail at bottom of case */
1296
1297 if ((size = ctf_type_size(src_fp, src_type)) > CTF_MAX_SIZE) {
1298 dtd->dtd_data.ctt_size = CTF_LSIZE_SENT;
1299 dtd->dtd_data.ctt_lsizehi = CTF_SIZE_TO_LSIZE_HI(size);
1300 dtd->dtd_data.ctt_lsizelo = CTF_SIZE_TO_LSIZE_LO(size);
1301 } else
1302 dtd->dtd_data.ctt_size = (ushort_t)size;
1303
1304 dtd->dtd_data.ctt_info = CTF_TYPE_INFO(kind, flag, vlen);
1305
1306 /*
1307 * Make a final pass through the members changing each dmd_type
1308 * (a src_fp type) to an equivalent type in dst_fp. We pass
1309 * through all members, leaving any that fail set to CTF_ERR.
1310 */
1311 for (dmd = ctf_list_next(&dtd->dtd_u.dtu_members);
1312 dmd != NULL; dmd = ctf_list_next(dmd)) {
1313 if ((dmd->dmd_type = ctf_add_type(dst_fp, src_fp,
1314 dmd->dmd_type)) == CTF_ERR)
1315 errs++;
1316 }
1317
1318 if (errs)
1319 return (CTF_ERR); /* errno is set for us */
1320 break;
1321 }
1322
1323 case CTF_K_ENUM:
1324 if (dst_type != CTF_ERR && dst_kind != CTF_K_FORWARD) {
1325 if (ctf_enum_iter(src_fp, src_type, enumcmp, &dst) ||
1326 ctf_enum_iter(dst_fp, dst_type, enumcmp, &src))
1327 return (ctf_set_errno(dst_fp, ECTF_CONFLICT));
1328 } else {
1329 dst_type = ctf_add_enum(dst_fp, flag, name);
1330 if ((dst.ctb_type = dst_type) == CTF_ERR ||
1331 ctf_enum_iter(src_fp, src_type, enumadd, &dst))
1332 return (CTF_ERR); /* errno is set for us */
1333 }
1334 break;
1335
1336 case CTF_K_FORWARD:
1337 if (dst_type == CTF_ERR) {
1338 dst_type = ctf_add_forward(dst_fp,
1339 flag, name, CTF_K_STRUCT); /* assume STRUCT */
1340 }
1341 break;
1342
1343 case CTF_K_TYPEDEF:
1344 src_type = ctf_type_reference(src_fp, src_type);
1345 src_type = ctf_add_type(dst_fp, src_fp, src_type);
1346
1347 if (src_type == CTF_ERR)
1348 return (CTF_ERR); /* errno is set for us */
1349
1350 /*
1351 * If dst_type is not CTF_ERR at this point, we should check if
1352 * ctf_type_reference(dst_fp, dst_type) != src_type and if so
1353 * fail with ECTF_CONFLICT. However, this causes problems with
1354 * <sys/types.h> typedefs that vary based on things like if
1355 * _ILP32x then pid_t is int otherwise long. We therefore omit
1356 * this check and assume that if the identically named typedef
1357 * already exists in dst_fp, it is correct or equivalent.
1358 */
1359 if (dst_type == CTF_ERR) {
1360 dst_type = ctf_add_typedef(dst_fp, flag,
1361 name, src_type);
1362 }
1363 break;
1364
1365 default:
1366 return (ctf_set_errno(dst_fp, ECTF_CORRUPT));
1367 }
1368
1369 return (dst_type);
1370}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette