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