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) 2019 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>
598 static int
599 ctf_merge_fixup_type(ctf_merge_types_t *cmp, ctf_id_t id)
600 {
601 int kind, ret;
602
603 kind = ctf_type_kind(cmp->cm_src, id);
604 switch (kind) {
605 case CTF_K_STRUCT:
606 case CTF_K_UNION:
607 ret = ctf_merge_fixup_sou(cmp, id);
608 break;
609 default:
610 VERIFY(0);
611 ret = CTF_ERR;
612 }
613
614 return (ret);
615 }
616
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.
624 */
625 static void
626 ctf_merge_fixup_dedup_map(ctf_merge_types_t *cmp)
627 {
628 int i;
629
630 for (i = 1; i < cmp->cm_src->ctf_typemax + 1; i++) {
631 ctf_id_t tid;
632
633 /*
634 * Missing types always have their id updated to exactly what it
635 * should be.
636 */
637 if (cmp->cm_tmap[i].cmt_missing == B_TRUE) {
638 VERIFY(cmp->cm_tmap[i].cmt_map != 0);
639 continue;
640 }
641
642 tid = i;
643 while (cmp->cm_tmap[tid].cmt_missing == B_FALSE) {
644 VERIFY(cmp->cm_tmap[tid].cmt_map != 0);
645 tid = cmp->cm_tmap[tid].cmt_map;
646 }
647 VERIFY(cmp->cm_tmap[tid].cmt_map != 0);
648 cmp->cm_tmap[i].cmt_map = cmp->cm_tmap[tid].cmt_map;
649 }
650 }
651
652
653 /*
654 * We're going to do three passes over the containers.
655 *
656 * Pass 1 checks for forward references in the output container that we know
684 }
685 }
686 }
687
688 /* Pass 2 */
689 for (i = 1; i <= cmp->cm_src->ctf_typemax; i++) {
690 if (cmp->cm_tmap[i].cmt_missing == B_TRUE) {
691 ret = ctf_merge_add_type(cmp, i);
692 if (ret != 0) {
693 ctf_dprintf("Failed to merge type %d\n", i);
694 return (ret);
695 }
696 }
697 }
698
699 ret = ctf_update(cmp->cm_out);
700 if (ret != 0)
701 return (ret);
702
703 if (cmp->cm_dedup == B_TRUE) {
704 ctf_merge_fixup_dedup_map(cmp);
705 }
706
707 ctf_dprintf("Beginning merge pass 3\n");
708 /* Pass 3 */
709 for (i = 1; i <= cmp->cm_src->ctf_typemax; i++) {
710 if (cmp->cm_tmap[i].cmt_fixup == B_TRUE) {
711 ret = ctf_merge_fixup_type(cmp, i);
712 if (ret != 0)
713 return (ret);
714 }
715 }
716
717 if (cmp->cm_dedup == B_TRUE) {
718 ctf_merge_fixup_dedup_map(cmp);
719 }
720
721 return (0);
722 }
723
724 /*
725 * Uniquification is slightly different from a stock merge. For starters, we
726 * don't need to replace any forward references in the output. In this case
727 * though, the types that already exist are in a parent container to the empty
728 * output container.
729 */
730 static int
731 ctf_merge_uniquify_types(ctf_merge_types_t *cmp)
732 {
733 int i, ret;
734
735 for (i = 1; i <= cmp->cm_src->ctf_typemax; i++) {
736 if (cmp->cm_tmap[i].cmt_missing == B_FALSE)
737 continue;
738 ret = ctf_merge_add_type(cmp, i);
739 if (ret != 0)
740 return (ret);
|
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 2019, 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>
598 static int
599 ctf_merge_fixup_type(ctf_merge_types_t *cmp, ctf_id_t id)
600 {
601 int kind, ret;
602
603 kind = ctf_type_kind(cmp->cm_src, id);
604 switch (kind) {
605 case CTF_K_STRUCT:
606 case CTF_K_UNION:
607 ret = ctf_merge_fixup_sou(cmp, id);
608 break;
609 default:
610 VERIFY(0);
611 ret = CTF_ERR;
612 }
613
614 return (ret);
615 }
616
617 /*
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.
637 */
638 static void
639 ctf_merge_dedup_remap(ctf_merge_types_t *cmp)
640 {
641 int i;
642
643 for (i = 1; i < cmp->cm_src->ctf_typemax + 1; i++) {
644 ctf_id_t tid;
645
646 if (cmp->cm_tmap[i].cmt_missing == B_TRUE) {
647 VERIFY(cmp->cm_tmap[i].cmt_map != 0);
648 continue;
649 }
650
651 tid = i;
652 while (cmp->cm_tmap[tid].cmt_missing == B_FALSE) {
653 VERIFY(cmp->cm_tmap[tid].cmt_map != 0);
654 tid = cmp->cm_tmap[tid].cmt_map;
655 }
656 VERIFY(cmp->cm_tmap[tid].cmt_map != 0);
657 cmp->cm_tmap[i].cmt_map = cmp->cm_tmap[tid].cmt_map;
658 }
659 }
660
661
662 /*
663 * We're going to do three passes over the containers.
664 *
665 * Pass 1 checks for forward references in the output container that we know
693 }
694 }
695 }
696
697 /* Pass 2 */
698 for (i = 1; i <= cmp->cm_src->ctf_typemax; i++) {
699 if (cmp->cm_tmap[i].cmt_missing == B_TRUE) {
700 ret = ctf_merge_add_type(cmp, i);
701 if (ret != 0) {
702 ctf_dprintf("Failed to merge type %d\n", i);
703 return (ret);
704 }
705 }
706 }
707
708 ret = ctf_update(cmp->cm_out);
709 if (ret != 0)
710 return (ret);
711
712 if (cmp->cm_dedup == B_TRUE) {
713 ctf_merge_dedup_remap(cmp);
714 }
715
716 ctf_dprintf("Beginning merge pass 3\n");
717 /* Pass 3 */
718 for (i = 1; i <= cmp->cm_src->ctf_typemax; i++) {
719 if (cmp->cm_tmap[i].cmt_fixup == B_TRUE) {
720 ret = ctf_merge_fixup_type(cmp, i);
721 if (ret != 0)
722 return (ret);
723 }
724 }
725
726 return (0);
727 }
728
729 /*
730 * Uniquification is slightly different from a stock merge. For starters, we
731 * don't need to replace any forward references in the output. In this case
732 * though, the types that already exist are in a parent container to the empty
733 * output container.
734 */
735 static int
736 ctf_merge_uniquify_types(ctf_merge_types_t *cmp)
737 {
738 int i, ret;
739
740 for (i = 1; i <= cmp->cm_src->ctf_typemax; i++) {
741 if (cmp->cm_tmap[i].cmt_missing == B_FALSE)
742 continue;
743 ret = ctf_merge_add_type(cmp, i);
744 if (ret != 0)
745 return (ret);
|