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