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