dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / lib / libctf / common / ctf_merge.c
blob8c14772f1bd0bd6353f256713d6b2b2b4ad7bb10
1 /*
2 * This file and its contents are supplied under the terms of the
3 * Common Development and Distribution License ("CDDL"), version 1.0.
4 * You may only use this file in accordance with the terms of version
5 * 1.0 of the CDDL.
7 * A full copy of the text of the CDDL should have accompanied this
8 * source. A copy of the CDDL is also available via the Internet at
9 * http://www.illumos.org/license/CDDL.
13 * Copyright (c) 2015 Joyent, Inc.
17 * To perform a merge of two CTF containers, we first diff the two containers
18 * types. For every type that's in the src container, but not in the dst
19 * container, we note it and add it to dst container. If there are any objects
20 * or functions associated with src, we go through and update the types that
21 * they refer to such that they all refer to types in the dst container.
23 * The bulk of the logic for the merge, after we've run the diff, occurs in
24 * ctf_merge_common().
26 * In terms of exported APIs, we don't really export a simple merge two
27 * containers, as the general way this is used, in something like ctfmerge(1),
28 * is to add all the containers and then let us figure out the best way to merge
29 * it. In the future we'll want to grow some control over the number of threads
30 * that we use to do this, if we end up wanting a muli-threaded merge. If we do,
31 * we should take care to do the merge in the same way every time.
34 #include <libctf_impl.h>
35 #include <sys/debug.h>
36 #include <sys/list.h>
37 #include <stddef.h>
38 #include <fcntl.h>
39 #include <sys/types.h>
40 #include <sys/stat.h>
41 #include <mergeq.h>
42 #include <errno.h>
44 typedef struct ctf_merge_tinfo {
45 uint16_t cmt_map; /* Map to the type in out */
46 boolean_t cmt_fixup;
47 boolean_t cmt_forward;
48 boolean_t cmt_missing;
49 } ctf_merge_tinfo_t;
52 * State required for doing an individual merge of two containers.
54 typedef struct ctf_merge_types {
55 ctf_file_t *cm_out; /* Output CTF file */
56 ctf_file_t *cm_src; /* Input CTF file */
57 ctf_merge_tinfo_t *cm_tmap; /* Type state information */
58 boolean_t cm_dedup; /* Are we doing a dedup? */
59 boolean_t cm_unique; /* are we doing a uniquify? */
60 } ctf_merge_types_t;
62 typedef struct ctf_merge_objmap {
63 list_node_t cmo_node;
64 const char *cmo_name; /* Symbol name */
65 ulong_t cmo_idx; /* Symbol ID */
66 ctf_id_t cmo_tid; /* Type ID */
67 } ctf_merge_objmap_t;
69 typedef struct ctf_merge_funcmap {
70 list_node_t cmf_node;
71 const char *cmf_name; /* Symbol name */
72 ulong_t cmf_idx; /* Symbol ID */
73 ctf_id_t cmf_rtid; /* Type ID */
74 uint_t cmf_flags; /* ctf_funcinfo_t ctc_flags */
75 uint_t cmf_argc; /* Number of arguments */
76 ctf_id_t cmf_args[]; /* Types of arguments */
77 } ctf_merge_funcmap_t;
79 typedef struct ctf_merge_input {
80 list_node_t cmi_node;
81 ctf_file_t *cmi_input;
82 list_t cmi_omap;
83 list_t cmi_fmap;
84 boolean_t cmi_created;
85 } ctf_merge_input_t;
87 struct ctf_merge_handle {
88 list_t cmh_inputs; /* Input list */
89 uint_t cmh_ninputs; /* Number of inputs */
90 uint_t cmh_nthreads; /* Number of threads to use */
91 ctf_file_t *cmh_unique; /* ctf to uniquify against */
92 boolean_t cmh_msyms; /* Should we merge symbols/funcs? */
93 int cmh_ofd; /* FD for output file */
94 int cmh_flags; /* Flags that control merge behavior */
95 char *cmh_label; /* Optional label */
96 char *cmh_pname; /* Parent name */
99 static int ctf_merge_add_type(ctf_merge_types_t *, ctf_id_t);
101 static ctf_id_t
102 ctf_merge_gettype(ctf_merge_types_t *cmp, ctf_id_t id)
104 if (cmp->cm_dedup == B_FALSE) {
105 VERIFY(cmp->cm_tmap[id].cmt_map != 0);
106 return (cmp->cm_tmap[id].cmt_map);
109 while (cmp->cm_tmap[id].cmt_missing == B_FALSE) {
110 VERIFY(cmp->cm_tmap[id].cmt_map != 0);
111 id = cmp->cm_tmap[id].cmt_map;
113 VERIFY(cmp->cm_tmap[id].cmt_map != 0);
114 return (cmp->cm_tmap[id].cmt_map);
117 static void
118 ctf_merge_diffcb(ctf_file_t *ifp, ctf_id_t iid, boolean_t same, ctf_file_t *ofp,
119 ctf_id_t oid, void *arg)
121 ctf_merge_types_t *cmp = arg;
122 ctf_merge_tinfo_t *cmt = cmp->cm_tmap;
124 if (same == B_TRUE) {
125 if (ctf_type_kind(ifp, iid) == CTF_K_FORWARD &&
126 ctf_type_kind(ofp, oid) != CTF_K_FORWARD) {
127 VERIFY(cmt[oid].cmt_map == 0);
130 * If we're uniquifying types, it's possible for the
131 * container that we're uniquifying against to have a
132 * forward which exists in the container being reduced.
133 * For example, genunix has the machcpu structure as a
134 * forward which is actually in unix and we uniquify
135 * unix against genunix. In such cases, we explicitly do
136 * not do any mapping of the forward information, lest
137 * we risk losing the real definition. Instead, mark
138 * that it's missing.
140 if (cmp->cm_unique == B_TRUE) {
141 cmt[oid].cmt_missing = B_TRUE;
142 return;
145 cmt[oid].cmt_map = iid;
146 cmt[oid].cmt_forward = B_TRUE;
147 ctf_dprintf("merge diff forward mapped %d->%d\n", oid,
148 iid);
149 return;
153 * We could have multiple things that a given type ends up
154 * matching in the world of forwards and pointers to forwards.
155 * For now just take the first one...
157 if (cmt[oid].cmt_map != 0)
158 return;
159 cmt[oid].cmt_map = iid;
160 ctf_dprintf("merge diff mapped %d->%d\n", oid, iid);
161 } else if (ifp == cmp->cm_src) {
162 VERIFY(cmt[iid].cmt_map == 0);
163 cmt[iid].cmt_missing = B_TRUE;
164 ctf_dprintf("merge diff said %d is missing\n", iid);
168 static int
169 ctf_merge_add_number(ctf_merge_types_t *cmp, ctf_id_t id)
171 int ret, flags;
172 const ctf_type_t *tp;
173 const char *name;
174 ctf_encoding_t en;
176 if (ctf_type_encoding(cmp->cm_src, id, &en) != 0)
177 return (CTF_ERR);
179 tp = LCTF_INDEX_TO_TYPEPTR(cmp->cm_src, id);
180 name = ctf_strraw(cmp->cm_src, tp->ctt_name);
181 if (CTF_INFO_ISROOT(tp->ctt_info) != 0)
182 flags = CTF_ADD_ROOT;
183 else
184 flags = CTF_ADD_NONROOT;
186 ret = ctf_add_encoded(cmp->cm_out, flags, name, &en,
187 ctf_type_kind(cmp->cm_src, id));
189 if (ret == CTF_ERR)
190 return (ret);
192 VERIFY(cmp->cm_tmap[id].cmt_map == 0);
193 cmp->cm_tmap[id].cmt_map = ret;
194 return (0);
197 static int
198 ctf_merge_add_array(ctf_merge_types_t *cmp, ctf_id_t id)
200 int ret, flags;
201 const ctf_type_t *tp;
202 ctf_arinfo_t ar;
204 if (ctf_array_info(cmp->cm_src, id, &ar) == CTF_ERR)
205 return (CTF_ERR);
207 tp = LCTF_INDEX_TO_TYPEPTR(cmp->cm_src, id);
208 if (CTF_INFO_ISROOT(tp->ctt_info) != 0)
209 flags = CTF_ADD_ROOT;
210 else
211 flags = CTF_ADD_NONROOT;
213 if (cmp->cm_tmap[ar.ctr_contents].cmt_map == 0) {
214 ret = ctf_merge_add_type(cmp, ar.ctr_contents);
215 if (ret != 0)
216 return (ret);
217 ASSERT(cmp->cm_tmap[ar.ctr_contents].cmt_map != 0);
219 ar.ctr_contents = ctf_merge_gettype(cmp, ar.ctr_contents);
221 if (cmp->cm_tmap[ar.ctr_index].cmt_map == 0) {
222 ret = ctf_merge_add_type(cmp, ar.ctr_index);
223 if (ret != 0)
224 return (ret);
225 ASSERT(cmp->cm_tmap[ar.ctr_index].cmt_map != 0);
227 ar.ctr_index = ctf_merge_gettype(cmp, ar.ctr_index);
229 ret = ctf_add_array(cmp->cm_out, flags, &ar);
230 if (ret == CTF_ERR)
231 return (ret);
233 VERIFY(cmp->cm_tmap[id].cmt_map == 0);
234 cmp->cm_tmap[id].cmt_map = ret;
236 return (0);
239 static int
240 ctf_merge_add_reftype(ctf_merge_types_t *cmp, ctf_id_t id)
242 int ret, flags;
243 const ctf_type_t *tp;
244 ctf_id_t reftype;
245 const char *name;
247 tp = LCTF_INDEX_TO_TYPEPTR(cmp->cm_src, id);
248 name = ctf_strraw(cmp->cm_src, tp->ctt_name);
249 if (CTF_INFO_ISROOT(tp->ctt_info) != 0)
250 flags = CTF_ADD_ROOT;
251 else
252 flags = CTF_ADD_NONROOT;
254 reftype = ctf_type_reference(cmp->cm_src, id);
255 if (reftype == CTF_ERR)
256 return (ctf_set_errno(cmp->cm_out, ctf_errno(cmp->cm_src)));
258 if (cmp->cm_tmap[reftype].cmt_map == 0) {
259 ret = ctf_merge_add_type(cmp, reftype);
260 if (ret != 0)
261 return (ret);
262 ASSERT(cmp->cm_tmap[reftype].cmt_map != 0);
264 reftype = ctf_merge_gettype(cmp, reftype);
266 ret = ctf_add_reftype(cmp->cm_out, flags, name, reftype,
267 ctf_type_kind(cmp->cm_src, id));
268 if (ret == CTF_ERR)
269 return (ret);
271 VERIFY(cmp->cm_tmap[id].cmt_map == 0);
272 cmp->cm_tmap[id].cmt_map = ret;
273 return (0);
276 static int
277 ctf_merge_add_typedef(ctf_merge_types_t *cmp, ctf_id_t id)
279 int ret, flags;
280 const ctf_type_t *tp;
281 const char *name;
282 ctf_id_t reftype;
284 tp = LCTF_INDEX_TO_TYPEPTR(cmp->cm_src, id);
285 name = ctf_strraw(cmp->cm_src, tp->ctt_name);
286 if (CTF_INFO_ISROOT(tp->ctt_info) != 0)
287 flags = CTF_ADD_ROOT;
288 else
289 flags = CTF_ADD_NONROOT;
291 reftype = ctf_type_reference(cmp->cm_src, id);
292 if (reftype == CTF_ERR)
293 return (ctf_set_errno(cmp->cm_out, ctf_errno(cmp->cm_src)));
295 if (cmp->cm_tmap[reftype].cmt_map == 0) {
296 ret = ctf_merge_add_type(cmp, reftype);
297 if (ret != 0)
298 return (ret);
299 ASSERT(cmp->cm_tmap[reftype].cmt_map != 0);
301 reftype = ctf_merge_gettype(cmp, reftype);
303 ret = ctf_add_typedef(cmp->cm_out, flags, name, reftype);
304 if (ret == CTF_ERR)
305 return (ret);
307 VERIFY(cmp->cm_tmap[id].cmt_map == 0);
308 cmp->cm_tmap[id].cmt_map = ret;
309 return (0);
312 typedef struct ctf_merge_enum {
313 ctf_file_t *cme_fp;
314 ctf_id_t cme_id;
315 } ctf_merge_enum_t;
317 static int
318 ctf_merge_add_enumerator(const char *name, int value, void *arg)
320 ctf_merge_enum_t *cmep = arg;
322 return (ctf_add_enumerator(cmep->cme_fp, cmep->cme_id, name, value) ==
323 CTF_ERR);
326 static int
327 ctf_merge_add_enum(ctf_merge_types_t *cmp, ctf_id_t id)
329 int flags;
330 const ctf_type_t *tp;
331 const char *name;
332 ctf_id_t enumid;
333 ctf_merge_enum_t cme;
335 tp = LCTF_INDEX_TO_TYPEPTR(cmp->cm_src, id);
336 name = ctf_strraw(cmp->cm_src, tp->ctt_name);
337 if (CTF_INFO_ISROOT(tp->ctt_info) != 0)
338 flags = CTF_ADD_ROOT;
339 else
340 flags = CTF_ADD_NONROOT;
342 enumid = ctf_add_enum(cmp->cm_out, flags, name);
343 if (enumid == CTF_ERR)
344 return (enumid);
346 cme.cme_fp = cmp->cm_out;
347 cme.cme_id = enumid;
348 if (ctf_enum_iter(cmp->cm_src, id, ctf_merge_add_enumerator,
349 &cme) != 0)
350 return (CTF_ERR);
352 VERIFY(cmp->cm_tmap[id].cmt_map == 0);
353 cmp->cm_tmap[id].cmt_map = enumid;
354 return (0);
357 static int
358 ctf_merge_add_func(ctf_merge_types_t *cmp, ctf_id_t id)
360 int ret, flags, i;
361 const ctf_type_t *tp;
362 ctf_funcinfo_t ctc;
363 ctf_id_t *argv;
365 tp = LCTF_INDEX_TO_TYPEPTR(cmp->cm_src, id);
366 if (CTF_INFO_ISROOT(tp->ctt_info) != 0)
367 flags = CTF_ADD_ROOT;
368 else
369 flags = CTF_ADD_NONROOT;
371 if (ctf_func_info_by_id(cmp->cm_src, id, &ctc) == CTF_ERR)
372 return (ctf_set_errno(cmp->cm_out, ctf_errno(cmp->cm_src)));
374 argv = ctf_alloc(sizeof (ctf_id_t) * ctc.ctc_argc);
375 if (argv == NULL)
376 return (ctf_set_errno(cmp->cm_out, ENOMEM));
377 if (ctf_func_args_by_id(cmp->cm_src, id, ctc.ctc_argc, argv) ==
378 CTF_ERR) {
379 ctf_free(argv, sizeof (ctf_id_t) * ctc.ctc_argc);
380 return (ctf_set_errno(cmp->cm_out, ctf_errno(cmp->cm_src)));
383 if (cmp->cm_tmap[ctc.ctc_return].cmt_map == 0) {
384 ret = ctf_merge_add_type(cmp, ctc.ctc_return);
385 if (ret != 0)
386 return (ret);
387 ASSERT(cmp->cm_tmap[ctc.ctc_return].cmt_map != 0);
389 ctc.ctc_return = ctf_merge_gettype(cmp, ctc.ctc_return);
391 for (i = 0; i < ctc.ctc_argc; i++) {
392 if (cmp->cm_tmap[argv[i]].cmt_map == 0) {
393 ret = ctf_merge_add_type(cmp, argv[i]);
394 if (ret != 0)
395 return (ret);
396 ASSERT(cmp->cm_tmap[argv[i]].cmt_map != 0);
398 argv[i] = ctf_merge_gettype(cmp, argv[i]);
401 ret = ctf_add_funcptr(cmp->cm_out, flags, &ctc, argv);
402 ctf_free(argv, sizeof (ctf_id_t) * ctc.ctc_argc);
403 if (ret == CTF_ERR)
404 return (ret);
406 VERIFY(cmp->cm_tmap[id].cmt_map == 0);
407 cmp->cm_tmap[id].cmt_map = ret;
408 return (0);
411 static int
412 ctf_merge_add_forward(ctf_merge_types_t *cmp, ctf_id_t id)
414 int ret, flags;
415 const ctf_type_t *tp;
416 const char *name;
418 tp = LCTF_INDEX_TO_TYPEPTR(cmp->cm_src, id);
419 name = ctf_strraw(cmp->cm_src, tp->ctt_name);
420 if (CTF_INFO_ISROOT(tp->ctt_info) != 0)
421 flags = CTF_ADD_ROOT;
422 else
423 flags = CTF_ADD_NONROOT;
426 * ctf_add_forward tries to check to see if a given forward already
427 * exists in one of its hash tables. If we're here then we know that we
428 * have a forward in a container that isn't present in another.
429 * Therefore, we choose a token hash table to satisfy the API choice
430 * here.
432 ret = ctf_add_forward(cmp->cm_out, flags, name, CTF_K_STRUCT);
433 if (ret == CTF_ERR)
434 return (CTF_ERR);
436 VERIFY(cmp->cm_tmap[id].cmt_map == 0);
437 cmp->cm_tmap[id].cmt_map = ret;
438 return (0);
441 typedef struct ctf_merge_su {
442 ctf_merge_types_t *cms_cm;
443 ctf_id_t cms_id;
444 } ctf_merge_su_t;
446 static int
447 ctf_merge_add_member(const char *name, ctf_id_t type, ulong_t offset, void *arg)
449 ctf_merge_su_t *cms = arg;
451 VERIFY(cms->cms_cm->cm_tmap[type].cmt_map != 0);
452 type = cms->cms_cm->cm_tmap[type].cmt_map;
454 ctf_dprintf("Trying to add member %s to %d\n", name, cms->cms_id);
455 return (ctf_add_member(cms->cms_cm->cm_out, cms->cms_id, name,
456 type, offset) == CTF_ERR);
460 * During the first pass, we always add the generic structure and union but none
461 * of its members as they might not all have been mapped yet. Instead we just
462 * mark all structures and unions as needing to be fixed up.
464 static int
465 ctf_merge_add_sou(ctf_merge_types_t *cmp, ctf_id_t id, boolean_t forward)
467 int flags, kind;
468 const ctf_type_t *tp;
469 const char *name;
470 ctf_id_t suid;
472 tp = LCTF_INDEX_TO_TYPEPTR(cmp->cm_src, id);
473 name = ctf_strraw(cmp->cm_src, tp->ctt_name);
474 if (CTF_INFO_ISROOT(tp->ctt_info) != 0)
475 flags = CTF_ADD_ROOT;
476 else
477 flags = CTF_ADD_NONROOT;
478 kind = ctf_type_kind(cmp->cm_src, id);
480 if (kind == CTF_K_STRUCT)
481 suid = ctf_add_struct(cmp->cm_out, flags, name);
482 else
483 suid = ctf_add_union(cmp->cm_out, flags, name);
485 if (suid == CTF_ERR)
486 return (suid);
489 * If this is a forward reference then it's mapping should already
490 * exist.
492 if (forward == B_FALSE) {
493 VERIFY(cmp->cm_tmap[id].cmt_map == 0);
494 cmp->cm_tmap[id].cmt_map = suid;
495 ctf_dprintf("added sou \"%s\" as (%d) %d->%d\n", name, kind, id,
496 suid);
497 } else {
498 VERIFY(cmp->cm_tmap[id].cmt_map == suid);
500 cmp->cm_tmap[id].cmt_fixup = B_TRUE;
502 return (0);
505 static int
506 ctf_merge_add_type(ctf_merge_types_t *cmp, ctf_id_t id)
508 int kind, ret;
511 * We may end up evaluating a type more than once as we may deal with it
512 * as we recursively evaluate some kind of reference and then we may see
513 * it normally.
515 if (cmp->cm_tmap[id].cmt_map != 0)
516 return (0);
518 kind = ctf_type_kind(cmp->cm_src, id);
519 switch (kind) {
520 case CTF_K_INTEGER:
521 case CTF_K_FLOAT:
522 ret = ctf_merge_add_number(cmp, id);
523 break;
524 case CTF_K_ARRAY:
525 ret = ctf_merge_add_array(cmp, id);
526 break;
527 case CTF_K_POINTER:
528 case CTF_K_VOLATILE:
529 case CTF_K_CONST:
530 case CTF_K_RESTRICT:
531 ret = ctf_merge_add_reftype(cmp, id);
532 break;
533 case CTF_K_TYPEDEF:
534 ret = ctf_merge_add_typedef(cmp, id);
535 break;
536 case CTF_K_ENUM:
537 ret = ctf_merge_add_enum(cmp, id);
538 break;
539 case CTF_K_FUNCTION:
540 ret = ctf_merge_add_func(cmp, id);
541 break;
542 case CTF_K_FORWARD:
543 ret = ctf_merge_add_forward(cmp, id);
544 break;
545 case CTF_K_STRUCT:
546 case CTF_K_UNION:
547 ret = ctf_merge_add_sou(cmp, id, B_FALSE);
548 break;
549 case CTF_K_UNKNOWN:
551 * We don't add uknown types, and we later assert that nothing
552 * should reference them.
554 return (0);
555 default:
556 abort();
559 return (ret);
562 static int
563 ctf_merge_fixup_sou(ctf_merge_types_t *cmp, ctf_id_t id)
565 ctf_dtdef_t *dtd;
566 ctf_merge_su_t cms;
567 ctf_id_t mapid;
568 ssize_t size;
570 mapid = cmp->cm_tmap[id].cmt_map;
571 VERIFY(mapid != 0);
572 dtd = ctf_dtd_lookup(cmp->cm_out, mapid);
573 VERIFY(dtd != NULL);
575 ctf_dprintf("Trying to fix up sou %d\n", id);
576 cms.cms_cm = cmp;
577 cms.cms_id = mapid;
578 if (ctf_member_iter(cmp->cm_src, id, ctf_merge_add_member, &cms) != 0)
579 return (CTF_ERR);
581 if ((size = ctf_type_size(cmp->cm_src, id)) == CTF_ERR)
582 return (CTF_ERR);
583 if (ctf_set_size(cmp->cm_out, mapid, size) == CTF_ERR)
584 return (CTF_ERR);
586 return (0);
589 static int
590 ctf_merge_fixup_type(ctf_merge_types_t *cmp, ctf_id_t id)
592 int kind, ret;
594 kind = ctf_type_kind(cmp->cm_src, id);
595 switch (kind) {
596 case CTF_K_STRUCT:
597 case CTF_K_UNION:
598 ret = ctf_merge_fixup_sou(cmp, id);
599 break;
600 default:
601 VERIFY(0);
602 ret = CTF_ERR;
605 return (ret);
609 * Now that we've successfully merged everything, we're going to clean
610 * up the merge type table. Traditionally if we had just two different
611 * files that we were working between, the types would be fully
612 * resolved. However, because we were comparing with ourself every step
613 * of the way and not our reduced self, we need to go through and update
614 * every mapped entry to what it now points to in the deduped file.
616 static void
617 ctf_merge_fixup_dedup_map(ctf_merge_types_t *cmp)
619 int i;
621 for (i = 1; i < cmp->cm_src->ctf_typemax + 1; i++) {
622 ctf_id_t tid;
625 * Missing types always have their id updated to exactly what it
626 * should be.
628 if (cmp->cm_tmap[i].cmt_missing == B_TRUE) {
629 VERIFY(cmp->cm_tmap[i].cmt_map != 0);
630 continue;
633 tid = i;
634 while (cmp->cm_tmap[tid].cmt_missing == B_FALSE) {
635 VERIFY(cmp->cm_tmap[tid].cmt_map != 0);
636 tid = cmp->cm_tmap[tid].cmt_map;
638 VERIFY(cmp->cm_tmap[tid].cmt_map != 0);
639 cmp->cm_tmap[i].cmt_map = cmp->cm_tmap[tid].cmt_map;
645 * We're going to do three passes over the containers.
647 * Pass 1 checks for forward references in the output container that we know
648 * exist in the source container.
650 * Pass 2 adds all the missing types from the source container. As part of this
651 * we may be adding a type as a forward reference that doesn't exist yet.
652 * Any types that we encounter in this form, we need to add to a third pass.
654 * Pass 3 is the fixup pass. Here we go through and find all the types that were
655 * missing in the first.
657 * Importantly, we *must* call ctf_update between the second and third pass,
658 * otherwise several of the libctf functions will not properly find the data in
659 * the container. If we're doing a dedup we also fix up the type mapping.
661 static int
662 ctf_merge_common(ctf_merge_types_t *cmp)
664 int ret, i;
666 ctf_phase_dump(cmp->cm_src, "merge-common-src");
667 ctf_phase_dump(cmp->cm_out, "merge-common-dest");
669 /* Pass 1 */
670 for (i = 1; i <= cmp->cm_src->ctf_typemax; i++) {
671 if (cmp->cm_tmap[i].cmt_forward == B_TRUE) {
672 ret = ctf_merge_add_sou(cmp, i, B_TRUE);
673 if (ret != 0) {
674 return (ret);
679 /* Pass 2 */
680 for (i = 1; i <= cmp->cm_src->ctf_typemax; i++) {
681 if (cmp->cm_tmap[i].cmt_missing == B_TRUE) {
682 ret = ctf_merge_add_type(cmp, i);
683 if (ret != 0) {
684 ctf_dprintf("Failed to merge type %d\n", i);
685 return (ret);
690 ret = ctf_update(cmp->cm_out);
691 if (ret != 0)
692 return (ret);
694 if (cmp->cm_dedup == B_TRUE) {
695 ctf_merge_fixup_dedup_map(cmp);
698 ctf_dprintf("Beginning merge pass 3\n");
699 /* Pass 3 */
700 for (i = 1; i <= cmp->cm_src->ctf_typemax; i++) {
701 if (cmp->cm_tmap[i].cmt_fixup == B_TRUE) {
702 ret = ctf_merge_fixup_type(cmp, i);
703 if (ret != 0)
704 return (ret);
708 if (cmp->cm_dedup == B_TRUE) {
709 ctf_merge_fixup_dedup_map(cmp);
712 return (0);
716 * Uniquification is slightly different from a stock merge. For starters, we
717 * don't need to replace any forward references in the output. In this case
718 * though, the types that already exist are in a parent container to the empty
719 * output container.
721 static int
722 ctf_merge_uniquify_types(ctf_merge_types_t *cmp)
724 int i, ret;
726 for (i = 1; i <= cmp->cm_src->ctf_typemax; i++) {
727 if (cmp->cm_tmap[i].cmt_missing == B_FALSE)
728 continue;
729 ret = ctf_merge_add_type(cmp, i);
730 if (ret != 0)
731 return (ret);
734 ret = ctf_update(cmp->cm_out);
735 if (ret != 0)
736 return (ret);
738 for (i = 1; i <= cmp->cm_src->ctf_typemax; i++) {
739 if (cmp->cm_tmap[i].cmt_fixup == B_FALSE)
740 continue;
741 ret = ctf_merge_fixup_type(cmp, i);
742 if (ret != 0)
743 return (ret);
746 return (0);
749 static int
750 ctf_merge_types_init(ctf_merge_types_t *cmp)
752 cmp->cm_tmap = ctf_alloc(sizeof (ctf_merge_tinfo_t) *
753 (cmp->cm_src->ctf_typemax + 1));
754 if (cmp->cm_tmap == NULL)
755 return (ctf_set_errno(cmp->cm_out, ENOMEM));
756 bzero(cmp->cm_tmap, sizeof (ctf_merge_tinfo_t) *
757 (cmp->cm_src->ctf_typemax + 1));
758 return (0);
761 static void
762 ctf_merge_types_fini(ctf_merge_types_t *cmp)
764 ctf_free(cmp->cm_tmap, sizeof (ctf_merge_tinfo_t) *
765 (cmp->cm_src->ctf_typemax + 1));
769 * Merge the types contained inside of two input files. The second input file is
770 * always going to be the destination. We're guaranteed that it's always
771 * writeable.
773 /*ARGSUSED*/
774 static int
775 ctf_merge_types(void *arg, void *arg2, void **outp, void *unsued)
777 int ret;
778 ctf_merge_types_t cm;
779 ctf_diff_t *cdp;
780 ctf_merge_objmap_t *cmo;
781 ctf_merge_funcmap_t *cmf;
782 ctf_merge_input_t *scmi = arg;
783 ctf_merge_input_t *dcmi = arg2;
784 ctf_file_t *out = dcmi->cmi_input;
785 ctf_file_t *source = scmi->cmi_input;
787 ctf_dprintf("merging %p->%p\n", source, out);
789 if (!(out->ctf_flags & LCTF_RDWR))
790 return (ctf_set_errno(out, ECTF_RDONLY));
792 if (ctf_getmodel(out) != ctf_getmodel(source))
793 return (ctf_set_errno(out, ECTF_DMODEL));
795 if ((ret = ctf_diff_init(out, source, &cdp)) != 0)
796 return (ret);
798 cm.cm_out = out;
799 cm.cm_src = source;
800 cm.cm_dedup = B_FALSE;
801 cm.cm_unique = B_FALSE;
802 ret = ctf_merge_types_init(&cm);
803 if (ret != 0) {
804 ctf_diff_fini(cdp);
805 return (ctf_set_errno(out, ret));
808 ret = ctf_diff_types(cdp, ctf_merge_diffcb, &cm);
809 if (ret != 0)
810 goto cleanup;
811 ret = ctf_merge_common(&cm);
812 ctf_dprintf("merge common returned with %d\n", ret);
813 if (ret == 0) {
814 ret = ctf_update(out);
815 ctf_dprintf("update returned with %d\n", ret);
816 } else {
817 goto cleanup;
821 * Now we need to fix up the object and function maps.
823 for (cmo = list_head(&scmi->cmi_omap); cmo != NULL;
824 cmo = list_next(&scmi->cmi_omap, cmo)) {
825 if (cmo->cmo_tid == 0)
826 continue;
827 VERIFY(cm.cm_tmap[cmo->cmo_tid].cmt_map != 0);
828 cmo->cmo_tid = cm.cm_tmap[cmo->cmo_tid].cmt_map;
831 for (cmf = list_head(&scmi->cmi_fmap); cmf != NULL;
832 cmf = list_next(&scmi->cmi_fmap, cmf)) {
833 int i;
835 VERIFY(cm.cm_tmap[cmf->cmf_rtid].cmt_map != 0);
836 cmf->cmf_rtid = cm.cm_tmap[cmf->cmf_rtid].cmt_map;
837 for (i = 0; i < cmf->cmf_argc; i++) {
838 VERIFY(cm.cm_tmap[cmf->cmf_args[i]].cmt_map != 0);
839 cmf->cmf_args[i] = cm.cm_tmap[cmf->cmf_args[i]].cmt_map;
844 * Now that we've fixed things up, we need to give our function and
845 * object maps to the destination, such that it can continue to update
846 * them going forward.
848 list_move_tail(&dcmi->cmi_fmap, &scmi->cmi_fmap);
849 list_move_tail(&dcmi->cmi_omap, &scmi->cmi_omap);
851 cleanup:
852 if (ret == 0)
853 *outp = dcmi;
854 ctf_merge_types_fini(&cm);
855 ctf_diff_fini(cdp);
856 if (ret != 0)
857 return (ctf_errno(out));
858 return (0);
861 static int
862 ctf_uniquify_types(ctf_merge_t *cmh, ctf_file_t *src, ctf_file_t **outp)
864 int err, ret;
865 ctf_file_t *out;
866 ctf_merge_types_t cm;
867 ctf_diff_t *cdp;
868 ctf_merge_input_t *cmi;
869 ctf_file_t *parent = cmh->cmh_unique;
871 *outp = NULL;
872 out = ctf_fdcreate(cmh->cmh_ofd, &err);
873 if (out == NULL)
874 return (ctf_set_errno(src, err));
876 out->ctf_parname = cmh->cmh_pname;
877 if (ctf_setmodel(out, ctf_getmodel(parent)) != 0) {
878 (void) ctf_set_errno(src, ctf_errno(out));
879 ctf_close(out);
880 return (CTF_ERR);
883 if (ctf_import(out, parent) != 0) {
884 (void) ctf_set_errno(src, ctf_errno(out));
885 ctf_close(out);
886 return (CTF_ERR);
889 if ((ret = ctf_diff_init(parent, src, &cdp)) != 0) {
890 ctf_close(out);
891 return (ctf_set_errno(src, ctf_errno(parent)));
894 cm.cm_out = parent;
895 cm.cm_src = src;
896 cm.cm_dedup = B_FALSE;
897 cm.cm_unique = B_TRUE;
898 ret = ctf_merge_types_init(&cm);
899 if (ret != 0) {
900 ctf_close(out);
901 ctf_diff_fini(cdp);
902 return (ctf_set_errno(src, ret));
905 ret = ctf_diff_types(cdp, ctf_merge_diffcb, &cm);
906 if (ret == 0) {
907 cm.cm_out = out;
908 ret = ctf_merge_uniquify_types(&cm);
909 if (ret == 0)
910 ret = ctf_update(out);
913 if (ret != 0) {
914 ctf_merge_types_fini(&cm);
915 ctf_diff_fini(cdp);
916 return (ctf_set_errno(src, ctf_errno(cm.cm_out)));
919 for (cmi = list_head(&cmh->cmh_inputs); cmi != NULL;
920 cmi = list_next(&cmh->cmh_inputs, cmi)) {
921 ctf_merge_objmap_t *cmo;
922 ctf_merge_funcmap_t *cmf;
924 for (cmo = list_head(&cmi->cmi_omap); cmo != NULL;
925 cmo = list_next(&cmi->cmi_omap, cmo)) {
926 if (cmo->cmo_tid == 0)
927 continue;
928 VERIFY(cm.cm_tmap[cmo->cmo_tid].cmt_map != 0);
929 cmo->cmo_tid = cm.cm_tmap[cmo->cmo_tid].cmt_map;
932 for (cmf = list_head(&cmi->cmi_fmap); cmf != NULL;
933 cmf = list_next(&cmi->cmi_fmap, cmf)) {
934 int i;
936 VERIFY(cm.cm_tmap[cmf->cmf_rtid].cmt_map != 0);
937 cmf->cmf_rtid = cm.cm_tmap[cmf->cmf_rtid].cmt_map;
938 for (i = 0; i < cmf->cmf_argc; i++) {
939 VERIFY(cm.cm_tmap[cmf->cmf_args[i]].cmt_map !=
941 cmf->cmf_args[i] =
942 cm.cm_tmap[cmf->cmf_args[i]].cmt_map;
947 ctf_merge_types_fini(&cm);
948 ctf_diff_fini(cdp);
949 *outp = out;
950 return (0);
953 static void
954 ctf_merge_fini_input(ctf_merge_input_t *cmi)
956 ctf_merge_objmap_t *cmo;
957 ctf_merge_funcmap_t *cmf;
959 while ((cmo = list_remove_head(&cmi->cmi_omap)) != NULL)
960 ctf_free(cmo, sizeof (ctf_merge_objmap_t));
962 while ((cmf = list_remove_head(&cmi->cmi_fmap)) != NULL)
963 ctf_free(cmf, sizeof (ctf_merge_funcmap_t) +
964 sizeof (ctf_id_t) * cmf->cmf_argc);
966 if (cmi->cmi_created == B_TRUE && cmi->cmi_input != NULL)
967 ctf_close(cmi->cmi_input);
969 ctf_free(cmi, sizeof (ctf_merge_input_t));
972 void
973 ctf_merge_fini(ctf_merge_t *cmh)
975 size_t len;
976 ctf_merge_input_t *cmi;
978 if (cmh->cmh_label != NULL) {
979 len = strlen(cmh->cmh_label) + 1;
980 ctf_free(cmh->cmh_label, len);
983 if (cmh->cmh_pname != NULL) {
984 len = strlen(cmh->cmh_pname) + 1;
985 ctf_free(cmh->cmh_pname, len);
988 while ((cmi = list_remove_head(&cmh->cmh_inputs)) != NULL)
989 ctf_merge_fini_input(cmi);
991 ctf_free(cmh, sizeof (ctf_merge_t));
994 ctf_merge_t *
995 ctf_merge_init(int fd, int *errp)
997 int err;
998 ctf_merge_t *out;
999 struct stat st;
1001 if (errp == NULL)
1002 errp = &err;
1004 if (fd != -1 && fstat(fd, &st) != 0) {
1005 *errp = EINVAL;
1006 return (NULL);
1009 out = ctf_alloc(sizeof (ctf_merge_t));
1010 if (out == NULL) {
1011 *errp = ENOMEM;
1012 return (NULL);
1015 if (fd == -1) {
1016 out->cmh_msyms = B_FALSE;
1017 } else {
1018 out->cmh_msyms = B_TRUE;
1021 list_create(&out->cmh_inputs, sizeof (ctf_merge_input_t),
1022 offsetof(ctf_merge_input_t, cmi_node));
1023 out->cmh_ninputs = 0;
1024 out->cmh_nthreads = 1;
1025 out->cmh_unique = NULL;
1026 out->cmh_ofd = fd;
1027 out->cmh_flags = 0;
1028 out->cmh_label = NULL;
1029 out->cmh_pname = NULL;
1031 return (out);
1035 ctf_merge_label(ctf_merge_t *cmh, const char *label)
1037 char *dup;
1039 if (label == NULL)
1040 return (EINVAL);
1042 dup = ctf_strdup(label);
1043 if (dup == NULL)
1044 return (EAGAIN);
1046 if (cmh->cmh_label != NULL) {
1047 size_t len = strlen(cmh->cmh_label) + 1;
1048 ctf_free(cmh->cmh_label, len);
1051 cmh->cmh_label = dup;
1052 return (0);
1055 static int
1056 ctf_merge_add_funcs(const char *name, ulong_t idx, ctf_funcinfo_t *fip,
1057 void *arg)
1059 ctf_merge_input_t *cmi = arg;
1060 ctf_merge_funcmap_t *fmap;
1062 fmap = ctf_alloc(sizeof (ctf_merge_funcmap_t) +
1063 sizeof (ctf_id_t) * fip->ctc_argc);
1064 if (fmap == NULL)
1065 return (ENOMEM);
1067 fmap->cmf_idx = idx;
1068 fmap->cmf_rtid = fip->ctc_return;
1069 fmap->cmf_flags = fip->ctc_flags;
1070 fmap->cmf_argc = fip->ctc_argc;
1071 fmap->cmf_name = name;
1073 if (ctf_func_args(cmi->cmi_input, idx, fmap->cmf_argc,
1074 fmap->cmf_args) != 0) {
1075 ctf_free(fmap, sizeof (ctf_merge_funcmap_t) +
1076 sizeof (ctf_id_t) * fip->ctc_argc);
1077 return (ctf_errno(cmi->cmi_input));
1080 list_insert_tail(&cmi->cmi_fmap, fmap);
1081 return (0);
1084 static int
1085 ctf_merge_add_objs(const char *name, ctf_id_t id, ulong_t idx, void *arg)
1087 ctf_merge_input_t *cmi = arg;
1088 ctf_merge_objmap_t *cmo;
1090 cmo = ctf_alloc(sizeof (ctf_merge_objmap_t));
1091 if (cmo == NULL)
1092 return (ENOMEM);
1094 cmo->cmo_name = name;
1095 cmo->cmo_idx = idx;
1096 cmo->cmo_tid = id;
1097 list_insert_tail(&cmi->cmi_omap, cmo);
1098 return (0);
1102 * Whenever we create an entry to merge, we then go and add a second empty
1103 * ctf_file_t which we use for the purposes of our merging. It's not the best,
1104 * but it's the best that we've got at the moment.
1107 ctf_merge_add(ctf_merge_t *cmh, ctf_file_t *input)
1109 int ret;
1110 ctf_merge_input_t *cmi;
1111 ctf_file_t *empty;
1113 if (input->ctf_flags & LCTF_CHILD)
1114 return (ECTF_MCHILD);
1116 cmi = ctf_alloc(sizeof (ctf_merge_input_t));
1117 if (cmi == NULL)
1118 return (ENOMEM);
1120 cmi->cmi_created = B_FALSE;
1121 cmi->cmi_input = input;
1122 list_create(&cmi->cmi_fmap, sizeof (ctf_merge_funcmap_t),
1123 offsetof(ctf_merge_funcmap_t, cmf_node));
1124 list_create(&cmi->cmi_omap, sizeof (ctf_merge_funcmap_t),
1125 offsetof(ctf_merge_objmap_t, cmo_node));
1127 if (cmh->cmh_msyms == B_TRUE) {
1128 if ((ret = ctf_function_iter(input, ctf_merge_add_funcs,
1129 cmi)) != 0) {
1130 ctf_merge_fini_input(cmi);
1131 return (ret);
1134 if ((ret = ctf_object_iter(input, ctf_merge_add_objs,
1135 cmi)) != 0) {
1136 ctf_merge_fini_input(cmi);
1137 return (ret);
1141 list_insert_tail(&cmh->cmh_inputs, cmi);
1142 cmh->cmh_ninputs++;
1144 /* And now the empty one to merge into this */
1145 cmi = ctf_alloc(sizeof (ctf_merge_input_t));
1146 if (cmi == NULL)
1147 return (ENOMEM);
1148 list_create(&cmi->cmi_fmap, sizeof (ctf_merge_funcmap_t),
1149 offsetof(ctf_merge_funcmap_t, cmf_node));
1150 list_create(&cmi->cmi_omap, sizeof (ctf_merge_funcmap_t),
1151 offsetof(ctf_merge_objmap_t, cmo_node));
1153 empty = ctf_fdcreate(cmh->cmh_ofd, &ret);
1154 if (empty == NULL)
1155 return (ret);
1156 cmi->cmi_input = empty;
1157 cmi->cmi_created = B_TRUE;
1159 if (ctf_setmodel(empty, ctf_getmodel(input)) == CTF_ERR) {
1160 return (ctf_errno(empty));
1163 list_insert_tail(&cmh->cmh_inputs, cmi);
1164 cmh->cmh_ninputs++;
1165 ctf_dprintf("added containers %p and %p\n", input, empty);
1166 return (0);
1170 ctf_merge_uniquify(ctf_merge_t *cmh, ctf_file_t *u, const char *pname)
1172 char *dup;
1174 if (u->ctf_flags & LCTF_CHILD)
1175 return (ECTF_MCHILD);
1176 if (pname == NULL)
1177 return (EINVAL);
1178 dup = ctf_strdup(pname);
1179 if (dup == NULL)
1180 return (EINVAL);
1181 if (cmh->cmh_pname != NULL) {
1182 size_t len = strlen(cmh->cmh_pname) + 1;
1183 ctf_free(cmh->cmh_pname, len);
1185 cmh->cmh_pname = dup;
1186 cmh->cmh_unique = u;
1187 return (0);
1190 static int
1191 ctf_merge_symbols(ctf_merge_t *cmh, ctf_file_t *fp)
1193 int err;
1194 ulong_t i;
1196 uintptr_t symbase = (uintptr_t)fp->ctf_symtab.cts_data;
1197 uintptr_t strbase = (uintptr_t)fp->ctf_strtab.cts_data;
1199 for (i = 0; i < fp->ctf_nsyms; i++) {
1200 const char *name;
1201 ctf_merge_input_t *cmi;
1202 ctf_merge_objmap_t *cmo;
1204 if (fp->ctf_symtab.cts_entsize == sizeof (Elf32_Sym)) {
1205 const Elf32_Sym *symp = (Elf32_Sym *)symbase + i;
1206 int type = ELF32_ST_TYPE(symp->st_info);
1207 if (type != STT_OBJECT)
1208 continue;
1209 if (ctf_sym_valid(strbase, type, symp->st_shndx,
1210 symp->st_value, symp->st_name) == B_FALSE)
1211 continue;
1212 name = (char *)(strbase + symp->st_name);
1213 } else {
1214 const Elf64_Sym *symp = (Elf64_Sym *)symbase + i;
1215 int type = ELF64_ST_TYPE(symp->st_info);
1216 if (type != STT_OBJECT)
1217 continue;
1218 if (ctf_sym_valid(strbase, type, symp->st_shndx,
1219 symp->st_value, symp->st_name) == B_FALSE)
1220 continue;
1221 name = (char *)(strbase + symp->st_name);
1224 cmo = NULL;
1225 for (cmi = list_head(&cmh->cmh_inputs); cmi != NULL;
1226 cmi = list_next(&cmh->cmh_inputs, cmi)) {
1227 for (cmo = list_head(&cmi->cmi_omap); cmo != NULL;
1228 cmo = list_next(&cmi->cmi_omap, cmo)) {
1229 if (strcmp(cmo->cmo_name, name) == 0)
1230 goto found;
1233 found:
1234 if (cmo != NULL) {
1235 if (cmo->cmo_tid == 0)
1236 continue;
1237 if ((err = ctf_add_object(fp, i, cmo->cmo_tid)) != 0) {
1238 ctf_dprintf("Failed to add symbol %s->%d: %s\n",
1239 name, cmo->cmo_tid,
1240 ctf_errmsg(ctf_errno(fp)));
1241 return (err);
1246 return (0);
1249 static int
1250 ctf_merge_functions(ctf_merge_t *cmh, ctf_file_t *fp)
1252 int err;
1253 ulong_t i;
1254 ctf_funcinfo_t fi;
1256 uintptr_t symbase = (uintptr_t)fp->ctf_symtab.cts_data;
1257 uintptr_t strbase = (uintptr_t)fp->ctf_strtab.cts_data;
1259 for (i = 0; i < fp->ctf_nsyms; i++) {
1260 const char *name;
1261 ctf_merge_input_t *cmi;
1262 ctf_merge_funcmap_t *cmf;
1264 if (fp->ctf_symtab.cts_entsize == sizeof (Elf32_Sym)) {
1265 const Elf32_Sym *symp = (Elf32_Sym *)symbase + i;
1266 int type = ELF32_ST_TYPE(symp->st_info);
1267 if (ELF32_ST_TYPE(symp->st_info) != STT_FUNC)
1268 continue;
1269 if (ctf_sym_valid(strbase, type, symp->st_shndx,
1270 symp->st_value, symp->st_name) == B_FALSE)
1271 continue;
1272 name = (char *)(strbase + symp->st_name);
1273 } else {
1274 const Elf64_Sym *symp = (Elf64_Sym *)symbase + i;
1275 int type = ELF64_ST_TYPE(symp->st_info);
1276 if (ELF64_ST_TYPE(symp->st_info) != STT_FUNC)
1277 continue;
1278 if (ctf_sym_valid(strbase, type, symp->st_shndx,
1279 symp->st_value, symp->st_name) == B_FALSE)
1280 continue;
1281 name = (char *)(strbase + symp->st_name);
1284 cmf = NULL;
1285 for (cmi = list_head(&cmh->cmh_inputs); cmi != NULL;
1286 cmi = list_next(&cmh->cmh_inputs, cmi)) {
1287 for (cmf = list_head(&cmi->cmi_fmap); cmf != NULL;
1288 cmf = list_next(&cmi->cmi_fmap, cmf)) {
1289 if (strcmp(cmf->cmf_name, name) == 0)
1290 goto found;
1293 found:
1294 if (cmf != NULL) {
1295 fi.ctc_return = cmf->cmf_rtid;
1296 fi.ctc_argc = cmf->cmf_argc;
1297 fi.ctc_flags = cmf->cmf_flags;
1298 if ((err = ctf_add_function(fp, i, &fi,
1299 cmf->cmf_args)) != 0)
1300 return (err);
1304 return (0);
1309 ctf_merge_merge(ctf_merge_t *cmh, ctf_file_t **outp)
1311 int err, merr;
1312 ctf_merge_input_t *cmi;
1313 ctf_id_t ltype;
1314 mergeq_t *mqp;
1315 ctf_merge_input_t *final;
1316 ctf_file_t *out;
1318 if (cmh->cmh_label != NULL && cmh->cmh_unique != NULL) {
1319 const char *label = ctf_label_topmost(cmh->cmh_unique);
1320 if (label == NULL)
1321 return (ECTF_NOLABEL);
1322 if (strcmp(label, cmh->cmh_label) != 0)
1323 return (ECTF_LCONFLICT);
1326 if (mergeq_init(&mqp, cmh->cmh_nthreads) == -1) {
1327 return (errno);
1331 * We should consider doing a divide and conquer and parallel merge
1332 * here. If we did, we'd want to use some number of threads to perform
1333 * this operation.
1335 VERIFY(cmh->cmh_ninputs % 2 == 0);
1336 for (cmi = list_head(&cmh->cmh_inputs); cmi != NULL;
1337 cmi = list_next(&cmh->cmh_inputs, cmi)) {
1338 if (mergeq_add(mqp, cmi) == -1) {
1339 err = errno;
1340 mergeq_fini(mqp);
1344 err = mergeq_merge(mqp, ctf_merge_types, NULL, (void **)&final, &merr);
1345 mergeq_fini(mqp);
1347 if (err == MERGEQ_ERROR) {
1348 return (errno);
1349 } else if (err == MERGEQ_UERROR) {
1350 return (merr);
1354 * Disassociate the generated ctf_file_t from the original input. That
1355 * way when the input gets cleaned up, we don't accidentally kill the
1356 * final reference to the ctf_file_t. If it gets uniquified then we'll
1357 * kill it.
1359 VERIFY(final->cmi_input != NULL);
1360 out = final->cmi_input;
1361 final->cmi_input = NULL;
1363 ctf_dprintf("preparing to uniquify against: %p\n", cmh->cmh_unique);
1364 if (cmh->cmh_unique != NULL) {
1365 ctf_file_t *u;
1366 err = ctf_uniquify_types(cmh, out, &u);
1367 if (err != 0) {
1368 err = ctf_errno(out);
1369 ctf_close(out);
1370 return (err);
1372 ctf_close(out);
1373 out = u;
1376 ltype = out->ctf_typemax;
1377 if ((out->ctf_flags & LCTF_CHILD) && ltype != 0)
1378 ltype += 0x8000;
1379 ctf_dprintf("trying to add the label\n");
1380 if (cmh->cmh_label != NULL &&
1381 ctf_add_label(out, cmh->cmh_label, ltype, 0) != 0) {
1382 ctf_close(out);
1383 return (ctf_errno(out));
1386 ctf_dprintf("merging symbols and the like\n");
1387 if (cmh->cmh_msyms == B_TRUE) {
1388 err = ctf_merge_symbols(cmh, out);
1389 if (err != 0) {
1390 ctf_close(out);
1391 return (ctf_errno(out));
1394 err = ctf_merge_functions(cmh, out);
1395 if (err != 0) {
1396 ctf_close(out);
1397 return (ctf_errno(out));
1401 err = ctf_update(out);
1402 if (err != 0) {
1403 ctf_close(out);
1404 return (ctf_errno(out));
1407 *outp = out;
1408 return (0);
1412 * When we get told that something is unique, eg. same is B_FALSE, then that
1413 * tells us that we need to add it to the output. If same is B_TRUE, then we'll
1414 * want to record it in the mapping table so that we know how to redirect types
1415 * to the extant ones.
1417 /*ARGSUSED*/
1418 static void
1419 ctf_dedup_cb(ctf_file_t *ifp, ctf_id_t iid, boolean_t same, ctf_file_t *ofp,
1420 ctf_id_t oid, void *arg)
1422 ctf_merge_types_t *cmp = arg;
1423 ctf_merge_tinfo_t *cmt = cmp->cm_tmap;
1425 if (same == B_TRUE) {
1427 * The output id here may itself map to something else.
1428 * Therefore, we need to basically walk a chain and see what it
1429 * points to until it itself points to a base type, eg. -1.
1430 * Otherwise we'll dedup to something which no longer exists.
1432 while (cmt[oid].cmt_missing == B_FALSE)
1433 oid = cmt[oid].cmt_map;
1434 cmt[iid].cmt_map = oid;
1435 ctf_dprintf("%d->%d \n", iid, oid);
1436 } else {
1437 VERIFY(cmt[iid].cmt_map == 0);
1438 cmt[iid].cmt_missing = B_TRUE;
1439 ctf_dprintf("%d is missing\n", iid);
1444 * Dedup a CTF container.
1446 * DWARF and other encoding formats that we use to create CTF data may create
1447 * multiple copies of a given type. However, after doing a conversion, and
1448 * before doing a merge, we'd prefer, if possible, to have every input container
1449 * to be unique.
1451 * Doing a deduplication is like a normal merge. However, when we diff the types
1452 * in the container, rather than doing a normal diff, we instead want to diff
1453 * against any already processed types. eg, for a given type i in a container,
1454 * we want to diff it from 0 to i - 1.
1457 ctf_merge_dedup(ctf_merge_t *cmp, ctf_file_t **outp)
1459 int ret;
1460 ctf_diff_t *cdp = NULL;
1461 ctf_merge_input_t *cmi, *cmc;
1462 ctf_file_t *ifp, *ofp;
1463 ctf_merge_objmap_t *cmo;
1464 ctf_merge_funcmap_t *cmf;
1465 ctf_merge_types_t cm;
1467 if (cmp == NULL || outp == NULL)
1468 return (EINVAL);
1470 ctf_dprintf("encountered %d inputs\n", cmp->cmh_ninputs);
1471 if (cmp->cmh_ninputs != 2)
1472 return (EINVAL);
1474 ctf_dprintf("passed argument sanity check\n");
1476 cmi = list_head(&cmp->cmh_inputs);
1477 VERIFY(cmi != NULL);
1478 cmc = list_next(&cmp->cmh_inputs, cmi);
1479 VERIFY(cmc != NULL);
1480 ifp = cmi->cmi_input;
1481 ofp = cmc->cmi_input;
1482 VERIFY(ifp != NULL);
1483 VERIFY(ofp != NULL);
1484 cm.cm_src = ifp;
1485 cm.cm_out = ofp;
1486 cm.cm_dedup = B_TRUE;
1487 cm.cm_unique = B_FALSE;
1489 if ((ret = ctf_merge_types_init(&cm)) != 0) {
1490 return (ret);
1493 if ((ret = ctf_diff_init(ifp, ifp, &cdp)) != 0)
1494 goto err;
1496 ctf_dprintf("Successfully initialized dedup\n");
1497 if ((ret = ctf_diff_self(cdp, ctf_dedup_cb, &cm)) != 0)
1498 goto err;
1500 ctf_dprintf("Successfully diffed types\n");
1501 ret = ctf_merge_common(&cm);
1502 ctf_dprintf("deduping types result: %d\n", ret);
1503 if (ret == 0)
1504 ret = ctf_update(cm.cm_out);
1505 if (ret != 0)
1506 goto err;
1508 ctf_dprintf("Successfully deduped types\n");
1509 ctf_phase_dump(cm.cm_out, "dedup-pre-syms");
1513 * Now we need to fix up the object and function maps.
1515 for (cmo = list_head(&cmi->cmi_omap); cmo != NULL;
1516 cmo = list_next(&cmi->cmi_omap, cmo)) {
1517 if (cmo->cmo_tid == 0)
1518 continue;
1519 ctf_dprintf("mapped %s %d->%d\n", cmo->cmo_name,
1520 cmo->cmo_tid, cm.cm_tmap[cmo->cmo_tid].cmt_map);
1521 cmo->cmo_tid = cm.cm_tmap[cmo->cmo_tid].cmt_map;
1524 for (cmf = list_head(&cmi->cmi_fmap); cmf != NULL;
1525 cmf = list_next(&cmi->cmi_fmap, cmf)) {
1526 int i;
1528 VERIFY(cm.cm_tmap[cmf->cmf_rtid].cmt_map != 0);
1529 cmf->cmf_rtid = cm.cm_tmap[cmf->cmf_rtid].cmt_map;
1530 for (i = 0; i < cmf->cmf_argc; i++) {
1531 VERIFY(cm.cm_tmap[cmf->cmf_args[i]].cmt_map != 0);
1532 cmf->cmf_args[i] = cm.cm_tmap[cmf->cmf_args[i]].cmt_map;
1536 if (cmp->cmh_msyms == B_TRUE) {
1537 ret = ctf_merge_symbols(cmp, cm.cm_out);
1538 if (ret != 0) {
1539 ret = ctf_errno(cm.cm_out);
1540 ctf_dprintf("failed to dedup symbols: %s\n",
1541 ctf_errmsg(ret));
1542 goto err;
1545 ret = ctf_merge_functions(cmp, cm.cm_out);
1546 if (ret != 0) {
1547 ret = ctf_errno(cm.cm_out);
1548 ctf_dprintf("failed to dedup functions: %s\n",
1549 ctf_errmsg(ret));
1550 goto err;
1554 ret = ctf_update(cm.cm_out);
1555 if (ret == 0) {
1556 cmc->cmi_input = NULL;
1557 *outp = cm.cm_out;
1559 err:
1560 ctf_merge_types_fini(&cm);
1561 ctf_diff_fini(cdp);
1562 return (ret);
1566 ctf_merge_set_nthreads(ctf_merge_t *cmp, const uint_t nthrs)
1568 if (nthrs == 0)
1569 return (EINVAL);
1570 cmp->cmh_nthreads = nthrs;
1571 return (0);