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