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
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
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>
39 #include <sys/types.h>
44 typedef struct ctf_merge_tinfo
{
45 uint16_t cmt_map
; /* Map to the type in out */
47 boolean_t cmt_forward
;
48 boolean_t cmt_missing
;
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? */
62 typedef struct ctf_merge_objmap
{
64 const char *cmo_name
; /* Symbol name */
65 ulong_t cmo_idx
; /* Symbol ID */
66 ctf_id_t cmo_tid
; /* Type ID */
69 typedef struct ctf_merge_funcmap
{
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
{
81 ctf_file_t
*cmi_input
;
84 boolean_t cmi_created
;
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
);
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
);
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
140 if (cmp
->cm_unique
== B_TRUE
) {
141 cmt
[oid
].cmt_missing
= B_TRUE
;
145 cmt
[oid
].cmt_map
= iid
;
146 cmt
[oid
].cmt_forward
= B_TRUE
;
147 ctf_dprintf("merge diff forward mapped %d->%d\n", oid
,
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)
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
);
169 ctf_merge_add_number(ctf_merge_types_t
*cmp
, ctf_id_t id
)
172 const ctf_type_t
*tp
;
176 if (ctf_type_encoding(cmp
->cm_src
, id
, &en
) != 0)
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
;
184 flags
= CTF_ADD_NONROOT
;
186 ret
= ctf_add_encoded(cmp
->cm_out
, flags
, name
, &en
,
187 ctf_type_kind(cmp
->cm_src
, id
));
192 VERIFY(cmp
->cm_tmap
[id
].cmt_map
== 0);
193 cmp
->cm_tmap
[id
].cmt_map
= ret
;
198 ctf_merge_add_array(ctf_merge_types_t
*cmp
, ctf_id_t id
)
201 const ctf_type_t
*tp
;
204 if (ctf_array_info(cmp
->cm_src
, id
, &ar
) == 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
;
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
);
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
);
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
);
233 VERIFY(cmp
->cm_tmap
[id
].cmt_map
== 0);
234 cmp
->cm_tmap
[id
].cmt_map
= ret
;
240 ctf_merge_add_reftype(ctf_merge_types_t
*cmp
, ctf_id_t id
)
243 const ctf_type_t
*tp
;
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
;
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
);
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
));
271 VERIFY(cmp
->cm_tmap
[id
].cmt_map
== 0);
272 cmp
->cm_tmap
[id
].cmt_map
= ret
;
277 ctf_merge_add_typedef(ctf_merge_types_t
*cmp
, ctf_id_t id
)
280 const ctf_type_t
*tp
;
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
;
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
);
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
);
307 VERIFY(cmp
->cm_tmap
[id
].cmt_map
== 0);
308 cmp
->cm_tmap
[id
].cmt_map
= ret
;
312 typedef struct ctf_merge_enum
{
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
) ==
327 ctf_merge_add_enum(ctf_merge_types_t
*cmp
, ctf_id_t id
)
330 const ctf_type_t
*tp
;
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
;
340 flags
= CTF_ADD_NONROOT
;
342 enumid
= ctf_add_enum(cmp
->cm_out
, flags
, name
);
343 if (enumid
== CTF_ERR
)
346 cme
.cme_fp
= cmp
->cm_out
;
348 if (ctf_enum_iter(cmp
->cm_src
, id
, ctf_merge_add_enumerator
,
352 VERIFY(cmp
->cm_tmap
[id
].cmt_map
== 0);
353 cmp
->cm_tmap
[id
].cmt_map
= enumid
;
358 ctf_merge_add_func(ctf_merge_types_t
*cmp
, ctf_id_t id
)
361 const ctf_type_t
*tp
;
365 tp
= LCTF_INDEX_TO_TYPEPTR(cmp
->cm_src
, id
);
366 if (CTF_INFO_ISROOT(tp
->ctt_info
) != 0)
367 flags
= CTF_ADD_ROOT
;
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
);
376 return (ctf_set_errno(cmp
->cm_out
, ENOMEM
));
377 if (ctf_func_args_by_id(cmp
->cm_src
, id
, ctc
.ctc_argc
, argv
) ==
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
);
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
]);
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
);
406 VERIFY(cmp
->cm_tmap
[id
].cmt_map
== 0);
407 cmp
->cm_tmap
[id
].cmt_map
= ret
;
412 ctf_merge_add_forward(ctf_merge_types_t
*cmp
, ctf_id_t id
)
415 const ctf_type_t
*tp
;
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
;
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
432 ret
= ctf_add_forward(cmp
->cm_out
, flags
, name
, CTF_K_STRUCT
);
436 VERIFY(cmp
->cm_tmap
[id
].cmt_map
== 0);
437 cmp
->cm_tmap
[id
].cmt_map
= ret
;
441 typedef struct ctf_merge_su
{
442 ctf_merge_types_t
*cms_cm
;
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.
465 ctf_merge_add_sou(ctf_merge_types_t
*cmp
, ctf_id_t id
, boolean_t forward
)
468 const ctf_type_t
*tp
;
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
;
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
);
483 suid
= ctf_add_union(cmp
->cm_out
, flags
, name
);
489 * If this is a forward reference then it's mapping should already
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
,
498 VERIFY(cmp
->cm_tmap
[id
].cmt_map
== suid
);
500 cmp
->cm_tmap
[id
].cmt_fixup
= B_TRUE
;
506 ctf_merge_add_type(ctf_merge_types_t
*cmp
, ctf_id_t id
)
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
515 if (cmp
->cm_tmap
[id
].cmt_map
!= 0)
518 kind
= ctf_type_kind(cmp
->cm_src
, id
);
522 ret
= ctf_merge_add_number(cmp
, id
);
525 ret
= ctf_merge_add_array(cmp
, id
);
531 ret
= ctf_merge_add_reftype(cmp
, id
);
534 ret
= ctf_merge_add_typedef(cmp
, id
);
537 ret
= ctf_merge_add_enum(cmp
, id
);
540 ret
= ctf_merge_add_func(cmp
, id
);
543 ret
= ctf_merge_add_forward(cmp
, id
);
547 ret
= ctf_merge_add_sou(cmp
, id
, B_FALSE
);
551 * We don't add uknown types, and we later assert that nothing
552 * should reference them.
563 ctf_merge_fixup_sou(ctf_merge_types_t
*cmp
, ctf_id_t id
)
570 mapid
= cmp
->cm_tmap
[id
].cmt_map
;
572 dtd
= ctf_dtd_lookup(cmp
->cm_out
, mapid
);
575 ctf_dprintf("Trying to fix up sou %d\n", id
);
578 if (ctf_member_iter(cmp
->cm_src
, id
, ctf_merge_add_member
, &cms
) != 0)
581 if ((size
= ctf_type_size(cmp
->cm_src
, id
)) == CTF_ERR
)
583 if (ctf_set_size(cmp
->cm_out
, mapid
, size
) == CTF_ERR
)
590 ctf_merge_fixup_type(ctf_merge_types_t
*cmp
, ctf_id_t id
)
594 kind
= ctf_type_kind(cmp
->cm_src
, id
);
598 ret
= ctf_merge_fixup_sou(cmp
, id
);
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.
617 ctf_merge_fixup_dedup_map(ctf_merge_types_t
*cmp
)
621 for (i
= 1; i
< cmp
->cm_src
->ctf_typemax
+ 1; i
++) {
625 * Missing types always have their id updated to exactly what it
628 if (cmp
->cm_tmap
[i
].cmt_missing
== B_TRUE
) {
629 VERIFY(cmp
->cm_tmap
[i
].cmt_map
!= 0);
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.
662 ctf_merge_common(ctf_merge_types_t
*cmp
)
666 ctf_phase_dump(cmp
->cm_src
, "merge-common-src");
667 ctf_phase_dump(cmp
->cm_out
, "merge-common-dest");
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
);
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
);
684 ctf_dprintf("Failed to merge type %d\n", i
);
690 ret
= ctf_update(cmp
->cm_out
);
694 if (cmp
->cm_dedup
== B_TRUE
) {
695 ctf_merge_fixup_dedup_map(cmp
);
698 ctf_dprintf("Beginning merge pass 3\n");
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
);
708 if (cmp
->cm_dedup
== B_TRUE
) {
709 ctf_merge_fixup_dedup_map(cmp
);
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
722 ctf_merge_uniquify_types(ctf_merge_types_t
*cmp
)
726 for (i
= 1; i
<= cmp
->cm_src
->ctf_typemax
; i
++) {
727 if (cmp
->cm_tmap
[i
].cmt_missing
== B_FALSE
)
729 ret
= ctf_merge_add_type(cmp
, i
);
734 ret
= ctf_update(cmp
->cm_out
);
738 for (i
= 1; i
<= cmp
->cm_src
->ctf_typemax
; i
++) {
739 if (cmp
->cm_tmap
[i
].cmt_fixup
== B_FALSE
)
741 ret
= ctf_merge_fixup_type(cmp
, i
);
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));
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
775 ctf_merge_types(void *arg
, void *arg2
, void **outp
, void *unsued
)
778 ctf_merge_types_t cm
;
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)
800 cm
.cm_dedup
= B_FALSE
;
801 cm
.cm_unique
= B_FALSE
;
802 ret
= ctf_merge_types_init(&cm
);
805 return (ctf_set_errno(out
, ret
));
808 ret
= ctf_diff_types(cdp
, ctf_merge_diffcb
, &cm
);
811 ret
= ctf_merge_common(&cm
);
812 ctf_dprintf("merge common returned with %d\n", ret
);
814 ret
= ctf_update(out
);
815 ctf_dprintf("update returned with %d\n", ret
);
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)
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
)) {
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
);
854 ctf_merge_types_fini(&cm
);
857 return (ctf_errno(out
));
862 ctf_uniquify_types(ctf_merge_t
*cmh
, ctf_file_t
*src
, ctf_file_t
**outp
)
866 ctf_merge_types_t cm
;
868 ctf_merge_input_t
*cmi
;
869 ctf_file_t
*parent
= cmh
->cmh_unique
;
872 out
= ctf_fdcreate(cmh
->cmh_ofd
, &err
);
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
));
883 if (ctf_import(out
, parent
) != 0) {
884 (void) ctf_set_errno(src
, ctf_errno(out
));
889 if ((ret
= ctf_diff_init(parent
, src
, &cdp
)) != 0) {
891 return (ctf_set_errno(src
, ctf_errno(parent
)));
896 cm
.cm_dedup
= B_FALSE
;
897 cm
.cm_unique
= B_TRUE
;
898 ret
= ctf_merge_types_init(&cm
);
902 return (ctf_set_errno(src
, ret
));
905 ret
= ctf_diff_types(cdp
, ctf_merge_diffcb
, &cm
);
908 ret
= ctf_merge_uniquify_types(&cm
);
910 ret
= ctf_update(out
);
914 ctf_merge_types_fini(&cm
);
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)
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
)) {
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
!=
942 cm
.cm_tmap
[cmf
->cmf_args
[i
]].cmt_map
;
947 ctf_merge_types_fini(&cm
);
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
));
973 ctf_merge_fini(ctf_merge_t
*cmh
)
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
));
995 ctf_merge_init(int fd
, int *errp
)
1004 if (fd
!= -1 && fstat(fd
, &st
) != 0) {
1009 out
= ctf_alloc(sizeof (ctf_merge_t
));
1016 out
->cmh_msyms
= B_FALSE
;
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
;
1028 out
->cmh_label
= NULL
;
1029 out
->cmh_pname
= NULL
;
1035 ctf_merge_label(ctf_merge_t
*cmh
, const char *label
)
1042 dup
= ctf_strdup(label
);
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
;
1056 ctf_merge_add_funcs(const char *name
, ulong_t idx
, ctf_funcinfo_t
*fip
,
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
);
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
);
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
));
1094 cmo
->cmo_name
= name
;
1097 list_insert_tail(&cmi
->cmi_omap
, cmo
);
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
)
1110 ctf_merge_input_t
*cmi
;
1113 if (input
->ctf_flags
& LCTF_CHILD
)
1114 return (ECTF_MCHILD
);
1116 cmi
= ctf_alloc(sizeof (ctf_merge_input_t
));
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
,
1130 ctf_merge_fini_input(cmi
);
1134 if ((ret
= ctf_object_iter(input
, ctf_merge_add_objs
,
1136 ctf_merge_fini_input(cmi
);
1141 list_insert_tail(&cmh
->cmh_inputs
, cmi
);
1144 /* And now the empty one to merge into this */
1145 cmi
= ctf_alloc(sizeof (ctf_merge_input_t
));
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
);
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
);
1165 ctf_dprintf("added containers %p and %p\n", input
, empty
);
1170 ctf_merge_uniquify(ctf_merge_t
*cmh
, ctf_file_t
*u
, const char *pname
)
1174 if (u
->ctf_flags
& LCTF_CHILD
)
1175 return (ECTF_MCHILD
);
1178 dup
= ctf_strdup(pname
);
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
;
1191 ctf_merge_symbols(ctf_merge_t
*cmh
, ctf_file_t
*fp
)
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
++) {
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
)
1209 if (ctf_sym_valid(strbase
, type
, symp
->st_shndx
,
1210 symp
->st_value
, symp
->st_name
) == B_FALSE
)
1212 name
= (char *)(strbase
+ symp
->st_name
);
1214 const Elf64_Sym
*symp
= (Elf64_Sym
*)symbase
+ i
;
1215 int type
= ELF64_ST_TYPE(symp
->st_info
);
1216 if (type
!= STT_OBJECT
)
1218 if (ctf_sym_valid(strbase
, type
, symp
->st_shndx
,
1219 symp
->st_value
, symp
->st_name
) == B_FALSE
)
1221 name
= (char *)(strbase
+ symp
->st_name
);
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)
1235 if (cmo
->cmo_tid
== 0)
1237 if ((err
= ctf_add_object(fp
, i
, cmo
->cmo_tid
)) != 0) {
1238 ctf_dprintf("Failed to add symbol %s->%d: %s\n",
1240 ctf_errmsg(ctf_errno(fp
)));
1250 ctf_merge_functions(ctf_merge_t
*cmh
, ctf_file_t
*fp
)
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
++) {
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
)
1269 if (ctf_sym_valid(strbase
, type
, symp
->st_shndx
,
1270 symp
->st_value
, symp
->st_name
) == B_FALSE
)
1272 name
= (char *)(strbase
+ symp
->st_name
);
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
)
1278 if (ctf_sym_valid(strbase
, type
, symp
->st_shndx
,
1279 symp
->st_value
, symp
->st_name
) == B_FALSE
)
1281 name
= (char *)(strbase
+ symp
->st_name
);
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)
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)
1309 ctf_merge_merge(ctf_merge_t
*cmh
, ctf_file_t
**outp
)
1312 ctf_merge_input_t
*cmi
;
1315 ctf_merge_input_t
*final
;
1318 if (cmh
->cmh_label
!= NULL
&& cmh
->cmh_unique
!= NULL
) {
1319 const char *label
= ctf_label_topmost(cmh
->cmh_unique
);
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) {
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
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) {
1344 err
= mergeq_merge(mqp
, ctf_merge_types
, NULL
, (void **)&final
, &merr
);
1347 if (err
== MERGEQ_ERROR
) {
1349 } else if (err
== MERGEQ_UERROR
) {
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
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
) {
1366 err
= ctf_uniquify_types(cmh
, out
, &u
);
1368 err
= ctf_errno(out
);
1376 ltype
= out
->ctf_typemax
;
1377 if ((out
->ctf_flags
& LCTF_CHILD
) && ltype
!= 0)
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) {
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
);
1391 return (ctf_errno(out
));
1394 err
= ctf_merge_functions(cmh
, out
);
1397 return (ctf_errno(out
));
1401 err
= ctf_update(out
);
1404 return (ctf_errno(out
));
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.
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
);
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
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
)
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
)
1470 ctf_dprintf("encountered %d inputs\n", cmp
->cmh_ninputs
);
1471 if (cmp
->cmh_ninputs
!= 2)
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
);
1486 cm
.cm_dedup
= B_TRUE
;
1487 cm
.cm_unique
= B_FALSE
;
1489 if ((ret
= ctf_merge_types_init(&cm
)) != 0) {
1493 if ((ret
= ctf_diff_init(ifp
, ifp
, &cdp
)) != 0)
1496 ctf_dprintf("Successfully initialized dedup\n");
1497 if ((ret
= ctf_diff_self(cdp
, ctf_dedup_cb
, &cm
)) != 0)
1500 ctf_dprintf("Successfully diffed types\n");
1501 ret
= ctf_merge_common(&cm
);
1502 ctf_dprintf("deduping types result: %d\n", ret
);
1504 ret
= ctf_update(cm
.cm_out
);
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)
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
)) {
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
);
1539 ret
= ctf_errno(cm
.cm_out
);
1540 ctf_dprintf("failed to dedup symbols: %s\n",
1545 ret
= ctf_merge_functions(cmp
, cm
.cm_out
);
1547 ret
= ctf_errno(cm
.cm_out
);
1548 ctf_dprintf("failed to dedup functions: %s\n",
1554 ret
= ctf_update(cm
.cm_out
);
1556 cmc
->cmi_input
= NULL
;
1560 ctf_merge_types_fini(&cm
);
1566 ctf_merge_set_nthreads(ctf_merge_t
*cmp
, const uint_t nthrs
)
1570 cmp
->cmh_nthreads
= nthrs
;