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