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