1bc1f688bSRobert Mustacchi /*
2bc1f688bSRobert Mustacchi  * This file and its contents are supplied under the terms of the
3bc1f688bSRobert Mustacchi  * Common Development and Distribution License ("CDDL"), version 1.0.
4bc1f688bSRobert Mustacchi  * You may only use this file in accordance with the terms of version
5bc1f688bSRobert Mustacchi  * 1.0 of the CDDL.
6bc1f688bSRobert Mustacchi  *
7bc1f688bSRobert Mustacchi  * A full copy of the text of the CDDL should have accompanied this
8bc1f688bSRobert Mustacchi  * source.  A copy of the CDDL is also available via the Internet at
9bc1f688bSRobert Mustacchi  * http://www.illumos.org/license/CDDL.
10bc1f688bSRobert Mustacchi  */
11bc1f688bSRobert Mustacchi 
12bc1f688bSRobert Mustacchi /*
13fe2dc8bdSJohn Levon  * Copyright 2020 Joyent, Inc.
14bc1f688bSRobert Mustacchi  */
15bc1f688bSRobert Mustacchi 
16bc1f688bSRobert Mustacchi /*
17bc1f688bSRobert Mustacchi  * To perform a merge of two CTF containers, we first diff the two containers
18bc1f688bSRobert Mustacchi  * types. For every type that's in the src container, but not in the dst
19bc1f688bSRobert Mustacchi  * container, we note it and add it to dst container. If there are any objects
20bc1f688bSRobert Mustacchi  * or functions associated with src, we go through and update the types that
21bc1f688bSRobert Mustacchi  * they refer to such that they all refer to types in the dst container.
22bc1f688bSRobert Mustacchi  *
23bc1f688bSRobert Mustacchi  * The bulk of the logic for the merge, after we've run the diff, occurs in
24bc1f688bSRobert Mustacchi  * ctf_merge_common().
25bc1f688bSRobert Mustacchi  *
26bc1f688bSRobert Mustacchi  * In terms of exported APIs, we don't really export a simple merge two
27bc1f688bSRobert Mustacchi  * containers, as the general way this is used, in something like ctfmerge(1),
28bc1f688bSRobert Mustacchi  * is to add all the containers and then let us figure out the best way to merge
29bc1f688bSRobert Mustacchi  * it.
30bc1f688bSRobert Mustacchi  */
31bc1f688bSRobert Mustacchi 
32bc1f688bSRobert Mustacchi #include <libctf_impl.h>
33bc1f688bSRobert Mustacchi #include <sys/debug.h>
34bc1f688bSRobert Mustacchi #include <sys/list.h>
35bc1f688bSRobert Mustacchi #include <stddef.h>
36bc1f688bSRobert Mustacchi #include <fcntl.h>
37bc1f688bSRobert Mustacchi #include <sys/types.h>
38bc1f688bSRobert Mustacchi #include <sys/stat.h>
39bc1f688bSRobert Mustacchi #include <mergeq.h>
40bc1f688bSRobert Mustacchi #include <errno.h>
41bc1f688bSRobert Mustacchi 
42bc1f688bSRobert Mustacchi typedef struct ctf_merge_tinfo {
43bc1f688bSRobert Mustacchi 	uint16_t cmt_map;	/* Map to the type in out */
44bc1f688bSRobert Mustacchi 	boolean_t cmt_fixup;
45bc1f688bSRobert Mustacchi 	boolean_t cmt_forward;
46bc1f688bSRobert Mustacchi 	boolean_t cmt_missing;
47bc1f688bSRobert Mustacchi } ctf_merge_tinfo_t;
48bc1f688bSRobert Mustacchi 
49bc1f688bSRobert Mustacchi /*
50bc1f688bSRobert Mustacchi  * State required for doing an individual merge of two containers.
51bc1f688bSRobert Mustacchi  */
52bc1f688bSRobert Mustacchi typedef struct ctf_merge_types {
53bc1f688bSRobert Mustacchi 	ctf_file_t *cm_out;		/* Output CTF file */
54bc1f688bSRobert Mustacchi 	ctf_file_t *cm_src;		/* Input CTF file */
55bc1f688bSRobert Mustacchi 	ctf_merge_tinfo_t *cm_tmap;	/* Type state information */
56bc1f688bSRobert Mustacchi 	boolean_t cm_dedup;		/* Are we doing a dedup? */
57bc1f688bSRobert Mustacchi 	boolean_t cm_unique;		/* are we doing a uniquify? */
58bc1f688bSRobert Mustacchi } ctf_merge_types_t;
59bc1f688bSRobert Mustacchi 
60bc1f688bSRobert Mustacchi typedef struct ctf_merge_objmap {
61bc1f688bSRobert Mustacchi 	list_node_t cmo_node;
62bc1f688bSRobert Mustacchi 	const char *cmo_name;		/* Symbol name */
6337e82d12SRobert Mustacchi 	const char *cmo_file;		/* Symbol file */
64bc1f688bSRobert Mustacchi 	ulong_t cmo_idx;		/* Symbol ID */
6537e82d12SRobert Mustacchi 	Elf64_Sym cmo_sym;		/* Symbol Entry */
66bc1f688bSRobert Mustacchi 	ctf_id_t cmo_tid;		/* Type ID */
67bc1f688bSRobert Mustacchi } ctf_merge_objmap_t;
68bc1f688bSRobert Mustacchi 
69bc1f688bSRobert Mustacchi typedef struct ctf_merge_funcmap {
70bc1f688bSRobert Mustacchi 	list_node_t cmf_node;
71bc1f688bSRobert Mustacchi 	const char *cmf_name;		/* Symbol name */
7237e82d12SRobert Mustacchi 	const char *cmf_file;		/* Symbol file */
73bc1f688bSRobert Mustacchi 	ulong_t cmf_idx;		/* Symbol ID */
7437e82d12SRobert Mustacchi 	Elf64_Sym cmf_sym;		/* Symbol Entry */
75bc1f688bSRobert Mustacchi 	ctf_id_t cmf_rtid;		/* Type ID */
76bc1f688bSRobert Mustacchi 	uint_t cmf_flags;		/* ctf_funcinfo_t ctc_flags */
77bc1f688bSRobert Mustacchi 	uint_t cmf_argc;		/* Number of arguments */
78bc1f688bSRobert Mustacchi 	ctf_id_t cmf_args[];		/* Types of arguments */
79bc1f688bSRobert Mustacchi } ctf_merge_funcmap_t;
80bc1f688bSRobert Mustacchi 
81bc1f688bSRobert Mustacchi typedef struct ctf_merge_input {
82bc1f688bSRobert Mustacchi 	list_node_t cmi_node;
83bc1f688bSRobert Mustacchi 	ctf_file_t *cmi_input;
84bc1f688bSRobert Mustacchi 	list_t cmi_omap;
85bc1f688bSRobert Mustacchi 	list_t cmi_fmap;
86bc1f688bSRobert Mustacchi 	boolean_t cmi_created;
87bc1f688bSRobert Mustacchi } ctf_merge_input_t;
88bc1f688bSRobert Mustacchi 
89bc1f688bSRobert Mustacchi struct ctf_merge_handle {
90bc1f688bSRobert Mustacchi 	list_t cmh_inputs;		/* Input list */
91bc1f688bSRobert Mustacchi 	uint_t cmh_ninputs;		/* Number of inputs */
92bc1f688bSRobert Mustacchi 	uint_t cmh_nthreads;		/* Number of threads to use */
93bc1f688bSRobert Mustacchi 	ctf_file_t *cmh_unique;		/* ctf to uniquify against */
94bc1f688bSRobert Mustacchi 	boolean_t cmh_msyms;		/* Should we merge symbols/funcs? */
95bc1f688bSRobert Mustacchi 	int cmh_ofd;			/* FD for output file */
96bc1f688bSRobert Mustacchi 	int cmh_flags;			/* Flags that control merge behavior */
97bc1f688bSRobert Mustacchi 	char *cmh_label;		/* Optional label */
98bc1f688bSRobert Mustacchi 	char *cmh_pname;		/* Parent name */
99bc1f688bSRobert Mustacchi };
100bc1f688bSRobert Mustacchi 
10137e82d12SRobert Mustacchi typedef struct ctf_merge_symbol_arg {
10237e82d12SRobert Mustacchi 	list_t *cmsa_objmap;
10337e82d12SRobert Mustacchi 	list_t *cmsa_funcmap;
10437e82d12SRobert Mustacchi 	ctf_file_t *cmsa_out;
10537e82d12SRobert Mustacchi 	boolean_t cmsa_dedup;
10637e82d12SRobert Mustacchi } ctf_merge_symbol_arg_t;
10737e82d12SRobert Mustacchi 
108bc1f688bSRobert Mustacchi static int ctf_merge_add_type(ctf_merge_types_t *, ctf_id_t);
109bc1f688bSRobert Mustacchi 
110bc1f688bSRobert Mustacchi static ctf_id_t
ctf_merge_gettype(ctf_merge_types_t * cmp,ctf_id_t id)111bc1f688bSRobert Mustacchi ctf_merge_gettype(ctf_merge_types_t *cmp, ctf_id_t id)
112bc1f688bSRobert Mustacchi {
113bc1f688bSRobert Mustacchi 	if (cmp->cm_dedup == B_FALSE) {
114bc1f688bSRobert Mustacchi 		VERIFY(cmp->cm_tmap[id].cmt_map != 0);
115bc1f688bSRobert Mustacchi 		return (cmp->cm_tmap[id].cmt_map);
116bc1f688bSRobert Mustacchi 	}
117bc1f688bSRobert Mustacchi 
118bc1f688bSRobert Mustacchi 	while (cmp->cm_tmap[id].cmt_missing == B_FALSE) {
119bc1f688bSRobert Mustacchi 		VERIFY(cmp->cm_tmap[id].cmt_map != 0);
120bc1f688bSRobert Mustacchi 		id = cmp->cm_tmap[id].cmt_map;
121bc1f688bSRobert Mustacchi 	}
122bc1f688bSRobert Mustacchi 	VERIFY(cmp->cm_tmap[id].cmt_map != 0);
123bc1f688bSRobert Mustacchi 	return (cmp->cm_tmap[id].cmt_map);
124bc1f688bSRobert Mustacchi }
125bc1f688bSRobert Mustacchi 
126bc1f688bSRobert 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)127bc1f688bSRobert Mustacchi ctf_merge_diffcb(ctf_file_t *ifp, ctf_id_t iid, boolean_t same, ctf_file_t *ofp,
128bc1f688bSRobert Mustacchi     ctf_id_t oid, void *arg)
129bc1f688bSRobert Mustacchi {
130bc1f688bSRobert Mustacchi 	ctf_merge_types_t *cmp = arg;
131bc1f688bSRobert Mustacchi 	ctf_merge_tinfo_t *cmt = cmp->cm_tmap;
1323dfdac06SAndy Fiddaman 	uint_t kind;
133bc1f688bSRobert Mustacchi 
134bc1f688bSRobert Mustacchi 	if (same == B_TRUE) {
135bc1f688bSRobert Mustacchi 		if (ctf_type_kind(ifp, iid) == CTF_K_FORWARD &&
1363dfdac06SAndy Fiddaman 		    (kind = ctf_type_kind(ofp, oid)) != CTF_K_FORWARD) {
137bc1f688bSRobert Mustacchi 			VERIFY(cmt[oid].cmt_map == 0);
138bc1f688bSRobert Mustacchi 
139bc1f688bSRobert Mustacchi 			/*
140bc1f688bSRobert Mustacchi 			 * If we're uniquifying types, it's possible for the
141bc1f688bSRobert Mustacchi 			 * container that we're uniquifying against to have a
142bc1f688bSRobert Mustacchi 			 * forward which exists in the container being reduced.
143bc1f688bSRobert Mustacchi 			 * For example, genunix has the machcpu structure as a
144bc1f688bSRobert Mustacchi 			 * forward which is actually in unix and we uniquify
145bc1f688bSRobert Mustacchi 			 * unix against genunix. In such cases, we explicitly do
146bc1f688bSRobert Mustacchi 			 * not do any mapping of the forward information, lest
147bc1f688bSRobert Mustacchi 			 * we risk losing the real definition. Instead, mark
148bc1f688bSRobert Mustacchi 			 * that it's missing.
149bc1f688bSRobert Mustacchi 			 */
150bc1f688bSRobert Mustacchi 			if (cmp->cm_unique == B_TRUE) {
151bc1f688bSRobert Mustacchi 				cmt[oid].cmt_missing = B_TRUE;
152bc1f688bSRobert Mustacchi 				return;
153bc1f688bSRobert Mustacchi 			}
154bc1f688bSRobert Mustacchi 
155bc1f688bSRobert Mustacchi 			cmt[oid].cmt_map = iid;
156bc1f688bSRobert Mustacchi 			cmt[oid].cmt_forward = B_TRUE;
1573dfdac06SAndy Fiddaman 			ctf_dprintf("merge diff forward mapped %ld->%ld (%u)\n",
1583dfdac06SAndy Fiddaman 			    oid, iid, kind);
159bc1f688bSRobert Mustacchi 			return;
160bc1f688bSRobert Mustacchi 		}
161bc1f688bSRobert Mustacchi 
162bc1f688bSRobert Mustacchi 		/*
163bc1f688bSRobert Mustacchi 		 * We could have multiple things that a given type ends up
164bc1f688bSRobert Mustacchi 		 * matching in the world of forwards and pointers to forwards.
165bc1f688bSRobert Mustacchi 		 * For now just take the first one...
166bc1f688bSRobert Mustacchi 		 */
167bc1f688bSRobert Mustacchi 		if (cmt[oid].cmt_map != 0)
168bc1f688bSRobert Mustacchi 			return;
169bc1f688bSRobert Mustacchi 		cmt[oid].cmt_map = iid;
170bc1f688bSRobert Mustacchi 		ctf_dprintf("merge diff mapped %d->%d\n", oid, iid);
171bc1f688bSRobert Mustacchi 	} else if (ifp == cmp->cm_src) {
172bc1f688bSRobert Mustacchi 		VERIFY(cmt[iid].cmt_map == 0);
173bc1f688bSRobert Mustacchi 		cmt[iid].cmt_missing = B_TRUE;
174bc1f688bSRobert Mustacchi 		ctf_dprintf("merge diff said %d is missing\n", iid);
175bc1f688bSRobert Mustacchi 	}
176bc1f688bSRobert Mustacchi }
177bc1f688bSRobert Mustacchi 
178bc1f688bSRobert Mustacchi static int
ctf_merge_add_number(ctf_merge_types_t * cmp,ctf_id_t id)179bc1f688bSRobert Mustacchi ctf_merge_add_number(ctf_merge_types_t *cmp, ctf_id_t id)
180bc1f688bSRobert Mustacchi {
181bc1f688bSRobert Mustacchi 	int ret, flags;
182bc1f688bSRobert Mustacchi 	const ctf_type_t *tp;
183bc1f688bSRobert Mustacchi 	const char *name;
184bc1f688bSRobert Mustacchi 	ctf_encoding_t en;
185bc1f688bSRobert Mustacchi 
186bc1f688bSRobert Mustacchi 	if (ctf_type_encoding(cmp->cm_src, id, &en) != 0)
187bc1f688bSRobert Mustacchi 		return (CTF_ERR);
188bc1f688bSRobert Mustacchi 
189bc1f688bSRobert Mustacchi 	tp = LCTF_INDEX_TO_TYPEPTR(cmp->cm_src, id);
190bc1f688bSRobert Mustacchi 	name = ctf_strraw(cmp->cm_src, tp->ctt_name);
191bc1f688bSRobert Mustacchi 	if (CTF_INFO_ISROOT(tp->ctt_info) != 0)
192bc1f688bSRobert Mustacchi 		flags = CTF_ADD_ROOT;
193bc1f688bSRobert Mustacchi 	else
194bc1f688bSRobert Mustacchi 		flags = CTF_ADD_NONROOT;
195bc1f688bSRobert Mustacchi 
196bc1f688bSRobert Mustacchi 	ret = ctf_add_encoded(cmp->cm_out, flags, name, &en,
197bc1f688bSRobert Mustacchi 	    ctf_type_kind(cmp->cm_src, id));
198bc1f688bSRobert Mustacchi 
199bc1f688bSRobert Mustacchi 	if (ret == CTF_ERR)
200bc1f688bSRobert Mustacchi 		return (ret);
201bc1f688bSRobert Mustacchi 
202bc1f688bSRobert Mustacchi 	VERIFY(cmp->cm_tmap[id].cmt_map == 0);
203bc1f688bSRobert Mustacchi 	cmp->cm_tmap[id].cmt_map = ret;
204bc1f688bSRobert Mustacchi 	return (0);
205bc1f688bSRobert Mustacchi }
206bc1f688bSRobert Mustacchi 
207bc1f688bSRobert Mustacchi static int
ctf_merge_add_array(ctf_merge_types_t * cmp,ctf_id_t id)208bc1f688bSRobert Mustacchi ctf_merge_add_array(ctf_merge_types_t *cmp, ctf_id_t id)
209bc1f688bSRobert Mustacchi {
210bc1f688bSRobert Mustacchi 	int ret, flags;
211bc1f688bSRobert Mustacchi 	const ctf_type_t *tp;
212bc1f688bSRobert Mustacchi 	ctf_arinfo_t ar;
213bc1f688bSRobert Mustacchi 
214bc1f688bSRobert Mustacchi 	if (ctf_array_info(cmp->cm_src, id, &ar) == CTF_ERR)
215bc1f688bSRobert Mustacchi 		return (CTF_ERR);
216bc1f688bSRobert Mustacchi 
217bc1f688bSRobert Mustacchi 	tp = LCTF_INDEX_TO_TYPEPTR(cmp->cm_src, id);
218bc1f688bSRobert Mustacchi 	if (CTF_INFO_ISROOT(tp->ctt_info) != 0)
219bc1f688bSRobert Mustacchi 		flags = CTF_ADD_ROOT;
220bc1f688bSRobert Mustacchi 	else
221bc1f688bSRobert Mustacchi 		flags = CTF_ADD_NONROOT;
222bc1f688bSRobert Mustacchi 
223bc1f688bSRobert Mustacchi 	if (cmp->cm_tmap[ar.ctr_contents].cmt_map == 0) {
224bc1f688bSRobert Mustacchi 		ret = ctf_merge_add_type(cmp, ar.ctr_contents);
225bc1f688bSRobert Mustacchi 		if (ret != 0)
226bc1f688bSRobert Mustacchi 			return (ret);
227bc1f688bSRobert Mustacchi 		ASSERT(cmp->cm_tmap[ar.ctr_contents].cmt_map != 0);
228bc1f688bSRobert Mustacchi 	}
229bc1f688bSRobert Mustacchi 	ar.ctr_contents = ctf_merge_gettype(cmp, ar.ctr_contents);
230bc1f688bSRobert Mustacchi 
231bc1f688bSRobert Mustacchi 	if (cmp->cm_tmap[ar.ctr_index].cmt_map == 0) {
232bc1f688bSRobert Mustacchi 		ret = ctf_merge_add_type(cmp, ar.ctr_index);
233bc1f688bSRobert Mustacchi 		if (ret != 0)
234bc1f688bSRobert Mustacchi 			return (ret);
235bc1f688bSRobert Mustacchi 		ASSERT(cmp->cm_tmap[ar.ctr_index].cmt_map != 0);
236bc1f688bSRobert Mustacchi 	}
237bc1f688bSRobert Mustacchi 	ar.ctr_index = ctf_merge_gettype(cmp, ar.ctr_index);
238bc1f688bSRobert Mustacchi 
239bc1f688bSRobert Mustacchi 	ret = ctf_add_array(cmp->cm_out, flags, &ar);
240bc1f688bSRobert Mustacchi 	if (ret == CTF_ERR)
241bc1f688bSRobert Mustacchi 		return (ret);
242bc1f688bSRobert Mustacchi 
243bc1f688bSRobert Mustacchi 	VERIFY(cmp->cm_tmap[id].cmt_map == 0);
244bc1f688bSRobert Mustacchi 	cmp->cm_tmap[id].cmt_map = ret;
245bc1f688bSRobert Mustacchi 
246bc1f688bSRobert Mustacchi 	return (0);
247bc1f688bSRobert Mustacchi }
248bc1f688bSRobert Mustacchi 
249bc1f688bSRobert Mustacchi static int
ctf_merge_add_reftype(ctf_merge_types_t * cmp,ctf_id_t id)250bc1f688bSRobert Mustacchi ctf_merge_add_reftype(ctf_merge_types_t *cmp, ctf_id_t id)
251bc1f688bSRobert Mustacchi {
252bc1f688bSRobert Mustacchi 	int ret, flags;
253bc1f688bSRobert Mustacchi 	const ctf_type_t *tp;
254bc1f688bSRobert Mustacchi 	ctf_id_t reftype;
255bc1f688bSRobert Mustacchi 	const char *name;
256bc1f688bSRobert Mustacchi 
257bc1f688bSRobert Mustacchi 	tp = LCTF_INDEX_TO_TYPEPTR(cmp->cm_src, id);
258bc1f688bSRobert Mustacchi 	name = ctf_strraw(cmp->cm_src, tp->ctt_name);
259bc1f688bSRobert Mustacchi 	if (CTF_INFO_ISROOT(tp->ctt_info) != 0)
260bc1f688bSRobert Mustacchi 		flags = CTF_ADD_ROOT;
261bc1f688bSRobert Mustacchi 	else
262bc1f688bSRobert Mustacchi 		flags = CTF_ADD_NONROOT;
263bc1f688bSRobert Mustacchi 
264bc1f688bSRobert Mustacchi 	reftype = ctf_type_reference(cmp->cm_src, id);
265bc1f688bSRobert Mustacchi 	if (reftype == CTF_ERR)
266bc1f688bSRobert Mustacchi 		return (ctf_set_errno(cmp->cm_out, ctf_errno(cmp->cm_src)));
267bc1f688bSRobert Mustacchi 
268bc1f688bSRobert Mustacchi 	if (cmp->cm_tmap[reftype].cmt_map == 0) {
269bc1f688bSRobert Mustacchi 		ret = ctf_merge_add_type(cmp, reftype);
270bc1f688bSRobert Mustacchi 		if (ret != 0)
271bc1f688bSRobert Mustacchi 			return (ret);
272bc1f688bSRobert Mustacchi 		ASSERT(cmp->cm_tmap[reftype].cmt_map != 0);
273bc1f688bSRobert Mustacchi 	}
274bc1f688bSRobert Mustacchi 	reftype = ctf_merge_gettype(cmp, reftype);
275bc1f688bSRobert Mustacchi 
276bc1f688bSRobert Mustacchi 	ret = ctf_add_reftype(cmp->cm_out, flags, name, reftype,
277bc1f688bSRobert Mustacchi 	    ctf_type_kind(cmp->cm_src, id));
278bc1f688bSRobert Mustacchi 	if (ret == CTF_ERR)
279bc1f688bSRobert Mustacchi 		return (ret);
280bc1f688bSRobert Mustacchi 
281bc1f688bSRobert Mustacchi 	VERIFY(cmp->cm_tmap[id].cmt_map == 0);
282bc1f688bSRobert Mustacchi 	cmp->cm_tmap[id].cmt_map = ret;
283bc1f688bSRobert Mustacchi 	return (0);
284bc1f688bSRobert Mustacchi }
285bc1f688bSRobert Mustacchi 
286bc1f688bSRobert Mustacchi static int
ctf_merge_add_typedef(ctf_merge_types_t * cmp,ctf_id_t id)287bc1f688bSRobert Mustacchi ctf_merge_add_typedef(ctf_merge_types_t *cmp, ctf_id_t id)
288bc1f688bSRobert Mustacchi {
289bc1f688bSRobert Mustacchi 	int ret, flags;
290bc1f688bSRobert Mustacchi 	const ctf_type_t *tp;
291bc1f688bSRobert Mustacchi 	const char *name;
292bc1f688bSRobert Mustacchi 	ctf_id_t reftype;
293bc1f688bSRobert Mustacchi 
294bc1f688bSRobert Mustacchi 	tp = LCTF_INDEX_TO_TYPEPTR(cmp->cm_src, id);
295bc1f688bSRobert Mustacchi 	name = ctf_strraw(cmp->cm_src, tp->ctt_name);
296bc1f688bSRobert Mustacchi 	if (CTF_INFO_ISROOT(tp->ctt_info) != 0)
297bc1f688bSRobert Mustacchi 		flags = CTF_ADD_ROOT;
298bc1f688bSRobert Mustacchi 	else
299bc1f688bSRobert Mustacchi 		flags = CTF_ADD_NONROOT;
300bc1f688bSRobert Mustacchi 
301bc1f688bSRobert Mustacchi 	reftype = ctf_type_reference(cmp->cm_src, id);
302bc1f688bSRobert Mustacchi 	if (reftype == CTF_ERR)
303bc1f688bSRobert Mustacchi 		return (ctf_set_errno(cmp->cm_out, ctf_errno(cmp->cm_src)));
304bc1f688bSRobert Mustacchi 
305bc1f688bSRobert Mustacchi 	if (cmp->cm_tmap[reftype].cmt_map == 0) {
306bc1f688bSRobert Mustacchi 		ret = ctf_merge_add_type(cmp, reftype);
307bc1f688bSRobert Mustacchi 		if (ret != 0)
308bc1f688bSRobert Mustacchi 			return (ret);
309bc1f688bSRobert Mustacchi 		ASSERT(cmp->cm_tmap[reftype].cmt_map != 0);
310bc1f688bSRobert Mustacchi 	}
311bc1f688bSRobert Mustacchi 	reftype = ctf_merge_gettype(cmp, reftype);
312bc1f688bSRobert Mustacchi 
313bc1f688bSRobert Mustacchi 	ret = ctf_add_typedef(cmp->cm_out, flags, name, reftype);
314bc1f688bSRobert Mustacchi 	if (ret == CTF_ERR)
315bc1f688bSRobert Mustacchi 		return (ret);
316bc1f688bSRobert Mustacchi 
317bc1f688bSRobert Mustacchi 	VERIFY(cmp->cm_tmap[id].cmt_map == 0);
318bc1f688bSRobert Mustacchi 	cmp->cm_tmap[id].cmt_map = ret;
319bc1f688bSRobert Mustacchi 	return (0);
320bc1f688bSRobert Mustacchi }
321bc1f688bSRobert Mustacchi 
322bc1f688bSRobert Mustacchi typedef struct ctf_merge_enum {
323bc1f688bSRobert Mustacchi 	ctf_file_t *cme_fp;
324bc1f688bSRobert Mustacchi 	ctf_id_t cme_id;
325bc1f688bSRobert Mustacchi } ctf_merge_enum_t;
326bc1f688bSRobert Mustacchi 
327bc1f688bSRobert Mustacchi static int
ctf_merge_add_enumerator(const char * name,int value,void * arg)328bc1f688bSRobert Mustacchi ctf_merge_add_enumerator(const char *name, int value, void *arg)
329bc1f688bSRobert Mustacchi {
330bc1f688bSRobert Mustacchi 	ctf_merge_enum_t *cmep = arg;
331bc1f688bSRobert Mustacchi 
332bc1f688bSRobert Mustacchi 	return (ctf_add_enumerator(cmep->cme_fp, cmep->cme_id, name, value) ==
333bc1f688bSRobert Mustacchi 	    CTF_ERR);
334bc1f688bSRobert Mustacchi }
335bc1f688bSRobert Mustacchi 
336bc1f688bSRobert Mustacchi static int
ctf_merge_add_enum(ctf_merge_types_t * cmp,ctf_id_t id)337bc1f688bSRobert Mustacchi ctf_merge_add_enum(ctf_merge_types_t *cmp, ctf_id_t id)
338bc1f688bSRobert Mustacchi {
339bc1f688bSRobert Mustacchi 	int flags;
340bc1f688bSRobert Mustacchi 	const ctf_type_t *tp;
341bc1f688bSRobert Mustacchi 	const char *name;
342bc1f688bSRobert Mustacchi 	ctf_id_t enumid;
343bc1f688bSRobert Mustacchi 	ctf_merge_enum_t cme;
344fe2dc8bdSJohn Levon 	size_t size;
345bc1f688bSRobert Mustacchi 
346bc1f688bSRobert Mustacchi 	tp = LCTF_INDEX_TO_TYPEPTR(cmp->cm_src, id);
347bc1f688bSRobert Mustacchi 	if (CTF_INFO_ISROOT(tp->ctt_info) != 0)
348bc1f688bSRobert Mustacchi 		flags = CTF_ADD_ROOT;
349bc1f688bSRobert Mustacchi 	else
350bc1f688bSRobert Mustacchi 		flags = CTF_ADD_NONROOT;
351bc1f688bSRobert Mustacchi 
352fe2dc8bdSJohn Levon 	name = ctf_strraw(cmp->cm_src, tp->ctt_name);
353fe2dc8bdSJohn Levon 	size = ctf_get_ctt_size(cmp->cm_src, tp, NULL, NULL);
354fe2dc8bdSJohn Levon 
355fe2dc8bdSJohn Levon 	enumid = ctf_add_enum(cmp->cm_out, flags, name, size);
356bc1f688bSRobert Mustacchi 	if (enumid == CTF_ERR)
357bc1f688bSRobert Mustacchi 		return (enumid);
358bc1f688bSRobert Mustacchi 
359bc1f688bSRobert Mustacchi 	cme.cme_fp = cmp->cm_out;
360bc1f688bSRobert Mustacchi 	cme.cme_id = enumid;
361bc1f688bSRobert Mustacchi 	if (ctf_enum_iter(cmp->cm_src, id, ctf_merge_add_enumerator,
362bc1f688bSRobert Mustacchi 	    &cme) != 0)
363bc1f688bSRobert Mustacchi 		return (CTF_ERR);
364bc1f688bSRobert Mustacchi 
365bc1f688bSRobert Mustacchi 	VERIFY(cmp->cm_tmap[id].cmt_map == 0);
366bc1f688bSRobert Mustacchi 	cmp->cm_tmap[id].cmt_map = enumid;
367bc1f688bSRobert Mustacchi 	return (0);
368bc1f688bSRobert Mustacchi }
369bc1f688bSRobert Mustacchi 
370bc1f688bSRobert Mustacchi static int
ctf_merge_add_func(ctf_merge_types_t * cmp,ctf_id_t id)371bc1f688bSRobert Mustacchi ctf_merge_add_func(ctf_merge_types_t *cmp, ctf_id_t id)
372bc1f688bSRobert Mustacchi {
373bc1f688bSRobert Mustacchi 	int ret, flags, i;
374bc1f688bSRobert Mustacchi 	const ctf_type_t *tp;
375bc1f688bSRobert Mustacchi 	ctf_funcinfo_t ctc;
376bc1f688bSRobert Mustacchi 	ctf_id_t *argv;
377bc1f688bSRobert Mustacchi 
378bc1f688bSRobert Mustacchi 	tp = LCTF_INDEX_TO_TYPEPTR(cmp->cm_src, id);
379bc1f688bSRobert Mustacchi 	if (CTF_INFO_ISROOT(tp->ctt_info) != 0)
380bc1f688bSRobert Mustacchi 		flags = CTF_ADD_ROOT;
381bc1f688bSRobert Mustacchi 	else
382bc1f688bSRobert Mustacchi 		flags = CTF_ADD_NONROOT;
383bc1f688bSRobert Mustacchi 
384bc1f688bSRobert Mustacchi 	if (ctf_func_info_by_id(cmp->cm_src, id, &ctc) == CTF_ERR)
385bc1f688bSRobert Mustacchi 		return (ctf_set_errno(cmp->cm_out, ctf_errno(cmp->cm_src)));
386bc1f688bSRobert Mustacchi 
387bc1f688bSRobert Mustacchi 	argv = ctf_alloc(sizeof (ctf_id_t) * ctc.ctc_argc);
388bc1f688bSRobert Mustacchi 	if (argv == NULL)
389bc1f688bSRobert Mustacchi 		return (ctf_set_errno(cmp->cm_out, ENOMEM));
390bc1f688bSRobert Mustacchi 	if (ctf_func_args_by_id(cmp->cm_src, id, ctc.ctc_argc, argv) ==
391bc1f688bSRobert Mustacchi 	    CTF_ERR) {
392bc1f688bSRobert Mustacchi 		ctf_free(argv, sizeof (ctf_id_t) * ctc.ctc_argc);
393bc1f688bSRobert Mustacchi 		return (ctf_set_errno(cmp->cm_out, ctf_errno(cmp->cm_src)));
394bc1f688bSRobert Mustacchi 	}
395bc1f688bSRobert Mustacchi 
396bc1f688bSRobert Mustacchi 	if (cmp->cm_tmap[ctc.ctc_return].cmt_map == 0) {
397bc1f688bSRobert Mustacchi 		ret = ctf_merge_add_type(cmp, ctc.ctc_return);
398bc1f688bSRobert Mustacchi 		if (ret != 0)
399bc1f688bSRobert Mustacchi 			return (ret);
400bc1f688bSRobert Mustacchi 		ASSERT(cmp->cm_tmap[ctc.ctc_return].cmt_map != 0);
401bc1f688bSRobert Mustacchi 	}
402bc1f688bSRobert Mustacchi 	ctc.ctc_return = ctf_merge_gettype(cmp, ctc.ctc_return);
403bc1f688bSRobert Mustacchi 
404bc1f688bSRobert Mustacchi 	for (i = 0; i < ctc.ctc_argc; i++) {
405bc1f688bSRobert Mustacchi 		if (cmp->cm_tmap[argv[i]].cmt_map == 0) {
406bc1f688bSRobert Mustacchi 			ret = ctf_merge_add_type(cmp, argv[i]);
407bc1f688bSRobert Mustacchi 			if (ret != 0)
408bc1f688bSRobert Mustacchi 				return (ret);
409bc1f688bSRobert Mustacchi 			ASSERT(cmp->cm_tmap[argv[i]].cmt_map != 0);
410bc1f688bSRobert Mustacchi 		}
411bc1f688bSRobert Mustacchi 		argv[i] = ctf_merge_gettype(cmp, argv[i]);
412bc1f688bSRobert Mustacchi 	}
413bc1f688bSRobert Mustacchi 
414bc1f688bSRobert Mustacchi 	ret = ctf_add_funcptr(cmp->cm_out, flags, &ctc, argv);
415bc1f688bSRobert Mustacchi 	ctf_free(argv, sizeof (ctf_id_t) * ctc.ctc_argc);
416bc1f688bSRobert Mustacchi 	if (ret == CTF_ERR)
417bc1f688bSRobert Mustacchi 		return (ret);
418bc1f688bSRobert Mustacchi 
419bc1f688bSRobert Mustacchi 	VERIFY(cmp->cm_tmap[id].cmt_map == 0);
420bc1f688bSRobert Mustacchi 	cmp->cm_tmap[id].cmt_map = ret;
421bc1f688bSRobert Mustacchi 	return (0);
422bc1f688bSRobert Mustacchi }
423bc1f688bSRobert Mustacchi 
424bc1f688bSRobert Mustacchi static int
ctf_merge_add_forward(ctf_merge_types_t * cmp,ctf_id_t id,uint_t kind)4253dfdac06SAndy Fiddaman ctf_merge_add_forward(ctf_merge_types_t *cmp, ctf_id_t id, uint_t kind)
426bc1f688bSRobert Mustacchi {
427bc1f688bSRobert Mustacchi 	int ret, flags;
428bc1f688bSRobert Mustacchi 	const ctf_type_t *tp;
429bc1f688bSRobert Mustacchi 	const char *name;
430bc1f688bSRobert Mustacchi 
431bc1f688bSRobert Mustacchi 	tp = LCTF_INDEX_TO_TYPEPTR(cmp->cm_src, id);
432bc1f688bSRobert Mustacchi 	name = ctf_strraw(cmp->cm_src, tp->ctt_name);
433bc1f688bSRobert Mustacchi 	if (CTF_INFO_ISROOT(tp->ctt_info) != 0)
434bc1f688bSRobert Mustacchi 		flags = CTF_ADD_ROOT;
435bc1f688bSRobert Mustacchi 	else
436bc1f688bSRobert Mustacchi 		flags = CTF_ADD_NONROOT;
437bc1f688bSRobert Mustacchi 
4383dfdac06SAndy Fiddaman 	ret = ctf_add_forward(cmp->cm_out, flags, name, kind);
439bc1f688bSRobert Mustacchi 	if (ret == CTF_ERR)
440bc1f688bSRobert Mustacchi 		return (CTF_ERR);
441bc1f688bSRobert Mustacchi 
442bc1f688bSRobert Mustacchi 	VERIFY(cmp->cm_tmap[id].cmt_map == 0);
443bc1f688bSRobert Mustacchi 	cmp->cm_tmap[id].cmt_map = ret;
444bc1f688bSRobert Mustacchi 	return (0);
445bc1f688bSRobert Mustacchi }
446bc1f688bSRobert Mustacchi 
447bc1f688bSRobert Mustacchi typedef struct ctf_merge_su {
448bc1f688bSRobert Mustacchi 	ctf_merge_types_t *cms_cm;
449bc1f688bSRobert Mustacchi 	ctf_id_t cms_id;
450bc1f688bSRobert Mustacchi } ctf_merge_su_t;
451bc1f688bSRobert Mustacchi 
452bc1f688bSRobert Mustacchi static int
ctf_merge_add_member(const char * name,ctf_id_t type,ulong_t offset,void * arg)453bc1f688bSRobert Mustacchi ctf_merge_add_member(const char *name, ctf_id_t type, ulong_t offset, void *arg)
454bc1f688bSRobert Mustacchi {
455bc1f688bSRobert Mustacchi 	ctf_merge_su_t *cms = arg;
456bc1f688bSRobert Mustacchi 
457bc1f688bSRobert Mustacchi 	VERIFY(cms->cms_cm->cm_tmap[type].cmt_map != 0);
458bc1f688bSRobert Mustacchi 	type = cms->cms_cm->cm_tmap[type].cmt_map;
459bc1f688bSRobert Mustacchi 
460bc1f688bSRobert Mustacchi 	ctf_dprintf("Trying to add member %s to %d\n", name, cms->cms_id);
461bc1f688bSRobert Mustacchi 	return (ctf_add_member(cms->cms_cm->cm_out, cms->cms_id, name,
462bc1f688bSRobert Mustacchi 	    type, offset) == CTF_ERR);
463bc1f688bSRobert Mustacchi }
464bc1f688bSRobert Mustacchi 
465bc1f688bSRobert Mustacchi /*
466bc1f688bSRobert Mustacchi  * During the first pass, we always add the generic structure and union but none
467bc1f688bSRobert Mustacchi  * of its members as they might not all have been mapped yet. Instead we just
468bc1f688bSRobert Mustacchi  * mark all structures and unions as needing to be fixed up.
469bc1f688bSRobert Mustacchi  */
470bc1f688bSRobert Mustacchi static int
ctf_merge_add_sou(ctf_merge_types_t * cmp,ctf_id_t id,boolean_t forward)471bc1f688bSRobert Mustacchi ctf_merge_add_sou(ctf_merge_types_t *cmp, ctf_id_t id, boolean_t forward)
472bc1f688bSRobert Mustacchi {
473bc1f688bSRobert Mustacchi 	int flags, kind;
474bc1f688bSRobert Mustacchi 	const ctf_type_t *tp;
475bc1f688bSRobert Mustacchi 	const char *name;
476bc1f688bSRobert Mustacchi 	ctf_id_t suid;
477bc1f688bSRobert Mustacchi 
478bc1f688bSRobert Mustacchi 	tp = LCTF_INDEX_TO_TYPEPTR(cmp->cm_src, id);
479bc1f688bSRobert Mustacchi 	name = ctf_strraw(cmp->cm_src, tp->ctt_name);
480bc1f688bSRobert Mustacchi 	if (CTF_INFO_ISROOT(tp->ctt_info) != 0)
481bc1f688bSRobert Mustacchi 		flags = CTF_ADD_ROOT;
482bc1f688bSRobert Mustacchi 	else
483bc1f688bSRobert Mustacchi 		flags = CTF_ADD_NONROOT;
484bc1f688bSRobert Mustacchi 	kind = ctf_type_kind(cmp->cm_src, id);
485bc1f688bSRobert Mustacchi 
486bc1f688bSRobert Mustacchi 	if (kind == CTF_K_STRUCT)
487bc1f688bSRobert Mustacchi 		suid = ctf_add_struct(cmp->cm_out, flags, name);
488bc1f688bSRobert Mustacchi 	else
489bc1f688bSRobert Mustacchi 		suid = ctf_add_union(cmp->cm_out, flags, name);
490bc1f688bSRobert Mustacchi 
4913dfdac06SAndy Fiddaman 	ctf_dprintf("added sou \"%s\" as (%d) %d->%d\n", name, kind, id, suid);
4923dfdac06SAndy Fiddaman 
493bc1f688bSRobert Mustacchi 	if (suid == CTF_ERR)
494bc1f688bSRobert Mustacchi 		return (suid);
495bc1f688bSRobert Mustacchi 
496bc1f688bSRobert Mustacchi 	if (forward == B_FALSE) {
497bc1f688bSRobert Mustacchi 		VERIFY(cmp->cm_tmap[id].cmt_map == 0);
498bc1f688bSRobert Mustacchi 		cmp->cm_tmap[id].cmt_map = suid;
499bc1f688bSRobert Mustacchi 	} else {
5003dfdac06SAndy Fiddaman 		/*
5013dfdac06SAndy Fiddaman 		 * If this is a forward reference then its mapping should
5023dfdac06SAndy Fiddaman 		 * already exist.
5033dfdac06SAndy Fiddaman 		 */
5043dfdac06SAndy Fiddaman 		if (cmp->cm_tmap[id].cmt_map != suid) {
5053dfdac06SAndy Fiddaman 			ctf_dprintf(
5063dfdac06SAndy Fiddaman 			    "mismatch sou \"%s\" as (%d) %d->%d (exp %d)\n",
5073dfdac06SAndy Fiddaman 			    name, kind, id, suid, cmp->cm_tmap[id].cmt_map);
5083dfdac06SAndy Fiddaman 			ctf_hash_dump("src structs",
5093dfdac06SAndy Fiddaman 			    &cmp->cm_src->ctf_structs, cmp->cm_src);
5103dfdac06SAndy Fiddaman 			ctf_hash_dump("src unions",
5113dfdac06SAndy Fiddaman 			    &cmp->cm_src->ctf_unions, cmp->cm_src);
5123dfdac06SAndy Fiddaman 			ctf_hash_dump("out structs",
5133dfdac06SAndy Fiddaman 			    &cmp->cm_out->ctf_structs, cmp->cm_out);
5143dfdac06SAndy Fiddaman 			ctf_hash_dump("out unions",
5153dfdac06SAndy Fiddaman 			    &cmp->cm_out->ctf_unions, cmp->cm_out);
5163dfdac06SAndy Fiddaman 		}
517bc1f688bSRobert Mustacchi 		VERIFY(cmp->cm_tmap[id].cmt_map == suid);
518bc1f688bSRobert Mustacchi 	}
519bc1f688bSRobert Mustacchi 	cmp->cm_tmap[id].cmt_fixup = B_TRUE;
520bc1f688bSRobert Mustacchi 
521bc1f688bSRobert Mustacchi 	return (0);
522bc1f688bSRobert Mustacchi }
523bc1f688bSRobert Mustacchi 
524bc1f688bSRobert Mustacchi static int
ctf_merge_add_type(ctf_merge_types_t * cmp,ctf_id_t id)525bc1f688bSRobert Mustacchi ctf_merge_add_type(ctf_merge_types_t *cmp, ctf_id_t id)
526bc1f688bSRobert Mustacchi {
527bc1f688bSRobert Mustacchi 	int kind, ret;
528bc1f688bSRobert Mustacchi 
529bc1f688bSRobert Mustacchi 	/*
530bc1f688bSRobert Mustacchi 	 * We may end up evaluating a type more than once as we may deal with it
531bc1f688bSRobert Mustacchi 	 * as we recursively evaluate some kind of reference and then we may see
532bc1f688bSRobert Mustacchi 	 * it normally.
533bc1f688bSRobert Mustacchi 	 */
534bc1f688bSRobert Mustacchi 	if (cmp->cm_tmap[id].cmt_map != 0)
535bc1f688bSRobert Mustacchi 		return (0);
536bc1f688bSRobert Mustacchi 
537bc1f688bSRobert Mustacchi 	kind = ctf_type_kind(cmp->cm_src, id);
538bc1f688bSRobert Mustacchi 	switch (kind) {
539bc1f688bSRobert Mustacchi 	case CTF_K_INTEGER:
540bc1f688bSRobert Mustacchi 	case CTF_K_FLOAT:
541bc1f688bSRobert Mustacchi 		ret = ctf_merge_add_number(cmp, id);
542bc1f688bSRobert Mustacchi 		break;
543bc1f688bSRobert Mustacchi 	case CTF_K_ARRAY:
544bc1f688bSRobert Mustacchi 		ret = ctf_merge_add_array(cmp, id);
545bc1f688bSRobert Mustacchi 		break;
546bc1f688bSRobert Mustacchi 	case CTF_K_POINTER:
547bc1f688bSRobert Mustacchi 	case CTF_K_VOLATILE:
548bc1f688bSRobert Mustacchi 	case CTF_K_CONST:
549bc1f688bSRobert Mustacchi 	case CTF_K_RESTRICT:
550bc1f688bSRobert Mustacchi 		ret = ctf_merge_add_reftype(cmp, id);
551bc1f688bSRobert Mustacchi 		break;
552bc1f688bSRobert Mustacchi 	case CTF_K_TYPEDEF:
553bc1f688bSRobert Mustacchi 		ret = ctf_merge_add_typedef(cmp, id);
554bc1f688bSRobert Mustacchi 		break;
555bc1f688bSRobert Mustacchi 	case CTF_K_ENUM:
556bc1f688bSRobert Mustacchi 		ret = ctf_merge_add_enum(cmp, id);
557bc1f688bSRobert Mustacchi 		break;
558bc1f688bSRobert Mustacchi 	case CTF_K_FUNCTION:
559bc1f688bSRobert Mustacchi 		ret = ctf_merge_add_func(cmp, id);
560bc1f688bSRobert Mustacchi 		break;
5613dfdac06SAndy Fiddaman 	case CTF_K_FORWARD: {
5623dfdac06SAndy Fiddaman 		const ctf_type_t *tp;
5633dfdac06SAndy Fiddaman 		uint_t kind;
5643dfdac06SAndy Fiddaman 
5653dfdac06SAndy Fiddaman 		tp = LCTF_INDEX_TO_TYPEPTR(cmp->cm_src, id);
5663dfdac06SAndy Fiddaman 
5673dfdac06SAndy Fiddaman 		/*
5683dfdac06SAndy Fiddaman 		 * For forward declarations, ctt_type is the CTF_K_*
5693dfdac06SAndy Fiddaman 		 * kind for the tag. Older versions of the CTF tools may
5703dfdac06SAndy Fiddaman 		 * not have filled this in so if ctt_type is unknown or
5713dfdac06SAndy Fiddaman 		 * invalid, treat it as a struct. This mirrors the logic in
5723dfdac06SAndy Fiddaman 		 * ctf_bufopen().
5733dfdac06SAndy Fiddaman 		 */
5743dfdac06SAndy Fiddaman 
5753dfdac06SAndy Fiddaman 		kind = tp->ctt_type;
5763dfdac06SAndy Fiddaman 		if (kind == CTF_K_UNKNOWN || kind >= CTF_K_MAX)
5773dfdac06SAndy Fiddaman 			kind = CTF_K_STRUCT;
5783dfdac06SAndy Fiddaman 
5793dfdac06SAndy Fiddaman 		ret = ctf_merge_add_forward(cmp, id, kind);
580bc1f688bSRobert Mustacchi 		break;
5813dfdac06SAndy Fiddaman 	}
582bc1f688bSRobert Mustacchi 	case CTF_K_STRUCT:
583bc1f688bSRobert Mustacchi 	case CTF_K_UNION:
584bc1f688bSRobert Mustacchi 		ret = ctf_merge_add_sou(cmp, id, B_FALSE);
585bc1f688bSRobert Mustacchi 		break;
586bc1f688bSRobert Mustacchi 	case CTF_K_UNKNOWN:
587bc1f688bSRobert Mustacchi 		/*
588bc1f688bSRobert Mustacchi 		 * We don't add unknown types, and we later assert that nothing
589bc1f688bSRobert Mustacchi 		 * should reference them.
590bc1f688bSRobert Mustacchi 		 */
591bc1f688bSRobert Mustacchi 		return (0);
592bc1f688bSRobert Mustacchi 	default:
593bc1f688bSRobert Mustacchi 		abort();
594bc1f688bSRobert Mustacchi 	}
595bc1f688bSRobert Mustacchi 
596bc1f688bSRobert Mustacchi 	return (ret);
597bc1f688bSRobert Mustacchi }
598bc1f688bSRobert Mustacchi 
599bc1f688bSRobert Mustacchi static int
ctf_merge_fixup_sou(ctf_merge_types_t * cmp,ctf_id_t id)600bc1f688bSRobert Mustacchi ctf_merge_fixup_sou(ctf_merge_types_t *cmp, ctf_id_t id)
601bc1f688bSRobert Mustacchi {
602bc1f688bSRobert Mustacchi 	ctf_dtdef_t *dtd;
603bc1f688bSRobert Mustacchi 	ctf_merge_su_t cms;
604bc1f688bSRobert Mustacchi 	ctf_id_t mapid;
605bc1f688bSRobert Mustacchi 	ssize_t size;
606bc1f688bSRobert Mustacchi 
607bc1f688bSRobert Mustacchi 	mapid = cmp->cm_tmap[id].cmt_map;
608bc1f688bSRobert Mustacchi 	VERIFY(mapid != 0);
609bc1f688bSRobert Mustacchi 	dtd = ctf_dtd_lookup(cmp->cm_out, mapid);
610bc1f688bSRobert Mustacchi 	VERIFY(dtd != NULL);
611bc1f688bSRobert Mustacchi 
612bc1f688bSRobert Mustacchi 	ctf_dprintf("Trying to fix up sou %d\n", id);
613bc1f688bSRobert Mustacchi 	cms.cms_cm = cmp;
614bc1f688bSRobert Mustacchi 	cms.cms_id = mapid;
615bc1f688bSRobert Mustacchi 	if (ctf_member_iter(cmp->cm_src, id, ctf_merge_add_member, &cms) != 0)
616bc1f688bSRobert Mustacchi 		return (CTF_ERR);
617bc1f688bSRobert Mustacchi 
618bc1f688bSRobert Mustacchi 	if ((size = ctf_type_size(cmp->cm_src, id)) == CTF_ERR)
619bc1f688bSRobert Mustacchi 		return (CTF_ERR);
620bc1f688bSRobert Mustacchi 	if (ctf_set_size(cmp->cm_out, mapid, size) == CTF_ERR)
621bc1f688bSRobert Mustacchi 		return (CTF_ERR);
622bc1f688bSRobert Mustacchi 
623bc1f688bSRobert Mustacchi 	return (0);
624bc1f688bSRobert Mustacchi }
625bc1f688bSRobert Mustacchi 
626bc1f688bSRobert Mustacchi static int
ctf_merge_fixup_type(ctf_merge_types_t * cmp,ctf_id_t id)627bc1f688bSRobert Mustacchi ctf_merge_fixup_type(ctf_merge_types_t *cmp, ctf_id_t id)
628bc1f688bSRobert Mustacchi {
629bc1f688bSRobert Mustacchi 	int kind, ret;
630bc1f688bSRobert Mustacchi 
631bc1f688bSRobert Mustacchi 	kind = ctf_type_kind(cmp->cm_src, id);
632bc1f688bSRobert Mustacchi 	switch (kind) {
633bc1f688bSRobert Mustacchi 	case CTF_K_STRUCT:
634bc1f688bSRobert Mustacchi 	case CTF_K_UNION:
635bc1f688bSRobert Mustacchi 		ret = ctf_merge_fixup_sou(cmp, id);
636bc1f688bSRobert Mustacchi 		break;
637bc1f688bSRobert Mustacchi 	default:
638bc1f688bSRobert Mustacchi 		VERIFY(0);
639bc1f688bSRobert Mustacchi 		ret = CTF_ERR;
640bc1f688bSRobert Mustacchi 	}
641bc1f688bSRobert Mustacchi 
642bc1f688bSRobert Mustacchi 	return (ret);
643bc1f688bSRobert Mustacchi }
644bc1f688bSRobert Mustacchi 
645bc1f688bSRobert Mustacchi /*
6465215e750SJohn Levon  * Now that we've successfully merged everything, we're going to remap the type
6475215e750SJohn Levon  * table.
6485215e750SJohn Levon  *
6495215e750SJohn Levon  * Remember we have two containers: ->cm_src is what we're working from, and
6505215e750SJohn Levon  * ->cm_out is where we are building the de-duplicated CTF.
6515215e750SJohn Levon  *
6525215e750SJohn Levon  * The index of this table is always the type IDs in ->cm_src.
6535215e750SJohn Levon  *
6545215e750SJohn Levon  * When we built this table originally in ctf_diff_self(), if we found a novel
6555215e750SJohn Levon  * type, we marked it as .cmt_missing to indicate it needs adding to ->cm_out.
6565215e750SJohn Levon  * Otherwise, .cmt_map indicated the ->cm_src type ID that this type duplicates.
6575215e750SJohn Levon  *
6585215e750SJohn Levon  * Then, in ctf_merge_common(), we walked through and added all "cmt_missing"
6595215e750SJohn Levon  * types to ->cm_out with ctf_merge_add_type(). These routines update cmt_map
6605215e750SJohn Levon  * to be the *new* type ID in ->cm_out.  In this function, you can read
6615215e750SJohn Levon  * "cmt_missing" as meaning "added to ->cm_out, and cmt_map updated".
6625215e750SJohn Levon  *
6635215e750SJohn Levon  * So at this point, we need to mop up all types where .cmt_missing == B_FALSE,
6645215e750SJohn Levon  * making sure *their* .cmt_map values also point to the ->cm_out container.
665bc1f688bSRobert Mustacchi  */
666bc1f688bSRobert Mustacchi static void
ctf_merge_dedup_remap(ctf_merge_types_t * cmp)6675215e750SJohn Levon ctf_merge_dedup_remap(ctf_merge_types_t *cmp)
668bc1f688bSRobert Mustacchi {
669bc1f688bSRobert Mustacchi 	int i;
670bc1f688bSRobert Mustacchi 
671bc1f688bSRobert Mustacchi 	for (i = 1; i < cmp->cm_src->ctf_typemax + 1; i++) {
672bc1f688bSRobert Mustacchi 		ctf_id_t tid;
673bc1f688bSRobert Mustacchi 
674bc1f688bSRobert Mustacchi 		if (cmp->cm_tmap[i].cmt_missing == B_TRUE) {
675bc1f688bSRobert Mustacchi 			VERIFY(cmp->cm_tmap[i].cmt_map != 0);
676bc1f688bSRobert Mustacchi 			continue;
677bc1f688bSRobert Mustacchi 		}
678bc1f688bSRobert Mustacchi 
679bc1f688bSRobert Mustacchi 		tid = i;
680bc1f688bSRobert Mustacchi 		while (cmp->cm_tmap[tid].cmt_missing == B_FALSE) {
681bc1f688bSRobert Mustacchi 			VERIFY(cmp->cm_tmap[tid].cmt_map != 0);
682bc1f688bSRobert Mustacchi 			tid = cmp->cm_tmap[tid].cmt_map;
683bc1f688bSRobert Mustacchi 		}
684bc1f688bSRobert Mustacchi 		VERIFY(cmp->cm_tmap[tid].cmt_map != 0);
685bc1f688bSRobert Mustacchi 		cmp->cm_tmap[i].cmt_map = cmp->cm_tmap[tid].cmt_map;
686bc1f688bSRobert Mustacchi 	}
687bc1f688bSRobert Mustacchi }
688bc1f688bSRobert Mustacchi 
689bc1f688bSRobert Mustacchi 
690bc1f688bSRobert Mustacchi /*
691bc1f688bSRobert Mustacchi  * We're going to do three passes over the containers.
692bc1f688bSRobert Mustacchi  *
693bc1f688bSRobert Mustacchi  * Pass 1 checks for forward references in the output container that we know
694bc1f688bSRobert Mustacchi  * exist in the source container.
695bc1f688bSRobert Mustacchi  *
696bc1f688bSRobert Mustacchi  * Pass 2 adds all the missing types from the source container. As part of this
697bc1f688bSRobert Mustacchi  * we may be adding a type as a forward reference that doesn't exist yet.
698bc1f688bSRobert Mustacchi  * Any types that we encounter in this form, we need to add to a third pass.
699bc1f688bSRobert Mustacchi  *
700bc1f688bSRobert Mustacchi  * Pass 3 is the fixup pass. Here we go through and find all the types that were
701bc1f688bSRobert Mustacchi  * missing in the first.
702bc1f688bSRobert Mustacchi  *
703bc1f688bSRobert Mustacchi  * Importantly, we *must* call ctf_update between the second and third pass,
704bc1f688bSRobert Mustacchi  * otherwise several of the libctf functions will not properly find the data in
705bc1f688bSRobert Mustacchi  * the container. If we're doing a dedup we also fix up the type mapping.
706bc1f688bSRobert Mustacchi  */
707bc1f688bSRobert Mustacchi static int
ctf_merge_common(ctf_merge_types_t * cmp)708bc1f688bSRobert Mustacchi ctf_merge_common(ctf_merge_types_t *cmp)
709bc1f688bSRobert Mustacchi {
710bc1f688bSRobert Mustacchi 	int ret, i;
711bc1f688bSRobert Mustacchi 
71237e82d12SRobert Mustacchi 	ctf_phase_dump(cmp->cm_src, "merge-common-src", NULL);
71337e82d12SRobert Mustacchi 	ctf_phase_dump(cmp->cm_out, "merge-common-dest", NULL);
714bc1f688bSRobert Mustacchi 
715bc1f688bSRobert Mustacchi 	/* Pass 1 */
716bc1f688bSRobert Mustacchi 	for (i = 1; i <= cmp->cm_src->ctf_typemax; i++) {
717bc1f688bSRobert Mustacchi 		if (cmp->cm_tmap[i].cmt_forward == B_TRUE) {
7183dfdac06SAndy Fiddaman 			ctf_dprintf("Forward %d\n", i);
719bc1f688bSRobert Mustacchi 			ret = ctf_merge_add_sou(cmp, i, B_TRUE);
720bc1f688bSRobert Mustacchi 			if (ret != 0) {
721bc1f688bSRobert Mustacchi 				return (ret);
722bc1f688bSRobert Mustacchi 			}
723bc1f688bSRobert Mustacchi 		}
724bc1f688bSRobert Mustacchi 	}
725bc1f688bSRobert Mustacchi 
726bc1f688bSRobert Mustacchi 	/* Pass 2 */
727bc1f688bSRobert Mustacchi 	for (i = 1; i <= cmp->cm_src->ctf_typemax; i++) {
728bc1f688bSRobert Mustacchi 		if (cmp->cm_tmap[i].cmt_missing == B_TRUE) {
729bc1f688bSRobert Mustacchi 			ret = ctf_merge_add_type(cmp, i);
730bc1f688bSRobert Mustacchi 			if (ret != 0) {
731bc1f688bSRobert Mustacchi 				ctf_dprintf("Failed to merge type %d\n", i);
732bc1f688bSRobert Mustacchi 				return (ret);
733bc1f688bSRobert Mustacchi 			}
734bc1f688bSRobert Mustacchi 		}
735bc1f688bSRobert Mustacchi 	}
736bc1f688bSRobert Mustacchi 
737bc1f688bSRobert Mustacchi 	ret = ctf_update(cmp->cm_out);
738bc1f688bSRobert Mustacchi 	if (ret != 0)
739bc1f688bSRobert Mustacchi 		return (ret);
740bc1f688bSRobert Mustacchi 
741bc1f688bSRobert Mustacchi 	if (cmp->cm_dedup == B_TRUE) {
7425215e750SJohn Levon 		ctf_merge_dedup_remap(cmp);
743bc1f688bSRobert Mustacchi 	}
744bc1f688bSRobert Mustacchi 
745bc1f688bSRobert Mustacchi 	ctf_dprintf("Beginning merge pass 3\n");
746bc1f688bSRobert Mustacchi 	/* Pass 3 */
747bc1f688bSRobert Mustacchi 	for (i = 1; i <= cmp->cm_src->ctf_typemax; i++) {
748bc1f688bSRobert Mustacchi 		if (cmp->cm_tmap[i].cmt_fixup == B_TRUE) {
749bc1f688bSRobert Mustacchi 			ret = ctf_merge_fixup_type(cmp, i);
750bc1f688bSRobert Mustacchi 			if (ret != 0)
751bc1f688bSRobert Mustacchi 				return (ret);
752bc1f688bSRobert Mustacchi 		}
753bc1f688bSRobert Mustacchi 	}
754bc1f688bSRobert Mustacchi 
755bc1f688bSRobert Mustacchi 	return (0);
756bc1f688bSRobert Mustacchi }
757bc1f688bSRobert Mustacchi 
758bc1f688bSRobert Mustacchi /*
759bc1f688bSRobert Mustacchi  * Uniquification is slightly different from a stock merge. For starters, we
760bc1f688bSRobert Mustacchi  * don't need to replace any forward references in the output. In this case
761bc1f688bSRobert Mustacchi  * though, the types that already exist are in a parent container to the empty
762bc1f688bSRobert Mustacchi  * output container.
763bc1f688bSRobert Mustacchi  */
764bc1f688bSRobert Mustacchi static int
ctf_merge_uniquify_types(ctf_merge_types_t * cmp)765bc1f688bSRobert Mustacchi ctf_merge_uniquify_types(ctf_merge_types_t *cmp)
766bc1f688bSRobert Mustacchi {
767bc1f688bSRobert Mustacchi 	int i, ret;
768bc1f688bSRobert Mustacchi 
769bc1f688bSRobert Mustacchi 	for (i = 1; i <= cmp->cm_src->ctf_typemax; i++) {
770bc1f688bSRobert Mustacchi 		if (cmp->cm_tmap[i].cmt_missing == B_FALSE)
771bc1f688bSRobert Mustacchi 			continue;
772bc1f688bSRobert Mustacchi 		ret = ctf_merge_add_type(cmp, i);
773bc1f688bSRobert Mustacchi 		if (ret != 0)
774bc1f688bSRobert Mustacchi 			return (ret);
775bc1f688bSRobert Mustacchi 	}
776bc1f688bSRobert Mustacchi 
777bc1f688bSRobert Mustacchi 	ret = ctf_update(cmp->cm_out);
778bc1f688bSRobert Mustacchi 	if (ret != 0)
779bc1f688bSRobert Mustacchi 		return (ret);
780bc1f688bSRobert Mustacchi 
781bc1f688bSRobert Mustacchi 	for (i = 1; i <= cmp->cm_src->ctf_typemax; i++) {
782bc1f688bSRobert Mustacchi 		if (cmp->cm_tmap[i].cmt_fixup == B_FALSE)
783bc1f688bSRobert Mustacchi 			continue;
784bc1f688bSRobert Mustacchi 		ret = ctf_merge_fixup_type(cmp, i);
785bc1f688bSRobert Mustacchi 		if (ret != 0)
786bc1f688bSRobert Mustacchi 			return (ret);
787bc1f688bSRobert Mustacchi 	}
788bc1f688bSRobert Mustacchi 
789bc1f688bSRobert Mustacchi 	return (0);
790bc1f688bSRobert Mustacchi }
791bc1f688bSRobert Mustacchi 
792bc1f688bSRobert Mustacchi static int
ctf_merge_types_init(ctf_merge_types_t * cmp)793bc1f688bSRobert Mustacchi ctf_merge_types_init(ctf_merge_types_t *cmp)
794bc1f688bSRobert Mustacchi {
795bc1f688bSRobert Mustacchi 	cmp->cm_tmap = ctf_alloc(sizeof (ctf_merge_tinfo_t) *
796bc1f688bSRobert Mustacchi 	    (cmp->cm_src->ctf_typemax + 1));
797bc1f688bSRobert Mustacchi 	if (cmp->cm_tmap == NULL)
798bc1f688bSRobert Mustacchi 		return (ctf_set_errno(cmp->cm_out, ENOMEM));
799bc1f688bSRobert Mustacchi 	bzero(cmp->cm_tmap, sizeof (ctf_merge_tinfo_t) *
800bc1f688bSRobert Mustacchi 	    (cmp->cm_src->ctf_typemax + 1));
801bc1f688bSRobert Mustacchi 	return (0);
802bc1f688bSRobert Mustacchi }
803bc1f688bSRobert Mustacchi 
804bc1f688bSRobert Mustacchi static void
ctf_merge_types_fini(ctf_merge_types_t * cmp)805bc1f688bSRobert Mustacchi ctf_merge_types_fini(ctf_merge_types_t *cmp)
806bc1f688bSRobert Mustacchi {
807bc1f688bSRobert Mustacchi 	ctf_free(cmp->cm_tmap, sizeof (ctf_merge_tinfo_t) *
808bc1f688bSRobert Mustacchi 	    (cmp->cm_src->ctf_typemax + 1));
809bc1f688bSRobert Mustacchi }
810bc1f688bSRobert Mustacchi 
81137e82d12SRobert Mustacchi /*
81237e82d12SRobert Mustacchi  * After performing a pass, we need to go through the object and function type
81337e82d12SRobert Mustacchi  * maps and potentially fix them up based on the new maps that we have.
81437e82d12SRobert Mustacchi  */
81537e82d12SRobert Mustacchi static void
ctf_merge_fixup_symmaps(ctf_merge_types_t * cmp,ctf_merge_input_t * cmi)81637e82d12SRobert Mustacchi ctf_merge_fixup_symmaps(ctf_merge_types_t *cmp, ctf_merge_input_t *cmi)
81737e82d12SRobert Mustacchi {
81837e82d12SRobert Mustacchi 	ctf_merge_objmap_t *cmo;
81937e82d12SRobert Mustacchi 	ctf_merge_funcmap_t *cmf;
82037e82d12SRobert Mustacchi 
82137e82d12SRobert Mustacchi 	for (cmo = list_head(&cmi->cmi_omap); cmo != NULL;
82237e82d12SRobert Mustacchi 	    cmo = list_next(&cmi->cmi_omap, cmo)) {
82337e82d12SRobert Mustacchi 		VERIFY3S(cmo->cmo_tid, !=, 0);
82437e82d12SRobert Mustacchi 		VERIFY(cmp->cm_tmap[cmo->cmo_tid].cmt_map != 0);
82537e82d12SRobert Mustacchi 		cmo->cmo_tid = cmp->cm_tmap[cmo->cmo_tid].cmt_map;
82637e82d12SRobert Mustacchi 	}
82737e82d12SRobert Mustacchi 
82837e82d12SRobert Mustacchi 	for (cmf = list_head(&cmi->cmi_fmap); cmf != NULL;
82937e82d12SRobert Mustacchi 	    cmf = list_next(&cmi->cmi_fmap, cmf)) {
83037e82d12SRobert Mustacchi 		int i;
83137e82d12SRobert Mustacchi 
83237e82d12SRobert Mustacchi 		VERIFY(cmp->cm_tmap[cmf->cmf_rtid].cmt_map != 0);
83337e82d12SRobert Mustacchi 		cmf->cmf_rtid = cmp->cm_tmap[cmf->cmf_rtid].cmt_map;
83437e82d12SRobert Mustacchi 		for (i = 0; i < cmf->cmf_argc; i++) {
83537e82d12SRobert Mustacchi 			VERIFY(cmp->cm_tmap[cmf->cmf_args[i]].cmt_map != 0);
83637e82d12SRobert Mustacchi 			cmf->cmf_args[i] =
83737e82d12SRobert Mustacchi 			    cmp->cm_tmap[cmf->cmf_args[i]].cmt_map;
83837e82d12SRobert Mustacchi 		}
83937e82d12SRobert Mustacchi 	}
84037e82d12SRobert Mustacchi }
84137e82d12SRobert Mustacchi 
842bc1f688bSRobert Mustacchi /*
843bc1f688bSRobert Mustacchi  * Merge the types contained inside of two input files. The second input file is
844bc1f688bSRobert Mustacchi  * always going to be the destination. We're guaranteed that it's always
845bc1f688bSRobert Mustacchi  * writeable.
846bc1f688bSRobert Mustacchi  */
847bc1f688bSRobert Mustacchi static int
ctf_merge_types(void * arg,void * arg2,void ** outp,void * unsued)848bc1f688bSRobert Mustacchi ctf_merge_types(void *arg, void *arg2, void **outp, void *unsued)
849bc1f688bSRobert Mustacchi {
850bc1f688bSRobert Mustacchi 	int ret;
851bc1f688bSRobert Mustacchi 	ctf_merge_types_t cm;
852bc1f688bSRobert Mustacchi 	ctf_diff_t *cdp;
853bc1f688bSRobert Mustacchi 	ctf_merge_input_t *scmi = arg;
854bc1f688bSRobert Mustacchi 	ctf_merge_input_t *dcmi = arg2;
855bc1f688bSRobert Mustacchi 	ctf_file_t *out = dcmi->cmi_input;
856bc1f688bSRobert Mustacchi 	ctf_file_t *source = scmi->cmi_input;
857bc1f688bSRobert Mustacchi 
858bc1f688bSRobert Mustacchi 	ctf_dprintf("merging %p->%p\n", source, out);
859bc1f688bSRobert Mustacchi 
860bc1f688bSRobert Mustacchi 	if (!(out->ctf_flags & LCTF_RDWR))
861bc1f688bSRobert Mustacchi 		return (ctf_set_errno(out, ECTF_RDONLY));
862bc1f688bSRobert Mustacchi 
863bc1f688bSRobert Mustacchi 	if (ctf_getmodel(out) != ctf_getmodel(source))
864bc1f688bSRobert Mustacchi 		return (ctf_set_errno(out, ECTF_DMODEL));
865bc1f688bSRobert Mustacchi 
866bc1f688bSRobert Mustacchi 	if ((ret = ctf_diff_init(out, source, &cdp)) != 0)
867bc1f688bSRobert Mustacchi 		return (ret);
868bc1f688bSRobert Mustacchi 
869bc1f688bSRobert Mustacchi 	cm.cm_out = out;
870bc1f688bSRobert Mustacchi 	cm.cm_src = source;
871bc1f688bSRobert Mustacchi 	cm.cm_dedup = B_FALSE;
872bc1f688bSRobert Mustacchi 	cm.cm_unique = B_FALSE;
873bc1f688bSRobert Mustacchi 	ret = ctf_merge_types_init(&cm);
874bc1f688bSRobert Mustacchi 	if (ret != 0) {
875bc1f688bSRobert Mustacchi 		ctf_diff_fini(cdp);
876bc1f688bSRobert Mustacchi 		return (ctf_set_errno(out, ret));
877bc1f688bSRobert Mustacchi 	}
878bc1f688bSRobert Mustacchi 
879bc1f688bSRobert Mustacchi 	ret = ctf_diff_types(cdp, ctf_merge_diffcb, &cm);
880bc1f688bSRobert Mustacchi 	if (ret != 0)
881bc1f688bSRobert Mustacchi 		goto cleanup;
882bc1f688bSRobert Mustacchi 	ret = ctf_merge_common(&cm);
883bc1f688bSRobert Mustacchi 	ctf_dprintf("merge common returned with %d\n", ret);
884bc1f688bSRobert Mustacchi 	if (ret == 0) {
885bc1f688bSRobert Mustacchi 		ret = ctf_update(out);
886bc1f688bSRobert Mustacchi 		ctf_dprintf("update returned with %d\n", ret);
887bc1f688bSRobert Mustacchi 	} else {
888bc1f688bSRobert Mustacchi 		goto cleanup;
889bc1f688bSRobert Mustacchi 	}
890bc1f688bSRobert Mustacchi 
891bc1f688bSRobert Mustacchi 	/*
892bc1f688bSRobert Mustacchi 	 * Now we need to fix up the object and function maps.
893bc1f688bSRobert Mustacchi 	 */
89437e82d12SRobert Mustacchi 	ctf_merge_fixup_symmaps(&cm, scmi);
895bc1f688bSRobert Mustacchi 
896bc1f688bSRobert Mustacchi 	/*
897bc1f688bSRobert Mustacchi 	 * Now that we've fixed things up, we need to give our function and
898bc1f688bSRobert Mustacchi 	 * object maps to the destination, such that it can continue to update
899bc1f688bSRobert Mustacchi 	 * them going forward.
900bc1f688bSRobert Mustacchi 	 */
901bc1f688bSRobert Mustacchi 	list_move_tail(&dcmi->cmi_fmap, &scmi->cmi_fmap);
902bc1f688bSRobert Mustacchi 	list_move_tail(&dcmi->cmi_omap, &scmi->cmi_omap);
903bc1f688bSRobert Mustacchi 
904bc1f688bSRobert Mustacchi cleanup:
905bc1f688bSRobert Mustacchi 	if (ret == 0)
906bc1f688bSRobert Mustacchi 		*outp = dcmi;
907bc1f688bSRobert Mustacchi 	ctf_merge_types_fini(&cm);
908bc1f688bSRobert Mustacchi 	ctf_diff_fini(cdp);
909bc1f688bSRobert Mustacchi 	if (ret != 0)
910bc1f688bSRobert Mustacchi 		return (ctf_errno(out));
91137e82d12SRobert Mustacchi 	ctf_phase_bump();
912bc1f688bSRobert Mustacchi 	return (0);
913bc1f688bSRobert Mustacchi }
914bc1f688bSRobert Mustacchi 
915bc1f688bSRobert Mustacchi static int
ctf_uniquify_types(ctf_merge_t * cmh,ctf_file_t * src,ctf_file_t ** outp)916bc1f688bSRobert Mustacchi ctf_uniquify_types(ctf_merge_t *cmh, ctf_file_t *src, ctf_file_t **outp)
917bc1f688bSRobert Mustacchi {
918bc1f688bSRobert Mustacchi 	int err, ret;
919bc1f688bSRobert Mustacchi 	ctf_file_t *out;
920bc1f688bSRobert Mustacchi 	ctf_merge_types_t cm;
921bc1f688bSRobert Mustacchi 	ctf_diff_t *cdp;
922bc1f688bSRobert Mustacchi 	ctf_merge_input_t *cmi;
923bc1f688bSRobert Mustacchi 	ctf_file_t *parent = cmh->cmh_unique;
924bc1f688bSRobert Mustacchi 
925bc1f688bSRobert Mustacchi 	*outp = NULL;
926bc1f688bSRobert Mustacchi 	out = ctf_fdcreate(cmh->cmh_ofd, &err);
927bc1f688bSRobert Mustacchi 	if (out == NULL)
928bc1f688bSRobert Mustacchi 		return (ctf_set_errno(src, err));
929bc1f688bSRobert Mustacchi 
930bc1f688bSRobert Mustacchi 	out->ctf_parname = cmh->cmh_pname;
931bc1f688bSRobert Mustacchi 	if (ctf_setmodel(out, ctf_getmodel(parent)) != 0) {
932bc1f688bSRobert Mustacchi 		(void) ctf_set_errno(src, ctf_errno(out));
933bc1f688bSRobert Mustacchi 		ctf_close(out);
934bc1f688bSRobert Mustacchi 		return (CTF_ERR);
935bc1f688bSRobert Mustacchi 	}
936bc1f688bSRobert Mustacchi 
937bc1f688bSRobert Mustacchi 	if (ctf_import(out, parent) != 0) {
938bc1f688bSRobert Mustacchi 		(void) ctf_set_errno(src, ctf_errno(out));
939bc1f688bSRobert Mustacchi 		ctf_close(out);
940bc1f688bSRobert Mustacchi 		return (CTF_ERR);
941bc1f688bSRobert Mustacchi 	}
942bc1f688bSRobert Mustacchi 
943bc1f688bSRobert Mustacchi 	if ((ret = ctf_diff_init(parent, src, &cdp)) != 0) {
944bc1f688bSRobert Mustacchi 		ctf_close(out);
945bc1f688bSRobert Mustacchi 		return (ctf_set_errno(src, ctf_errno(parent)));
946bc1f688bSRobert Mustacchi 	}
947bc1f688bSRobert Mustacchi 
948bc1f688bSRobert Mustacchi 	cm.cm_out = parent;
949bc1f688bSRobert Mustacchi 	cm.cm_src = src;
950bc1f688bSRobert Mustacchi 	cm.cm_dedup = B_FALSE;
951bc1f688bSRobert Mustacchi 	cm.cm_unique = B_TRUE;
952bc1f688bSRobert Mustacchi 	ret = ctf_merge_types_init(&cm);
953bc1f688bSRobert Mustacchi 	if (ret != 0) {
954bc1f688bSRobert Mustacchi 		ctf_close(out);
955bc1f688bSRobert Mustacchi 		ctf_diff_fini(cdp);
956bc1f688bSRobert Mustacchi 		return (ctf_set_errno(src, ret));
957bc1f688bSRobert Mustacchi 	}
958bc1f688bSRobert Mustacchi 
959bc1f688bSRobert Mustacchi 	ret = ctf_diff_types(cdp, ctf_merge_diffcb, &cm);
960bc1f688bSRobert Mustacchi 	if (ret == 0) {
961bc1f688bSRobert Mustacchi 		cm.cm_out = out;
962bc1f688bSRobert Mustacchi 		ret = ctf_merge_uniquify_types(&cm);
963bc1f688bSRobert Mustacchi 		if (ret == 0)
964bc1f688bSRobert Mustacchi 			ret = ctf_update(out);
965bc1f688bSRobert Mustacchi 	}
966bc1f688bSRobert Mustacchi 
967bc1f688bSRobert Mustacchi 	if (ret != 0) {
968bc1f688bSRobert Mustacchi 		ctf_merge_types_fini(&cm);
969bc1f688bSRobert Mustacchi 		ctf_diff_fini(cdp);
970bc1f688bSRobert Mustacchi 		return (ctf_set_errno(src, ctf_errno(cm.cm_out)));
971bc1f688bSRobert Mustacchi 	}
972bc1f688bSRobert Mustacchi 
973bc1f688bSRobert Mustacchi 	for (cmi = list_head(&cmh->cmh_inputs); cmi != NULL;
974bc1f688bSRobert Mustacchi 	    cmi = list_next(&cmh->cmh_inputs, cmi)) {
97537e82d12SRobert Mustacchi 		ctf_merge_fixup_symmaps(&cm, cmi);
976bc1f688bSRobert Mustacchi 	}
977bc1f688bSRobert Mustacchi 
978bc1f688bSRobert Mustacchi 	ctf_merge_types_fini(&cm);
979bc1f688bSRobert Mustacchi 	ctf_diff_fini(cdp);
980bc1f688bSRobert Mustacchi 	*outp = out;
981bc1f688bSRobert Mustacchi 	return (0);
982bc1f688bSRobert Mustacchi }
983bc1f688bSRobert Mustacchi 
984bc1f688bSRobert Mustacchi static void
ctf_merge_fini_input(ctf_merge_input_t * cmi)985bc1f688bSRobert Mustacchi ctf_merge_fini_input(ctf_merge_input_t *cmi)
986bc1f688bSRobert Mustacchi {
987bc1f688bSRobert Mustacchi 	ctf_merge_objmap_t *cmo;
988bc1f688bSRobert Mustacchi 	ctf_merge_funcmap_t *cmf;
989bc1f688bSRobert Mustacchi 
990bc1f688bSRobert Mustacchi 	while ((cmo = list_remove_head(&cmi->cmi_omap)) != NULL)
991bc1f688bSRobert Mustacchi 		ctf_free(cmo, sizeof (ctf_merge_objmap_t));
992bc1f688bSRobert Mustacchi 
993bc1f688bSRobert Mustacchi 	while ((cmf = list_remove_head(&cmi->cmi_fmap)) != NULL)
994bc1f688bSRobert Mustacchi 		ctf_free(cmf, sizeof (ctf_merge_funcmap_t) +
995bc1f688bSRobert Mustacchi 		    sizeof (ctf_id_t) * cmf->cmf_argc);
996bc1f688bSRobert Mustacchi 
997bc1f688bSRobert Mustacchi 	if (cmi->cmi_created == B_TRUE && cmi->cmi_input != NULL)
998bc1f688bSRobert Mustacchi 		ctf_close(cmi->cmi_input);
999bc1f688bSRobert Mustacchi 
1000bc1f688bSRobert Mustacchi 	ctf_free(cmi, sizeof (ctf_merge_input_t));
1001bc1f688bSRobert Mustacchi }
1002bc1f688bSRobert Mustacchi 
1003bc1f688bSRobert Mustacchi void
ctf_merge_fini(ctf_merge_t * cmh)1004bc1f688bSRobert Mustacchi ctf_merge_fini(ctf_merge_t *cmh)
1005bc1f688bSRobert Mustacchi {
1006bc1f688bSRobert Mustacchi 	ctf_merge_input_t *cmi;
1007bc1f688bSRobert Mustacchi 
1008*88a08813SAndy Fiddaman 	ctf_strfree(cmh->cmh_label);
1009*88a08813SAndy Fiddaman 	ctf_strfree(cmh->cmh_pname);
1010bc1f688bSRobert Mustacchi 
1011bc1f688bSRobert Mustacchi 	while ((cmi = list_remove_head(&cmh->cmh_inputs)) != NULL)
1012bc1f688bSRobert Mustacchi 		ctf_merge_fini_input(cmi);
1013bc1f688bSRobert Mustacchi 
1014bc1f688bSRobert Mustacchi 	ctf_free(cmh, sizeof (ctf_merge_t));
1015bc1f688bSRobert Mustacchi }
1016bc1f688bSRobert Mustacchi 
1017bc1f688bSRobert Mustacchi ctf_merge_t *
ctf_merge_init(int fd,int * errp)1018bc1f688bSRobert Mustacchi ctf_merge_init(int fd, int *errp)
1019bc1f688bSRobert Mustacchi {
1020bc1f688bSRobert Mustacchi 	int err;
1021bc1f688bSRobert Mustacchi 	ctf_merge_t *out;
1022bc1f688bSRobert Mustacchi 	struct stat st;
1023bc1f688bSRobert Mustacchi 
1024bc1f688bSRobert Mustacchi 	if (errp == NULL)
1025bc1f688bSRobert Mustacchi 		errp = &err;
1026bc1f688bSRobert Mustacchi 
1027bc1f688bSRobert Mustacchi 	if (fd != -1 && fstat(fd, &st) != 0) {
1028bc1f688bSRobert Mustacchi 		*errp = EINVAL;
1029bc1f688bSRobert Mustacchi 		return (NULL);
1030bc1f688bSRobert Mustacchi 	}
1031bc1f688bSRobert Mustacchi 
1032bc1f688bSRobert Mustacchi 	out = ctf_alloc(sizeof (ctf_merge_t));
1033bc1f688bSRobert Mustacchi 	if (out == NULL) {
1034bc1f688bSRobert Mustacchi 		*errp = ENOMEM;
1035bc1f688bSRobert Mustacchi 		return (NULL);
1036bc1f688bSRobert Mustacchi 	}
1037bc1f688bSRobert Mustacchi 
1038bc1f688bSRobert Mustacchi 	if (fd == -1) {
1039bc1f688bSRobert Mustacchi 		out->cmh_msyms = B_FALSE;
1040bc1f688bSRobert Mustacchi 	} else {
1041bc1f688bSRobert Mustacchi 		out->cmh_msyms = B_TRUE;
1042bc1f688bSRobert Mustacchi 	}
1043bc1f688bSRobert Mustacchi 
1044bc1f688bSRobert Mustacchi 	list_create(&out->cmh_inputs, sizeof (ctf_merge_input_t),
1045bc1f688bSRobert Mustacchi 	    offsetof(ctf_merge_input_t, cmi_node));
1046bc1f688bSRobert Mustacchi 	out->cmh_ninputs = 0;
1047bc1f688bSRobert Mustacchi 	out->cmh_nthreads = 1;
1048bc1f688bSRobert Mustacchi 	out->cmh_unique = NULL;
1049bc1f688bSRobert Mustacchi 	out->cmh_ofd = fd;
1050bc1f688bSRobert Mustacchi 	out->cmh_flags = 0;
1051bc1f688bSRobert Mustacchi 	out->cmh_label = NULL;
1052bc1f688bSRobert Mustacchi 	out->cmh_pname = NULL;
1053bc1f688bSRobert Mustacchi 
1054bc1f688bSRobert Mustacchi 	return (out);
1055bc1f688bSRobert Mustacchi }
1056bc1f688bSRobert Mustacchi 
1057bc1f688bSRobert Mustacchi int
ctf_merge_label(ctf_merge_t * cmh,const char * label)1058bc1f688bSRobert Mustacchi ctf_merge_label(ctf_merge_t *cmh, const char *label)
1059bc1f688bSRobert Mustacchi {
1060bc1f688bSRobert Mustacchi 	char *dup;
1061bc1f688bSRobert Mustacchi 
1062bc1f688bSRobert Mustacchi 	if (label == NULL)
1063bc1f688bSRobert Mustacchi 		return (EINVAL);
1064bc1f688bSRobert Mustacchi 
1065bc1f688bSRobert Mustacchi 	dup = ctf_strdup(label);
1066bc1f688bSRobert Mustacchi 	if (dup == NULL)
1067bc1f688bSRobert Mustacchi 		return (EAGAIN);
1068bc1f688bSRobert Mustacchi 
1069*88a08813SAndy Fiddaman 	ctf_strfree(cmh->cmh_label);
1070bc1f688bSRobert Mustacchi 	cmh->cmh_label = dup;
1071bc1f688bSRobert Mustacchi 	return (0);
1072bc1f688bSRobert Mustacchi }
1073bc1f688bSRobert Mustacchi 
1074bc1f688bSRobert Mustacchi static int
ctf_merge_add_function(ctf_merge_input_t * cmi,ctf_funcinfo_t * fip,ulong_t idx,const char * file,const char * name,const Elf64_Sym * symp)107537e82d12SRobert Mustacchi ctf_merge_add_function(ctf_merge_input_t *cmi, ctf_funcinfo_t *fip, ulong_t idx,
107637e82d12SRobert Mustacchi     const char *file, const char *name, const Elf64_Sym *symp)
1077bc1f688bSRobert Mustacchi {
1078bc1f688bSRobert Mustacchi 	ctf_merge_funcmap_t *fmap;
1079bc1f688bSRobert Mustacchi 
1080bc1f688bSRobert Mustacchi 	fmap = ctf_alloc(sizeof (ctf_merge_funcmap_t) +
1081bc1f688bSRobert Mustacchi 	    sizeof (ctf_id_t) * fip->ctc_argc);
1082bc1f688bSRobert Mustacchi 	if (fmap == NULL)
1083bc1f688bSRobert Mustacchi 		return (ENOMEM);
1084bc1f688bSRobert Mustacchi 
1085bc1f688bSRobert Mustacchi 	fmap->cmf_idx = idx;
108637e82d12SRobert Mustacchi 	fmap->cmf_sym = *symp;
1087bc1f688bSRobert Mustacchi 	fmap->cmf_rtid = fip->ctc_return;
1088bc1f688bSRobert Mustacchi 	fmap->cmf_flags = fip->ctc_flags;
1089bc1f688bSRobert Mustacchi 	fmap->cmf_argc = fip->ctc_argc;
1090bc1f688bSRobert Mustacchi 	fmap->cmf_name = name;
109137e82d12SRobert Mustacchi 	if (ELF64_ST_BIND(symp->st_info) == STB_LOCAL) {
109237e82d12SRobert Mustacchi 		fmap->cmf_file = file;
109337e82d12SRobert Mustacchi 	} else {
109437e82d12SRobert Mustacchi 		fmap->cmf_file = NULL;
109537e82d12SRobert Mustacchi 	}
1096bc1f688bSRobert Mustacchi 
1097bc1f688bSRobert Mustacchi 	if (ctf_func_args(cmi->cmi_input, idx, fmap->cmf_argc,
1098bc1f688bSRobert Mustacchi 	    fmap->cmf_args) != 0) {
1099bc1f688bSRobert Mustacchi 		ctf_free(fmap, sizeof (ctf_merge_funcmap_t) +
1100bc1f688bSRobert Mustacchi 		    sizeof (ctf_id_t) * fip->ctc_argc);
1101bc1f688bSRobert Mustacchi 		return (ctf_errno(cmi->cmi_input));
1102bc1f688bSRobert Mustacchi 	}
1103bc1f688bSRobert Mustacchi 
110437e82d12SRobert Mustacchi 	ctf_dprintf("added initial function %s, %lu, %s %u\n", name, idx,
110537e82d12SRobert Mustacchi 	    fmap->cmf_file != NULL ? fmap->cmf_file : "global",
110637e82d12SRobert Mustacchi 	    ELF64_ST_BIND(symp->st_info));
1107bc1f688bSRobert Mustacchi 	list_insert_tail(&cmi->cmi_fmap, fmap);
1108bc1f688bSRobert Mustacchi 	return (0);
1109bc1f688bSRobert Mustacchi }
1110bc1f688bSRobert Mustacchi 
1111bc1f688bSRobert Mustacchi static int
ctf_merge_add_object(ctf_merge_input_t * cmi,ctf_id_t id,ulong_t idx,const char * file,const char * name,const Elf64_Sym * symp)111237e82d12SRobert Mustacchi ctf_merge_add_object(ctf_merge_input_t *cmi, ctf_id_t id, ulong_t idx,
111337e82d12SRobert Mustacchi     const char *file, const char *name, const Elf64_Sym *symp)
1114bc1f688bSRobert Mustacchi {
1115bc1f688bSRobert Mustacchi 	ctf_merge_objmap_t *cmo;
1116bc1f688bSRobert Mustacchi 
1117bc1f688bSRobert Mustacchi 	cmo = ctf_alloc(sizeof (ctf_merge_objmap_t));
1118bc1f688bSRobert Mustacchi 	if (cmo == NULL)
1119bc1f688bSRobert Mustacchi 		return (ENOMEM);
1120bc1f688bSRobert Mustacchi 
1121bc1f688bSRobert Mustacchi 	cmo->cmo_name = name;
112237e82d12SRobert Mustacchi 	if (ELF64_ST_BIND(symp->st_info) == STB_LOCAL) {
112337e82d12SRobert Mustacchi 		cmo->cmo_file = file;
112437e82d12SRobert Mustacchi 	} else {
112537e82d12SRobert Mustacchi 		cmo->cmo_file = NULL;
112637e82d12SRobert Mustacchi 	}
1127bc1f688bSRobert Mustacchi 	cmo->cmo_idx = idx;
1128bc1f688bSRobert Mustacchi 	cmo->cmo_tid = id;
112937e82d12SRobert Mustacchi 	cmo->cmo_sym = *symp;
1130bc1f688bSRobert Mustacchi 	list_insert_tail(&cmi->cmi_omap, cmo);
113137e82d12SRobert Mustacchi 
113237e82d12SRobert Mustacchi 	ctf_dprintf("added initial object %s, %lu, %ld, %s\n", name, idx, id,
113337e82d12SRobert Mustacchi 	    cmo->cmo_file != NULL ? cmo->cmo_file : "global");
113437e82d12SRobert Mustacchi 
1135bc1f688bSRobert Mustacchi 	return (0);
1136bc1f688bSRobert Mustacchi }
1137bc1f688bSRobert Mustacchi 
113837e82d12SRobert Mustacchi static int
ctf_merge_add_symbol(const Elf64_Sym * symp,ulong_t idx,const char * file,const char * name,boolean_t primary,void * arg)113937e82d12SRobert Mustacchi ctf_merge_add_symbol(const Elf64_Sym *symp, ulong_t idx, const char *file,
114037e82d12SRobert Mustacchi     const char *name, boolean_t primary, void *arg)
114137e82d12SRobert Mustacchi {
114237e82d12SRobert Mustacchi 	ctf_merge_input_t *cmi = arg;
114337e82d12SRobert Mustacchi 	ctf_file_t *fp = cmi->cmi_input;
114437e82d12SRobert Mustacchi 	ushort_t *data, funcbase;
114537e82d12SRobert Mustacchi 	uint_t type;
114637e82d12SRobert Mustacchi 	ctf_funcinfo_t fi;
114737e82d12SRobert Mustacchi 
114837e82d12SRobert Mustacchi 	/*
114937e82d12SRobert Mustacchi 	 * See if there is type information for this. If there is no
115037e82d12SRobert Mustacchi 	 * type information for this entry or no translation, then we
115137e82d12SRobert Mustacchi 	 * will find the value zero. This indicates no type ID for
115237e82d12SRobert Mustacchi 	 * objects and encodes unknown information for functions.
115337e82d12SRobert Mustacchi 	 */
115437e82d12SRobert Mustacchi 	if (fp->ctf_sxlate[idx] == -1u)
115537e82d12SRobert Mustacchi 		return (0);
115637e82d12SRobert Mustacchi 	data = (ushort_t *)((uintptr_t)fp->ctf_buf + fp->ctf_sxlate[idx]);
115737e82d12SRobert Mustacchi 	if (*data == 0)
115837e82d12SRobert Mustacchi 		return (0);
115937e82d12SRobert Mustacchi 
116037e82d12SRobert Mustacchi 	type = ELF64_ST_TYPE(symp->st_info);
116137e82d12SRobert Mustacchi 
116237e82d12SRobert Mustacchi 	switch (type) {
116337e82d12SRobert Mustacchi 	case STT_FUNC:
116437e82d12SRobert Mustacchi 		funcbase = *data;
116537e82d12SRobert Mustacchi 		if (LCTF_INFO_KIND(fp, funcbase) != CTF_K_FUNCTION)
116637e82d12SRobert Mustacchi 			return (0);
116737e82d12SRobert Mustacchi 		data++;
116837e82d12SRobert Mustacchi 		fi.ctc_return = *data;
116937e82d12SRobert Mustacchi 		data++;
117037e82d12SRobert Mustacchi 		fi.ctc_argc = LCTF_INFO_VLEN(fp, funcbase);
117137e82d12SRobert Mustacchi 		fi.ctc_flags = 0;
117237e82d12SRobert Mustacchi 
117337e82d12SRobert Mustacchi 		if (fi.ctc_argc != 0 && data[fi.ctc_argc - 1] == 0) {
117437e82d12SRobert Mustacchi 			fi.ctc_flags |= CTF_FUNC_VARARG;
117537e82d12SRobert Mustacchi 			fi.ctc_argc--;
117637e82d12SRobert Mustacchi 		}
117737e82d12SRobert Mustacchi 		return (ctf_merge_add_function(cmi, &fi, idx, file, name,
117837e82d12SRobert Mustacchi 		    symp));
117937e82d12SRobert Mustacchi 	case STT_OBJECT:
118037e82d12SRobert Mustacchi 		return (ctf_merge_add_object(cmi, *data, idx, file, name,
118137e82d12SRobert Mustacchi 		    symp));
118237e82d12SRobert Mustacchi 	default:
118337e82d12SRobert Mustacchi 		return (0);
118437e82d12SRobert Mustacchi 	}
118537e82d12SRobert Mustacchi }
118637e82d12SRobert Mustacchi 
1187bc1f688bSRobert Mustacchi /*
1188bc1f688bSRobert Mustacchi  * Whenever we create an entry to merge, we then go and add a second empty
1189bc1f688bSRobert Mustacchi  * ctf_file_t which we use for the purposes of our merging. It's not the best,
1190bc1f688bSRobert Mustacchi  * but it's the best that we've got at the moment.
1191bc1f688bSRobert Mustacchi  */
1192bc1f688bSRobert Mustacchi int
ctf_merge_add(ctf_merge_t * cmh,ctf_file_t * input)1193bc1f688bSRobert Mustacchi ctf_merge_add(ctf_merge_t *cmh, ctf_file_t *input)
1194bc1f688bSRobert Mustacchi {
1195bc1f688bSRobert Mustacchi 	int ret;
1196bc1f688bSRobert Mustacchi 	ctf_merge_input_t *cmi;
1197bc1f688bSRobert Mustacchi 	ctf_file_t *empty;
1198bc1f688bSRobert Mustacchi 
119937e82d12SRobert Mustacchi 	ctf_dprintf("adding input %p\n", input);
120037e82d12SRobert Mustacchi 
1201bc1f688bSRobert Mustacchi 	if (input->ctf_flags & LCTF_CHILD)
1202bc1f688bSRobert Mustacchi 		return (ECTF_MCHILD);
1203bc1f688bSRobert Mustacchi 
1204bc1f688bSRobert Mustacchi 	cmi = ctf_alloc(sizeof (ctf_merge_input_t));
1205bc1f688bSRobert Mustacchi 	if (cmi == NULL)
1206bc1f688bSRobert Mustacchi 		return (ENOMEM);
1207bc1f688bSRobert Mustacchi 
1208bc1f688bSRobert Mustacchi 	cmi->cmi_created = B_FALSE;
1209bc1f688bSRobert Mustacchi 	cmi->cmi_input = input;
1210bc1f688bSRobert Mustacchi 	list_create(&cmi->cmi_fmap, sizeof (ctf_merge_funcmap_t),
1211bc1f688bSRobert Mustacchi 	    offsetof(ctf_merge_funcmap_t, cmf_node));
1212bc1f688bSRobert Mustacchi 	list_create(&cmi->cmi_omap, sizeof (ctf_merge_funcmap_t),
1213bc1f688bSRobert Mustacchi 	    offsetof(ctf_merge_objmap_t, cmo_node));
1214bc1f688bSRobert Mustacchi 
1215bc1f688bSRobert Mustacchi 	if (cmh->cmh_msyms == B_TRUE) {
121637e82d12SRobert Mustacchi 		if ((ret = ctf_symtab_iter(input, ctf_merge_add_symbol,
1217bc1f688bSRobert Mustacchi 		    cmi)) != 0) {
1218bc1f688bSRobert Mustacchi 			ctf_merge_fini_input(cmi);
1219bc1f688bSRobert Mustacchi 			return (ret);
1220bc1f688bSRobert Mustacchi 		}
1221bc1f688bSRobert Mustacchi 	}
1222bc1f688bSRobert Mustacchi 
1223bc1f688bSRobert Mustacchi 	list_insert_tail(&cmh->cmh_inputs, cmi);
1224bc1f688bSRobert Mustacchi 	cmh->cmh_ninputs++;
1225bc1f688bSRobert Mustacchi 
1226bc1f688bSRobert Mustacchi 	/* And now the empty one to merge into this */
1227bc1f688bSRobert Mustacchi 	cmi = ctf_alloc(sizeof (ctf_merge_input_t));
1228bc1f688bSRobert Mustacchi 	if (cmi == NULL)
1229bc1f688bSRobert Mustacchi 		return (ENOMEM);
1230bc1f688bSRobert Mustacchi 	list_create(&cmi->cmi_fmap, sizeof (ctf_merge_funcmap_t),
1231bc1f688bSRobert Mustacchi 	    offsetof(ctf_merge_funcmap_t, cmf_node));
1232bc1f688bSRobert Mustacchi 	list_create(&cmi->cmi_omap, sizeof (ctf_merge_funcmap_t),
1233bc1f688bSRobert Mustacchi 	    offsetof(ctf_merge_objmap_t, cmo_node));
1234bc1f688bSRobert Mustacchi 
1235bc1f688bSRobert Mustacchi 	empty = ctf_fdcreate(cmh->cmh_ofd, &ret);
1236bc1f688bSRobert Mustacchi 	if (empty == NULL)
1237bc1f688bSRobert Mustacchi 		return (ret);
1238bc1f688bSRobert Mustacchi 	cmi->cmi_input = empty;
1239bc1f688bSRobert Mustacchi 	cmi->cmi_created = B_TRUE;
1240bc1f688bSRobert Mustacchi 
1241bc1f688bSRobert Mustacchi 	if (ctf_setmodel(empty, ctf_getmodel(input)) == CTF_ERR) {
1242bc1f688bSRobert Mustacchi 		return (ctf_errno(empty));
1243bc1f688bSRobert Mustacchi 	}
1244bc1f688bSRobert Mustacchi 
1245bc1f688bSRobert Mustacchi 	list_insert_tail(&cmh->cmh_inputs, cmi);
1246bc1f688bSRobert Mustacchi 	cmh->cmh_ninputs++;
1247bc1f688bSRobert Mustacchi 	ctf_dprintf("added containers %p and %p\n", input, empty);
1248bc1f688bSRobert Mustacchi 	return (0);
1249bc1f688bSRobert Mustacchi }
1250bc1f688bSRobert Mustacchi 
1251bc1f688bSRobert Mustacchi int
ctf_merge_uniquify(ctf_merge_t * cmh,ctf_file_t * u,const char * pname)1252bc1f688bSRobert Mustacchi ctf_merge_uniquify(ctf_merge_t *cmh, ctf_file_t *u, const char *pname)
1253bc1f688bSRobert Mustacchi {
1254bc1f688bSRobert Mustacchi 	char *dup;
1255bc1f688bSRobert Mustacchi 
1256bc1f688bSRobert Mustacchi 	if (u->ctf_flags & LCTF_CHILD)
1257bc1f688bSRobert Mustacchi 		return (ECTF_MCHILD);
1258bc1f688bSRobert Mustacchi 	if (pname == NULL)
1259bc1f688bSRobert Mustacchi 		return (EINVAL);
1260bc1f688bSRobert Mustacchi 	dup = ctf_strdup(pname);
1261bc1f688bSRobert Mustacchi 	if (dup == NULL)
1262bc1f688bSRobert Mustacchi 		return (EINVAL);
1263*88a08813SAndy Fiddaman 	ctf_strfree(cmh->cmh_pname);
1264bc1f688bSRobert Mustacchi 	cmh->cmh_pname = dup;
1265bc1f688bSRobert Mustacchi 	cmh->cmh_unique = u;
1266bc1f688bSRobert Mustacchi 	return (0);
1267bc1f688bSRobert Mustacchi }
1268bc1f688bSRobert Mustacchi 
126937e82d12SRobert Mustacchi /*
127037e82d12SRobert Mustacchi  * Symbol matching rules: the purpose of this is to verify that the type
127137e82d12SRobert Mustacchi  * information that we have for a given symbol actually matches the output
127237e82d12SRobert Mustacchi  * symbol. This is unfortunately complicated by several different factors:
127337e82d12SRobert Mustacchi  *
127437e82d12SRobert Mustacchi  * 1. When merging multiple .o's into a single item, the symbol table index will
127537e82d12SRobert Mustacchi  * not match.
127637e82d12SRobert Mustacchi  *
127737e82d12SRobert Mustacchi  * 2. Visibility of a symbol may not be identical to the object file or the
127837e82d12SRobert Mustacchi  * DWARF information due to symbol reduction via a mapfile.
127937e82d12SRobert Mustacchi  *
128037e82d12SRobert Mustacchi  * As such, we have to employ the following rules:
128137e82d12SRobert Mustacchi  *
128237e82d12SRobert Mustacchi  * 1. A global symbol table entry always matches a global CTF symbol with the
128337e82d12SRobert Mustacchi  * same name.
128437e82d12SRobert Mustacchi  *
128537e82d12SRobert Mustacchi  * 2. A local symbol table entry always matches a local CTF symbol if they have
128637e82d12SRobert Mustacchi  * the same name and they belong to the same file.
128737e82d12SRobert Mustacchi  *
128837e82d12SRobert Mustacchi  * 3. A weak symbol matches a non-weak symbol. This happens if we find that the
128937e82d12SRobert Mustacchi  * types match, the values match, the sizes match, and the section indexes
129037e82d12SRobert Mustacchi  * match. This happens when we do a conversion in one pass, it almost never
129137e82d12SRobert Mustacchi  * happens when we're merging multiple object files. If we match a CTF global
129237e82d12SRobert Mustacchi  * symbol, that's a fixed match, otherwise it's a fuzzy match.
129337e82d12SRobert Mustacchi  *
129437e82d12SRobert Mustacchi  * 4. A local symbol table entry matches a global CTF entry if the
129537e82d12SRobert Mustacchi  * other pieces fail, but they have the same name. This is considered a fuzzy
129637e82d12SRobert Mustacchi  * match and is not used unless we have no other options.
129737e82d12SRobert Mustacchi  *
129837e82d12SRobert Mustacchi  * 5. A weak symbol table entry matches a weak CTF entry if the other pieces
129937e82d12SRobert Mustacchi  * fail, but they have the same name. This is considered a fuzzy match and is
130037e82d12SRobert Mustacchi  * not used unless we have no other options. When merging independent .o files,
130137e82d12SRobert Mustacchi  * this is often the only recourse we have to matching weak symbols.
130237e82d12SRobert Mustacchi  *
130337e82d12SRobert Mustacchi  * In the end, this would all be much simpler if we were able to do this as part
130437e82d12SRobert Mustacchi  * of libld which would be able to do all the symbol transformations.
130537e82d12SRobert Mustacchi  */
130637e82d12SRobert Mustacchi static boolean_t
ctf_merge_symbol_match(const char * ctf_file,const char * ctf_name,const Elf64_Sym * ctf_symp,const char * symtab_file,const char * symtab_name,const Elf64_Sym * symtab_symp,boolean_t * is_fuzzy)130737e82d12SRobert Mustacchi ctf_merge_symbol_match(const char *ctf_file, const char *ctf_name,
130837e82d12SRobert Mustacchi     const Elf64_Sym *ctf_symp, const char *symtab_file, const char *symtab_name,
130937e82d12SRobert Mustacchi     const Elf64_Sym *symtab_symp, boolean_t *is_fuzzy)
1310bc1f688bSRobert Mustacchi {
131137e82d12SRobert Mustacchi 	*is_fuzzy = B_FALSE;
131237e82d12SRobert Mustacchi 	uint_t symtab_bind, ctf_bind;
1313bc1f688bSRobert Mustacchi 
131437e82d12SRobert Mustacchi 	symtab_bind = ELF64_ST_BIND(symtab_symp->st_info);
131537e82d12SRobert Mustacchi 	ctf_bind = ELF64_ST_BIND(ctf_symp->st_info);
131637e82d12SRobert Mustacchi 
131737e82d12SRobert Mustacchi 	ctf_dprintf("comparing merge match for %s/%s/%u->%s/%s/%u\n",
131837e82d12SRobert Mustacchi 	    symtab_file, symtab_name, symtab_bind,
131937e82d12SRobert Mustacchi 	    ctf_file, ctf_name, ctf_bind);
132037e82d12SRobert Mustacchi 	if (strcmp(ctf_name, symtab_name) != 0) {
132137e82d12SRobert Mustacchi 		return (B_FALSE);
132237e82d12SRobert Mustacchi 	}
132337e82d12SRobert Mustacchi 
132437e82d12SRobert Mustacchi 	if (symtab_bind == STB_GLOBAL && ctf_bind == STB_GLOBAL) {
132537e82d12SRobert Mustacchi 		return (B_TRUE);
132637e82d12SRobert Mustacchi 	} else if (symtab_bind == STB_GLOBAL) {
132737e82d12SRobert Mustacchi 		return (B_FALSE);
132837e82d12SRobert Mustacchi 	}
132937e82d12SRobert Mustacchi 
133037e82d12SRobert Mustacchi 	if (ctf_bind == STB_LOCAL && ctf_bind == symtab_bind &&
133137e82d12SRobert Mustacchi 	    ctf_file != NULL && symtab_file != NULL &&
133237e82d12SRobert Mustacchi 	    strcmp(ctf_file, symtab_file) == 0) {
133337e82d12SRobert Mustacchi 		return (B_TRUE);
133437e82d12SRobert Mustacchi 	}
133537e82d12SRobert Mustacchi 
133637e82d12SRobert Mustacchi 	if (symtab_bind == STB_WEAK && ctf_bind != STB_WEAK &&
133737e82d12SRobert Mustacchi 	    ELF64_ST_TYPE(symtab_symp->st_info) ==
133837e82d12SRobert Mustacchi 	    ELF64_ST_TYPE(ctf_symp->st_info) &&
133937e82d12SRobert Mustacchi 	    symtab_symp->st_value == ctf_symp->st_value &&
134037e82d12SRobert Mustacchi 	    symtab_symp->st_size == ctf_symp->st_size &&
134137e82d12SRobert Mustacchi 	    symtab_symp->st_shndx == ctf_symp->st_shndx) {
134237e82d12SRobert Mustacchi 		if (ctf_bind == STB_GLOBAL) {
134337e82d12SRobert Mustacchi 			return (B_TRUE);
1344bc1f688bSRobert Mustacchi 		}
134537e82d12SRobert Mustacchi 
134637e82d12SRobert Mustacchi 		if (ctf_bind == STB_LOCAL && ctf_file != NULL &&
134737e82d12SRobert Mustacchi 		    symtab_file != NULL && strcmp(ctf_file, symtab_file) == 0) {
134837e82d12SRobert Mustacchi 			*is_fuzzy = B_TRUE;
134937e82d12SRobert Mustacchi 			return (B_TRUE);
1350bc1f688bSRobert Mustacchi 		}
1351bc1f688bSRobert Mustacchi 	}
1352bc1f688bSRobert Mustacchi 
135337e82d12SRobert Mustacchi 	if (ctf_bind == STB_GLOBAL ||
135437e82d12SRobert Mustacchi 	    (ctf_bind == STB_WEAK && symtab_bind == STB_WEAK)) {
135537e82d12SRobert Mustacchi 		*is_fuzzy = B_TRUE;
135637e82d12SRobert Mustacchi 		return (B_TRUE);
135737e82d12SRobert Mustacchi 	}
135837e82d12SRobert Mustacchi 
135937e82d12SRobert Mustacchi 	return (B_FALSE);
1360bc1f688bSRobert Mustacchi }
1361bc1f688bSRobert Mustacchi 
136237e82d12SRobert Mustacchi /*
136337e82d12SRobert Mustacchi  * For each symbol, try and find a match. We will attempt to find an exact
136437e82d12SRobert Mustacchi  * match; however, we will settle for a fuzzy match in general. There is one
136537e82d12SRobert Mustacchi  * case where we will not opt to use a fuzzy match, which is when performing the
136637e82d12SRobert Mustacchi  * deduplication of a container. In such a case we are trying to reduce common
136737e82d12SRobert Mustacchi  * types and a fuzzy match would be inappropriate as if we're in the context of
136837e82d12SRobert Mustacchi  * a single container, the conversion process should have identified any exact
136937e82d12SRobert Mustacchi  * or fuzzy matches that were required.
137037e82d12SRobert Mustacchi  */
1371bc1f688bSRobert Mustacchi static int
ctf_merge_symbols(const Elf64_Sym * symp,ulong_t idx,const char * file,const char * name,boolean_t primary,void * arg)137237e82d12SRobert Mustacchi ctf_merge_symbols(const Elf64_Sym *symp, ulong_t idx, const char *file,
137337e82d12SRobert Mustacchi     const char *name, boolean_t primary, void *arg)
1374bc1f688bSRobert Mustacchi {
1375bc1f688bSRobert Mustacchi 	int err;
137637e82d12SRobert Mustacchi 	uint_t type, bind;
137737e82d12SRobert Mustacchi 	ctf_merge_symbol_arg_t *csa = arg;
137837e82d12SRobert Mustacchi 	ctf_file_t *fp = csa->cmsa_out;
137937e82d12SRobert Mustacchi 
138037e82d12SRobert Mustacchi 	type = ELF64_ST_TYPE(symp->st_info);
138137e82d12SRobert Mustacchi 	bind = ELF64_ST_BIND(symp->st_info);
138237e82d12SRobert Mustacchi 
138337e82d12SRobert Mustacchi 	ctf_dprintf("Trying to find match for %s/%s/%u\n", file, name,
138437e82d12SRobert Mustacchi 	    ELF64_ST_BIND(symp->st_info));
138537e82d12SRobert Mustacchi 
138637e82d12SRobert Mustacchi 	if (type == STT_OBJECT) {
138737e82d12SRobert Mustacchi 		ctf_merge_objmap_t *cmo, *match = NULL;
138837e82d12SRobert Mustacchi 
138937e82d12SRobert Mustacchi 		for (cmo = list_head(csa->cmsa_objmap); cmo != NULL;
139037e82d12SRobert Mustacchi 		    cmo = list_next(csa->cmsa_objmap, cmo)) {
139137e82d12SRobert Mustacchi 			boolean_t is_fuzzy = B_FALSE;
139237e82d12SRobert Mustacchi 			if (ctf_merge_symbol_match(cmo->cmo_file, cmo->cmo_name,
139337e82d12SRobert Mustacchi 			    &cmo->cmo_sym, file, name, symp, &is_fuzzy)) {
139437e82d12SRobert Mustacchi 				if (is_fuzzy && csa->cmsa_dedup &&
139537e82d12SRobert Mustacchi 				    bind != STB_WEAK) {
139637e82d12SRobert Mustacchi 					continue;
139737e82d12SRobert Mustacchi 				}
139837e82d12SRobert Mustacchi 				match = cmo;
139937e82d12SRobert Mustacchi 				if (is_fuzzy) {
140037e82d12SRobert Mustacchi 					continue;
140137e82d12SRobert Mustacchi 				}
140237e82d12SRobert Mustacchi 				break;
140337e82d12SRobert Mustacchi 			}
140437e82d12SRobert Mustacchi 		}
1405bc1f688bSRobert Mustacchi 
140637e82d12SRobert Mustacchi 		if (match == NULL) {
140737e82d12SRobert Mustacchi 			return (0);
1408bc1f688bSRobert Mustacchi 		}
1409bc1f688bSRobert Mustacchi 
141037e82d12SRobert Mustacchi 		if ((err = ctf_add_object(fp, idx, match->cmo_tid)) != 0) {
141137e82d12SRobert Mustacchi 			ctf_dprintf("Failed to add symbol %s->%d: %s\n", name,
141237e82d12SRobert Mustacchi 			    match->cmo_tid, ctf_errmsg(ctf_errno(fp)));
141337e82d12SRobert Mustacchi 			return (ctf_errno(fp));
141437e82d12SRobert Mustacchi 		}
141537e82d12SRobert Mustacchi 		ctf_dprintf("mapped object into output %s/%s->%ld\n", file,
141637e82d12SRobert Mustacchi 		    name, match->cmo_tid);
141737e82d12SRobert Mustacchi 	} else {
141837e82d12SRobert Mustacchi 		ctf_merge_funcmap_t *cmf, *match = NULL;
141937e82d12SRobert Mustacchi 		ctf_funcinfo_t fi;
142037e82d12SRobert Mustacchi 
142137e82d12SRobert Mustacchi 		for (cmf = list_head(csa->cmsa_funcmap); cmf != NULL;
142237e82d12SRobert Mustacchi 		    cmf = list_next(csa->cmsa_funcmap, cmf)) {
142337e82d12SRobert Mustacchi 			boolean_t is_fuzzy = B_FALSE;
142437e82d12SRobert Mustacchi 			if (ctf_merge_symbol_match(cmf->cmf_file, cmf->cmf_name,
142537e82d12SRobert Mustacchi 			    &cmf->cmf_sym, file, name, symp, &is_fuzzy)) {
142637e82d12SRobert Mustacchi 				if (is_fuzzy && csa->cmsa_dedup &&
142737e82d12SRobert Mustacchi 				    bind != STB_WEAK) {
142837e82d12SRobert Mustacchi 					continue;
142937e82d12SRobert Mustacchi 				}
143037e82d12SRobert Mustacchi 				match = cmf;
143137e82d12SRobert Mustacchi 				if (is_fuzzy) {
143237e82d12SRobert Mustacchi 					continue;
143337e82d12SRobert Mustacchi 				}
143437e82d12SRobert Mustacchi 				break;
1435bc1f688bSRobert Mustacchi 			}
1436bc1f688bSRobert Mustacchi 		}
143737e82d12SRobert Mustacchi 
143837e82d12SRobert Mustacchi 		if (match == NULL) {
143937e82d12SRobert Mustacchi 			return (0);
1440bc1f688bSRobert Mustacchi 		}
144137e82d12SRobert Mustacchi 
144237e82d12SRobert Mustacchi 		fi.ctc_return = match->cmf_rtid;
144337e82d12SRobert Mustacchi 		fi.ctc_argc = match->cmf_argc;
144437e82d12SRobert Mustacchi 		fi.ctc_flags = match->cmf_flags;
144537e82d12SRobert Mustacchi 		if ((err = ctf_add_function(fp, idx, &fi, match->cmf_args)) !=
144637e82d12SRobert Mustacchi 		    0) {
144737e82d12SRobert Mustacchi 			ctf_dprintf("Failed to add function %s: %s\n", name,
144837e82d12SRobert Mustacchi 			    ctf_errmsg(ctf_errno(fp)));
144937e82d12SRobert Mustacchi 			return (ctf_errno(fp));
145037e82d12SRobert Mustacchi 		}
145137e82d12SRobert Mustacchi 		ctf_dprintf("mapped function into output %s/%s\n", file,
145237e82d12SRobert Mustacchi 		    name);
1453bc1f688bSRobert Mustacchi 	}
1454bc1f688bSRobert Mustacchi 
1455bc1f688bSRobert Mustacchi 	return (0);
1456bc1f688bSRobert Mustacchi }
1457bc1f688bSRobert Mustacchi 
1458bc1f688bSRobert Mustacchi int
ctf_merge_merge(ctf_merge_t * cmh,ctf_file_t ** outp)1459bc1f688bSRobert Mustacchi ctf_merge_merge(ctf_merge_t *cmh, ctf_file_t **outp)
1460bc1f688bSRobert Mustacchi {
1461bc1f688bSRobert Mustacchi 	int err, merr;
1462bc1f688bSRobert Mustacchi 	ctf_merge_input_t *cmi;
1463bc1f688bSRobert Mustacchi 	ctf_id_t ltype;
1464bc1f688bSRobert Mustacchi 	mergeq_t *mqp;
1465bc1f688bSRobert Mustacchi 	ctf_merge_input_t *final;
1466bc1f688bSRobert Mustacchi 	ctf_file_t *out;
1467bc1f688bSRobert Mustacchi 
146837e82d12SRobert Mustacchi 	ctf_dprintf("Beginning ctf_merge_merge()\n");
1469bc1f688bSRobert Mustacchi 	if (cmh->cmh_label != NULL && cmh->cmh_unique != NULL) {
1470bc1f688bSRobert Mustacchi 		const char *label = ctf_label_topmost(cmh->cmh_unique);
1471bc1f688bSRobert Mustacchi 		if (label == NULL)
1472bc1f688bSRobert Mustacchi 			return (ECTF_NOLABEL);
1473bc1f688bSRobert Mustacchi 		if (strcmp(label, cmh->cmh_label) != 0)
1474bc1f688bSRobert Mustacchi 			return (ECTF_LCONFLICT);
1475bc1f688bSRobert Mustacchi 	}
1476bc1f688bSRobert Mustacchi 
1477bc1f688bSRobert Mustacchi 	if (mergeq_init(&mqp, cmh->cmh_nthreads) == -1) {
1478bc1f688bSRobert Mustacchi 		return (errno);
1479bc1f688bSRobert Mustacchi 	}
1480bc1f688bSRobert Mustacchi 
1481bc1f688bSRobert Mustacchi 	VERIFY(cmh->cmh_ninputs % 2 == 0);
1482bc1f688bSRobert Mustacchi 	for (cmi = list_head(&cmh->cmh_inputs); cmi != NULL;
1483bc1f688bSRobert Mustacchi 	    cmi = list_next(&cmh->cmh_inputs, cmi)) {
1484bc1f688bSRobert Mustacchi 		if (mergeq_add(mqp, cmi) == -1) {
1485bc1f688bSRobert Mustacchi 			err = errno;
1486bc1f688bSRobert Mustacchi 			mergeq_fini(mqp);
1487bc1f688bSRobert Mustacchi 		}
1488bc1f688bSRobert Mustacchi 	}
1489bc1f688bSRobert Mustacchi 
1490bc1f688bSRobert Mustacchi 	err = mergeq_merge(mqp, ctf_merge_types, NULL, (void **)&final, &merr);
1491bc1f688bSRobert Mustacchi 	mergeq_fini(mqp);
1492bc1f688bSRobert Mustacchi 
1493bc1f688bSRobert Mustacchi 	if (err == MERGEQ_ERROR) {
1494bc1f688bSRobert Mustacchi 		return (errno);
1495bc1f688bSRobert Mustacchi 	} else if (err == MERGEQ_UERROR) {
1496bc1f688bSRobert Mustacchi 		return (merr);
1497bc1f688bSRobert Mustacchi 	}
1498bc1f688bSRobert Mustacchi 
1499bc1f688bSRobert Mustacchi 	/*
1500bc1f688bSRobert Mustacchi 	 * Disassociate the generated ctf_file_t from the original input. That
1501bc1f688bSRobert Mustacchi 	 * way when the input gets cleaned up, we don't accidentally kill the
1502bc1f688bSRobert Mustacchi 	 * final reference to the ctf_file_t. If it gets uniquified then we'll
1503bc1f688bSRobert Mustacchi 	 * kill it.
1504bc1f688bSRobert Mustacchi 	 */
1505bc1f688bSRobert Mustacchi 	VERIFY(final->cmi_input != NULL);
1506bc1f688bSRobert Mustacchi 	out = final->cmi_input;
1507bc1f688bSRobert Mustacchi 	final->cmi_input = NULL;
1508bc1f688bSRobert Mustacchi 
1509bc1f688bSRobert Mustacchi 	ctf_dprintf("preparing to uniquify against: %p\n", cmh->cmh_unique);
1510bc1f688bSRobert Mustacchi 	if (cmh->cmh_unique != NULL) {
1511bc1f688bSRobert Mustacchi 		ctf_file_t *u;
1512bc1f688bSRobert Mustacchi 		err = ctf_uniquify_types(cmh, out, &u);
1513bc1f688bSRobert Mustacchi 		if (err != 0) {
1514bc1f688bSRobert Mustacchi 			err = ctf_errno(out);
1515bc1f688bSRobert Mustacchi 			ctf_close(out);
1516bc1f688bSRobert Mustacchi 			return (err);
1517bc1f688bSRobert Mustacchi 		}
1518bc1f688bSRobert Mustacchi 		ctf_close(out);
1519bc1f688bSRobert Mustacchi 		out = u;
1520bc1f688bSRobert Mustacchi 	}
1521bc1f688bSRobert Mustacchi 
1522bc1f688bSRobert Mustacchi 	ltype = out->ctf_typemax;
1523bc1f688bSRobert Mustacchi 	if ((out->ctf_flags & LCTF_CHILD) && ltype != 0)
1524bc1f688bSRobert Mustacchi 		ltype += CTF_CHILD_START;
1525bc1f688bSRobert Mustacchi 	ctf_dprintf("trying to add the label\n");
1526bc1f688bSRobert Mustacchi 	if (cmh->cmh_label != NULL &&
1527bc1f688bSRobert Mustacchi 	    ctf_add_label(out, cmh->cmh_label, ltype, 0) != 0) {
1528bc1f688bSRobert Mustacchi 		ctf_close(out);
1529bc1f688bSRobert Mustacchi 		return (ctf_errno(out));
1530bc1f688bSRobert Mustacchi 	}
1531bc1f688bSRobert Mustacchi 
1532bc1f688bSRobert Mustacchi 	ctf_dprintf("merging symbols and the like\n");
1533bc1f688bSRobert Mustacchi 	if (cmh->cmh_msyms == B_TRUE) {
153437e82d12SRobert Mustacchi 		ctf_merge_symbol_arg_t arg;
153537e82d12SRobert Mustacchi 		arg.cmsa_objmap = &final->cmi_omap;
153637e82d12SRobert Mustacchi 		arg.cmsa_funcmap = &final->cmi_fmap;
153737e82d12SRobert Mustacchi 		arg.cmsa_out = out;
153837e82d12SRobert Mustacchi 		arg.cmsa_dedup = B_FALSE;
153937e82d12SRobert Mustacchi 		err = ctf_symtab_iter(out, ctf_merge_symbols, &arg);
1540bc1f688bSRobert Mustacchi 		if (err != 0) {
1541bc1f688bSRobert Mustacchi 			ctf_close(out);
154237e82d12SRobert Mustacchi 			return (err);
1543bc1f688bSRobert Mustacchi 		}
1544bc1f688bSRobert Mustacchi 	}
1545bc1f688bSRobert Mustacchi 
1546bc1f688bSRobert Mustacchi 	err = ctf_update(out);
1547bc1f688bSRobert Mustacchi 	if (err != 0) {
154837e82d12SRobert Mustacchi 		err = ctf_errno(out);
1549bc1f688bSRobert Mustacchi 		ctf_close(out);
155037e82d12SRobert Mustacchi 		return (err);
1551bc1f688bSRobert Mustacchi 	}
1552bc1f688bSRobert Mustacchi 
1553bc1f688bSRobert Mustacchi 	*outp = out;
1554bc1f688bSRobert Mustacchi 	return (0);
1555bc1f688bSRobert Mustacchi }
1556bc1f688bSRobert Mustacchi 
1557bc1f688bSRobert Mustacchi /*
1558bc1f688bSRobert Mustacchi  * When we get told that something is unique, eg. same is B_FALSE, then that
1559bc1f688bSRobert Mustacchi  * tells us that we need to add it to the output. If same is B_TRUE, then we'll
1560bc1f688bSRobert Mustacchi  * want to record it in the mapping table so that we know how to redirect types
1561bc1f688bSRobert Mustacchi  * to the extant ones.
1562bc1f688bSRobert Mustacchi  */
1563bc1f688bSRobert 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)1564bc1f688bSRobert Mustacchi ctf_dedup_cb(ctf_file_t *ifp, ctf_id_t iid, boolean_t same, ctf_file_t *ofp,
1565bc1f688bSRobert Mustacchi     ctf_id_t oid, void *arg)
1566bc1f688bSRobert Mustacchi {
1567bc1f688bSRobert Mustacchi 	ctf_merge_types_t *cmp = arg;
1568bc1f688bSRobert Mustacchi 	ctf_merge_tinfo_t *cmt = cmp->cm_tmap;
1569bc1f688bSRobert Mustacchi 
1570bc1f688bSRobert Mustacchi 	if (same == B_TRUE) {
1571bc1f688bSRobert Mustacchi 		/*
1572bc1f688bSRobert Mustacchi 		 * The output id here may itself map to something else.
1573bc1f688bSRobert Mustacchi 		 * Therefore, we need to basically walk a chain and see what it
1574bc1f688bSRobert Mustacchi 		 * points to until it itself points to a base type, eg. -1.
1575bc1f688bSRobert Mustacchi 		 * Otherwise we'll dedup to something which no longer exists.
1576bc1f688bSRobert Mustacchi 		 */
1577bc1f688bSRobert Mustacchi 		while (cmt[oid].cmt_missing == B_FALSE)
1578bc1f688bSRobert Mustacchi 			oid = cmt[oid].cmt_map;
1579bc1f688bSRobert Mustacchi 		cmt[iid].cmt_map = oid;
15803dfdac06SAndy Fiddaman 		ctf_dprintf("dedup %d->%d \n", iid, oid);
1581bc1f688bSRobert Mustacchi 	} else {
1582bc1f688bSRobert Mustacchi 		VERIFY(cmt[iid].cmt_map == 0);
1583bc1f688bSRobert Mustacchi 		cmt[iid].cmt_missing = B_TRUE;
15843dfdac06SAndy Fiddaman 		ctf_dprintf("dedup %d is missing\n", iid);
1585bc1f688bSRobert Mustacchi 	}
1586bc1f688bSRobert Mustacchi }
1587bc1f688bSRobert Mustacchi 
1588bc1f688bSRobert Mustacchi /*
1589bc1f688bSRobert Mustacchi  * Dedup a CTF container.
1590bc1f688bSRobert Mustacchi  *
1591bc1f688bSRobert Mustacchi  * DWARF and other encoding formats that we use to create CTF data may create
1592bc1f688bSRobert Mustacchi  * multiple copies of a given type. However, after doing a conversion, and
1593bc1f688bSRobert Mustacchi  * before doing a merge, we'd prefer, if possible, to have every input container
1594bc1f688bSRobert Mustacchi  * to be unique.
1595bc1f688bSRobert Mustacchi  *
1596bc1f688bSRobert Mustacchi  * Doing a deduplication is like a normal merge. However, when we diff the types
1597bc1f688bSRobert Mustacchi  * in the container, rather than doing a normal diff, we instead want to diff
1598bc1f688bSRobert Mustacchi  * against any already processed types. eg, for a given type i in a container,
1599bc1f688bSRobert Mustacchi  * we want to diff it from 0 to i - 1.
1600bc1f688bSRobert Mustacchi  */
1601bc1f688bSRobert Mustacchi int
ctf_merge_dedup(ctf_merge_t * cmp,ctf_file_t ** outp)1602bc1f688bSRobert Mustacchi ctf_merge_dedup(ctf_merge_t *cmp, ctf_file_t **outp)
1603bc1f688bSRobert Mustacchi {
1604bc1f688bSRobert Mustacchi 	int ret;
1605bc1f688bSRobert Mustacchi 	ctf_diff_t *cdp = NULL;
1606bc1f688bSRobert Mustacchi 	ctf_merge_input_t *cmi, *cmc;
1607bc1f688bSRobert Mustacchi 	ctf_file_t *ifp, *ofp;
1608bc1f688bSRobert Mustacchi 	ctf_merge_types_t cm;
1609bc1f688bSRobert Mustacchi 
1610bc1f688bSRobert Mustacchi 	if (cmp == NULL || outp == NULL)
1611bc1f688bSRobert Mustacchi 		return (EINVAL);
1612bc1f688bSRobert Mustacchi 
1613bc1f688bSRobert Mustacchi 	ctf_dprintf("encountered %d inputs\n", cmp->cmh_ninputs);
1614bc1f688bSRobert Mustacchi 	if (cmp->cmh_ninputs != 2)
1615bc1f688bSRobert Mustacchi 		return (EINVAL);
1616bc1f688bSRobert Mustacchi 
1617bc1f688bSRobert Mustacchi 	ctf_dprintf("passed argument sanity check\n");
1618bc1f688bSRobert Mustacchi 
1619bc1f688bSRobert Mustacchi 	cmi = list_head(&cmp->cmh_inputs);
1620bc1f688bSRobert Mustacchi 	VERIFY(cmi != NULL);
1621bc1f688bSRobert Mustacchi 	cmc = list_next(&cmp->cmh_inputs, cmi);
1622bc1f688bSRobert Mustacchi 	VERIFY(cmc != NULL);
1623bc1f688bSRobert Mustacchi 	ifp = cmi->cmi_input;
1624bc1f688bSRobert Mustacchi 	ofp = cmc->cmi_input;
1625bc1f688bSRobert Mustacchi 	VERIFY(ifp != NULL);
1626bc1f688bSRobert Mustacchi 	VERIFY(ofp != NULL);
1627bc1f688bSRobert Mustacchi 	cm.cm_src = ifp;
1628bc1f688bSRobert Mustacchi 	cm.cm_out = ofp;
1629bc1f688bSRobert Mustacchi 	cm.cm_dedup = B_TRUE;
1630bc1f688bSRobert Mustacchi 	cm.cm_unique = B_FALSE;
1631bc1f688bSRobert Mustacchi 
1632bc1f688bSRobert Mustacchi 	if ((ret = ctf_merge_types_init(&cm)) != 0) {
1633bc1f688bSRobert Mustacchi 		return (ret);
1634bc1f688bSRobert Mustacchi 	}
1635bc1f688bSRobert Mustacchi 
1636bc1f688bSRobert Mustacchi 	if ((ret = ctf_diff_init(ifp, ifp, &cdp)) != 0)
1637bc1f688bSRobert Mustacchi 		goto err;
1638bc1f688bSRobert Mustacchi 
1639bc1f688bSRobert Mustacchi 	ctf_dprintf("Successfully initialized dedup\n");
1640bc1f688bSRobert Mustacchi 	if ((ret = ctf_diff_self(cdp, ctf_dedup_cb, &cm)) != 0)
1641bc1f688bSRobert Mustacchi 		goto err;
1642bc1f688bSRobert Mustacchi 
1643bc1f688bSRobert Mustacchi 	ctf_dprintf("Successfully diffed types\n");
1644bc1f688bSRobert Mustacchi 	ret = ctf_merge_common(&cm);
1645bc1f688bSRobert Mustacchi 	ctf_dprintf("deduping types result: %d\n", ret);
1646bc1f688bSRobert Mustacchi 	if (ret == 0)
1647bc1f688bSRobert Mustacchi 		ret = ctf_update(cm.cm_out);
1648bc1f688bSRobert Mustacchi 	if (ret != 0)
1649bc1f688bSRobert Mustacchi 		goto err;
1650bc1f688bSRobert Mustacchi 
1651bc1f688bSRobert Mustacchi 	ctf_dprintf("Successfully deduped types\n");
165237e82d12SRobert Mustacchi 	ctf_phase_dump(cm.cm_out, "dedup-pre-syms", NULL);
1653bc1f688bSRobert Mustacchi 
1654bc1f688bSRobert Mustacchi 	/*
1655bc1f688bSRobert Mustacchi 	 * Now we need to fix up the object and function maps.
1656bc1f688bSRobert Mustacchi 	 */
165737e82d12SRobert Mustacchi 	ctf_merge_fixup_symmaps(&cm, cmi);
1658bc1f688bSRobert Mustacchi 
1659bc1f688bSRobert Mustacchi 	if (cmp->cmh_msyms == B_TRUE) {
166037e82d12SRobert Mustacchi 		ctf_merge_symbol_arg_t arg;
166137e82d12SRobert Mustacchi 		arg.cmsa_objmap = &cmi->cmi_omap;
166237e82d12SRobert Mustacchi 		arg.cmsa_funcmap = &cmi->cmi_fmap;
166337e82d12SRobert Mustacchi 		arg.cmsa_out = cm.cm_out;
166437e82d12SRobert Mustacchi 		arg.cmsa_dedup = B_TRUE;
166537e82d12SRobert Mustacchi 		ret = ctf_symtab_iter(cm.cm_out, ctf_merge_symbols, &arg);
1666bc1f688bSRobert Mustacchi 		if (ret != 0) {
1667bc1f688bSRobert Mustacchi 			ctf_dprintf("failed to dedup symbols: %s\n",
1668bc1f688bSRobert Mustacchi 			    ctf_errmsg(ret));
1669bc1f688bSRobert Mustacchi 			goto err;
1670bc1f688bSRobert Mustacchi 		}
1671bc1f688bSRobert Mustacchi 	}
1672bc1f688bSRobert Mustacchi 
1673bc1f688bSRobert Mustacchi 	ret = ctf_update(cm.cm_out);
1674bc1f688bSRobert Mustacchi 	if (ret == 0) {
1675bc1f688bSRobert Mustacchi 		cmc->cmi_input = NULL;
1676bc1f688bSRobert Mustacchi 		*outp = cm.cm_out;
1677bc1f688bSRobert Mustacchi 	}
167837e82d12SRobert Mustacchi 	ctf_phase_dump(cm.cm_out, "dedup-post-syms", NULL);
1679bc1f688bSRobert Mustacchi err:
1680bc1f688bSRobert Mustacchi 	ctf_merge_types_fini(&cm);
1681bc1f688bSRobert Mustacchi 	ctf_diff_fini(cdp);
1682bc1f688bSRobert Mustacchi 	return (ret);
1683bc1f688bSRobert Mustacchi }
1684bc1f688bSRobert Mustacchi 
1685bc1f688bSRobert Mustacchi int
ctf_merge_set_nthreads(ctf_merge_t * cmp,const uint_t nthrs)1686bc1f688bSRobert Mustacchi ctf_merge_set_nthreads(ctf_merge_t *cmp, const uint_t nthrs)
1687bc1f688bSRobert Mustacchi {
1688bc1f688bSRobert Mustacchi 	if (nthrs == 0)
1689bc1f688bSRobert Mustacchi 		return (EINVAL);
1690bc1f688bSRobert Mustacchi 	cmp->cmh_nthreads = nthrs;
1691bc1f688bSRobert Mustacchi 	return (0);
1692bc1f688bSRobert Mustacchi }
1693