Print this page
10812 ctf tools shouldn't add blank labels
10813 ctf symbol mapping needs work
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
   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>


  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,


 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                 }


 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;


 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);


 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);


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) {


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         }


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) {


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 }
   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>


  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         const char *cmo_file;           /* Symbol file */
  64         ulong_t cmo_idx;                /* Symbol ID */
  65         Elf64_Sym cmo_sym;              /* Symbol Entry */
  66         ctf_id_t cmo_tid;               /* Type ID */
  67 } ctf_merge_objmap_t;
  68 
  69 typedef struct ctf_merge_funcmap {
  70         list_node_t cmf_node;
  71         const char *cmf_name;           /* Symbol name */
  72         const char *cmf_file;           /* Symbol file */
  73         ulong_t cmf_idx;                /* Symbol ID */
  74         Elf64_Sym cmf_sym;              /* Symbol Entry */
  75         ctf_id_t cmf_rtid;              /* Type ID */
  76         uint_t cmf_flags;               /* ctf_funcinfo_t ctc_flags */
  77         uint_t cmf_argc;                /* Number of arguments */
  78         ctf_id_t cmf_args[];            /* Types of arguments */
  79 } ctf_merge_funcmap_t;
  80 
  81 typedef struct ctf_merge_input {
  82         list_node_t cmi_node;
  83         ctf_file_t *cmi_input;
  84         list_t cmi_omap;
  85         list_t cmi_fmap;
  86         boolean_t cmi_created;
  87 } ctf_merge_input_t;
  88 
  89 struct ctf_merge_handle {
  90         list_t cmh_inputs;              /* Input list */
  91         uint_t cmh_ninputs;             /* Number of inputs */
  92         uint_t cmh_nthreads;            /* Number of threads to use */
  93         ctf_file_t *cmh_unique;         /* ctf to uniquify against */
  94         boolean_t cmh_msyms;            /* Should we merge symbols/funcs? */
  95         int cmh_ofd;                    /* FD for output file */
  96         int cmh_flags;                  /* Flags that control merge behavior */
  97         char *cmh_label;                /* Optional label */
  98         char *cmh_pname;                /* Parent name */
  99 };
 100 
 101 typedef struct ctf_merge_symbol_arg {
 102         list_t *cmsa_objmap;
 103         list_t *cmsa_funcmap;
 104         ctf_file_t *cmsa_out;
 105         boolean_t cmsa_dedup;
 106 } ctf_merge_symbol_arg_t;
 107 
 108 static int ctf_merge_add_type(ctf_merge_types_t *, ctf_id_t);
 109 
 110 static ctf_id_t
 111 ctf_merge_gettype(ctf_merge_types_t *cmp, ctf_id_t id)
 112 {
 113         if (cmp->cm_dedup == B_FALSE) {
 114                 VERIFY(cmp->cm_tmap[id].cmt_map != 0);
 115                 return (cmp->cm_tmap[id].cmt_map);
 116         }
 117 
 118         while (cmp->cm_tmap[id].cmt_missing == B_FALSE) {
 119                 VERIFY(cmp->cm_tmap[id].cmt_map != 0);
 120                 id = cmp->cm_tmap[id].cmt_map;
 121         }
 122         VERIFY(cmp->cm_tmap[id].cmt_map != 0);
 123         return (cmp->cm_tmap[id].cmt_map);
 124 }
 125 
 126 static void
 127 ctf_merge_diffcb(ctf_file_t *ifp, ctf_id_t iid, boolean_t same, ctf_file_t *ofp,


 655  *
 656  * Pass 1 checks for forward references in the output container that we know
 657  * exist in the source container.
 658  *
 659  * Pass 2 adds all the missing types from the source container. As part of this
 660  * we may be adding a type as a forward reference that doesn't exist yet.
 661  * Any types that we encounter in this form, we need to add to a third pass.
 662  *
 663  * Pass 3 is the fixup pass. Here we go through and find all the types that were
 664  * missing in the first.
 665  *
 666  * Importantly, we *must* call ctf_update between the second and third pass,
 667  * otherwise several of the libctf functions will not properly find the data in
 668  * the container. If we're doing a dedup we also fix up the type mapping.
 669  */
 670 static int
 671 ctf_merge_common(ctf_merge_types_t *cmp)
 672 {
 673         int ret, i;
 674 
 675         ctf_phase_dump(cmp->cm_src, "merge-common-src", NULL);
 676         ctf_phase_dump(cmp->cm_out, "merge-common-dest", NULL);
 677 
 678         /* Pass 1 */
 679         for (i = 1; i <= cmp->cm_src->ctf_typemax; i++) {
 680                 if (cmp->cm_tmap[i].cmt_forward == B_TRUE) {
 681                         ret = ctf_merge_add_sou(cmp, i, B_TRUE);
 682                         if (ret != 0) {
 683                                 return (ret);
 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                 }


 758 static int
 759 ctf_merge_types_init(ctf_merge_types_t *cmp)
 760 {
 761         cmp->cm_tmap = ctf_alloc(sizeof (ctf_merge_tinfo_t) *
 762             (cmp->cm_src->ctf_typemax + 1));
 763         if (cmp->cm_tmap == NULL)
 764                 return (ctf_set_errno(cmp->cm_out, ENOMEM));
 765         bzero(cmp->cm_tmap, sizeof (ctf_merge_tinfo_t) *
 766             (cmp->cm_src->ctf_typemax + 1));
 767         return (0);
 768 }
 769 
 770 static void
 771 ctf_merge_types_fini(ctf_merge_types_t *cmp)
 772 {
 773         ctf_free(cmp->cm_tmap, sizeof (ctf_merge_tinfo_t) *
 774             (cmp->cm_src->ctf_typemax + 1));
 775 }
 776 
 777 /*
 778  * After performing a pass, we need to go through the object and function type
 779  * maps and potentially fix them up based on the new maps that we have.
 780  */
 781 static void
 782 ctf_merge_fixup_symmaps(ctf_merge_types_t *cmp, ctf_merge_input_t *cmi)
 783 {
 784         ctf_merge_objmap_t *cmo;
 785         ctf_merge_funcmap_t *cmf;
 786 
 787         for (cmo = list_head(&cmi->cmi_omap); cmo != NULL;
 788             cmo = list_next(&cmi->cmi_omap, cmo)) {
 789                 VERIFY3S(cmo->cmo_tid, !=, 0);
 790                 VERIFY(cmp->cm_tmap[cmo->cmo_tid].cmt_map != 0);
 791                 cmo->cmo_tid = cmp->cm_tmap[cmo->cmo_tid].cmt_map;
 792         }
 793 
 794         for (cmf = list_head(&cmi->cmi_fmap); cmf != NULL;
 795             cmf = list_next(&cmi->cmi_fmap, cmf)) {
 796                 int i;
 797 
 798                 VERIFY(cmp->cm_tmap[cmf->cmf_rtid].cmt_map != 0);
 799                 cmf->cmf_rtid = cmp->cm_tmap[cmf->cmf_rtid].cmt_map;
 800                 for (i = 0; i < cmf->cmf_argc; i++) {
 801                         VERIFY(cmp->cm_tmap[cmf->cmf_args[i]].cmt_map != 0);
 802                         cmf->cmf_args[i] =
 803                             cmp->cm_tmap[cmf->cmf_args[i]].cmt_map;
 804                 }
 805         }
 806 }
 807 
 808 /*
 809  * Merge the types contained inside of two input files. The second input file is
 810  * always going to be the destination. We're guaranteed that it's always
 811  * writeable.
 812  */
 813 static int
 814 ctf_merge_types(void *arg, void *arg2, void **outp, void *unsued)
 815 {
 816         int ret;
 817         ctf_merge_types_t cm;
 818         ctf_diff_t *cdp;


 819         ctf_merge_input_t *scmi = arg;
 820         ctf_merge_input_t *dcmi = arg2;
 821         ctf_file_t *out = dcmi->cmi_input;
 822         ctf_file_t *source = scmi->cmi_input;
 823 
 824         ctf_dprintf("merging %p->%p\n", source, out);
 825 
 826         if (!(out->ctf_flags & LCTF_RDWR))
 827                 return (ctf_set_errno(out, ECTF_RDONLY));
 828 
 829         if (ctf_getmodel(out) != ctf_getmodel(source))
 830                 return (ctf_set_errno(out, ECTF_DMODEL));
 831 
 832         if ((ret = ctf_diff_init(out, source, &cdp)) != 0)
 833                 return (ret);
 834 
 835         cm.cm_out = out;
 836         cm.cm_src = source;
 837         cm.cm_dedup = B_FALSE;
 838         cm.cm_unique = B_FALSE;


 840         if (ret != 0) {
 841                 ctf_diff_fini(cdp);
 842                 return (ctf_set_errno(out, ret));
 843         }
 844 
 845         ret = ctf_diff_types(cdp, ctf_merge_diffcb, &cm);
 846         if (ret != 0)
 847                 goto cleanup;
 848         ret = ctf_merge_common(&cm);
 849         ctf_dprintf("merge common returned with %d\n", ret);
 850         if (ret == 0) {
 851                 ret = ctf_update(out);
 852                 ctf_dprintf("update returned with %d\n", ret);
 853         } else {
 854                 goto cleanup;
 855         }
 856 
 857         /*
 858          * Now we need to fix up the object and function maps.
 859          */
 860         ctf_merge_fixup_symmaps(&cm, scmi);






 861 












 862         /*
 863          * Now that we've fixed things up, we need to give our function and
 864          * object maps to the destination, such that it can continue to update
 865          * them going forward.
 866          */
 867         list_move_tail(&dcmi->cmi_fmap, &scmi->cmi_fmap);
 868         list_move_tail(&dcmi->cmi_omap, &scmi->cmi_omap);
 869 
 870 cleanup:
 871         if (ret == 0)
 872                 *outp = dcmi;
 873         ctf_merge_types_fini(&cm);
 874         ctf_diff_fini(cdp);
 875         if (ret != 0)
 876                 return (ctf_errno(out));
 877         ctf_phase_bump();
 878         return (0);
 879 }
 880 

































 881 static int
 882 ctf_uniquify_types(ctf_merge_t *cmh, ctf_file_t *src, ctf_file_t **outp)
 883 {
 884         int err, ret;
 885         ctf_file_t *out;
 886         ctf_merge_types_t cm;
 887         ctf_diff_t *cdp;
 888         ctf_merge_input_t *cmi;
 889         ctf_file_t *parent = cmh->cmh_unique;
 890 
 891         *outp = NULL;
 892         out = ctf_fdcreate(cmh->cmh_ofd, &err);
 893         if (out == NULL)
 894                 return (ctf_set_errno(src, err));
 895 
 896         out->ctf_parname = cmh->cmh_pname;
 897         if (ctf_setmodel(out, ctf_getmodel(parent)) != 0) {
 898                 (void) ctf_set_errno(src, ctf_errno(out));
 899                 ctf_close(out);
 900                 return (CTF_ERR);


 921                 ctf_diff_fini(cdp);
 922                 return (ctf_set_errno(src, ret));
 923         }
 924 
 925         ret = ctf_diff_types(cdp, ctf_merge_diffcb, &cm);
 926         if (ret == 0) {
 927                 cm.cm_out = out;
 928                 ret = ctf_merge_uniquify_types(&cm);
 929                 if (ret == 0)
 930                         ret = ctf_update(out);
 931         }
 932 
 933         if (ret != 0) {
 934                 ctf_merge_types_fini(&cm);
 935                 ctf_diff_fini(cdp);
 936                 return (ctf_set_errno(src, ctf_errno(cm.cm_out)));
 937         }
 938 
 939         for (cmi = list_head(&cmh->cmh_inputs); cmi != NULL;
 940             cmi = list_next(&cmh->cmh_inputs, cmi)) {
 941                 ctf_merge_fixup_symmaps(&cm, cmi);
 942         }
 943 
 944         ctf_merge_types_fini(&cm);
 945         ctf_diff_fini(cdp);
 946         *outp = out;
 947         return (0);
 948 }
 949 
 950 static void
 951 ctf_merge_fini_input(ctf_merge_input_t *cmi)
 952 {
 953         ctf_merge_objmap_t *cmo;
 954         ctf_merge_funcmap_t *cmf;
 955 
 956         while ((cmo = list_remove_head(&cmi->cmi_omap)) != NULL)
 957                 ctf_free(cmo, sizeof (ctf_merge_objmap_t));
 958 
 959         while ((cmf = list_remove_head(&cmi->cmi_fmap)) != NULL)
 960                 ctf_free(cmf, sizeof (ctf_merge_funcmap_t) +
 961                     sizeof (ctf_id_t) * cmf->cmf_argc);


1033 {
1034         char *dup;
1035 
1036         if (label == NULL)
1037                 return (EINVAL);
1038 
1039         dup = ctf_strdup(label);
1040         if (dup == NULL)
1041                 return (EAGAIN);
1042 
1043         if (cmh->cmh_label != NULL) {
1044                 size_t len = strlen(cmh->cmh_label) + 1;
1045                 ctf_free(cmh->cmh_label, len);
1046         }
1047 
1048         cmh->cmh_label = dup;
1049         return (0);
1050 }
1051 
1052 static int
1053 ctf_merge_add_function(ctf_merge_input_t *cmi, ctf_funcinfo_t *fip, ulong_t idx,
1054     const char *file, const char *name, const Elf64_Sym *symp)
1055 {

1056         ctf_merge_funcmap_t *fmap;
1057 
1058         fmap = ctf_alloc(sizeof (ctf_merge_funcmap_t) +
1059             sizeof (ctf_id_t) * fip->ctc_argc);
1060         if (fmap == NULL)
1061                 return (ENOMEM);
1062 
1063         fmap->cmf_idx = idx;
1064         fmap->cmf_sym = *symp;
1065         fmap->cmf_rtid = fip->ctc_return;
1066         fmap->cmf_flags = fip->ctc_flags;
1067         fmap->cmf_argc = fip->ctc_argc;
1068         fmap->cmf_name = name;
1069         if (ELF64_ST_BIND(symp->st_info) == STB_LOCAL) {
1070                 fmap->cmf_file = file;
1071         } else {
1072                 fmap->cmf_file = NULL;
1073         }
1074 
1075         if (ctf_func_args(cmi->cmi_input, idx, fmap->cmf_argc,
1076             fmap->cmf_args) != 0) {
1077                 ctf_free(fmap, sizeof (ctf_merge_funcmap_t) +
1078                     sizeof (ctf_id_t) * fip->ctc_argc);
1079                 return (ctf_errno(cmi->cmi_input));
1080         }
1081 
1082         ctf_dprintf("added initial function %s, %lu, %s %u\n", name, idx,
1083             fmap->cmf_file != NULL ? fmap->cmf_file : "global",
1084             ELF64_ST_BIND(symp->st_info));
1085         list_insert_tail(&cmi->cmi_fmap, fmap);
1086         return (0);
1087 }
1088 
1089 static int
1090 ctf_merge_add_object(ctf_merge_input_t *cmi, ctf_id_t id, ulong_t idx,
1091     const char *file, const char *name, const Elf64_Sym *symp)
1092 {

1093         ctf_merge_objmap_t *cmo;
1094 
1095         cmo = ctf_alloc(sizeof (ctf_merge_objmap_t));
1096         if (cmo == NULL)
1097                 return (ENOMEM);
1098 
1099         cmo->cmo_name = name;
1100         if (ELF64_ST_BIND(symp->st_info) == STB_LOCAL) {
1101                 cmo->cmo_file = file;
1102         } else {
1103                 cmo->cmo_file = NULL;
1104         }
1105         cmo->cmo_idx = idx;
1106         cmo->cmo_tid = id;
1107         cmo->cmo_sym = *symp;
1108         list_insert_tail(&cmi->cmi_omap, cmo);
1109 
1110         ctf_dprintf("added initial object %s, %lu, %ld, %s\n", name, idx, id,
1111             cmo->cmo_file != NULL ? cmo->cmo_file : "global");
1112 
1113         return (0);
1114 }
1115 
1116 static int
1117 ctf_merge_add_symbol(const Elf64_Sym *symp, ulong_t idx, const char *file,
1118     const char *name, boolean_t primary, void *arg)
1119 {
1120         ctf_merge_input_t *cmi = arg;
1121         ctf_file_t *fp = cmi->cmi_input;
1122         ushort_t *data, funcbase;
1123         uint_t type;
1124         ctf_funcinfo_t fi;
1125 
1126         /*
1127          * See if there is type information for this. If there is no
1128          * type information for this entry or no translation, then we
1129          * will find the value zero. This indicates no type ID for
1130          * objects and encodes unknown information for functions.
1131          */
1132         if (fp->ctf_sxlate[idx] == -1u)
1133                 return (0);
1134         data = (ushort_t *)((uintptr_t)fp->ctf_buf + fp->ctf_sxlate[idx]);
1135         if (*data == 0)
1136                 return (0);
1137 
1138         type = ELF64_ST_TYPE(symp->st_info);
1139 
1140         switch (type) {
1141         case STT_FUNC:
1142                 funcbase = *data;
1143                 if (LCTF_INFO_KIND(fp, funcbase) != CTF_K_FUNCTION)
1144                         return (0);
1145                 data++;
1146                 fi.ctc_return = *data;
1147                 data++;
1148                 fi.ctc_argc = LCTF_INFO_VLEN(fp, funcbase);
1149                 fi.ctc_flags = 0;
1150 
1151                 if (fi.ctc_argc != 0 && data[fi.ctc_argc - 1] == 0) {
1152                         fi.ctc_flags |= CTF_FUNC_VARARG;
1153                         fi.ctc_argc--;
1154                 }
1155                 return (ctf_merge_add_function(cmi, &fi, idx, file, name,
1156                     symp));
1157         case STT_OBJECT:
1158                 return (ctf_merge_add_object(cmi, *data, idx, file, name,
1159                     symp));
1160         default:
1161                 return (0);
1162         }
1163 }
1164 
1165 /*
1166  * Whenever we create an entry to merge, we then go and add a second empty
1167  * ctf_file_t which we use for the purposes of our merging. It's not the best,
1168  * but it's the best that we've got at the moment.
1169  */
1170 int
1171 ctf_merge_add(ctf_merge_t *cmh, ctf_file_t *input)
1172 {
1173         int ret;
1174         ctf_merge_input_t *cmi;
1175         ctf_file_t *empty;
1176 
1177         ctf_dprintf("adding input %p\n", input);
1178 
1179         if (input->ctf_flags & LCTF_CHILD)
1180                 return (ECTF_MCHILD);
1181 
1182         cmi = ctf_alloc(sizeof (ctf_merge_input_t));
1183         if (cmi == NULL)
1184                 return (ENOMEM);
1185 
1186         cmi->cmi_created = B_FALSE;
1187         cmi->cmi_input = input;
1188         list_create(&cmi->cmi_fmap, sizeof (ctf_merge_funcmap_t),
1189             offsetof(ctf_merge_funcmap_t, cmf_node));
1190         list_create(&cmi->cmi_omap, sizeof (ctf_merge_funcmap_t),
1191             offsetof(ctf_merge_objmap_t, cmo_node));
1192 
1193         if (cmh->cmh_msyms == B_TRUE) {
1194                 if ((ret = ctf_symtab_iter(input, ctf_merge_add_symbol,
1195                     cmi)) != 0) {
1196                         ctf_merge_fini_input(cmi);
1197                         return (ret);
1198                 }





1199         }

1200 
1201         list_insert_tail(&cmh->cmh_inputs, cmi);
1202         cmh->cmh_ninputs++;
1203 
1204         /* And now the empty one to merge into this */
1205         cmi = ctf_alloc(sizeof (ctf_merge_input_t));
1206         if (cmi == NULL)
1207                 return (ENOMEM);
1208         list_create(&cmi->cmi_fmap, sizeof (ctf_merge_funcmap_t),
1209             offsetof(ctf_merge_funcmap_t, cmf_node));
1210         list_create(&cmi->cmi_omap, sizeof (ctf_merge_funcmap_t),
1211             offsetof(ctf_merge_objmap_t, cmo_node));
1212 
1213         empty = ctf_fdcreate(cmh->cmh_ofd, &ret);
1214         if (empty == NULL)
1215                 return (ret);
1216         cmi->cmi_input = empty;
1217         cmi->cmi_created = B_TRUE;
1218 
1219         if (ctf_setmodel(empty, ctf_getmodel(input)) == CTF_ERR) {


1230 ctf_merge_uniquify(ctf_merge_t *cmh, ctf_file_t *u, const char *pname)
1231 {
1232         char *dup;
1233 
1234         if (u->ctf_flags & LCTF_CHILD)
1235                 return (ECTF_MCHILD);
1236         if (pname == NULL)
1237                 return (EINVAL);
1238         dup = ctf_strdup(pname);
1239         if (dup == NULL)
1240                 return (EINVAL);
1241         if (cmh->cmh_pname != NULL) {
1242                 size_t len = strlen(cmh->cmh_pname) + 1;
1243                 ctf_free(cmh->cmh_pname, len);
1244         }
1245         cmh->cmh_pname = dup;
1246         cmh->cmh_unique = u;
1247         return (0);
1248 }
1249 
1250 /*
1251  * Symbol matching rules: the purpose of this is to verify that the type
1252  * information that we have for a given symbol actually matches the output
1253  * symbol. This is unfortunately complicated by several different factors:
1254  *
1255  * 1. When merging multiple .o's into a single item, the symbol table index will
1256  * not match.
1257  *
1258  * 2. Visibility of a symbol may not be identical to the object file or the
1259  * DWARF information due to symbol reduction via a mapfile.
1260  *
1261  * As such, we have to employ the following rules:
1262  *
1263  * 1. A global symbol table entry always matches a global CTF symbol with the
1264  * same name.
1265  *
1266  * 2. A local symbol table entry always matches a local CTF symbol if they have
1267  * the same name and they belong to the same file.
1268  *
1269  * 3. A weak symbol matches a non-weak symbol. This happens if we find that the
1270  * types match, the values match, the sizes match, and the section indexes
1271  * match. This happens when we do a conversion in one pass, it almost never
1272  * happens when we're merging multiple object files. If we match a CTF global
1273  * symbol, that's a fixed match, otherwise it's a fuzzy match.
1274  *
1275  * 4. A local symbol table entry matches a global CTF entry if the
1276  * other pieces fail, but they have the same name. This is considered a fuzzy
1277  * match and is not used unless we have no other options.
1278  *
1279  * 5. A weak symbol table entry matches a weak CTF entry if the other pieces
1280  * fail, but they have the same name. This is considered a fuzzy match and is
1281  * not used unless we have no other options. When merging independent .o files,
1282  * this is often the only recourse we have to matching weak symbols.
1283  *
1284  * In the end, this would all be much simpler if we were able to do this as part
1285  * of libld which would be able to do all the symbol transformations.
1286  */
1287 static boolean_t
1288 ctf_merge_symbol_match(const char *ctf_file, const char *ctf_name,
1289     const Elf64_Sym *ctf_symp, const char *symtab_file, const char *symtab_name,
1290     const Elf64_Sym *symtab_symp, boolean_t *is_fuzzy)
1291 {
1292         *is_fuzzy = B_FALSE;
1293         uint_t symtab_bind, ctf_bind;
1294 
1295         symtab_bind = ELF64_ST_BIND(symtab_symp->st_info);
1296         ctf_bind = ELF64_ST_BIND(ctf_symp->st_info);
1297 
1298         ctf_dprintf("comparing merge match for %s/%s/%u->%s/%s/%u\n",
1299             symtab_file, symtab_name, symtab_bind,
1300             ctf_file, ctf_name, ctf_bind);
1301         if (strcmp(ctf_name, symtab_name) != 0) {
1302                 return (B_FALSE);
1303         }
1304 
1305         if (symtab_bind == STB_GLOBAL && ctf_bind == STB_GLOBAL) {
1306                 return (B_TRUE);
1307         } else if (symtab_bind == STB_GLOBAL) {
1308                 return (B_FALSE);














1309         }
1310 
1311         if (ctf_bind == STB_LOCAL && ctf_bind == symtab_bind &&
1312             ctf_file != NULL && symtab_file != NULL &&
1313             strcmp(ctf_file, symtab_file) == 0) {
1314                 return (B_TRUE);



1315         }
1316 
1317         if (symtab_bind == STB_WEAK && ctf_bind != STB_WEAK &&
1318             ELF64_ST_TYPE(symtab_symp->st_info) ==
1319             ELF64_ST_TYPE(ctf_symp->st_info) &&
1320             symtab_symp->st_value == ctf_symp->st_value &&
1321             symtab_symp->st_size == ctf_symp->st_size &&
1322             symtab_symp->st_shndx == ctf_symp->st_shndx) {
1323                 if (ctf_bind == STB_GLOBAL) {
1324                         return (B_TRUE);
1325                 }
1326 
1327                 if (ctf_bind == STB_LOCAL && ctf_file != NULL &&
1328                     symtab_file != NULL && strcmp(ctf_file, symtab_file) == 0) {
1329                         *is_fuzzy = B_TRUE;
1330                         return (B_TRUE);




1331                 }
1332         }
1333 
1334         if (ctf_bind == STB_GLOBAL ||
1335             (ctf_bind == STB_WEAK && symtab_bind == STB_WEAK)) {
1336                 *is_fuzzy = B_TRUE;
1337                 return (B_TRUE);
1338         }
1339 
1340         return (B_FALSE);
1341 }
1342 
1343 /*
1344  * For each symbol, try and find a match. We will attempt to find an exact
1345  * match; however, we will settle for a fuzzy match in general. There is one
1346  * case where we will not opt to use a fuzzy match, which is when performing the
1347  * deduplication of a container. In such a case we are trying to reduce common
1348  * types and a fuzzy match would be inappropriate as if we're in the context of
1349  * a single container, the conversion process should have identified any exact
1350  * or fuzzy matches that were required.
1351  */
1352 static int
1353 ctf_merge_symbols(const Elf64_Sym *symp, ulong_t idx, const char *file,
1354     const char *name, boolean_t primary, void *arg)
1355 {
1356         int err;
1357         uint_t type, bind;
1358         ctf_merge_symbol_arg_t *csa = arg;
1359         ctf_file_t *fp = csa->cmsa_out;
1360 
1361         type = ELF64_ST_TYPE(symp->st_info);
1362         bind = ELF64_ST_BIND(symp->st_info);
1363 
1364         ctf_dprintf("Trying to find match for %s/%s/%u\n", file, name,
1365             ELF64_ST_BIND(symp->st_info));


1366 
1367         if (type == STT_OBJECT) {
1368                 ctf_merge_objmap_t *cmo, *match = NULL;
1369 
1370                 for (cmo = list_head(csa->cmsa_objmap); cmo != NULL;
1371                     cmo = list_next(csa->cmsa_objmap, cmo)) {
1372                         boolean_t is_fuzzy = B_FALSE;
1373                         if (ctf_merge_symbol_match(cmo->cmo_file, cmo->cmo_name,
1374                             &cmo->cmo_sym, file, name, symp, &is_fuzzy)) {
1375                                 if (is_fuzzy && csa->cmsa_dedup &&
1376                                     bind != STB_WEAK) {
1377                                         continue;
1378                                 }
1379                                 match = cmo;
1380                                 if (is_fuzzy) {
1381                                         continue;
1382                                 }
1383                                 break;
1384                         }
1385                 }
1386 
1387                 if (match == NULL) {
1388                         return (0);
1389                 }
1390 
1391                 if ((err = ctf_add_object(fp, idx, match->cmo_tid)) != 0) {
1392                         ctf_dprintf("Failed to add symbol %s->%d: %s\n", name,
1393                             match->cmo_tid, ctf_errmsg(ctf_errno(fp)));
1394                         return (ctf_errno(fp));
1395                 }
1396                 ctf_dprintf("mapped object into output %s/%s->%ld\n", file,
1397                     name, match->cmo_tid);
1398         } else {
1399                 ctf_merge_funcmap_t *cmf, *match = NULL;
1400                 ctf_funcinfo_t fi;
1401 
1402                 for (cmf = list_head(csa->cmsa_funcmap); cmf != NULL;
1403                     cmf = list_next(csa->cmsa_funcmap, cmf)) {
1404                         boolean_t is_fuzzy = B_FALSE;
1405                         if (ctf_merge_symbol_match(cmf->cmf_file, cmf->cmf_name,
1406                             &cmf->cmf_sym, file, name, symp, &is_fuzzy)) {
1407                                 if (is_fuzzy && csa->cmsa_dedup &&
1408                                     bind != STB_WEAK) {
1409                                         continue;
1410                                 }
1411                                 match = cmf;
1412                                 if (is_fuzzy) {
1413                                         continue;

1414                                 }
1415                                 break;







1416                         }
1417                 }
1418 
1419                 if (match == NULL) {
1420                         return (0);





1421                 }
1422 
1423                 fi.ctc_return = match->cmf_rtid;
1424                 fi.ctc_argc = match->cmf_argc;
1425                 fi.ctc_flags = match->cmf_flags;
1426                 if ((err = ctf_add_function(fp, idx, &fi, match->cmf_args)) !=
1427                     0) {
1428                         ctf_dprintf("Failed to add function %s: %s\n", name,
1429                             ctf_errmsg(ctf_errno(fp)));
1430                         return (ctf_errno(fp));
1431                 }
1432                 ctf_dprintf("mapped function into output %s/%s\n", file,
1433                     name);
1434         }
1435 
1436         return (0);

1437 }
1438 
1439 int
1440 ctf_merge_merge(ctf_merge_t *cmh, ctf_file_t **outp)
1441 {
1442         int err, merr;
1443         ctf_merge_input_t *cmi;
1444         ctf_id_t ltype;
1445         mergeq_t *mqp;
1446         ctf_merge_input_t *final;
1447         ctf_file_t *out;
1448 
1449         ctf_dprintf("Beginning ctf_merge_merge()\n");
1450         if (cmh->cmh_label != NULL && cmh->cmh_unique != NULL) {
1451                 const char *label = ctf_label_topmost(cmh->cmh_unique);
1452                 if (label == NULL)
1453                         return (ECTF_NOLABEL);
1454                 if (strcmp(label, cmh->cmh_label) != 0)
1455                         return (ECTF_LCONFLICT);
1456         }
1457 
1458         if (mergeq_init(&mqp, cmh->cmh_nthreads) == -1) {
1459                 return (errno);
1460         }
1461 
1462         VERIFY(cmh->cmh_ninputs % 2 == 0);
1463         for (cmi = list_head(&cmh->cmh_inputs); cmi != NULL;
1464             cmi = list_next(&cmh->cmh_inputs, cmi)) {
1465                 if (mergeq_add(mqp, cmi) == -1) {
1466                         err = errno;
1467                         mergeq_fini(mqp);
1468                 }
1469         }


1495                         err = ctf_errno(out);
1496                         ctf_close(out);
1497                         return (err);
1498                 }
1499                 ctf_close(out);
1500                 out = u;
1501         }
1502 
1503         ltype = out->ctf_typemax;
1504         if ((out->ctf_flags & LCTF_CHILD) && ltype != 0)
1505                 ltype += CTF_CHILD_START;
1506         ctf_dprintf("trying to add the label\n");
1507         if (cmh->cmh_label != NULL &&
1508             ctf_add_label(out, cmh->cmh_label, ltype, 0) != 0) {
1509                 ctf_close(out);
1510                 return (ctf_errno(out));
1511         }
1512 
1513         ctf_dprintf("merging symbols and the like\n");
1514         if (cmh->cmh_msyms == B_TRUE) {
1515                 ctf_merge_symbol_arg_t arg;
1516                 arg.cmsa_objmap = &final->cmi_omap;
1517                 arg.cmsa_funcmap = &final->cmi_fmap;
1518                 arg.cmsa_out = out;
1519                 arg.cmsa_dedup = B_FALSE;
1520                 err = ctf_symtab_iter(out, ctf_merge_symbols, &arg);
1521                 if (err != 0) {
1522                         ctf_close(out);
1523                         return (err);
1524                 }





1525         }

1526 
1527         err = ctf_update(out);
1528         if (err != 0) {
1529                 err = ctf_errno(out);
1530                 ctf_close(out);
1531                 return (err);
1532         }
1533 
1534         *outp = out;
1535         return (0);
1536 }
1537 
1538 /*
1539  * When we get told that something is unique, eg. same is B_FALSE, then that
1540  * tells us that we need to add it to the output. If same is B_TRUE, then we'll
1541  * want to record it in the mapping table so that we know how to redirect types
1542  * to the extant ones.
1543  */
1544 static void
1545 ctf_dedup_cb(ctf_file_t *ifp, ctf_id_t iid, boolean_t same, ctf_file_t *ofp,
1546     ctf_id_t oid, void *arg)
1547 {
1548         ctf_merge_types_t *cmp = arg;
1549         ctf_merge_tinfo_t *cmt = cmp->cm_tmap;
1550 
1551         if (same == B_TRUE) {


1613         if ((ret = ctf_merge_types_init(&cm)) != 0) {
1614                 return (ret);
1615         }
1616 
1617         if ((ret = ctf_diff_init(ifp, ifp, &cdp)) != 0)
1618                 goto err;
1619 
1620         ctf_dprintf("Successfully initialized dedup\n");
1621         if ((ret = ctf_diff_self(cdp, ctf_dedup_cb, &cm)) != 0)
1622                 goto err;
1623 
1624         ctf_dprintf("Successfully diffed types\n");
1625         ret = ctf_merge_common(&cm);
1626         ctf_dprintf("deduping types result: %d\n", ret);
1627         if (ret == 0)
1628                 ret = ctf_update(cm.cm_out);
1629         if (ret != 0)
1630                 goto err;
1631 
1632         ctf_dprintf("Successfully deduped types\n");
1633         ctf_phase_dump(cm.cm_out, "dedup-pre-syms", NULL);
1634 
1635         /*
1636          * Now we need to fix up the object and function maps.
1637          */
1638         ctf_merge_fixup_symmaps(&cm, cmi);
1639 
1640         if (cmp->cmh_msyms == B_TRUE) {
1641                 ctf_merge_symbol_arg_t arg;
1642                 arg.cmsa_objmap = &cmi->cmi_omap;
1643                 arg.cmsa_funcmap = &cmi->cmi_fmap;
1644                 arg.cmsa_out = cm.cm_out;
1645                 arg.cmsa_dedup = B_TRUE;
1646                 ret = ctf_symtab_iter(cm.cm_out, ctf_merge_symbols, &arg);
1647                 if (ret != 0) {

1648                         ctf_dprintf("failed to dedup symbols: %s\n",
1649                             ctf_errmsg(ret));
1650                         goto err;
1651                 }







1652         }

1653 
1654         ret = ctf_update(cm.cm_out);
1655         if (ret == 0) {
1656                 cmc->cmi_input = NULL;
1657                 *outp = cm.cm_out;
1658         }
1659         ctf_phase_dump(cm.cm_out, "dedup-post-syms", NULL);
1660 err:
1661         ctf_merge_types_fini(&cm);
1662         ctf_diff_fini(cdp);
1663         return (ret);
1664 }
1665 
1666 int
1667 ctf_merge_set_nthreads(ctf_merge_t *cmp, const uint_t nthrs)
1668 {
1669         if (nthrs == 0)
1670                 return (EINVAL);
1671         cmp->cmh_nthreads = nthrs;
1672         return (0);
1673 }