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