xref: /titanic_51/usr/src/lib/libctf/common/ctf_merge.c (revision 7fd791373689a6af05e27efec3b1ab556e02aa23)
1*7fd79137SRobert Mustacchi /*
2*7fd79137SRobert Mustacchi  * This file and its contents are supplied under the terms of the
3*7fd79137SRobert Mustacchi  * Common Development and Distribution License ("CDDL"), version 1.0.
4*7fd79137SRobert Mustacchi  * You may only use this file in accordance with the terms of version
5*7fd79137SRobert Mustacchi  * 1.0 of the CDDL.
6*7fd79137SRobert Mustacchi  *
7*7fd79137SRobert Mustacchi  * A full copy of the text of the CDDL should have accompanied this
8*7fd79137SRobert Mustacchi  * source.  A copy of the CDDL is also available via the Internet at
9*7fd79137SRobert Mustacchi  * http://www.illumos.org/license/CDDL.
10*7fd79137SRobert Mustacchi  */
11*7fd79137SRobert Mustacchi 
12*7fd79137SRobert Mustacchi /*
13*7fd79137SRobert Mustacchi  * Copyright (c) 2015 Joyent, Inc.
14*7fd79137SRobert Mustacchi  */
15*7fd79137SRobert Mustacchi 
16*7fd79137SRobert Mustacchi /*
17*7fd79137SRobert Mustacchi  * To perform a merge of two CTF containers, we first diff the two containers
18*7fd79137SRobert Mustacchi  * types. For every type that's in the src container, but not in the dst
19*7fd79137SRobert Mustacchi  * container, we note it and add it to dst container. If there are any objects
20*7fd79137SRobert Mustacchi  * or functions associated with src, we go through and update the types that
21*7fd79137SRobert Mustacchi  * they refer to such that they all refer to types in the dst container.
22*7fd79137SRobert Mustacchi  *
23*7fd79137SRobert Mustacchi  * The bulk of the logic for the merge, after we've run the diff, occurs in
24*7fd79137SRobert Mustacchi  * ctf_merge_common().
25*7fd79137SRobert Mustacchi  *
26*7fd79137SRobert Mustacchi  * In terms of exported APIs, we don't really export a simple merge two
27*7fd79137SRobert Mustacchi  * containers, as the general way this is used, in something like ctfmerge(1),
28*7fd79137SRobert Mustacchi  * is to add all the containers and then let us figure out the best way to merge
29*7fd79137SRobert Mustacchi  * it.
30*7fd79137SRobert Mustacchi  */
31*7fd79137SRobert Mustacchi 
32*7fd79137SRobert Mustacchi #include <libctf_impl.h>
33*7fd79137SRobert Mustacchi #include <sys/debug.h>
34*7fd79137SRobert Mustacchi #include <sys/list.h>
35*7fd79137SRobert Mustacchi #include <stddef.h>
36*7fd79137SRobert Mustacchi #include <fcntl.h>
37*7fd79137SRobert Mustacchi #include <sys/types.h>
38*7fd79137SRobert Mustacchi #include <sys/stat.h>
39*7fd79137SRobert Mustacchi #include <mergeq.h>
40*7fd79137SRobert Mustacchi #include <errno.h>
41*7fd79137SRobert Mustacchi 
42*7fd79137SRobert Mustacchi typedef struct ctf_merge_tinfo {
43*7fd79137SRobert Mustacchi 	uint16_t cmt_map;	/* Map to the type in out */
44*7fd79137SRobert Mustacchi 	boolean_t cmt_fixup;
45*7fd79137SRobert Mustacchi 	boolean_t cmt_forward;
46*7fd79137SRobert Mustacchi 	boolean_t cmt_missing;
47*7fd79137SRobert Mustacchi } ctf_merge_tinfo_t;
48*7fd79137SRobert Mustacchi 
49*7fd79137SRobert Mustacchi /*
50*7fd79137SRobert Mustacchi  * State required for doing an individual merge of two containers.
51*7fd79137SRobert Mustacchi  */
52*7fd79137SRobert Mustacchi typedef struct ctf_merge_types {
53*7fd79137SRobert Mustacchi 	ctf_file_t *cm_out;		/* Output CTF file */
54*7fd79137SRobert Mustacchi 	ctf_file_t *cm_src;		/* Input CTF file */
55*7fd79137SRobert Mustacchi 	ctf_merge_tinfo_t *cm_tmap;	/* Type state information */
56*7fd79137SRobert Mustacchi 	boolean_t cm_dedup;		/* Are we doing a dedup? */
57*7fd79137SRobert Mustacchi 	boolean_t cm_unique;		/* are we doing a uniquify? */
58*7fd79137SRobert Mustacchi } ctf_merge_types_t;
59*7fd79137SRobert Mustacchi 
60*7fd79137SRobert Mustacchi typedef struct ctf_merge_objmap {
61*7fd79137SRobert Mustacchi 	list_node_t cmo_node;
62*7fd79137SRobert Mustacchi 	const char *cmo_name;		/* Symbol name */
63*7fd79137SRobert Mustacchi 	ulong_t cmo_idx;		/* Symbol ID */
64*7fd79137SRobert Mustacchi 	ctf_id_t cmo_tid;		/* Type ID */
65*7fd79137SRobert Mustacchi } ctf_merge_objmap_t;
66*7fd79137SRobert Mustacchi 
67*7fd79137SRobert Mustacchi typedef struct ctf_merge_funcmap {
68*7fd79137SRobert Mustacchi 	list_node_t cmf_node;
69*7fd79137SRobert Mustacchi 	const char *cmf_name;		/* Symbol name */
70*7fd79137SRobert Mustacchi 	ulong_t cmf_idx;		/* Symbol ID */
71*7fd79137SRobert Mustacchi 	ctf_id_t cmf_rtid;		/* Type ID */
72*7fd79137SRobert Mustacchi 	uint_t cmf_flags;		/* ctf_funcinfo_t ctc_flags */
73*7fd79137SRobert Mustacchi 	uint_t cmf_argc;		/* Number of arguments */
74*7fd79137SRobert Mustacchi 	ctf_id_t cmf_args[];		/* Types of arguments */
75*7fd79137SRobert Mustacchi } ctf_merge_funcmap_t;
76*7fd79137SRobert Mustacchi 
77*7fd79137SRobert Mustacchi typedef struct ctf_merge_input {
78*7fd79137SRobert Mustacchi 	list_node_t cmi_node;
79*7fd79137SRobert Mustacchi 	ctf_file_t *cmi_input;
80*7fd79137SRobert Mustacchi 	list_t cmi_omap;
81*7fd79137SRobert Mustacchi 	list_t cmi_fmap;
82*7fd79137SRobert Mustacchi 	boolean_t cmi_created;
83*7fd79137SRobert Mustacchi } ctf_merge_input_t;
84*7fd79137SRobert Mustacchi 
85*7fd79137SRobert Mustacchi struct ctf_merge_handle {
86*7fd79137SRobert Mustacchi 	list_t cmh_inputs;		/* Input list */
87*7fd79137SRobert Mustacchi 	uint_t cmh_ninputs;		/* Number of inputs */
88*7fd79137SRobert Mustacchi 	uint_t cmh_nthreads;		/* Number of threads to use */
89*7fd79137SRobert Mustacchi 	ctf_file_t *cmh_unique;		/* ctf to uniquify against */
90*7fd79137SRobert Mustacchi 	boolean_t cmh_msyms;		/* Should we merge symbols/funcs? */
91*7fd79137SRobert Mustacchi 	int cmh_ofd;			/* FD for output file */
92*7fd79137SRobert Mustacchi 	int cmh_flags;			/* Flags that control merge behavior */
93*7fd79137SRobert Mustacchi 	char *cmh_label;		/* Optional label */
94*7fd79137SRobert Mustacchi 	char *cmh_pname;		/* Parent name */
95*7fd79137SRobert Mustacchi };
96*7fd79137SRobert Mustacchi 
97*7fd79137SRobert Mustacchi static int ctf_merge_add_type(ctf_merge_types_t *, ctf_id_t);
98*7fd79137SRobert Mustacchi 
99*7fd79137SRobert Mustacchi static ctf_id_t
100*7fd79137SRobert Mustacchi ctf_merge_gettype(ctf_merge_types_t *cmp, ctf_id_t id)
101*7fd79137SRobert Mustacchi {
102*7fd79137SRobert Mustacchi 	if (cmp->cm_dedup == B_FALSE) {
103*7fd79137SRobert Mustacchi 		VERIFY(cmp->cm_tmap[id].cmt_map != 0);
104*7fd79137SRobert Mustacchi 		return (cmp->cm_tmap[id].cmt_map);
105*7fd79137SRobert Mustacchi 	}
106*7fd79137SRobert Mustacchi 
107*7fd79137SRobert Mustacchi 	while (cmp->cm_tmap[id].cmt_missing == B_FALSE) {
108*7fd79137SRobert Mustacchi 		VERIFY(cmp->cm_tmap[id].cmt_map != 0);
109*7fd79137SRobert Mustacchi 		id = cmp->cm_tmap[id].cmt_map;
110*7fd79137SRobert Mustacchi 	}
111*7fd79137SRobert Mustacchi 	VERIFY(cmp->cm_tmap[id].cmt_map != 0);
112*7fd79137SRobert Mustacchi 	return (cmp->cm_tmap[id].cmt_map);
113*7fd79137SRobert Mustacchi }
114*7fd79137SRobert Mustacchi 
115*7fd79137SRobert Mustacchi static void
116*7fd79137SRobert Mustacchi ctf_merge_diffcb(ctf_file_t *ifp, ctf_id_t iid, boolean_t same, ctf_file_t *ofp,
117*7fd79137SRobert Mustacchi     ctf_id_t oid, void *arg)
118*7fd79137SRobert Mustacchi {
119*7fd79137SRobert Mustacchi 	ctf_merge_types_t *cmp = arg;
120*7fd79137SRobert Mustacchi 	ctf_merge_tinfo_t *cmt = cmp->cm_tmap;
121*7fd79137SRobert Mustacchi 
122*7fd79137SRobert Mustacchi 	if (same == B_TRUE) {
123*7fd79137SRobert Mustacchi 		if (ctf_type_kind(ifp, iid) == CTF_K_FORWARD &&
124*7fd79137SRobert Mustacchi 		    ctf_type_kind(ofp, oid) != CTF_K_FORWARD) {
125*7fd79137SRobert Mustacchi 			VERIFY(cmt[oid].cmt_map == 0);
126*7fd79137SRobert Mustacchi 
127*7fd79137SRobert Mustacchi 			/*
128*7fd79137SRobert Mustacchi 			 * If we're uniquifying types, it's possible for the
129*7fd79137SRobert Mustacchi 			 * container that we're uniquifying against to have a
130*7fd79137SRobert Mustacchi 			 * forward which exists in the container being reduced.
131*7fd79137SRobert Mustacchi 			 * For example, genunix has the machcpu structure as a
132*7fd79137SRobert Mustacchi 			 * forward which is actually in unix and we uniquify
133*7fd79137SRobert Mustacchi 			 * unix against genunix. In such cases, we explicitly do
134*7fd79137SRobert Mustacchi 			 * not do any mapping of the forward information, lest
135*7fd79137SRobert Mustacchi 			 * we risk losing the real definition. Instead, mark
136*7fd79137SRobert Mustacchi 			 * that it's missing.
137*7fd79137SRobert Mustacchi 			 */
138*7fd79137SRobert Mustacchi 			if (cmp->cm_unique == B_TRUE) {
139*7fd79137SRobert Mustacchi 				cmt[oid].cmt_missing = B_TRUE;
140*7fd79137SRobert Mustacchi 				return;
141*7fd79137SRobert Mustacchi 			}
142*7fd79137SRobert Mustacchi 
143*7fd79137SRobert Mustacchi 			cmt[oid].cmt_map = iid;
144*7fd79137SRobert Mustacchi 			cmt[oid].cmt_forward = B_TRUE;
145*7fd79137SRobert Mustacchi 			ctf_dprintf("merge diff forward mapped %d->%d\n", oid,
146*7fd79137SRobert Mustacchi 			    iid);
147*7fd79137SRobert Mustacchi 			return;
148*7fd79137SRobert Mustacchi 		}
149*7fd79137SRobert Mustacchi 
150*7fd79137SRobert Mustacchi 		/*
151*7fd79137SRobert Mustacchi 		 * We could have multiple things that a given type ends up
152*7fd79137SRobert Mustacchi 		 * matching in the world of forwards and pointers to forwards.
153*7fd79137SRobert Mustacchi 		 * For now just take the first one...
154*7fd79137SRobert Mustacchi 		 */
155*7fd79137SRobert Mustacchi 		if (cmt[oid].cmt_map != 0)
156*7fd79137SRobert Mustacchi 			return;
157*7fd79137SRobert Mustacchi 		cmt[oid].cmt_map = iid;
158*7fd79137SRobert Mustacchi 		ctf_dprintf("merge diff mapped %d->%d\n", oid, iid);
159*7fd79137SRobert Mustacchi 	} else if (ifp == cmp->cm_src) {
160*7fd79137SRobert Mustacchi 		VERIFY(cmt[iid].cmt_map == 0);
161*7fd79137SRobert Mustacchi 		cmt[iid].cmt_missing = B_TRUE;
162*7fd79137SRobert Mustacchi 		ctf_dprintf("merge diff said %d is missing\n", iid);
163*7fd79137SRobert Mustacchi 	}
164*7fd79137SRobert Mustacchi }
165*7fd79137SRobert Mustacchi 
166*7fd79137SRobert Mustacchi static int
167*7fd79137SRobert Mustacchi ctf_merge_add_number(ctf_merge_types_t *cmp, ctf_id_t id)
168*7fd79137SRobert Mustacchi {
169*7fd79137SRobert Mustacchi 	int ret, flags;
170*7fd79137SRobert Mustacchi 	const ctf_type_t *tp;
171*7fd79137SRobert Mustacchi 	const char *name;
172*7fd79137SRobert Mustacchi 	ctf_encoding_t en;
173*7fd79137SRobert Mustacchi 
174*7fd79137SRobert Mustacchi 	if (ctf_type_encoding(cmp->cm_src, id, &en) != 0)
175*7fd79137SRobert Mustacchi 		return (CTF_ERR);
176*7fd79137SRobert Mustacchi 
177*7fd79137SRobert Mustacchi 	tp = LCTF_INDEX_TO_TYPEPTR(cmp->cm_src, id);
178*7fd79137SRobert Mustacchi 	name = ctf_strraw(cmp->cm_src, tp->ctt_name);
179*7fd79137SRobert Mustacchi 	if (CTF_INFO_ISROOT(tp->ctt_info) != 0)
180*7fd79137SRobert Mustacchi 		flags = CTF_ADD_ROOT;
181*7fd79137SRobert Mustacchi 	else
182*7fd79137SRobert Mustacchi 		flags = CTF_ADD_NONROOT;
183*7fd79137SRobert Mustacchi 
184*7fd79137SRobert Mustacchi 	ret = ctf_add_encoded(cmp->cm_out, flags, name, &en,
185*7fd79137SRobert Mustacchi 	    ctf_type_kind(cmp->cm_src, id));
186*7fd79137SRobert Mustacchi 
187*7fd79137SRobert Mustacchi 	if (ret == CTF_ERR)
188*7fd79137SRobert Mustacchi 		return (ret);
189*7fd79137SRobert Mustacchi 
190*7fd79137SRobert Mustacchi 	VERIFY(cmp->cm_tmap[id].cmt_map == 0);
191*7fd79137SRobert Mustacchi 	cmp->cm_tmap[id].cmt_map = ret;
192*7fd79137SRobert Mustacchi 	return (0);
193*7fd79137SRobert Mustacchi }
194*7fd79137SRobert Mustacchi 
195*7fd79137SRobert Mustacchi static int
196*7fd79137SRobert Mustacchi ctf_merge_add_array(ctf_merge_types_t *cmp, ctf_id_t id)
197*7fd79137SRobert Mustacchi {
198*7fd79137SRobert Mustacchi 	int ret, flags;
199*7fd79137SRobert Mustacchi 	const ctf_type_t *tp;
200*7fd79137SRobert Mustacchi 	ctf_arinfo_t ar;
201*7fd79137SRobert Mustacchi 
202*7fd79137SRobert Mustacchi 	if (ctf_array_info(cmp->cm_src, id, &ar) == CTF_ERR)
203*7fd79137SRobert Mustacchi 		return (CTF_ERR);
204*7fd79137SRobert Mustacchi 
205*7fd79137SRobert Mustacchi 	tp = LCTF_INDEX_TO_TYPEPTR(cmp->cm_src, id);
206*7fd79137SRobert Mustacchi 	if (CTF_INFO_ISROOT(tp->ctt_info) != 0)
207*7fd79137SRobert Mustacchi 		flags = CTF_ADD_ROOT;
208*7fd79137SRobert Mustacchi 	else
209*7fd79137SRobert Mustacchi 		flags = CTF_ADD_NONROOT;
210*7fd79137SRobert Mustacchi 
211*7fd79137SRobert Mustacchi 	if (cmp->cm_tmap[ar.ctr_contents].cmt_map == 0) {
212*7fd79137SRobert Mustacchi 		ret = ctf_merge_add_type(cmp, ar.ctr_contents);
213*7fd79137SRobert Mustacchi 		if (ret != 0)
214*7fd79137SRobert Mustacchi 			return (ret);
215*7fd79137SRobert Mustacchi 		ASSERT(cmp->cm_tmap[ar.ctr_contents].cmt_map != 0);
216*7fd79137SRobert Mustacchi 	}
217*7fd79137SRobert Mustacchi 	ar.ctr_contents = ctf_merge_gettype(cmp, ar.ctr_contents);
218*7fd79137SRobert Mustacchi 
219*7fd79137SRobert Mustacchi 	if (cmp->cm_tmap[ar.ctr_index].cmt_map == 0) {
220*7fd79137SRobert Mustacchi 		ret = ctf_merge_add_type(cmp, ar.ctr_index);
221*7fd79137SRobert Mustacchi 		if (ret != 0)
222*7fd79137SRobert Mustacchi 			return (ret);
223*7fd79137SRobert Mustacchi 		ASSERT(cmp->cm_tmap[ar.ctr_index].cmt_map != 0);
224*7fd79137SRobert Mustacchi 	}
225*7fd79137SRobert Mustacchi 	ar.ctr_index = ctf_merge_gettype(cmp, ar.ctr_index);
226*7fd79137SRobert Mustacchi 
227*7fd79137SRobert Mustacchi 	ret = ctf_add_array(cmp->cm_out, flags, &ar);
228*7fd79137SRobert Mustacchi 	if (ret == CTF_ERR)
229*7fd79137SRobert Mustacchi 		return (ret);
230*7fd79137SRobert Mustacchi 
231*7fd79137SRobert Mustacchi 	VERIFY(cmp->cm_tmap[id].cmt_map == 0);
232*7fd79137SRobert Mustacchi 	cmp->cm_tmap[id].cmt_map = ret;
233*7fd79137SRobert Mustacchi 
234*7fd79137SRobert Mustacchi 	return (0);
235*7fd79137SRobert Mustacchi }
236*7fd79137SRobert Mustacchi 
237*7fd79137SRobert Mustacchi static int
238*7fd79137SRobert Mustacchi ctf_merge_add_reftype(ctf_merge_types_t *cmp, ctf_id_t id)
239*7fd79137SRobert Mustacchi {
240*7fd79137SRobert Mustacchi 	int ret, flags;
241*7fd79137SRobert Mustacchi 	const ctf_type_t *tp;
242*7fd79137SRobert Mustacchi 	ctf_id_t reftype;
243*7fd79137SRobert Mustacchi 	const char *name;
244*7fd79137SRobert Mustacchi 
245*7fd79137SRobert Mustacchi 	tp = LCTF_INDEX_TO_TYPEPTR(cmp->cm_src, id);
246*7fd79137SRobert Mustacchi 	name = ctf_strraw(cmp->cm_src, tp->ctt_name);
247*7fd79137SRobert Mustacchi 	if (CTF_INFO_ISROOT(tp->ctt_info) != 0)
248*7fd79137SRobert Mustacchi 		flags = CTF_ADD_ROOT;
249*7fd79137SRobert Mustacchi 	else
250*7fd79137SRobert Mustacchi 		flags = CTF_ADD_NONROOT;
251*7fd79137SRobert Mustacchi 
252*7fd79137SRobert Mustacchi 	reftype = ctf_type_reference(cmp->cm_src, id);
253*7fd79137SRobert Mustacchi 	if (reftype == CTF_ERR)
254*7fd79137SRobert Mustacchi 		return (ctf_set_errno(cmp->cm_out, ctf_errno(cmp->cm_src)));
255*7fd79137SRobert Mustacchi 
256*7fd79137SRobert Mustacchi 	if (cmp->cm_tmap[reftype].cmt_map == 0) {
257*7fd79137SRobert Mustacchi 		ret = ctf_merge_add_type(cmp, reftype);
258*7fd79137SRobert Mustacchi 		if (ret != 0)
259*7fd79137SRobert Mustacchi 			return (ret);
260*7fd79137SRobert Mustacchi 		ASSERT(cmp->cm_tmap[reftype].cmt_map != 0);
261*7fd79137SRobert Mustacchi 	}
262*7fd79137SRobert Mustacchi 	reftype = ctf_merge_gettype(cmp, reftype);
263*7fd79137SRobert Mustacchi 
264*7fd79137SRobert Mustacchi 	ret = ctf_add_reftype(cmp->cm_out, flags, name, reftype,
265*7fd79137SRobert Mustacchi 	    ctf_type_kind(cmp->cm_src, id));
266*7fd79137SRobert Mustacchi 	if (ret == CTF_ERR)
267*7fd79137SRobert Mustacchi 		return (ret);
268*7fd79137SRobert Mustacchi 
269*7fd79137SRobert Mustacchi 	VERIFY(cmp->cm_tmap[id].cmt_map == 0);
270*7fd79137SRobert Mustacchi 	cmp->cm_tmap[id].cmt_map = ret;
271*7fd79137SRobert Mustacchi 	return (0);
272*7fd79137SRobert Mustacchi }
273*7fd79137SRobert Mustacchi 
274*7fd79137SRobert Mustacchi static int
275*7fd79137SRobert Mustacchi ctf_merge_add_typedef(ctf_merge_types_t *cmp, ctf_id_t id)
276*7fd79137SRobert Mustacchi {
277*7fd79137SRobert Mustacchi 	int ret, flags;
278*7fd79137SRobert Mustacchi 	const ctf_type_t *tp;
279*7fd79137SRobert Mustacchi 	const char *name;
280*7fd79137SRobert Mustacchi 	ctf_id_t reftype;
281*7fd79137SRobert Mustacchi 
282*7fd79137SRobert Mustacchi 	tp = LCTF_INDEX_TO_TYPEPTR(cmp->cm_src, id);
283*7fd79137SRobert Mustacchi 	name = ctf_strraw(cmp->cm_src, tp->ctt_name);
284*7fd79137SRobert Mustacchi 	if (CTF_INFO_ISROOT(tp->ctt_info) != 0)
285*7fd79137SRobert Mustacchi 		flags = CTF_ADD_ROOT;
286*7fd79137SRobert Mustacchi 	else
287*7fd79137SRobert Mustacchi 		flags = CTF_ADD_NONROOT;
288*7fd79137SRobert Mustacchi 
289*7fd79137SRobert Mustacchi 	reftype = ctf_type_reference(cmp->cm_src, id);
290*7fd79137SRobert Mustacchi 	if (reftype == CTF_ERR)
291*7fd79137SRobert Mustacchi 		return (ctf_set_errno(cmp->cm_out, ctf_errno(cmp->cm_src)));
292*7fd79137SRobert Mustacchi 
293*7fd79137SRobert Mustacchi 	if (cmp->cm_tmap[reftype].cmt_map == 0) {
294*7fd79137SRobert Mustacchi 		ret = ctf_merge_add_type(cmp, reftype);
295*7fd79137SRobert Mustacchi 		if (ret != 0)
296*7fd79137SRobert Mustacchi 			return (ret);
297*7fd79137SRobert Mustacchi 		ASSERT(cmp->cm_tmap[reftype].cmt_map != 0);
298*7fd79137SRobert Mustacchi 	}
299*7fd79137SRobert Mustacchi 	reftype = ctf_merge_gettype(cmp, reftype);
300*7fd79137SRobert Mustacchi 
301*7fd79137SRobert Mustacchi 	ret = ctf_add_typedef(cmp->cm_out, flags, name, reftype);
302*7fd79137SRobert Mustacchi 	if (ret == CTF_ERR)
303*7fd79137SRobert Mustacchi 		return (ret);
304*7fd79137SRobert Mustacchi 
305*7fd79137SRobert Mustacchi 	VERIFY(cmp->cm_tmap[id].cmt_map == 0);
306*7fd79137SRobert Mustacchi 	cmp->cm_tmap[id].cmt_map = ret;
307*7fd79137SRobert Mustacchi 	return (0);
308*7fd79137SRobert Mustacchi }
309*7fd79137SRobert Mustacchi 
310*7fd79137SRobert Mustacchi typedef struct ctf_merge_enum {
311*7fd79137SRobert Mustacchi 	ctf_file_t *cme_fp;
312*7fd79137SRobert Mustacchi 	ctf_id_t cme_id;
313*7fd79137SRobert Mustacchi } ctf_merge_enum_t;
314*7fd79137SRobert Mustacchi 
315*7fd79137SRobert Mustacchi static int
316*7fd79137SRobert Mustacchi ctf_merge_add_enumerator(const char *name, int value, void *arg)
317*7fd79137SRobert Mustacchi {
318*7fd79137SRobert Mustacchi 	ctf_merge_enum_t *cmep = arg;
319*7fd79137SRobert Mustacchi 
320*7fd79137SRobert Mustacchi 	return (ctf_add_enumerator(cmep->cme_fp, cmep->cme_id, name, value) ==
321*7fd79137SRobert Mustacchi 	    CTF_ERR);
322*7fd79137SRobert Mustacchi }
323*7fd79137SRobert Mustacchi 
324*7fd79137SRobert Mustacchi static int
325*7fd79137SRobert Mustacchi ctf_merge_add_enum(ctf_merge_types_t *cmp, ctf_id_t id)
326*7fd79137SRobert Mustacchi {
327*7fd79137SRobert Mustacchi 	int flags;
328*7fd79137SRobert Mustacchi 	const ctf_type_t *tp;
329*7fd79137SRobert Mustacchi 	const char *name;
330*7fd79137SRobert Mustacchi 	ctf_id_t enumid;
331*7fd79137SRobert Mustacchi 	ctf_merge_enum_t cme;
332*7fd79137SRobert Mustacchi 
333*7fd79137SRobert Mustacchi 	tp = LCTF_INDEX_TO_TYPEPTR(cmp->cm_src, id);
334*7fd79137SRobert Mustacchi 	name = ctf_strraw(cmp->cm_src, tp->ctt_name);
335*7fd79137SRobert Mustacchi 	if (CTF_INFO_ISROOT(tp->ctt_info) != 0)
336*7fd79137SRobert Mustacchi 		flags = CTF_ADD_ROOT;
337*7fd79137SRobert Mustacchi 	else
338*7fd79137SRobert Mustacchi 		flags = CTF_ADD_NONROOT;
339*7fd79137SRobert Mustacchi 
340*7fd79137SRobert Mustacchi 	enumid = ctf_add_enum(cmp->cm_out, flags, name);
341*7fd79137SRobert Mustacchi 	if (enumid == CTF_ERR)
342*7fd79137SRobert Mustacchi 		return (enumid);
343*7fd79137SRobert Mustacchi 
344*7fd79137SRobert Mustacchi 	cme.cme_fp = cmp->cm_out;
345*7fd79137SRobert Mustacchi 	cme.cme_id = enumid;
346*7fd79137SRobert Mustacchi 	if (ctf_enum_iter(cmp->cm_src, id, ctf_merge_add_enumerator,
347*7fd79137SRobert Mustacchi 	    &cme) != 0)
348*7fd79137SRobert Mustacchi 		return (CTF_ERR);
349*7fd79137SRobert Mustacchi 
350*7fd79137SRobert Mustacchi 	VERIFY(cmp->cm_tmap[id].cmt_map == 0);
351*7fd79137SRobert Mustacchi 	cmp->cm_tmap[id].cmt_map = enumid;
352*7fd79137SRobert Mustacchi 	return (0);
353*7fd79137SRobert Mustacchi }
354*7fd79137SRobert Mustacchi 
355*7fd79137SRobert Mustacchi static int
356*7fd79137SRobert Mustacchi ctf_merge_add_func(ctf_merge_types_t *cmp, ctf_id_t id)
357*7fd79137SRobert Mustacchi {
358*7fd79137SRobert Mustacchi 	int ret, flags, i;
359*7fd79137SRobert Mustacchi 	const ctf_type_t *tp;
360*7fd79137SRobert Mustacchi 	ctf_funcinfo_t ctc;
361*7fd79137SRobert Mustacchi 	ctf_id_t *argv;
362*7fd79137SRobert Mustacchi 
363*7fd79137SRobert Mustacchi 	tp = LCTF_INDEX_TO_TYPEPTR(cmp->cm_src, id);
364*7fd79137SRobert Mustacchi 	if (CTF_INFO_ISROOT(tp->ctt_info) != 0)
365*7fd79137SRobert Mustacchi 		flags = CTF_ADD_ROOT;
366*7fd79137SRobert Mustacchi 	else
367*7fd79137SRobert Mustacchi 		flags = CTF_ADD_NONROOT;
368*7fd79137SRobert Mustacchi 
369*7fd79137SRobert Mustacchi 	if (ctf_func_info_by_id(cmp->cm_src, id, &ctc) == CTF_ERR)
370*7fd79137SRobert Mustacchi 		return (ctf_set_errno(cmp->cm_out, ctf_errno(cmp->cm_src)));
371*7fd79137SRobert Mustacchi 
372*7fd79137SRobert Mustacchi 	argv = ctf_alloc(sizeof (ctf_id_t) * ctc.ctc_argc);
373*7fd79137SRobert Mustacchi 	if (argv == NULL)
374*7fd79137SRobert Mustacchi 		return (ctf_set_errno(cmp->cm_out, ENOMEM));
375*7fd79137SRobert Mustacchi 	if (ctf_func_args_by_id(cmp->cm_src, id, ctc.ctc_argc, argv) ==
376*7fd79137SRobert Mustacchi 	    CTF_ERR) {
377*7fd79137SRobert Mustacchi 		ctf_free(argv, sizeof (ctf_id_t) * ctc.ctc_argc);
378*7fd79137SRobert Mustacchi 		return (ctf_set_errno(cmp->cm_out, ctf_errno(cmp->cm_src)));
379*7fd79137SRobert Mustacchi 	}
380*7fd79137SRobert Mustacchi 
381*7fd79137SRobert Mustacchi 	if (cmp->cm_tmap[ctc.ctc_return].cmt_map == 0) {
382*7fd79137SRobert Mustacchi 		ret = ctf_merge_add_type(cmp, ctc.ctc_return);
383*7fd79137SRobert Mustacchi 		if (ret != 0)
384*7fd79137SRobert Mustacchi 			return (ret);
385*7fd79137SRobert Mustacchi 		ASSERT(cmp->cm_tmap[ctc.ctc_return].cmt_map != 0);
386*7fd79137SRobert Mustacchi 	}
387*7fd79137SRobert Mustacchi 	ctc.ctc_return = ctf_merge_gettype(cmp, ctc.ctc_return);
388*7fd79137SRobert Mustacchi 
389*7fd79137SRobert Mustacchi 	for (i = 0; i < ctc.ctc_argc; i++) {
390*7fd79137SRobert Mustacchi 		if (cmp->cm_tmap[argv[i]].cmt_map == 0) {
391*7fd79137SRobert Mustacchi 			ret = ctf_merge_add_type(cmp, argv[i]);
392*7fd79137SRobert Mustacchi 			if (ret != 0)
393*7fd79137SRobert Mustacchi 				return (ret);
394*7fd79137SRobert Mustacchi 			ASSERT(cmp->cm_tmap[argv[i]].cmt_map != 0);
395*7fd79137SRobert Mustacchi 		}
396*7fd79137SRobert Mustacchi 		argv[i] = ctf_merge_gettype(cmp, argv[i]);
397*7fd79137SRobert Mustacchi 	}
398*7fd79137SRobert Mustacchi 
399*7fd79137SRobert Mustacchi 	ret = ctf_add_funcptr(cmp->cm_out, flags, &ctc, argv);
400*7fd79137SRobert Mustacchi 	ctf_free(argv, sizeof (ctf_id_t) * ctc.ctc_argc);
401*7fd79137SRobert Mustacchi 	if (ret == CTF_ERR)
402*7fd79137SRobert Mustacchi 		return (ret);
403*7fd79137SRobert Mustacchi 
404*7fd79137SRobert Mustacchi 	VERIFY(cmp->cm_tmap[id].cmt_map == 0);
405*7fd79137SRobert Mustacchi 	cmp->cm_tmap[id].cmt_map = ret;
406*7fd79137SRobert Mustacchi 	return (0);
407*7fd79137SRobert Mustacchi }
408*7fd79137SRobert Mustacchi 
409*7fd79137SRobert Mustacchi static int
410*7fd79137SRobert Mustacchi ctf_merge_add_forward(ctf_merge_types_t *cmp, ctf_id_t id)
411*7fd79137SRobert Mustacchi {
412*7fd79137SRobert Mustacchi 	int ret, flags;
413*7fd79137SRobert Mustacchi 	const ctf_type_t *tp;
414*7fd79137SRobert Mustacchi 	const char *name;
415*7fd79137SRobert Mustacchi 
416*7fd79137SRobert Mustacchi 	tp = LCTF_INDEX_TO_TYPEPTR(cmp->cm_src, id);
417*7fd79137SRobert Mustacchi 	name = ctf_strraw(cmp->cm_src, tp->ctt_name);
418*7fd79137SRobert Mustacchi 	if (CTF_INFO_ISROOT(tp->ctt_info) != 0)
419*7fd79137SRobert Mustacchi 		flags = CTF_ADD_ROOT;
420*7fd79137SRobert Mustacchi 	else
421*7fd79137SRobert Mustacchi 		flags = CTF_ADD_NONROOT;
422*7fd79137SRobert Mustacchi 
423*7fd79137SRobert Mustacchi 	/*
424*7fd79137SRobert Mustacchi 	 * ctf_add_forward tries to check to see if a given forward already
425*7fd79137SRobert Mustacchi 	 * exists in one of its hash tables.  If we're here then we know that we
426*7fd79137SRobert Mustacchi 	 * have a forward in a container that isn't present in another.
427*7fd79137SRobert Mustacchi 	 * Therefore, we choose a token hash table to satisfy the API choice
428*7fd79137SRobert Mustacchi 	 * here.
429*7fd79137SRobert Mustacchi 	 */
430*7fd79137SRobert Mustacchi 	ret = ctf_add_forward(cmp->cm_out, flags, name, CTF_K_STRUCT);
431*7fd79137SRobert Mustacchi 	if (ret == CTF_ERR)
432*7fd79137SRobert Mustacchi 		return (CTF_ERR);
433*7fd79137SRobert Mustacchi 
434*7fd79137SRobert Mustacchi 	VERIFY(cmp->cm_tmap[id].cmt_map == 0);
435*7fd79137SRobert Mustacchi 	cmp->cm_tmap[id].cmt_map = ret;
436*7fd79137SRobert Mustacchi 	return (0);
437*7fd79137SRobert Mustacchi }
438*7fd79137SRobert Mustacchi 
439*7fd79137SRobert Mustacchi typedef struct ctf_merge_su {
440*7fd79137SRobert Mustacchi 	ctf_merge_types_t *cms_cm;
441*7fd79137SRobert Mustacchi 	ctf_id_t cms_id;
442*7fd79137SRobert Mustacchi } ctf_merge_su_t;
443*7fd79137SRobert Mustacchi 
444*7fd79137SRobert Mustacchi static int
445*7fd79137SRobert Mustacchi ctf_merge_add_member(const char *name, ctf_id_t type, ulong_t offset, void *arg)
446*7fd79137SRobert Mustacchi {
447*7fd79137SRobert Mustacchi 	ctf_merge_su_t *cms = arg;
448*7fd79137SRobert Mustacchi 
449*7fd79137SRobert Mustacchi 	VERIFY(cms->cms_cm->cm_tmap[type].cmt_map != 0);
450*7fd79137SRobert Mustacchi 	type = cms->cms_cm->cm_tmap[type].cmt_map;
451*7fd79137SRobert Mustacchi 
452*7fd79137SRobert Mustacchi 	ctf_dprintf("Trying to add member %s to %d\n", name, cms->cms_id);
453*7fd79137SRobert Mustacchi 	return (ctf_add_member(cms->cms_cm->cm_out, cms->cms_id, name,
454*7fd79137SRobert Mustacchi 	    type, offset) == CTF_ERR);
455*7fd79137SRobert Mustacchi }
456*7fd79137SRobert Mustacchi 
457*7fd79137SRobert Mustacchi /*
458*7fd79137SRobert Mustacchi  * During the first pass, we always add the generic structure and union but none
459*7fd79137SRobert Mustacchi  * of its members as they might not all have been mapped yet. Instead we just
460*7fd79137SRobert Mustacchi  * mark all structures and unions as needing to be fixed up.
461*7fd79137SRobert Mustacchi  */
462*7fd79137SRobert Mustacchi static int
463*7fd79137SRobert Mustacchi ctf_merge_add_sou(ctf_merge_types_t *cmp, ctf_id_t id, boolean_t forward)
464*7fd79137SRobert Mustacchi {
465*7fd79137SRobert Mustacchi 	int flags, kind;
466*7fd79137SRobert Mustacchi 	const ctf_type_t *tp;
467*7fd79137SRobert Mustacchi 	const char *name;
468*7fd79137SRobert Mustacchi 	ctf_id_t suid;
469*7fd79137SRobert Mustacchi 
470*7fd79137SRobert Mustacchi 	tp = LCTF_INDEX_TO_TYPEPTR(cmp->cm_src, id);
471*7fd79137SRobert Mustacchi 	name = ctf_strraw(cmp->cm_src, tp->ctt_name);
472*7fd79137SRobert Mustacchi 	if (CTF_INFO_ISROOT(tp->ctt_info) != 0)
473*7fd79137SRobert Mustacchi 		flags = CTF_ADD_ROOT;
474*7fd79137SRobert Mustacchi 	else
475*7fd79137SRobert Mustacchi 		flags = CTF_ADD_NONROOT;
476*7fd79137SRobert Mustacchi 	kind = ctf_type_kind(cmp->cm_src, id);
477*7fd79137SRobert Mustacchi 
478*7fd79137SRobert Mustacchi 	if (kind == CTF_K_STRUCT)
479*7fd79137SRobert Mustacchi 		suid = ctf_add_struct(cmp->cm_out, flags, name);
480*7fd79137SRobert Mustacchi 	else
481*7fd79137SRobert Mustacchi 		suid = ctf_add_union(cmp->cm_out, flags, name);
482*7fd79137SRobert Mustacchi 
483*7fd79137SRobert Mustacchi 	if (suid == CTF_ERR)
484*7fd79137SRobert Mustacchi 		return (suid);
485*7fd79137SRobert Mustacchi 
486*7fd79137SRobert Mustacchi 	/*
487*7fd79137SRobert Mustacchi 	 * If this is a forward reference then its mapping should already
488*7fd79137SRobert Mustacchi 	 * exist.
489*7fd79137SRobert Mustacchi 	 */
490*7fd79137SRobert Mustacchi 	if (forward == B_FALSE) {
491*7fd79137SRobert Mustacchi 		VERIFY(cmp->cm_tmap[id].cmt_map == 0);
492*7fd79137SRobert Mustacchi 		cmp->cm_tmap[id].cmt_map = suid;
493*7fd79137SRobert Mustacchi 		ctf_dprintf("added sou \"%s\" as (%d) %d->%d\n", name, kind, id,
494*7fd79137SRobert Mustacchi 		    suid);
495*7fd79137SRobert Mustacchi 	} else {
496*7fd79137SRobert Mustacchi 		VERIFY(cmp->cm_tmap[id].cmt_map == suid);
497*7fd79137SRobert Mustacchi 	}
498*7fd79137SRobert Mustacchi 	cmp->cm_tmap[id].cmt_fixup = B_TRUE;
499*7fd79137SRobert Mustacchi 
500*7fd79137SRobert Mustacchi 	return (0);
501*7fd79137SRobert Mustacchi }
502*7fd79137SRobert Mustacchi 
503*7fd79137SRobert Mustacchi static int
504*7fd79137SRobert Mustacchi ctf_merge_add_type(ctf_merge_types_t *cmp, ctf_id_t id)
505*7fd79137SRobert Mustacchi {
506*7fd79137SRobert Mustacchi 	int kind, ret;
507*7fd79137SRobert Mustacchi 
508*7fd79137SRobert Mustacchi 	/*
509*7fd79137SRobert Mustacchi 	 * We may end up evaluating a type more than once as we may deal with it
510*7fd79137SRobert Mustacchi 	 * as we recursively evaluate some kind of reference and then we may see
511*7fd79137SRobert Mustacchi 	 * it normally.
512*7fd79137SRobert Mustacchi 	 */
513*7fd79137SRobert Mustacchi 	if (cmp->cm_tmap[id].cmt_map != 0)
514*7fd79137SRobert Mustacchi 		return (0);
515*7fd79137SRobert Mustacchi 
516*7fd79137SRobert Mustacchi 	kind = ctf_type_kind(cmp->cm_src, id);
517*7fd79137SRobert Mustacchi 	switch (kind) {
518*7fd79137SRobert Mustacchi 	case CTF_K_INTEGER:
519*7fd79137SRobert Mustacchi 	case CTF_K_FLOAT:
520*7fd79137SRobert Mustacchi 		ret = ctf_merge_add_number(cmp, id);
521*7fd79137SRobert Mustacchi 		break;
522*7fd79137SRobert Mustacchi 	case CTF_K_ARRAY:
523*7fd79137SRobert Mustacchi 		ret = ctf_merge_add_array(cmp, id);
524*7fd79137SRobert Mustacchi 		break;
525*7fd79137SRobert Mustacchi 	case CTF_K_POINTER:
526*7fd79137SRobert Mustacchi 	case CTF_K_VOLATILE:
527*7fd79137SRobert Mustacchi 	case CTF_K_CONST:
528*7fd79137SRobert Mustacchi 	case CTF_K_RESTRICT:
529*7fd79137SRobert Mustacchi 		ret = ctf_merge_add_reftype(cmp, id);
530*7fd79137SRobert Mustacchi 		break;
531*7fd79137SRobert Mustacchi 	case CTF_K_TYPEDEF:
532*7fd79137SRobert Mustacchi 		ret = ctf_merge_add_typedef(cmp, id);
533*7fd79137SRobert Mustacchi 		break;
534*7fd79137SRobert Mustacchi 	case CTF_K_ENUM:
535*7fd79137SRobert Mustacchi 		ret = ctf_merge_add_enum(cmp, id);
536*7fd79137SRobert Mustacchi 		break;
537*7fd79137SRobert Mustacchi 	case CTF_K_FUNCTION:
538*7fd79137SRobert Mustacchi 		ret = ctf_merge_add_func(cmp, id);
539*7fd79137SRobert Mustacchi 		break;
540*7fd79137SRobert Mustacchi 	case CTF_K_FORWARD:
541*7fd79137SRobert Mustacchi 		ret = ctf_merge_add_forward(cmp, id);
542*7fd79137SRobert Mustacchi 		break;
543*7fd79137SRobert Mustacchi 	case CTF_K_STRUCT:
544*7fd79137SRobert Mustacchi 	case CTF_K_UNION:
545*7fd79137SRobert Mustacchi 		ret = ctf_merge_add_sou(cmp, id, B_FALSE);
546*7fd79137SRobert Mustacchi 		break;
547*7fd79137SRobert Mustacchi 	case CTF_K_UNKNOWN:
548*7fd79137SRobert Mustacchi 		/*
549*7fd79137SRobert Mustacchi 		 * We don't add unknown types, and we later assert that nothing
550*7fd79137SRobert Mustacchi 		 * should reference them.
551*7fd79137SRobert Mustacchi 		 */
552*7fd79137SRobert Mustacchi 		return (0);
553*7fd79137SRobert Mustacchi 	default:
554*7fd79137SRobert Mustacchi 		abort();
555*7fd79137SRobert Mustacchi 	}
556*7fd79137SRobert Mustacchi 
557*7fd79137SRobert Mustacchi 	return (ret);
558*7fd79137SRobert Mustacchi }
559*7fd79137SRobert Mustacchi 
560*7fd79137SRobert Mustacchi static int
561*7fd79137SRobert Mustacchi ctf_merge_fixup_sou(ctf_merge_types_t *cmp, ctf_id_t id)
562*7fd79137SRobert Mustacchi {
563*7fd79137SRobert Mustacchi 	ctf_dtdef_t *dtd;
564*7fd79137SRobert Mustacchi 	ctf_merge_su_t cms;
565*7fd79137SRobert Mustacchi 	ctf_id_t mapid;
566*7fd79137SRobert Mustacchi 	ssize_t size;
567*7fd79137SRobert Mustacchi 
568*7fd79137SRobert Mustacchi 	mapid = cmp->cm_tmap[id].cmt_map;
569*7fd79137SRobert Mustacchi 	VERIFY(mapid != 0);
570*7fd79137SRobert Mustacchi 	dtd = ctf_dtd_lookup(cmp->cm_out, mapid);
571*7fd79137SRobert Mustacchi 	VERIFY(dtd != NULL);
572*7fd79137SRobert Mustacchi 
573*7fd79137SRobert Mustacchi 	ctf_dprintf("Trying to fix up sou %d\n", id);
574*7fd79137SRobert Mustacchi 	cms.cms_cm = cmp;
575*7fd79137SRobert Mustacchi 	cms.cms_id = mapid;
576*7fd79137SRobert Mustacchi 	if (ctf_member_iter(cmp->cm_src, id, ctf_merge_add_member, &cms) != 0)
577*7fd79137SRobert Mustacchi 		return (CTF_ERR);
578*7fd79137SRobert Mustacchi 
579*7fd79137SRobert Mustacchi 	if ((size = ctf_type_size(cmp->cm_src, id)) == CTF_ERR)
580*7fd79137SRobert Mustacchi 		return (CTF_ERR);
581*7fd79137SRobert Mustacchi 	if (ctf_set_size(cmp->cm_out, mapid, size) == CTF_ERR)
582*7fd79137SRobert Mustacchi 		return (CTF_ERR);
583*7fd79137SRobert Mustacchi 
584*7fd79137SRobert Mustacchi 	return (0);
585*7fd79137SRobert Mustacchi }
586*7fd79137SRobert Mustacchi 
587*7fd79137SRobert Mustacchi static int
588*7fd79137SRobert Mustacchi ctf_merge_fixup_type(ctf_merge_types_t *cmp, ctf_id_t id)
589*7fd79137SRobert Mustacchi {
590*7fd79137SRobert Mustacchi 	int kind, ret;
591*7fd79137SRobert Mustacchi 
592*7fd79137SRobert Mustacchi 	kind = ctf_type_kind(cmp->cm_src, id);
593*7fd79137SRobert Mustacchi 	switch (kind) {
594*7fd79137SRobert Mustacchi 	case CTF_K_STRUCT:
595*7fd79137SRobert Mustacchi 	case CTF_K_UNION:
596*7fd79137SRobert Mustacchi 		ret = ctf_merge_fixup_sou(cmp, id);
597*7fd79137SRobert Mustacchi 		break;
598*7fd79137SRobert Mustacchi 	default:
599*7fd79137SRobert Mustacchi 		VERIFY(0);
600*7fd79137SRobert Mustacchi 		ret = CTF_ERR;
601*7fd79137SRobert Mustacchi 	}
602*7fd79137SRobert Mustacchi 
603*7fd79137SRobert Mustacchi 	return (ret);
604*7fd79137SRobert Mustacchi }
605*7fd79137SRobert Mustacchi 
606*7fd79137SRobert Mustacchi /*
607*7fd79137SRobert Mustacchi  * Now that we've successfully merged everything, we're going to clean
608*7fd79137SRobert Mustacchi  * up the merge type table. Traditionally if we had just two different
609*7fd79137SRobert Mustacchi  * files that we were working between, the types would be fully
610*7fd79137SRobert Mustacchi  * resolved. However, because we were comparing with ourself every step
611*7fd79137SRobert Mustacchi  * of the way and not our reduced self, we need to go through and update
612*7fd79137SRobert Mustacchi  * every mapped entry to what it now points to in the deduped file.
613*7fd79137SRobert Mustacchi  */
614*7fd79137SRobert Mustacchi static void
615*7fd79137SRobert Mustacchi ctf_merge_fixup_dedup_map(ctf_merge_types_t *cmp)
616*7fd79137SRobert Mustacchi {
617*7fd79137SRobert Mustacchi 	int i;
618*7fd79137SRobert Mustacchi 
619*7fd79137SRobert Mustacchi 	for (i = 1; i < cmp->cm_src->ctf_typemax + 1; i++) {
620*7fd79137SRobert Mustacchi 		ctf_id_t tid;
621*7fd79137SRobert Mustacchi 
622*7fd79137SRobert Mustacchi 		/*
623*7fd79137SRobert Mustacchi 		 * Missing types always have their id updated to exactly what it
624*7fd79137SRobert Mustacchi 		 * should be.
625*7fd79137SRobert Mustacchi 		 */
626*7fd79137SRobert Mustacchi 		if (cmp->cm_tmap[i].cmt_missing == B_TRUE) {
627*7fd79137SRobert Mustacchi 			VERIFY(cmp->cm_tmap[i].cmt_map != 0);
628*7fd79137SRobert Mustacchi 			continue;
629*7fd79137SRobert Mustacchi 		}
630*7fd79137SRobert Mustacchi 
631*7fd79137SRobert Mustacchi 		tid = i;
632*7fd79137SRobert Mustacchi 		while (cmp->cm_tmap[tid].cmt_missing == B_FALSE) {
633*7fd79137SRobert Mustacchi 			VERIFY(cmp->cm_tmap[tid].cmt_map != 0);
634*7fd79137SRobert Mustacchi 			tid = cmp->cm_tmap[tid].cmt_map;
635*7fd79137SRobert Mustacchi 		}
636*7fd79137SRobert Mustacchi 		VERIFY(cmp->cm_tmap[tid].cmt_map != 0);
637*7fd79137SRobert Mustacchi 		cmp->cm_tmap[i].cmt_map = cmp->cm_tmap[tid].cmt_map;
638*7fd79137SRobert Mustacchi 	}
639*7fd79137SRobert Mustacchi }
640*7fd79137SRobert Mustacchi 
641*7fd79137SRobert Mustacchi 
642*7fd79137SRobert Mustacchi /*
643*7fd79137SRobert Mustacchi  * We're going to do three passes over the containers.
644*7fd79137SRobert Mustacchi  *
645*7fd79137SRobert Mustacchi  * Pass 1 checks for forward references in the output container that we know
646*7fd79137SRobert Mustacchi  * exist in the source container.
647*7fd79137SRobert Mustacchi  *
648*7fd79137SRobert Mustacchi  * Pass 2 adds all the missing types from the source container. As part of this
649*7fd79137SRobert Mustacchi  * we may be adding a type as a forward reference that doesn't exist yet.
650*7fd79137SRobert Mustacchi  * Any types that we encounter in this form, we need to add to a third pass.
651*7fd79137SRobert Mustacchi  *
652*7fd79137SRobert Mustacchi  * Pass 3 is the fixup pass. Here we go through and find all the types that were
653*7fd79137SRobert Mustacchi  * missing in the first.
654*7fd79137SRobert Mustacchi  *
655*7fd79137SRobert Mustacchi  * Importantly, we *must* call ctf_update between the second and third pass,
656*7fd79137SRobert Mustacchi  * otherwise several of the libctf functions will not properly find the data in
657*7fd79137SRobert Mustacchi  * the container. If we're doing a dedup we also fix up the type mapping.
658*7fd79137SRobert Mustacchi  */
659*7fd79137SRobert Mustacchi static int
660*7fd79137SRobert Mustacchi ctf_merge_common(ctf_merge_types_t *cmp)
661*7fd79137SRobert Mustacchi {
662*7fd79137SRobert Mustacchi 	int ret, i;
663*7fd79137SRobert Mustacchi 
664*7fd79137SRobert Mustacchi 	ctf_phase_dump(cmp->cm_src, "merge-common-src");
665*7fd79137SRobert Mustacchi 	ctf_phase_dump(cmp->cm_out, "merge-common-dest");
666*7fd79137SRobert Mustacchi 
667*7fd79137SRobert Mustacchi 	/* Pass 1 */
668*7fd79137SRobert Mustacchi 	for (i = 1; i <= cmp->cm_src->ctf_typemax; i++) {
669*7fd79137SRobert Mustacchi 		if (cmp->cm_tmap[i].cmt_forward == B_TRUE) {
670*7fd79137SRobert Mustacchi 			ret = ctf_merge_add_sou(cmp, i, B_TRUE);
671*7fd79137SRobert Mustacchi 			if (ret != 0) {
672*7fd79137SRobert Mustacchi 				return (ret);
673*7fd79137SRobert Mustacchi 			}
674*7fd79137SRobert Mustacchi 		}
675*7fd79137SRobert Mustacchi 	}
676*7fd79137SRobert Mustacchi 
677*7fd79137SRobert Mustacchi 	/* Pass 2 */
678*7fd79137SRobert Mustacchi 	for (i = 1; i <= cmp->cm_src->ctf_typemax; i++) {
679*7fd79137SRobert Mustacchi 		if (cmp->cm_tmap[i].cmt_missing == B_TRUE) {
680*7fd79137SRobert Mustacchi 			ret = ctf_merge_add_type(cmp, i);
681*7fd79137SRobert Mustacchi 			if (ret != 0) {
682*7fd79137SRobert Mustacchi 				ctf_dprintf("Failed to merge type %d\n", i);
683*7fd79137SRobert Mustacchi 				return (ret);
684*7fd79137SRobert Mustacchi 			}
685*7fd79137SRobert Mustacchi 		}
686*7fd79137SRobert Mustacchi 	}
687*7fd79137SRobert Mustacchi 
688*7fd79137SRobert Mustacchi 	ret = ctf_update(cmp->cm_out);
689*7fd79137SRobert Mustacchi 	if (ret != 0)
690*7fd79137SRobert Mustacchi 		return (ret);
691*7fd79137SRobert Mustacchi 
692*7fd79137SRobert Mustacchi 	if (cmp->cm_dedup == B_TRUE) {
693*7fd79137SRobert Mustacchi 		ctf_merge_fixup_dedup_map(cmp);
694*7fd79137SRobert Mustacchi 	}
695*7fd79137SRobert Mustacchi 
696*7fd79137SRobert Mustacchi 	ctf_dprintf("Beginning merge pass 3\n");
697*7fd79137SRobert Mustacchi 	/* Pass 3 */
698*7fd79137SRobert Mustacchi 	for (i = 1; i <= cmp->cm_src->ctf_typemax; i++) {
699*7fd79137SRobert Mustacchi 		if (cmp->cm_tmap[i].cmt_fixup == B_TRUE) {
700*7fd79137SRobert Mustacchi 			ret = ctf_merge_fixup_type(cmp, i);
701*7fd79137SRobert Mustacchi 			if (ret != 0)
702*7fd79137SRobert Mustacchi 				return (ret);
703*7fd79137SRobert Mustacchi 		}
704*7fd79137SRobert Mustacchi 	}
705*7fd79137SRobert Mustacchi 
706*7fd79137SRobert Mustacchi 	if (cmp->cm_dedup == B_TRUE) {
707*7fd79137SRobert Mustacchi 		ctf_merge_fixup_dedup_map(cmp);
708*7fd79137SRobert Mustacchi 	}
709*7fd79137SRobert Mustacchi 
710*7fd79137SRobert Mustacchi 	return (0);
711*7fd79137SRobert Mustacchi }
712*7fd79137SRobert Mustacchi 
713*7fd79137SRobert Mustacchi /*
714*7fd79137SRobert Mustacchi  * Uniquification is slightly different from a stock merge. For starters, we
715*7fd79137SRobert Mustacchi  * don't need to replace any forward references in the output. In this case
716*7fd79137SRobert Mustacchi  * though, the types that already exist are in a parent container to the empty
717*7fd79137SRobert Mustacchi  * output container.
718*7fd79137SRobert Mustacchi  */
719*7fd79137SRobert Mustacchi static int
720*7fd79137SRobert Mustacchi ctf_merge_uniquify_types(ctf_merge_types_t *cmp)
721*7fd79137SRobert Mustacchi {
722*7fd79137SRobert Mustacchi 	int i, ret;
723*7fd79137SRobert Mustacchi 
724*7fd79137SRobert Mustacchi 	for (i = 1; i <= cmp->cm_src->ctf_typemax; i++) {
725*7fd79137SRobert Mustacchi 		if (cmp->cm_tmap[i].cmt_missing == B_FALSE)
726*7fd79137SRobert Mustacchi 			continue;
727*7fd79137SRobert Mustacchi 		ret = ctf_merge_add_type(cmp, i);
728*7fd79137SRobert Mustacchi 		if (ret != 0)
729*7fd79137SRobert Mustacchi 			return (ret);
730*7fd79137SRobert Mustacchi 	}
731*7fd79137SRobert Mustacchi 
732*7fd79137SRobert Mustacchi 	ret = ctf_update(cmp->cm_out);
733*7fd79137SRobert Mustacchi 	if (ret != 0)
734*7fd79137SRobert Mustacchi 		return (ret);
735*7fd79137SRobert Mustacchi 
736*7fd79137SRobert Mustacchi 	for (i = 1; i <= cmp->cm_src->ctf_typemax; i++) {
737*7fd79137SRobert Mustacchi 		if (cmp->cm_tmap[i].cmt_fixup == B_FALSE)
738*7fd79137SRobert Mustacchi 			continue;
739*7fd79137SRobert Mustacchi 		ret = ctf_merge_fixup_type(cmp, i);
740*7fd79137SRobert Mustacchi 		if (ret != 0)
741*7fd79137SRobert Mustacchi 			return (ret);
742*7fd79137SRobert Mustacchi 	}
743*7fd79137SRobert Mustacchi 
744*7fd79137SRobert Mustacchi 	return (0);
745*7fd79137SRobert Mustacchi }
746*7fd79137SRobert Mustacchi 
747*7fd79137SRobert Mustacchi static int
748*7fd79137SRobert Mustacchi ctf_merge_types_init(ctf_merge_types_t *cmp)
749*7fd79137SRobert Mustacchi {
750*7fd79137SRobert Mustacchi 	cmp->cm_tmap = ctf_alloc(sizeof (ctf_merge_tinfo_t) *
751*7fd79137SRobert Mustacchi 	    (cmp->cm_src->ctf_typemax + 1));
752*7fd79137SRobert Mustacchi 	if (cmp->cm_tmap == NULL)
753*7fd79137SRobert Mustacchi 		return (ctf_set_errno(cmp->cm_out, ENOMEM));
754*7fd79137SRobert Mustacchi 	bzero(cmp->cm_tmap, sizeof (ctf_merge_tinfo_t) *
755*7fd79137SRobert Mustacchi 	    (cmp->cm_src->ctf_typemax + 1));
756*7fd79137SRobert Mustacchi 	return (0);
757*7fd79137SRobert Mustacchi }
758*7fd79137SRobert Mustacchi 
759*7fd79137SRobert Mustacchi static void
760*7fd79137SRobert Mustacchi ctf_merge_types_fini(ctf_merge_types_t *cmp)
761*7fd79137SRobert Mustacchi {
762*7fd79137SRobert Mustacchi 	ctf_free(cmp->cm_tmap, sizeof (ctf_merge_tinfo_t) *
763*7fd79137SRobert Mustacchi 	    (cmp->cm_src->ctf_typemax + 1));
764*7fd79137SRobert Mustacchi }
765*7fd79137SRobert Mustacchi 
766*7fd79137SRobert Mustacchi /*
767*7fd79137SRobert Mustacchi  * Merge the types contained inside of two input files. The second input file is
768*7fd79137SRobert Mustacchi  * always going to be the destination. We're guaranteed that it's always
769*7fd79137SRobert Mustacchi  * writeable.
770*7fd79137SRobert Mustacchi  */
771*7fd79137SRobert Mustacchi static int
772*7fd79137SRobert Mustacchi ctf_merge_types(void *arg, void *arg2, void **outp, void *unsued)
773*7fd79137SRobert Mustacchi {
774*7fd79137SRobert Mustacchi 	int ret;
775*7fd79137SRobert Mustacchi 	ctf_merge_types_t cm;
776*7fd79137SRobert Mustacchi 	ctf_diff_t *cdp;
777*7fd79137SRobert Mustacchi 	ctf_merge_objmap_t *cmo;
778*7fd79137SRobert Mustacchi 	ctf_merge_funcmap_t *cmf;
779*7fd79137SRobert Mustacchi 	ctf_merge_input_t *scmi = arg;
780*7fd79137SRobert Mustacchi 	ctf_merge_input_t *dcmi = arg2;
781*7fd79137SRobert Mustacchi 	ctf_file_t *out = dcmi->cmi_input;
782*7fd79137SRobert Mustacchi 	ctf_file_t *source = scmi->cmi_input;
783*7fd79137SRobert Mustacchi 
784*7fd79137SRobert Mustacchi 	ctf_dprintf("merging %p->%p\n", source, out);
785*7fd79137SRobert Mustacchi 
786*7fd79137SRobert Mustacchi 	if (!(out->ctf_flags & LCTF_RDWR))
787*7fd79137SRobert Mustacchi 		return (ctf_set_errno(out, ECTF_RDONLY));
788*7fd79137SRobert Mustacchi 
789*7fd79137SRobert Mustacchi 	if (ctf_getmodel(out) != ctf_getmodel(source))
790*7fd79137SRobert Mustacchi 		return (ctf_set_errno(out, ECTF_DMODEL));
791*7fd79137SRobert Mustacchi 
792*7fd79137SRobert Mustacchi 	if ((ret = ctf_diff_init(out, source, &cdp)) != 0)
793*7fd79137SRobert Mustacchi 		return (ret);
794*7fd79137SRobert Mustacchi 
795*7fd79137SRobert Mustacchi 	cm.cm_out = out;
796*7fd79137SRobert Mustacchi 	cm.cm_src = source;
797*7fd79137SRobert Mustacchi 	cm.cm_dedup = B_FALSE;
798*7fd79137SRobert Mustacchi 	cm.cm_unique = B_FALSE;
799*7fd79137SRobert Mustacchi 	ret = ctf_merge_types_init(&cm);
800*7fd79137SRobert Mustacchi 	if (ret != 0) {
801*7fd79137SRobert Mustacchi 		ctf_diff_fini(cdp);
802*7fd79137SRobert Mustacchi 		return (ctf_set_errno(out, ret));
803*7fd79137SRobert Mustacchi 	}
804*7fd79137SRobert Mustacchi 
805*7fd79137SRobert Mustacchi 	ret = ctf_diff_types(cdp, ctf_merge_diffcb, &cm);
806*7fd79137SRobert Mustacchi 	if (ret != 0)
807*7fd79137SRobert Mustacchi 		goto cleanup;
808*7fd79137SRobert Mustacchi 	ret = ctf_merge_common(&cm);
809*7fd79137SRobert Mustacchi 	ctf_dprintf("merge common returned with %d\n", ret);
810*7fd79137SRobert Mustacchi 	if (ret == 0) {
811*7fd79137SRobert Mustacchi 		ret = ctf_update(out);
812*7fd79137SRobert Mustacchi 		ctf_dprintf("update returned with %d\n", ret);
813*7fd79137SRobert Mustacchi 	} else {
814*7fd79137SRobert Mustacchi 		goto cleanup;
815*7fd79137SRobert Mustacchi 	}
816*7fd79137SRobert Mustacchi 
817*7fd79137SRobert Mustacchi 	/*
818*7fd79137SRobert Mustacchi 	 * Now we need to fix up the object and function maps.
819*7fd79137SRobert Mustacchi 	 */
820*7fd79137SRobert Mustacchi 	for (cmo = list_head(&scmi->cmi_omap); cmo != NULL;
821*7fd79137SRobert Mustacchi 	    cmo = list_next(&scmi->cmi_omap, cmo)) {
822*7fd79137SRobert Mustacchi 		if (cmo->cmo_tid == 0)
823*7fd79137SRobert Mustacchi 			continue;
824*7fd79137SRobert Mustacchi 		VERIFY(cm.cm_tmap[cmo->cmo_tid].cmt_map != 0);
825*7fd79137SRobert Mustacchi 		cmo->cmo_tid = cm.cm_tmap[cmo->cmo_tid].cmt_map;
826*7fd79137SRobert Mustacchi 	}
827*7fd79137SRobert Mustacchi 
828*7fd79137SRobert Mustacchi 	for (cmf = list_head(&scmi->cmi_fmap); cmf != NULL;
829*7fd79137SRobert Mustacchi 	    cmf = list_next(&scmi->cmi_fmap, cmf)) {
830*7fd79137SRobert Mustacchi 		int i;
831*7fd79137SRobert Mustacchi 
832*7fd79137SRobert Mustacchi 		VERIFY(cm.cm_tmap[cmf->cmf_rtid].cmt_map != 0);
833*7fd79137SRobert Mustacchi 		cmf->cmf_rtid = cm.cm_tmap[cmf->cmf_rtid].cmt_map;
834*7fd79137SRobert Mustacchi 		for (i = 0; i < cmf->cmf_argc; i++) {
835*7fd79137SRobert Mustacchi 			VERIFY(cm.cm_tmap[cmf->cmf_args[i]].cmt_map != 0);
836*7fd79137SRobert Mustacchi 			cmf->cmf_args[i] = cm.cm_tmap[cmf->cmf_args[i]].cmt_map;
837*7fd79137SRobert Mustacchi 		}
838*7fd79137SRobert Mustacchi 	}
839*7fd79137SRobert Mustacchi 
840*7fd79137SRobert Mustacchi 	/*
841*7fd79137SRobert Mustacchi 	 * Now that we've fixed things up, we need to give our function and
842*7fd79137SRobert Mustacchi 	 * object maps to the destination, such that it can continue to update
843*7fd79137SRobert Mustacchi 	 * them going forward.
844*7fd79137SRobert Mustacchi 	 */
845*7fd79137SRobert Mustacchi 	list_move_tail(&dcmi->cmi_fmap, &scmi->cmi_fmap);
846*7fd79137SRobert Mustacchi 	list_move_tail(&dcmi->cmi_omap, &scmi->cmi_omap);
847*7fd79137SRobert Mustacchi 
848*7fd79137SRobert Mustacchi cleanup:
849*7fd79137SRobert Mustacchi 	if (ret == 0)
850*7fd79137SRobert Mustacchi 		*outp = dcmi;
851*7fd79137SRobert Mustacchi 	ctf_merge_types_fini(&cm);
852*7fd79137SRobert Mustacchi 	ctf_diff_fini(cdp);
853*7fd79137SRobert Mustacchi 	if (ret != 0)
854*7fd79137SRobert Mustacchi 		return (ctf_errno(out));
855*7fd79137SRobert Mustacchi 	return (0);
856*7fd79137SRobert Mustacchi }
857*7fd79137SRobert Mustacchi 
858*7fd79137SRobert Mustacchi /*
859*7fd79137SRobert Mustacchi  * After performing a pass, we need to go through the object and function type
860*7fd79137SRobert Mustacchi  * maps and potentially fix them up based on the new maps that we haev.
861*7fd79137SRobert Mustacchi  */
862*7fd79137SRobert Mustacchi static void
863*7fd79137SRobert Mustacchi ctf_merge_fixup_nontypes(ctf_merge_types_t *cmp, ctf_merge_input_t *cmi)
864*7fd79137SRobert Mustacchi {
865*7fd79137SRobert Mustacchi 	ctf_merge_objmap_t *cmo;
866*7fd79137SRobert Mustacchi 	ctf_merge_funcmap_t *cmf;
867*7fd79137SRobert Mustacchi 
868*7fd79137SRobert Mustacchi 	for (cmo = list_head(&cmi->cmi_omap); cmo != NULL;
869*7fd79137SRobert Mustacchi 	    cmo = list_next(&cmi->cmi_omap, cmo)) {
870*7fd79137SRobert Mustacchi 		if (cmo->cmo_tid == 0)
871*7fd79137SRobert Mustacchi 			continue;
872*7fd79137SRobert Mustacchi 		VERIFY(cmp->cm_tmap[cmo->cmo_tid].cmt_map != 0);
873*7fd79137SRobert Mustacchi 		cmo->cmo_tid = cmp->cm_tmap[cmo->cmo_tid].cmt_map;
874*7fd79137SRobert Mustacchi 	}
875*7fd79137SRobert Mustacchi 
876*7fd79137SRobert Mustacchi 	for (cmf = list_head(&cmi->cmi_fmap); cmf != NULL;
877*7fd79137SRobert Mustacchi 	    cmf = list_next(&cmi->cmi_fmap, cmf)) {
878*7fd79137SRobert Mustacchi 		int i;
879*7fd79137SRobert Mustacchi 
880*7fd79137SRobert Mustacchi 		VERIFY(cmp->cm_tmap[cmf->cmf_rtid].cmt_map != 0);
881*7fd79137SRobert Mustacchi 		cmf->cmf_rtid = cmp->cm_tmap[cmf->cmf_rtid].cmt_map;
882*7fd79137SRobert Mustacchi 		for (i = 0; i < cmf->cmf_argc; i++) {
883*7fd79137SRobert Mustacchi 			VERIFY(cmp->cm_tmap[cmf->cmf_args[i]].cmt_map !=
884*7fd79137SRobert Mustacchi 			    0);
885*7fd79137SRobert Mustacchi 			cmf->cmf_args[i] =
886*7fd79137SRobert Mustacchi 			    cmp->cm_tmap[cmf->cmf_args[i]].cmt_map;
887*7fd79137SRobert Mustacchi 		}
888*7fd79137SRobert Mustacchi 	}
889*7fd79137SRobert Mustacchi }
890*7fd79137SRobert Mustacchi 
891*7fd79137SRobert Mustacchi static int
892*7fd79137SRobert Mustacchi ctf_uniquify_types(ctf_merge_t *cmh, ctf_file_t *src, ctf_file_t **outp)
893*7fd79137SRobert Mustacchi {
894*7fd79137SRobert Mustacchi 	int err, ret;
895*7fd79137SRobert Mustacchi 	ctf_file_t *out;
896*7fd79137SRobert Mustacchi 	ctf_merge_types_t cm;
897*7fd79137SRobert Mustacchi 	ctf_diff_t *cdp;
898*7fd79137SRobert Mustacchi 	ctf_merge_input_t *cmi;
899*7fd79137SRobert Mustacchi 	ctf_file_t *parent = cmh->cmh_unique;
900*7fd79137SRobert Mustacchi 
901*7fd79137SRobert Mustacchi 	*outp = NULL;
902*7fd79137SRobert Mustacchi 	out = ctf_fdcreate(cmh->cmh_ofd, &err);
903*7fd79137SRobert Mustacchi 	if (out == NULL)
904*7fd79137SRobert Mustacchi 		return (ctf_set_errno(src, err));
905*7fd79137SRobert Mustacchi 
906*7fd79137SRobert Mustacchi 	out->ctf_parname = cmh->cmh_pname;
907*7fd79137SRobert Mustacchi 	if (ctf_setmodel(out, ctf_getmodel(parent)) != 0) {
908*7fd79137SRobert Mustacchi 		(void) ctf_set_errno(src, ctf_errno(out));
909*7fd79137SRobert Mustacchi 		ctf_close(out);
910*7fd79137SRobert Mustacchi 		return (CTF_ERR);
911*7fd79137SRobert Mustacchi 	}
912*7fd79137SRobert Mustacchi 
913*7fd79137SRobert Mustacchi 	if (ctf_import(out, parent) != 0) {
914*7fd79137SRobert Mustacchi 		(void) ctf_set_errno(src, ctf_errno(out));
915*7fd79137SRobert Mustacchi 		ctf_close(out);
916*7fd79137SRobert Mustacchi 		return (CTF_ERR);
917*7fd79137SRobert Mustacchi 	}
918*7fd79137SRobert Mustacchi 
919*7fd79137SRobert Mustacchi 	if ((ret = ctf_diff_init(parent, src, &cdp)) != 0) {
920*7fd79137SRobert Mustacchi 		ctf_close(out);
921*7fd79137SRobert Mustacchi 		return (ctf_set_errno(src, ctf_errno(parent)));
922*7fd79137SRobert Mustacchi 	}
923*7fd79137SRobert Mustacchi 
924*7fd79137SRobert Mustacchi 	cm.cm_out = parent;
925*7fd79137SRobert Mustacchi 	cm.cm_src = src;
926*7fd79137SRobert Mustacchi 	cm.cm_dedup = B_FALSE;
927*7fd79137SRobert Mustacchi 	cm.cm_unique = B_TRUE;
928*7fd79137SRobert Mustacchi 	ret = ctf_merge_types_init(&cm);
929*7fd79137SRobert Mustacchi 	if (ret != 0) {
930*7fd79137SRobert Mustacchi 		ctf_close(out);
931*7fd79137SRobert Mustacchi 		ctf_diff_fini(cdp);
932*7fd79137SRobert Mustacchi 		return (ctf_set_errno(src, ret));
933*7fd79137SRobert Mustacchi 	}
934*7fd79137SRobert Mustacchi 
935*7fd79137SRobert Mustacchi 	ret = ctf_diff_types(cdp, ctf_merge_diffcb, &cm);
936*7fd79137SRobert Mustacchi 	if (ret == 0) {
937*7fd79137SRobert Mustacchi 		cm.cm_out = out;
938*7fd79137SRobert Mustacchi 		ret = ctf_merge_uniquify_types(&cm);
939*7fd79137SRobert Mustacchi 		if (ret == 0)
940*7fd79137SRobert Mustacchi 			ret = ctf_update(out);
941*7fd79137SRobert Mustacchi 	}
942*7fd79137SRobert Mustacchi 
943*7fd79137SRobert Mustacchi 	if (ret != 0) {
944*7fd79137SRobert Mustacchi 		ctf_merge_types_fini(&cm);
945*7fd79137SRobert Mustacchi 		ctf_diff_fini(cdp);
946*7fd79137SRobert Mustacchi 		return (ctf_set_errno(src, ctf_errno(cm.cm_out)));
947*7fd79137SRobert Mustacchi 	}
948*7fd79137SRobert Mustacchi 
949*7fd79137SRobert Mustacchi 	for (cmi = list_head(&cmh->cmh_inputs); cmi != NULL;
950*7fd79137SRobert Mustacchi 	    cmi = list_next(&cmh->cmh_inputs, cmi)) {
951*7fd79137SRobert Mustacchi 		ctf_merge_fixup_nontypes(&cm, cmi);
952*7fd79137SRobert Mustacchi 	}
953*7fd79137SRobert Mustacchi 
954*7fd79137SRobert Mustacchi 	ctf_merge_types_fini(&cm);
955*7fd79137SRobert Mustacchi 	ctf_diff_fini(cdp);
956*7fd79137SRobert Mustacchi 	*outp = out;
957*7fd79137SRobert Mustacchi 	return (0);
958*7fd79137SRobert Mustacchi }
959*7fd79137SRobert Mustacchi 
960*7fd79137SRobert Mustacchi static void
961*7fd79137SRobert Mustacchi ctf_merge_fini_input(ctf_merge_input_t *cmi)
962*7fd79137SRobert Mustacchi {
963*7fd79137SRobert Mustacchi 	ctf_merge_objmap_t *cmo;
964*7fd79137SRobert Mustacchi 	ctf_merge_funcmap_t *cmf;
965*7fd79137SRobert Mustacchi 
966*7fd79137SRobert Mustacchi 	while ((cmo = list_remove_head(&cmi->cmi_omap)) != NULL)
967*7fd79137SRobert Mustacchi 		ctf_free(cmo, sizeof (ctf_merge_objmap_t));
968*7fd79137SRobert Mustacchi 
969*7fd79137SRobert Mustacchi 	while ((cmf = list_remove_head(&cmi->cmi_fmap)) != NULL)
970*7fd79137SRobert Mustacchi 		ctf_free(cmf, sizeof (ctf_merge_funcmap_t) +
971*7fd79137SRobert Mustacchi 		    sizeof (ctf_id_t) * cmf->cmf_argc);
972*7fd79137SRobert Mustacchi 
973*7fd79137SRobert Mustacchi 	if (cmi->cmi_created == B_TRUE && cmi->cmi_input != NULL)
974*7fd79137SRobert Mustacchi 		ctf_close(cmi->cmi_input);
975*7fd79137SRobert Mustacchi 
976*7fd79137SRobert Mustacchi 	ctf_free(cmi, sizeof (ctf_merge_input_t));
977*7fd79137SRobert Mustacchi }
978*7fd79137SRobert Mustacchi 
979*7fd79137SRobert Mustacchi void
980*7fd79137SRobert Mustacchi ctf_merge_fini(ctf_merge_t *cmh)
981*7fd79137SRobert Mustacchi {
982*7fd79137SRobert Mustacchi 	size_t len;
983*7fd79137SRobert Mustacchi 	ctf_merge_input_t *cmi;
984*7fd79137SRobert Mustacchi 
985*7fd79137SRobert Mustacchi 	if (cmh->cmh_label != NULL) {
986*7fd79137SRobert Mustacchi 		len = strlen(cmh->cmh_label) + 1;
987*7fd79137SRobert Mustacchi 		ctf_free(cmh->cmh_label, len);
988*7fd79137SRobert Mustacchi 	}
989*7fd79137SRobert Mustacchi 
990*7fd79137SRobert Mustacchi 	if (cmh->cmh_pname != NULL) {
991*7fd79137SRobert Mustacchi 		len = strlen(cmh->cmh_pname) + 1;
992*7fd79137SRobert Mustacchi 		ctf_free(cmh->cmh_pname, len);
993*7fd79137SRobert Mustacchi 	}
994*7fd79137SRobert Mustacchi 
995*7fd79137SRobert Mustacchi 	while ((cmi = list_remove_head(&cmh->cmh_inputs)) != NULL)
996*7fd79137SRobert Mustacchi 		ctf_merge_fini_input(cmi);
997*7fd79137SRobert Mustacchi 
998*7fd79137SRobert Mustacchi 	ctf_free(cmh, sizeof (ctf_merge_t));
999*7fd79137SRobert Mustacchi }
1000*7fd79137SRobert Mustacchi 
1001*7fd79137SRobert Mustacchi ctf_merge_t *
1002*7fd79137SRobert Mustacchi ctf_merge_init(int fd, int *errp)
1003*7fd79137SRobert Mustacchi {
1004*7fd79137SRobert Mustacchi 	int err;
1005*7fd79137SRobert Mustacchi 	ctf_merge_t *out;
1006*7fd79137SRobert Mustacchi 	struct stat st;
1007*7fd79137SRobert Mustacchi 
1008*7fd79137SRobert Mustacchi 	if (errp == NULL)
1009*7fd79137SRobert Mustacchi 		errp = &err;
1010*7fd79137SRobert Mustacchi 
1011*7fd79137SRobert Mustacchi 	if (fd != -1 && fstat(fd, &st) != 0) {
1012*7fd79137SRobert Mustacchi 		*errp = EINVAL;
1013*7fd79137SRobert Mustacchi 		return (NULL);
1014*7fd79137SRobert Mustacchi 	}
1015*7fd79137SRobert Mustacchi 
1016*7fd79137SRobert Mustacchi 	out = ctf_alloc(sizeof (ctf_merge_t));
1017*7fd79137SRobert Mustacchi 	if (out == NULL) {
1018*7fd79137SRobert Mustacchi 		*errp = ENOMEM;
1019*7fd79137SRobert Mustacchi 		return (NULL);
1020*7fd79137SRobert Mustacchi 	}
1021*7fd79137SRobert Mustacchi 
1022*7fd79137SRobert Mustacchi 	if (fd == -1) {
1023*7fd79137SRobert Mustacchi 		out->cmh_msyms = B_FALSE;
1024*7fd79137SRobert Mustacchi 	} else {
1025*7fd79137SRobert Mustacchi 		out->cmh_msyms = B_TRUE;
1026*7fd79137SRobert Mustacchi 	}
1027*7fd79137SRobert Mustacchi 
1028*7fd79137SRobert Mustacchi 	list_create(&out->cmh_inputs, sizeof (ctf_merge_input_t),
1029*7fd79137SRobert Mustacchi 	    offsetof(ctf_merge_input_t, cmi_node));
1030*7fd79137SRobert Mustacchi 	out->cmh_ninputs = 0;
1031*7fd79137SRobert Mustacchi 	out->cmh_nthreads = 1;
1032*7fd79137SRobert Mustacchi 	out->cmh_unique = NULL;
1033*7fd79137SRobert Mustacchi 	out->cmh_ofd = fd;
1034*7fd79137SRobert Mustacchi 	out->cmh_flags = 0;
1035*7fd79137SRobert Mustacchi 	out->cmh_label = NULL;
1036*7fd79137SRobert Mustacchi 	out->cmh_pname = NULL;
1037*7fd79137SRobert Mustacchi 
1038*7fd79137SRobert Mustacchi 	return (out);
1039*7fd79137SRobert Mustacchi }
1040*7fd79137SRobert Mustacchi 
1041*7fd79137SRobert Mustacchi int
1042*7fd79137SRobert Mustacchi ctf_merge_label(ctf_merge_t *cmh, const char *label)
1043*7fd79137SRobert Mustacchi {
1044*7fd79137SRobert Mustacchi 	char *dup;
1045*7fd79137SRobert Mustacchi 
1046*7fd79137SRobert Mustacchi 	if (label == NULL)
1047*7fd79137SRobert Mustacchi 		return (EINVAL);
1048*7fd79137SRobert Mustacchi 
1049*7fd79137SRobert Mustacchi 	dup = ctf_strdup(label);
1050*7fd79137SRobert Mustacchi 	if (dup == NULL)
1051*7fd79137SRobert Mustacchi 		return (EAGAIN);
1052*7fd79137SRobert Mustacchi 
1053*7fd79137SRobert Mustacchi 	if (cmh->cmh_label != NULL) {
1054*7fd79137SRobert Mustacchi 		size_t len = strlen(cmh->cmh_label) + 1;
1055*7fd79137SRobert Mustacchi 		ctf_free(cmh->cmh_label, len);
1056*7fd79137SRobert Mustacchi 	}
1057*7fd79137SRobert Mustacchi 
1058*7fd79137SRobert Mustacchi 	cmh->cmh_label = dup;
1059*7fd79137SRobert Mustacchi 	return (0);
1060*7fd79137SRobert Mustacchi }
1061*7fd79137SRobert Mustacchi 
1062*7fd79137SRobert Mustacchi static int
1063*7fd79137SRobert Mustacchi ctf_merge_add_funcs_cb(const char *name, ulong_t idx, ctf_funcinfo_t *fip,
1064*7fd79137SRobert Mustacchi     void *arg)
1065*7fd79137SRobert Mustacchi {
1066*7fd79137SRobert Mustacchi 	ctf_merge_input_t *cmi = arg;
1067*7fd79137SRobert Mustacchi 	ctf_merge_funcmap_t *fmap;
1068*7fd79137SRobert Mustacchi 
1069*7fd79137SRobert Mustacchi 	fmap = ctf_alloc(sizeof (ctf_merge_funcmap_t) +
1070*7fd79137SRobert Mustacchi 	    sizeof (ctf_id_t) * fip->ctc_argc);
1071*7fd79137SRobert Mustacchi 	if (fmap == NULL)
1072*7fd79137SRobert Mustacchi 		return (ENOMEM);
1073*7fd79137SRobert Mustacchi 
1074*7fd79137SRobert Mustacchi 	fmap->cmf_idx = idx;
1075*7fd79137SRobert Mustacchi 	fmap->cmf_rtid = fip->ctc_return;
1076*7fd79137SRobert Mustacchi 	fmap->cmf_flags = fip->ctc_flags;
1077*7fd79137SRobert Mustacchi 	fmap->cmf_argc = fip->ctc_argc;
1078*7fd79137SRobert Mustacchi 	fmap->cmf_name = name;
1079*7fd79137SRobert Mustacchi 
1080*7fd79137SRobert Mustacchi 	if (ctf_func_args(cmi->cmi_input, idx, fmap->cmf_argc,
1081*7fd79137SRobert Mustacchi 	    fmap->cmf_args) != 0) {
1082*7fd79137SRobert Mustacchi 		ctf_free(fmap, sizeof (ctf_merge_funcmap_t) +
1083*7fd79137SRobert Mustacchi 		    sizeof (ctf_id_t) * fip->ctc_argc);
1084*7fd79137SRobert Mustacchi 		return (ctf_errno(cmi->cmi_input));
1085*7fd79137SRobert Mustacchi 	}
1086*7fd79137SRobert Mustacchi 
1087*7fd79137SRobert Mustacchi 	list_insert_tail(&cmi->cmi_fmap, fmap);
1088*7fd79137SRobert Mustacchi 	return (0);
1089*7fd79137SRobert Mustacchi }
1090*7fd79137SRobert Mustacchi 
1091*7fd79137SRobert Mustacchi static int
1092*7fd79137SRobert Mustacchi ctf_merge_add_objs_cb(const char *name, ctf_id_t id, ulong_t idx, void *arg)
1093*7fd79137SRobert Mustacchi {
1094*7fd79137SRobert Mustacchi 	ctf_merge_input_t *cmi = arg;
1095*7fd79137SRobert Mustacchi 	ctf_merge_objmap_t *cmo;
1096*7fd79137SRobert Mustacchi 
1097*7fd79137SRobert Mustacchi 	cmo = ctf_alloc(sizeof (ctf_merge_objmap_t));
1098*7fd79137SRobert Mustacchi 	if (cmo == NULL)
1099*7fd79137SRobert Mustacchi 		return (ENOMEM);
1100*7fd79137SRobert Mustacchi 
1101*7fd79137SRobert Mustacchi 	cmo->cmo_name = name;
1102*7fd79137SRobert Mustacchi 	cmo->cmo_idx = idx;
1103*7fd79137SRobert Mustacchi 	cmo->cmo_tid = id;
1104*7fd79137SRobert Mustacchi 	list_insert_tail(&cmi->cmi_omap, cmo);
1105*7fd79137SRobert Mustacchi 	return (0);
1106*7fd79137SRobert Mustacchi }
1107*7fd79137SRobert Mustacchi 
1108*7fd79137SRobert Mustacchi /*
1109*7fd79137SRobert Mustacchi  * Whenever we create an entry to merge, we then go and add a second empty
1110*7fd79137SRobert Mustacchi  * ctf_file_t which we use for the purposes of our merging. It's not the best,
1111*7fd79137SRobert Mustacchi  * but it's the best that we've got at the moment.
1112*7fd79137SRobert Mustacchi  */
1113*7fd79137SRobert Mustacchi int
1114*7fd79137SRobert Mustacchi ctf_merge_add(ctf_merge_t *cmh, ctf_file_t *input)
1115*7fd79137SRobert Mustacchi {
1116*7fd79137SRobert Mustacchi 	int ret;
1117*7fd79137SRobert Mustacchi 	ctf_merge_input_t *cmi;
1118*7fd79137SRobert Mustacchi 	ctf_file_t *empty;
1119*7fd79137SRobert Mustacchi 
1120*7fd79137SRobert Mustacchi 	if (input->ctf_flags & LCTF_CHILD)
1121*7fd79137SRobert Mustacchi 		return (ECTF_MCHILD);
1122*7fd79137SRobert Mustacchi 
1123*7fd79137SRobert Mustacchi 	cmi = ctf_alloc(sizeof (ctf_merge_input_t));
1124*7fd79137SRobert Mustacchi 	if (cmi == NULL)
1125*7fd79137SRobert Mustacchi 		return (ENOMEM);
1126*7fd79137SRobert Mustacchi 
1127*7fd79137SRobert Mustacchi 	cmi->cmi_created = B_FALSE;
1128*7fd79137SRobert Mustacchi 	cmi->cmi_input = input;
1129*7fd79137SRobert Mustacchi 	list_create(&cmi->cmi_fmap, sizeof (ctf_merge_funcmap_t),
1130*7fd79137SRobert Mustacchi 	    offsetof(ctf_merge_funcmap_t, cmf_node));
1131*7fd79137SRobert Mustacchi 	list_create(&cmi->cmi_omap, sizeof (ctf_merge_funcmap_t),
1132*7fd79137SRobert Mustacchi 	    offsetof(ctf_merge_objmap_t, cmo_node));
1133*7fd79137SRobert Mustacchi 
1134*7fd79137SRobert Mustacchi 	if (cmh->cmh_msyms == B_TRUE) {
1135*7fd79137SRobert Mustacchi 		if ((ret = ctf_function_iter(input, ctf_merge_add_funcs_cb,
1136*7fd79137SRobert Mustacchi 		    cmi)) != 0) {
1137*7fd79137SRobert Mustacchi 			ctf_merge_fini_input(cmi);
1138*7fd79137SRobert Mustacchi 			return (ret);
1139*7fd79137SRobert Mustacchi 		}
1140*7fd79137SRobert Mustacchi 
1141*7fd79137SRobert Mustacchi 		if ((ret = ctf_object_iter(input, ctf_merge_add_objs_cb,
1142*7fd79137SRobert Mustacchi 		    cmi)) != 0) {
1143*7fd79137SRobert Mustacchi 			ctf_merge_fini_input(cmi);
1144*7fd79137SRobert Mustacchi 			return (ret);
1145*7fd79137SRobert Mustacchi 		}
1146*7fd79137SRobert Mustacchi 	}
1147*7fd79137SRobert Mustacchi 
1148*7fd79137SRobert Mustacchi 	list_insert_tail(&cmh->cmh_inputs, cmi);
1149*7fd79137SRobert Mustacchi 	cmh->cmh_ninputs++;
1150*7fd79137SRobert Mustacchi 
1151*7fd79137SRobert Mustacchi 	/* And now the empty one to merge into this */
1152*7fd79137SRobert Mustacchi 	cmi = ctf_alloc(sizeof (ctf_merge_input_t));
1153*7fd79137SRobert Mustacchi 	if (cmi == NULL)
1154*7fd79137SRobert Mustacchi 		return (ENOMEM);
1155*7fd79137SRobert Mustacchi 	list_create(&cmi->cmi_fmap, sizeof (ctf_merge_funcmap_t),
1156*7fd79137SRobert Mustacchi 	    offsetof(ctf_merge_funcmap_t, cmf_node));
1157*7fd79137SRobert Mustacchi 	list_create(&cmi->cmi_omap, sizeof (ctf_merge_funcmap_t),
1158*7fd79137SRobert Mustacchi 	    offsetof(ctf_merge_objmap_t, cmo_node));
1159*7fd79137SRobert Mustacchi 
1160*7fd79137SRobert Mustacchi 	empty = ctf_fdcreate(cmh->cmh_ofd, &ret);
1161*7fd79137SRobert Mustacchi 	if (empty == NULL)
1162*7fd79137SRobert Mustacchi 		return (ret);
1163*7fd79137SRobert Mustacchi 	cmi->cmi_input = empty;
1164*7fd79137SRobert Mustacchi 	cmi->cmi_created = B_TRUE;
1165*7fd79137SRobert Mustacchi 
1166*7fd79137SRobert Mustacchi 	if (ctf_setmodel(empty, ctf_getmodel(input)) == CTF_ERR) {
1167*7fd79137SRobert Mustacchi 		return (ctf_errno(empty));
1168*7fd79137SRobert Mustacchi 	}
1169*7fd79137SRobert Mustacchi 
1170*7fd79137SRobert Mustacchi 	list_insert_tail(&cmh->cmh_inputs, cmi);
1171*7fd79137SRobert Mustacchi 	cmh->cmh_ninputs++;
1172*7fd79137SRobert Mustacchi 	ctf_dprintf("added containers %p and %p\n", input, empty);
1173*7fd79137SRobert Mustacchi 	return (0);
1174*7fd79137SRobert Mustacchi }
1175*7fd79137SRobert Mustacchi 
1176*7fd79137SRobert Mustacchi int
1177*7fd79137SRobert Mustacchi ctf_merge_uniquify(ctf_merge_t *cmh, ctf_file_t *u, const char *pname)
1178*7fd79137SRobert Mustacchi {
1179*7fd79137SRobert Mustacchi 	char *dup;
1180*7fd79137SRobert Mustacchi 
1181*7fd79137SRobert Mustacchi 	if (u->ctf_flags & LCTF_CHILD)
1182*7fd79137SRobert Mustacchi 		return (ECTF_MCHILD);
1183*7fd79137SRobert Mustacchi 	if (pname == NULL)
1184*7fd79137SRobert Mustacchi 		return (EINVAL);
1185*7fd79137SRobert Mustacchi 	dup = ctf_strdup(pname);
1186*7fd79137SRobert Mustacchi 	if (dup == NULL)
1187*7fd79137SRobert Mustacchi 		return (EINVAL);
1188*7fd79137SRobert Mustacchi 	if (cmh->cmh_pname != NULL) {
1189*7fd79137SRobert Mustacchi 		size_t len = strlen(cmh->cmh_pname) + 1;
1190*7fd79137SRobert Mustacchi 		ctf_free(cmh->cmh_pname, len);
1191*7fd79137SRobert Mustacchi 	}
1192*7fd79137SRobert Mustacchi 	cmh->cmh_pname = dup;
1193*7fd79137SRobert Mustacchi 	cmh->cmh_unique = u;
1194*7fd79137SRobert Mustacchi 	return (0);
1195*7fd79137SRobert Mustacchi }
1196*7fd79137SRobert Mustacchi 
1197*7fd79137SRobert Mustacchi static int
1198*7fd79137SRobert Mustacchi ctf_merge_symbols(ctf_merge_t *cmh, ctf_file_t *fp)
1199*7fd79137SRobert Mustacchi {
1200*7fd79137SRobert Mustacchi 	int err;
1201*7fd79137SRobert Mustacchi 	ulong_t i;
1202*7fd79137SRobert Mustacchi 
1203*7fd79137SRobert Mustacchi 	uintptr_t symbase = (uintptr_t)fp->ctf_symtab.cts_data;
1204*7fd79137SRobert Mustacchi 	uintptr_t strbase = (uintptr_t)fp->ctf_strtab.cts_data;
1205*7fd79137SRobert Mustacchi 
1206*7fd79137SRobert Mustacchi 	for (i = 0; i < fp->ctf_nsyms; i++) {
1207*7fd79137SRobert Mustacchi 		const char *name;
1208*7fd79137SRobert Mustacchi 		ctf_merge_input_t *cmi;
1209*7fd79137SRobert Mustacchi 		ctf_merge_objmap_t *cmo;
1210*7fd79137SRobert Mustacchi 
1211*7fd79137SRobert Mustacchi 		if (fp->ctf_symtab.cts_entsize == sizeof (Elf32_Sym)) {
1212*7fd79137SRobert Mustacchi 			const Elf32_Sym *symp = (Elf32_Sym *)symbase + i;
1213*7fd79137SRobert Mustacchi 			int type = ELF32_ST_TYPE(symp->st_info);
1214*7fd79137SRobert Mustacchi 			if (type != STT_OBJECT)
1215*7fd79137SRobert Mustacchi 				continue;
1216*7fd79137SRobert Mustacchi 			if (ctf_sym_valid(strbase, type, symp->st_shndx,
1217*7fd79137SRobert Mustacchi 			    symp->st_value, symp->st_name) == B_FALSE)
1218*7fd79137SRobert Mustacchi 				continue;
1219*7fd79137SRobert Mustacchi 			name = (char *)(strbase + symp->st_name);
1220*7fd79137SRobert Mustacchi 		} else {
1221*7fd79137SRobert Mustacchi 			const Elf64_Sym *symp = (Elf64_Sym *)symbase + i;
1222*7fd79137SRobert Mustacchi 			int type = ELF64_ST_TYPE(symp->st_info);
1223*7fd79137SRobert Mustacchi 			if (type != STT_OBJECT)
1224*7fd79137SRobert Mustacchi 				continue;
1225*7fd79137SRobert Mustacchi 			if (ctf_sym_valid(strbase, type, symp->st_shndx,
1226*7fd79137SRobert Mustacchi 			    symp->st_value, symp->st_name) == B_FALSE)
1227*7fd79137SRobert Mustacchi 				continue;
1228*7fd79137SRobert Mustacchi 			name = (char *)(strbase + symp->st_name);
1229*7fd79137SRobert Mustacchi 		}
1230*7fd79137SRobert Mustacchi 
1231*7fd79137SRobert Mustacchi 		cmo = NULL;
1232*7fd79137SRobert Mustacchi 		for (cmi = list_head(&cmh->cmh_inputs); cmi != NULL;
1233*7fd79137SRobert Mustacchi 		    cmi = list_next(&cmh->cmh_inputs, cmi)) {
1234*7fd79137SRobert Mustacchi 			for (cmo = list_head(&cmi->cmi_omap); cmo != NULL;
1235*7fd79137SRobert Mustacchi 			    cmo = list_next(&cmi->cmi_omap, cmo)) {
1236*7fd79137SRobert Mustacchi 				if (strcmp(cmo->cmo_name, name) == 0)
1237*7fd79137SRobert Mustacchi 					goto found;
1238*7fd79137SRobert Mustacchi 			}
1239*7fd79137SRobert Mustacchi 		}
1240*7fd79137SRobert Mustacchi found:
1241*7fd79137SRobert Mustacchi 		if (cmo != NULL) {
1242*7fd79137SRobert Mustacchi 			if (cmo->cmo_tid == 0)
1243*7fd79137SRobert Mustacchi 				continue;
1244*7fd79137SRobert Mustacchi 			if ((err = ctf_add_object(fp, i, cmo->cmo_tid)) != 0) {
1245*7fd79137SRobert Mustacchi 				ctf_dprintf("Failed to add symbol %s->%d: %s\n",
1246*7fd79137SRobert Mustacchi 				    name, cmo->cmo_tid,
1247*7fd79137SRobert Mustacchi 				    ctf_errmsg(ctf_errno(fp)));
1248*7fd79137SRobert Mustacchi 				return (err);
1249*7fd79137SRobert Mustacchi 			}
1250*7fd79137SRobert Mustacchi 		}
1251*7fd79137SRobert Mustacchi 	}
1252*7fd79137SRobert Mustacchi 
1253*7fd79137SRobert Mustacchi 	return (0);
1254*7fd79137SRobert Mustacchi }
1255*7fd79137SRobert Mustacchi 
1256*7fd79137SRobert Mustacchi static int
1257*7fd79137SRobert Mustacchi ctf_merge_functions(ctf_merge_t *cmh, ctf_file_t *fp)
1258*7fd79137SRobert Mustacchi {
1259*7fd79137SRobert Mustacchi 	int err;
1260*7fd79137SRobert Mustacchi 	ulong_t i;
1261*7fd79137SRobert Mustacchi 	ctf_funcinfo_t fi;
1262*7fd79137SRobert Mustacchi 
1263*7fd79137SRobert Mustacchi 	uintptr_t symbase = (uintptr_t)fp->ctf_symtab.cts_data;
1264*7fd79137SRobert Mustacchi 	uintptr_t strbase = (uintptr_t)fp->ctf_strtab.cts_data;
1265*7fd79137SRobert Mustacchi 
1266*7fd79137SRobert Mustacchi 	for (i = 0; i < fp->ctf_nsyms; i++) {
1267*7fd79137SRobert Mustacchi 		const char *name;
1268*7fd79137SRobert Mustacchi 		ctf_merge_input_t *cmi;
1269*7fd79137SRobert Mustacchi 		ctf_merge_funcmap_t *cmf;
1270*7fd79137SRobert Mustacchi 
1271*7fd79137SRobert Mustacchi 		if (fp->ctf_symtab.cts_entsize == sizeof (Elf32_Sym)) {
1272*7fd79137SRobert Mustacchi 			const Elf32_Sym *symp = (Elf32_Sym *)symbase + i;
1273*7fd79137SRobert Mustacchi 			int type = ELF32_ST_TYPE(symp->st_info);
1274*7fd79137SRobert Mustacchi 			if (ELF32_ST_TYPE(symp->st_info) != STT_FUNC)
1275*7fd79137SRobert Mustacchi 				continue;
1276*7fd79137SRobert Mustacchi 			if (ctf_sym_valid(strbase, type, symp->st_shndx,
1277*7fd79137SRobert Mustacchi 			    symp->st_value, symp->st_name) == B_FALSE)
1278*7fd79137SRobert Mustacchi 				continue;
1279*7fd79137SRobert Mustacchi 			name = (char *)(strbase + symp->st_name);
1280*7fd79137SRobert Mustacchi 		} else {
1281*7fd79137SRobert Mustacchi 			const Elf64_Sym *symp = (Elf64_Sym *)symbase + i;
1282*7fd79137SRobert Mustacchi 			int type = ELF64_ST_TYPE(symp->st_info);
1283*7fd79137SRobert Mustacchi 			if (ELF64_ST_TYPE(symp->st_info) != STT_FUNC)
1284*7fd79137SRobert Mustacchi 				continue;
1285*7fd79137SRobert Mustacchi 			if (ctf_sym_valid(strbase, type, symp->st_shndx,
1286*7fd79137SRobert Mustacchi 			    symp->st_value, symp->st_name) == B_FALSE)
1287*7fd79137SRobert Mustacchi 				continue;
1288*7fd79137SRobert Mustacchi 			name = (char *)(strbase + symp->st_name);
1289*7fd79137SRobert Mustacchi 		}
1290*7fd79137SRobert Mustacchi 
1291*7fd79137SRobert Mustacchi 		cmf = NULL;
1292*7fd79137SRobert Mustacchi 		for (cmi = list_head(&cmh->cmh_inputs); cmi != NULL;
1293*7fd79137SRobert Mustacchi 		    cmi = list_next(&cmh->cmh_inputs, cmi)) {
1294*7fd79137SRobert Mustacchi 			for (cmf = list_head(&cmi->cmi_fmap); cmf != NULL;
1295*7fd79137SRobert Mustacchi 			    cmf = list_next(&cmi->cmi_fmap, cmf)) {
1296*7fd79137SRobert Mustacchi 				if (strcmp(cmf->cmf_name, name) == 0)
1297*7fd79137SRobert Mustacchi 					goto found;
1298*7fd79137SRobert Mustacchi 			}
1299*7fd79137SRobert Mustacchi 		}
1300*7fd79137SRobert Mustacchi found:
1301*7fd79137SRobert Mustacchi 		if (cmf != NULL) {
1302*7fd79137SRobert Mustacchi 			fi.ctc_return = cmf->cmf_rtid;
1303*7fd79137SRobert Mustacchi 			fi.ctc_argc = cmf->cmf_argc;
1304*7fd79137SRobert Mustacchi 			fi.ctc_flags = cmf->cmf_flags;
1305*7fd79137SRobert Mustacchi 			if ((err = ctf_add_function(fp, i, &fi,
1306*7fd79137SRobert Mustacchi 			    cmf->cmf_args)) != 0)
1307*7fd79137SRobert Mustacchi 				return (err);
1308*7fd79137SRobert Mustacchi 		}
1309*7fd79137SRobert Mustacchi 	}
1310*7fd79137SRobert Mustacchi 
1311*7fd79137SRobert Mustacchi 	return (0);
1312*7fd79137SRobert Mustacchi 
1313*7fd79137SRobert Mustacchi }
1314*7fd79137SRobert Mustacchi 
1315*7fd79137SRobert Mustacchi int
1316*7fd79137SRobert Mustacchi ctf_merge_merge(ctf_merge_t *cmh, ctf_file_t **outp)
1317*7fd79137SRobert Mustacchi {
1318*7fd79137SRobert Mustacchi 	int err, merr;
1319*7fd79137SRobert Mustacchi 	ctf_merge_input_t *cmi;
1320*7fd79137SRobert Mustacchi 	ctf_id_t ltype;
1321*7fd79137SRobert Mustacchi 	mergeq_t *mqp;
1322*7fd79137SRobert Mustacchi 	ctf_merge_input_t *final;
1323*7fd79137SRobert Mustacchi 	ctf_file_t *out;
1324*7fd79137SRobert Mustacchi 
1325*7fd79137SRobert Mustacchi 	if (cmh->cmh_label != NULL && cmh->cmh_unique != NULL) {
1326*7fd79137SRobert Mustacchi 		const char *label = ctf_label_topmost(cmh->cmh_unique);
1327*7fd79137SRobert Mustacchi 		if (label == NULL)
1328*7fd79137SRobert Mustacchi 			return (ECTF_NOLABEL);
1329*7fd79137SRobert Mustacchi 		if (strcmp(label, cmh->cmh_label) != 0)
1330*7fd79137SRobert Mustacchi 			return (ECTF_LCONFLICT);
1331*7fd79137SRobert Mustacchi 	}
1332*7fd79137SRobert Mustacchi 
1333*7fd79137SRobert Mustacchi 	if (mergeq_init(&mqp, cmh->cmh_nthreads) == -1) {
1334*7fd79137SRobert Mustacchi 		return (errno);
1335*7fd79137SRobert Mustacchi 	}
1336*7fd79137SRobert Mustacchi 
1337*7fd79137SRobert Mustacchi 	VERIFY(cmh->cmh_ninputs % 2 == 0);
1338*7fd79137SRobert Mustacchi 	for (cmi = list_head(&cmh->cmh_inputs); cmi != NULL;
1339*7fd79137SRobert Mustacchi 	    cmi = list_next(&cmh->cmh_inputs, cmi)) {
1340*7fd79137SRobert Mustacchi 		if (mergeq_add(mqp, cmi) == -1) {
1341*7fd79137SRobert Mustacchi 			err = errno;
1342*7fd79137SRobert Mustacchi 			mergeq_fini(mqp);
1343*7fd79137SRobert Mustacchi 		}
1344*7fd79137SRobert Mustacchi 	}
1345*7fd79137SRobert Mustacchi 
1346*7fd79137SRobert Mustacchi 	err = mergeq_merge(mqp, ctf_merge_types, NULL, (void **)&final, &merr);
1347*7fd79137SRobert Mustacchi 	mergeq_fini(mqp);
1348*7fd79137SRobert Mustacchi 
1349*7fd79137SRobert Mustacchi 	if (err == MERGEQ_ERROR) {
1350*7fd79137SRobert Mustacchi 		return (errno);
1351*7fd79137SRobert Mustacchi 	} else if (err == MERGEQ_UERROR) {
1352*7fd79137SRobert Mustacchi 		return (merr);
1353*7fd79137SRobert Mustacchi 	}
1354*7fd79137SRobert Mustacchi 
1355*7fd79137SRobert Mustacchi 	/*
1356*7fd79137SRobert Mustacchi 	 * Disassociate the generated ctf_file_t from the original input. That
1357*7fd79137SRobert Mustacchi 	 * way when the input gets cleaned up, we don't accidentally kill the
1358*7fd79137SRobert Mustacchi 	 * final reference to the ctf_file_t. If it gets uniquified then we'll
1359*7fd79137SRobert Mustacchi 	 * kill it.
1360*7fd79137SRobert Mustacchi 	 */
1361*7fd79137SRobert Mustacchi 	VERIFY(final->cmi_input != NULL);
1362*7fd79137SRobert Mustacchi 	out = final->cmi_input;
1363*7fd79137SRobert Mustacchi 	final->cmi_input = NULL;
1364*7fd79137SRobert Mustacchi 
1365*7fd79137SRobert Mustacchi 	ctf_dprintf("preparing to uniquify against: %p\n", cmh->cmh_unique);
1366*7fd79137SRobert Mustacchi 	if (cmh->cmh_unique != NULL) {
1367*7fd79137SRobert Mustacchi 		ctf_file_t *u;
1368*7fd79137SRobert Mustacchi 		err = ctf_uniquify_types(cmh, out, &u);
1369*7fd79137SRobert Mustacchi 		if (err != 0) {
1370*7fd79137SRobert Mustacchi 			err = ctf_errno(out);
1371*7fd79137SRobert Mustacchi 			ctf_close(out);
1372*7fd79137SRobert Mustacchi 			return (err);
1373*7fd79137SRobert Mustacchi 		}
1374*7fd79137SRobert Mustacchi 		ctf_close(out);
1375*7fd79137SRobert Mustacchi 		out = u;
1376*7fd79137SRobert Mustacchi 	}
1377*7fd79137SRobert Mustacchi 
1378*7fd79137SRobert Mustacchi 	ltype = out->ctf_typemax;
1379*7fd79137SRobert Mustacchi 	if ((out->ctf_flags & LCTF_CHILD) && ltype != 0)
1380*7fd79137SRobert Mustacchi 		ltype += CTF_CHILD_START;
1381*7fd79137SRobert Mustacchi 	ctf_dprintf("trying to add the label\n");
1382*7fd79137SRobert Mustacchi 	if (cmh->cmh_label != NULL &&
1383*7fd79137SRobert Mustacchi 	    ctf_add_label(out, cmh->cmh_label, ltype, 0) != 0) {
1384*7fd79137SRobert Mustacchi 		ctf_close(out);
1385*7fd79137SRobert Mustacchi 		return (ctf_errno(out));
1386*7fd79137SRobert Mustacchi 	}
1387*7fd79137SRobert Mustacchi 
1388*7fd79137SRobert Mustacchi 	ctf_dprintf("merging symbols and the like\n");
1389*7fd79137SRobert Mustacchi 	if (cmh->cmh_msyms == B_TRUE) {
1390*7fd79137SRobert Mustacchi 		err = ctf_merge_symbols(cmh, out);
1391*7fd79137SRobert Mustacchi 		if (err != 0) {
1392*7fd79137SRobert Mustacchi 			ctf_close(out);
1393*7fd79137SRobert Mustacchi 			return (ctf_errno(out));
1394*7fd79137SRobert Mustacchi 		}
1395*7fd79137SRobert Mustacchi 
1396*7fd79137SRobert Mustacchi 		err = ctf_merge_functions(cmh, out);
1397*7fd79137SRobert Mustacchi 		if (err != 0) {
1398*7fd79137SRobert Mustacchi 			ctf_close(out);
1399*7fd79137SRobert Mustacchi 			return (ctf_errno(out));
1400*7fd79137SRobert Mustacchi 		}
1401*7fd79137SRobert Mustacchi 	}
1402*7fd79137SRobert Mustacchi 
1403*7fd79137SRobert Mustacchi 	err = ctf_update(out);
1404*7fd79137SRobert Mustacchi 	if (err != 0) {
1405*7fd79137SRobert Mustacchi 		ctf_close(out);
1406*7fd79137SRobert Mustacchi 		return (ctf_errno(out));
1407*7fd79137SRobert Mustacchi 	}
1408*7fd79137SRobert Mustacchi 
1409*7fd79137SRobert Mustacchi 	*outp = out;
1410*7fd79137SRobert Mustacchi 	return (0);
1411*7fd79137SRobert Mustacchi }
1412*7fd79137SRobert Mustacchi 
1413*7fd79137SRobert Mustacchi /*
1414*7fd79137SRobert Mustacchi  * When we get told that something is unique, eg. same is B_FALSE, then that
1415*7fd79137SRobert Mustacchi  * tells us that we need to add it to the output. If same is B_TRUE, then we'll
1416*7fd79137SRobert Mustacchi  * want to record it in the mapping table so that we know how to redirect types
1417*7fd79137SRobert Mustacchi  * to the extant ones.
1418*7fd79137SRobert Mustacchi  */
1419*7fd79137SRobert Mustacchi static void
1420*7fd79137SRobert Mustacchi ctf_dedup_cb(ctf_file_t *ifp, ctf_id_t iid, boolean_t same, ctf_file_t *ofp,
1421*7fd79137SRobert Mustacchi     ctf_id_t oid, void *arg)
1422*7fd79137SRobert Mustacchi {
1423*7fd79137SRobert Mustacchi 	ctf_merge_types_t *cmp = arg;
1424*7fd79137SRobert Mustacchi 	ctf_merge_tinfo_t *cmt = cmp->cm_tmap;
1425*7fd79137SRobert Mustacchi 
1426*7fd79137SRobert Mustacchi 	if (same == B_TRUE) {
1427*7fd79137SRobert Mustacchi 		/*
1428*7fd79137SRobert Mustacchi 		 * The output id here may itself map to something else.
1429*7fd79137SRobert Mustacchi 		 * Therefore, we need to basically walk a chain and see what it
1430*7fd79137SRobert Mustacchi 		 * points to until it itself points to a base type, eg. -1.
1431*7fd79137SRobert Mustacchi 		 * Otherwise we'll dedup to something which no longer exists.
1432*7fd79137SRobert Mustacchi 		 */
1433*7fd79137SRobert Mustacchi 		while (cmt[oid].cmt_missing == B_FALSE)
1434*7fd79137SRobert Mustacchi 			oid = cmt[oid].cmt_map;
1435*7fd79137SRobert Mustacchi 		cmt[iid].cmt_map = oid;
1436*7fd79137SRobert Mustacchi 		ctf_dprintf("%d->%d \n", iid, oid);
1437*7fd79137SRobert Mustacchi 	} else {
1438*7fd79137SRobert Mustacchi 		VERIFY(cmt[iid].cmt_map == 0);
1439*7fd79137SRobert Mustacchi 		cmt[iid].cmt_missing = B_TRUE;
1440*7fd79137SRobert Mustacchi 		ctf_dprintf("%d is missing\n", iid);
1441*7fd79137SRobert Mustacchi 	}
1442*7fd79137SRobert Mustacchi }
1443*7fd79137SRobert Mustacchi 
1444*7fd79137SRobert Mustacchi /*
1445*7fd79137SRobert Mustacchi  * Dedup a CTF container.
1446*7fd79137SRobert Mustacchi  *
1447*7fd79137SRobert Mustacchi  * DWARF and other encoding formats that we use to create CTF data may create
1448*7fd79137SRobert Mustacchi  * multiple copies of a given type. However, after doing a conversion, and
1449*7fd79137SRobert Mustacchi  * before doing a merge, we'd prefer, if possible, to have every input container
1450*7fd79137SRobert Mustacchi  * to be unique.
1451*7fd79137SRobert Mustacchi  *
1452*7fd79137SRobert Mustacchi  * Doing a deduplication is like a normal merge. However, when we diff the types
1453*7fd79137SRobert Mustacchi  * in the container, rather than doing a normal diff, we instead want to diff
1454*7fd79137SRobert Mustacchi  * against any already processed types. eg, for a given type i in a container,
1455*7fd79137SRobert Mustacchi  * we want to diff it from 0 to i - 1.
1456*7fd79137SRobert Mustacchi  */
1457*7fd79137SRobert Mustacchi int
1458*7fd79137SRobert Mustacchi ctf_merge_dedup(ctf_merge_t *cmp, ctf_file_t **outp)
1459*7fd79137SRobert Mustacchi {
1460*7fd79137SRobert Mustacchi 	int ret;
1461*7fd79137SRobert Mustacchi 	ctf_diff_t *cdp = NULL;
1462*7fd79137SRobert Mustacchi 	ctf_merge_input_t *cmi, *cmc;
1463*7fd79137SRobert Mustacchi 	ctf_file_t *ifp, *ofp;
1464*7fd79137SRobert Mustacchi 	ctf_merge_types_t cm;
1465*7fd79137SRobert Mustacchi 
1466*7fd79137SRobert Mustacchi 	if (cmp == NULL || outp == NULL)
1467*7fd79137SRobert Mustacchi 		return (EINVAL);
1468*7fd79137SRobert Mustacchi 
1469*7fd79137SRobert Mustacchi 	ctf_dprintf("encountered %d inputs\n", cmp->cmh_ninputs);
1470*7fd79137SRobert Mustacchi 	if (cmp->cmh_ninputs != 2)
1471*7fd79137SRobert Mustacchi 		return (EINVAL);
1472*7fd79137SRobert Mustacchi 
1473*7fd79137SRobert Mustacchi 	ctf_dprintf("passed argument sanity check\n");
1474*7fd79137SRobert Mustacchi 
1475*7fd79137SRobert Mustacchi 	cmi = list_head(&cmp->cmh_inputs);
1476*7fd79137SRobert Mustacchi 	VERIFY(cmi != NULL);
1477*7fd79137SRobert Mustacchi 	cmc = list_next(&cmp->cmh_inputs, cmi);
1478*7fd79137SRobert Mustacchi 	VERIFY(cmc != NULL);
1479*7fd79137SRobert Mustacchi 	ifp = cmi->cmi_input;
1480*7fd79137SRobert Mustacchi 	ofp = cmc->cmi_input;
1481*7fd79137SRobert Mustacchi 	VERIFY(ifp != NULL);
1482*7fd79137SRobert Mustacchi 	VERIFY(ofp != NULL);
1483*7fd79137SRobert Mustacchi 	cm.cm_src = ifp;
1484*7fd79137SRobert Mustacchi 	cm.cm_out = ofp;
1485*7fd79137SRobert Mustacchi 	cm.cm_dedup = B_TRUE;
1486*7fd79137SRobert Mustacchi 	cm.cm_unique = B_FALSE;
1487*7fd79137SRobert Mustacchi 
1488*7fd79137SRobert Mustacchi 	if ((ret = ctf_merge_types_init(&cm)) != 0) {
1489*7fd79137SRobert Mustacchi 		return (ret);
1490*7fd79137SRobert Mustacchi 	}
1491*7fd79137SRobert Mustacchi 
1492*7fd79137SRobert Mustacchi 	if ((ret = ctf_diff_init(ifp, ifp, &cdp)) != 0)
1493*7fd79137SRobert Mustacchi 		goto err;
1494*7fd79137SRobert Mustacchi 
1495*7fd79137SRobert Mustacchi 	ctf_dprintf("Successfully initialized dedup\n");
1496*7fd79137SRobert Mustacchi 	if ((ret = ctf_diff_self(cdp, ctf_dedup_cb, &cm)) != 0)
1497*7fd79137SRobert Mustacchi 		goto err;
1498*7fd79137SRobert Mustacchi 
1499*7fd79137SRobert Mustacchi 	ctf_dprintf("Successfully diffed types\n");
1500*7fd79137SRobert Mustacchi 	ret = ctf_merge_common(&cm);
1501*7fd79137SRobert Mustacchi 	ctf_dprintf("deduping types result: %d\n", ret);
1502*7fd79137SRobert Mustacchi 	if (ret == 0)
1503*7fd79137SRobert Mustacchi 		ret = ctf_update(cm.cm_out);
1504*7fd79137SRobert Mustacchi 	if (ret != 0)
1505*7fd79137SRobert Mustacchi 		goto err;
1506*7fd79137SRobert Mustacchi 
1507*7fd79137SRobert Mustacchi 	ctf_dprintf("Successfully deduped types\n");
1508*7fd79137SRobert Mustacchi 	ctf_phase_dump(cm.cm_out, "dedup-pre-syms");
1509*7fd79137SRobert Mustacchi 
1510*7fd79137SRobert Mustacchi 	/*
1511*7fd79137SRobert Mustacchi 	 * Now we need to fix up the object and function maps.
1512*7fd79137SRobert Mustacchi 	 */
1513*7fd79137SRobert Mustacchi 	ctf_merge_fixup_nontypes(&cm, cmi);
1514*7fd79137SRobert Mustacchi 
1515*7fd79137SRobert Mustacchi 	if (cmp->cmh_msyms == B_TRUE) {
1516*7fd79137SRobert Mustacchi 		ret = ctf_merge_symbols(cmp, cm.cm_out);
1517*7fd79137SRobert Mustacchi 		if (ret != 0) {
1518*7fd79137SRobert Mustacchi 			ret = ctf_errno(cm.cm_out);
1519*7fd79137SRobert Mustacchi 			ctf_dprintf("failed to dedup symbols: %s\n",
1520*7fd79137SRobert Mustacchi 			    ctf_errmsg(ret));
1521*7fd79137SRobert Mustacchi 			goto err;
1522*7fd79137SRobert Mustacchi 		}
1523*7fd79137SRobert Mustacchi 
1524*7fd79137SRobert Mustacchi 		ret = ctf_merge_functions(cmp, cm.cm_out);
1525*7fd79137SRobert Mustacchi 		if (ret != 0) {
1526*7fd79137SRobert Mustacchi 			ret = ctf_errno(cm.cm_out);
1527*7fd79137SRobert Mustacchi 			ctf_dprintf("failed to dedup functions: %s\n",
1528*7fd79137SRobert Mustacchi 			    ctf_errmsg(ret));
1529*7fd79137SRobert Mustacchi 			goto err;
1530*7fd79137SRobert Mustacchi 		}
1531*7fd79137SRobert Mustacchi 	}
1532*7fd79137SRobert Mustacchi 
1533*7fd79137SRobert Mustacchi 	ret = ctf_update(cm.cm_out);
1534*7fd79137SRobert Mustacchi 	if (ret == 0) {
1535*7fd79137SRobert Mustacchi 		cmc->cmi_input = NULL;
1536*7fd79137SRobert Mustacchi 		*outp = cm.cm_out;
1537*7fd79137SRobert Mustacchi 	}
1538*7fd79137SRobert Mustacchi err:
1539*7fd79137SRobert Mustacchi 	ctf_merge_types_fini(&cm);
1540*7fd79137SRobert Mustacchi 	ctf_diff_fini(cdp);
1541*7fd79137SRobert Mustacchi 	return (ret);
1542*7fd79137SRobert Mustacchi }
1543*7fd79137SRobert Mustacchi 
1544*7fd79137SRobert Mustacchi int
1545*7fd79137SRobert Mustacchi ctf_merge_set_nthreads(ctf_merge_t *cmp, const uint_t nthrs)
1546*7fd79137SRobert Mustacchi {
1547*7fd79137SRobert Mustacchi 	if (nthrs == 0)
1548*7fd79137SRobert Mustacchi 		return (EINVAL);
1549*7fd79137SRobert Mustacchi 	cmp->cmh_nthreads = nthrs;
1550*7fd79137SRobert Mustacchi 	return (0);
1551*7fd79137SRobert Mustacchi }
1552