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>

*** 8,18 **** * source. A copy of the CDDL is also available via the Internet at * http://www.illumos.org/license/CDDL. */ /* ! * Copyright (c) 2015 Joyent, Inc. */ /* * To perform a merge of two CTF containers, we first diff the two containers * types. For every type that's in the src container, but not in the dst --- 8,18 ---- * source. A copy of the CDDL is also available via the Internet at * http://www.illumos.org/license/CDDL. */ /* ! * Copyright (c) 2019 Joyent, Inc. */ /* * To perform a merge of two CTF containers, we first diff the two containers * types. For every type that's in the src container, but not in the dst
*** 58,75 **** --- 58,79 ---- } ctf_merge_types_t; typedef struct ctf_merge_objmap { list_node_t cmo_node; const char *cmo_name; /* Symbol name */ + const char *cmo_file; /* Symbol file */ ulong_t cmo_idx; /* Symbol ID */ + Elf64_Sym cmo_sym; /* Symbol Entry */ ctf_id_t cmo_tid; /* Type ID */ } ctf_merge_objmap_t; typedef struct ctf_merge_funcmap { list_node_t cmf_node; const char *cmf_name; /* Symbol name */ + const char *cmf_file; /* Symbol file */ ulong_t cmf_idx; /* Symbol ID */ + Elf64_Sym cmf_sym; /* Symbol Entry */ ctf_id_t cmf_rtid; /* Type ID */ uint_t cmf_flags; /* ctf_funcinfo_t ctc_flags */ uint_t cmf_argc; /* Number of arguments */ ctf_id_t cmf_args[]; /* Types of arguments */ } ctf_merge_funcmap_t;
*** 92,101 **** --- 96,112 ---- int cmh_flags; /* Flags that control merge behavior */ char *cmh_label; /* Optional label */ char *cmh_pname; /* Parent name */ }; + typedef struct ctf_merge_symbol_arg { + list_t *cmsa_objmap; + list_t *cmsa_funcmap; + ctf_file_t *cmsa_out; + boolean_t cmsa_dedup; + } ctf_merge_symbol_arg_t; + static int ctf_merge_add_type(ctf_merge_types_t *, ctf_id_t); static ctf_id_t ctf_merge_gettype(ctf_merge_types_t *cmp, ctf_id_t id) {
*** 659,670 **** static int ctf_merge_common(ctf_merge_types_t *cmp) { int ret, i; ! ctf_phase_dump(cmp->cm_src, "merge-common-src"); ! ctf_phase_dump(cmp->cm_out, "merge-common-dest"); /* Pass 1 */ for (i = 1; i <= cmp->cm_src->ctf_typemax; i++) { if (cmp->cm_tmap[i].cmt_forward == B_TRUE) { ret = ctf_merge_add_sou(cmp, i, B_TRUE); --- 670,681 ---- static int ctf_merge_common(ctf_merge_types_t *cmp) { int ret, i; ! ctf_phase_dump(cmp->cm_src, "merge-common-src", NULL); ! ctf_phase_dump(cmp->cm_out, "merge-common-dest", NULL); /* Pass 1 */ for (i = 1; i <= cmp->cm_src->ctf_typemax; i++) { if (cmp->cm_tmap[i].cmt_forward == B_TRUE) { ret = ctf_merge_add_sou(cmp, i, B_TRUE);
*** 762,771 **** --- 773,813 ---- ctf_free(cmp->cm_tmap, sizeof (ctf_merge_tinfo_t) * (cmp->cm_src->ctf_typemax + 1)); } /* + * After performing a pass, we need to go through the object and function type + * maps and potentially fix them up based on the new maps that we have. + */ + static void + ctf_merge_fixup_symmaps(ctf_merge_types_t *cmp, ctf_merge_input_t *cmi) + { + ctf_merge_objmap_t *cmo; + ctf_merge_funcmap_t *cmf; + + for (cmo = list_head(&cmi->cmi_omap); cmo != NULL; + cmo = list_next(&cmi->cmi_omap, cmo)) { + VERIFY3S(cmo->cmo_tid, !=, 0); + VERIFY(cmp->cm_tmap[cmo->cmo_tid].cmt_map != 0); + cmo->cmo_tid = cmp->cm_tmap[cmo->cmo_tid].cmt_map; + } + + for (cmf = list_head(&cmi->cmi_fmap); cmf != NULL; + cmf = list_next(&cmi->cmi_fmap, cmf)) { + int i; + + VERIFY(cmp->cm_tmap[cmf->cmf_rtid].cmt_map != 0); + cmf->cmf_rtid = cmp->cm_tmap[cmf->cmf_rtid].cmt_map; + for (i = 0; i < cmf->cmf_argc; i++) { + VERIFY(cmp->cm_tmap[cmf->cmf_args[i]].cmt_map != 0); + cmf->cmf_args[i] = + cmp->cm_tmap[cmf->cmf_args[i]].cmt_map; + } + } + } + + /* * Merge the types contained inside of two input files. The second input file is * always going to be the destination. We're guaranteed that it's always * writeable. */ static int
*** 772,783 **** ctf_merge_types(void *arg, void *arg2, void **outp, void *unsued) { int ret; ctf_merge_types_t cm; ctf_diff_t *cdp; - ctf_merge_objmap_t *cmo; - ctf_merge_funcmap_t *cmf; ctf_merge_input_t *scmi = arg; ctf_merge_input_t *dcmi = arg2; ctf_file_t *out = dcmi->cmi_input; ctf_file_t *source = scmi->cmi_input; --- 814,823 ----
*** 815,844 **** } /* * Now we need to fix up the object and function maps. */ ! for (cmo = list_head(&scmi->cmi_omap); cmo != NULL; ! cmo = list_next(&scmi->cmi_omap, cmo)) { ! if (cmo->cmo_tid == 0) ! continue; ! VERIFY(cm.cm_tmap[cmo->cmo_tid].cmt_map != 0); ! cmo->cmo_tid = cm.cm_tmap[cmo->cmo_tid].cmt_map; ! } - for (cmf = list_head(&scmi->cmi_fmap); cmf != NULL; - cmf = list_next(&scmi->cmi_fmap, cmf)) { - int i; - - VERIFY(cm.cm_tmap[cmf->cmf_rtid].cmt_map != 0); - cmf->cmf_rtid = cm.cm_tmap[cmf->cmf_rtid].cmt_map; - for (i = 0; i < cmf->cmf_argc; i++) { - VERIFY(cm.cm_tmap[cmf->cmf_args[i]].cmt_map != 0); - cmf->cmf_args[i] = cm.cm_tmap[cmf->cmf_args[i]].cmt_map; - } - } - /* * Now that we've fixed things up, we need to give our function and * object maps to the destination, such that it can continue to update * them going forward. */ --- 855,866 ---- } /* * Now we need to fix up the object and function maps. */ ! ctf_merge_fixup_symmaps(&cm, scmi); /* * Now that we've fixed things up, we need to give our function and * object maps to the destination, such that it can continue to update * them going forward. */
*** 850,895 **** *outp = dcmi; ctf_merge_types_fini(&cm); ctf_diff_fini(cdp); if (ret != 0) return (ctf_errno(out)); return (0); } - /* - * After performing a pass, we need to go through the object and function type - * maps and potentially fix them up based on the new maps that we haev. - */ - static void - ctf_merge_fixup_nontypes(ctf_merge_types_t *cmp, ctf_merge_input_t *cmi) - { - ctf_merge_objmap_t *cmo; - ctf_merge_funcmap_t *cmf; - - for (cmo = list_head(&cmi->cmi_omap); cmo != NULL; - cmo = list_next(&cmi->cmi_omap, cmo)) { - if (cmo->cmo_tid == 0) - continue; - VERIFY(cmp->cm_tmap[cmo->cmo_tid].cmt_map != 0); - cmo->cmo_tid = cmp->cm_tmap[cmo->cmo_tid].cmt_map; - } - - for (cmf = list_head(&cmi->cmi_fmap); cmf != NULL; - cmf = list_next(&cmi->cmi_fmap, cmf)) { - int i; - - VERIFY(cmp->cm_tmap[cmf->cmf_rtid].cmt_map != 0); - cmf->cmf_rtid = cmp->cm_tmap[cmf->cmf_rtid].cmt_map; - for (i = 0; i < cmf->cmf_argc; i++) { - VERIFY(cmp->cm_tmap[cmf->cmf_args[i]].cmt_map != - 0); - cmf->cmf_args[i] = - cmp->cm_tmap[cmf->cmf_args[i]].cmt_map; - } - } - } - static int ctf_uniquify_types(ctf_merge_t *cmh, ctf_file_t *src, ctf_file_t **outp) { int err, ret; ctf_file_t *out; --- 872,885 ---- *outp = dcmi; ctf_merge_types_fini(&cm); ctf_diff_fini(cdp); if (ret != 0) return (ctf_errno(out)); + ctf_phase_bump(); return (0); } static int ctf_uniquify_types(ctf_merge_t *cmh, ctf_file_t *src, ctf_file_t **outp) { int err, ret; ctf_file_t *out;
*** 946,956 **** return (ctf_set_errno(src, ctf_errno(cm.cm_out))); } for (cmi = list_head(&cmh->cmh_inputs); cmi != NULL; cmi = list_next(&cmh->cmh_inputs, cmi)) { ! ctf_merge_fixup_nontypes(&cm, cmi); } ctf_merge_types_fini(&cm); ctf_diff_fini(cdp); *outp = out; --- 936,946 ---- return (ctf_set_errno(src, ctf_errno(cm.cm_out))); } for (cmi = list_head(&cmh->cmh_inputs); cmi != NULL; cmi = list_next(&cmh->cmh_inputs, cmi)) { ! ctf_merge_fixup_symmaps(&cm, cmi); } ctf_merge_types_fini(&cm); ctf_diff_fini(cdp); *outp = out;
*** 1058,1112 **** cmh->cmh_label = dup; return (0); } static int ! ctf_merge_add_funcs_cb(const char *name, ulong_t idx, ctf_funcinfo_t *fip, ! void *arg) { - ctf_merge_input_t *cmi = arg; ctf_merge_funcmap_t *fmap; fmap = ctf_alloc(sizeof (ctf_merge_funcmap_t) + sizeof (ctf_id_t) * fip->ctc_argc); if (fmap == NULL) return (ENOMEM); fmap->cmf_idx = idx; fmap->cmf_rtid = fip->ctc_return; fmap->cmf_flags = fip->ctc_flags; fmap->cmf_argc = fip->ctc_argc; fmap->cmf_name = name; if (ctf_func_args(cmi->cmi_input, idx, fmap->cmf_argc, fmap->cmf_args) != 0) { ctf_free(fmap, sizeof (ctf_merge_funcmap_t) + sizeof (ctf_id_t) * fip->ctc_argc); return (ctf_errno(cmi->cmi_input)); } list_insert_tail(&cmi->cmi_fmap, fmap); return (0); } static int ! ctf_merge_add_objs_cb(const char *name, ctf_id_t id, ulong_t idx, void *arg) { - ctf_merge_input_t *cmi = arg; ctf_merge_objmap_t *cmo; cmo = ctf_alloc(sizeof (ctf_merge_objmap_t)); if (cmo == NULL) return (ENOMEM); cmo->cmo_name = name; cmo->cmo_idx = idx; cmo->cmo_tid = id; list_insert_tail(&cmi->cmi_omap, cmo); return (0); } /* * Whenever we create an entry to merge, we then go and add a second empty * ctf_file_t which we use for the purposes of our merging. It's not the best, * but it's the best that we've got at the moment. */ --- 1048,1169 ---- cmh->cmh_label = dup; return (0); } static int ! ctf_merge_add_function(ctf_merge_input_t *cmi, ctf_funcinfo_t *fip, ulong_t idx, ! const char *file, const char *name, const Elf64_Sym *symp) { ctf_merge_funcmap_t *fmap; fmap = ctf_alloc(sizeof (ctf_merge_funcmap_t) + sizeof (ctf_id_t) * fip->ctc_argc); if (fmap == NULL) return (ENOMEM); fmap->cmf_idx = idx; + fmap->cmf_sym = *symp; fmap->cmf_rtid = fip->ctc_return; fmap->cmf_flags = fip->ctc_flags; fmap->cmf_argc = fip->ctc_argc; fmap->cmf_name = name; + if (ELF64_ST_BIND(symp->st_info) == STB_LOCAL) { + fmap->cmf_file = file; + } else { + fmap->cmf_file = NULL; + } if (ctf_func_args(cmi->cmi_input, idx, fmap->cmf_argc, fmap->cmf_args) != 0) { ctf_free(fmap, sizeof (ctf_merge_funcmap_t) + sizeof (ctf_id_t) * fip->ctc_argc); return (ctf_errno(cmi->cmi_input)); } + ctf_dprintf("added initial function %s, %lu, %s %u\n", name, idx, + fmap->cmf_file != NULL ? fmap->cmf_file : "global", + ELF64_ST_BIND(symp->st_info)); list_insert_tail(&cmi->cmi_fmap, fmap); return (0); } static int ! ctf_merge_add_object(ctf_merge_input_t *cmi, ctf_id_t id, ulong_t idx, ! const char *file, const char *name, const Elf64_Sym *symp) { ctf_merge_objmap_t *cmo; cmo = ctf_alloc(sizeof (ctf_merge_objmap_t)); if (cmo == NULL) return (ENOMEM); cmo->cmo_name = name; + if (ELF64_ST_BIND(symp->st_info) == STB_LOCAL) { + cmo->cmo_file = file; + } else { + cmo->cmo_file = NULL; + } cmo->cmo_idx = idx; cmo->cmo_tid = id; + cmo->cmo_sym = *symp; list_insert_tail(&cmi->cmi_omap, cmo); + + ctf_dprintf("added initial object %s, %lu, %ld, %s\n", name, idx, id, + cmo->cmo_file != NULL ? cmo->cmo_file : "global"); + return (0); } + static int + ctf_merge_add_symbol(const Elf64_Sym *symp, ulong_t idx, const char *file, + const char *name, boolean_t primary, void *arg) + { + ctf_merge_input_t *cmi = arg; + ctf_file_t *fp = cmi->cmi_input; + ushort_t *data, funcbase; + uint_t type; + ctf_funcinfo_t fi; + + /* + * See if there is type information for this. If there is no + * type information for this entry or no translation, then we + * will find the value zero. This indicates no type ID for + * objects and encodes unknown information for functions. + */ + if (fp->ctf_sxlate[idx] == -1u) + return (0); + data = (ushort_t *)((uintptr_t)fp->ctf_buf + fp->ctf_sxlate[idx]); + if (*data == 0) + return (0); + + type = ELF64_ST_TYPE(symp->st_info); + + switch (type) { + case STT_FUNC: + funcbase = *data; + if (LCTF_INFO_KIND(fp, funcbase) != CTF_K_FUNCTION) + return (0); + data++; + fi.ctc_return = *data; + data++; + fi.ctc_argc = LCTF_INFO_VLEN(fp, funcbase); + fi.ctc_flags = 0; + + if (fi.ctc_argc != 0 && data[fi.ctc_argc - 1] == 0) { + fi.ctc_flags |= CTF_FUNC_VARARG; + fi.ctc_argc--; + } + return (ctf_merge_add_function(cmi, &fi, idx, file, name, + symp)); + case STT_OBJECT: + return (ctf_merge_add_object(cmi, *data, idx, file, name, + symp)); + default: + return (0); + } + } + /* * Whenever we create an entry to merge, we then go and add a second empty * ctf_file_t which we use for the purposes of our merging. It's not the best, * but it's the best that we've got at the moment. */
*** 1115,1124 **** --- 1172,1183 ---- { int ret; ctf_merge_input_t *cmi; ctf_file_t *empty; + ctf_dprintf("adding input %p\n", input); + if (input->ctf_flags & LCTF_CHILD) return (ECTF_MCHILD); cmi = ctf_alloc(sizeof (ctf_merge_input_t)); if (cmi == NULL)
*** 1130,1151 **** offsetof(ctf_merge_funcmap_t, cmf_node)); list_create(&cmi->cmi_omap, sizeof (ctf_merge_funcmap_t), offsetof(ctf_merge_objmap_t, cmo_node)); if (cmh->cmh_msyms == B_TRUE) { ! if ((ret = ctf_function_iter(input, ctf_merge_add_funcs_cb, cmi)) != 0) { ctf_merge_fini_input(cmi); return (ret); } - - if ((ret = ctf_object_iter(input, ctf_merge_add_objs_cb, - cmi)) != 0) { - ctf_merge_fini_input(cmi); - return (ret); } - } list_insert_tail(&cmh->cmh_inputs, cmi); cmh->cmh_ninputs++; /* And now the empty one to merge into this */ --- 1189,1204 ---- offsetof(ctf_merge_funcmap_t, cmf_node)); list_create(&cmi->cmi_omap, sizeof (ctf_merge_funcmap_t), offsetof(ctf_merge_objmap_t, cmo_node)); if (cmh->cmh_msyms == B_TRUE) { ! if ((ret = ctf_symtab_iter(input, ctf_merge_add_symbol, cmi)) != 0) { ctf_merge_fini_input(cmi); return (ret); } } list_insert_tail(&cmh->cmh_inputs, cmi); cmh->cmh_ninputs++; /* And now the empty one to merge into this */
*** 1192,1317 **** cmh->cmh_pname = dup; cmh->cmh_unique = u; return (0); } ! static int ! ctf_merge_symbols(ctf_merge_t *cmh, ctf_file_t *fp) { ! int err; ! ulong_t i; ! uintptr_t symbase = (uintptr_t)fp->ctf_symtab.cts_data; ! uintptr_t strbase = (uintptr_t)fp->ctf_strtab.cts_data; ! for (i = 0; i < fp->ctf_nsyms; i++) { ! const char *name; ! ctf_merge_input_t *cmi; ! ctf_merge_objmap_t *cmo; ! if (fp->ctf_symtab.cts_entsize == sizeof (Elf32_Sym)) { ! const Elf32_Sym *symp = (Elf32_Sym *)symbase + i; ! int type = ELF32_ST_TYPE(symp->st_info); ! if (type != STT_OBJECT) ! continue; ! if (ctf_sym_valid(strbase, type, symp->st_shndx, ! symp->st_value, symp->st_name) == B_FALSE) ! continue; ! name = (char *)(strbase + symp->st_name); ! } else { ! const Elf64_Sym *symp = (Elf64_Sym *)symbase + i; ! int type = ELF64_ST_TYPE(symp->st_info); ! if (type != STT_OBJECT) ! continue; ! if (ctf_sym_valid(strbase, type, symp->st_shndx, ! symp->st_value, symp->st_name) == B_FALSE) ! continue; ! name = (char *)(strbase + symp->st_name); } ! cmo = NULL; ! for (cmi = list_head(&cmh->cmh_inputs); cmi != NULL; ! cmi = list_next(&cmh->cmh_inputs, cmi)) { ! for (cmo = list_head(&cmi->cmi_omap); cmo != NULL; ! cmo = list_next(&cmi->cmi_omap, cmo)) { ! if (strcmp(cmo->cmo_name, name) == 0) ! goto found; } } ! found: ! if (cmo != NULL) { ! if (cmo->cmo_tid == 0) ! continue; ! if ((err = ctf_add_object(fp, i, cmo->cmo_tid)) != 0) { ! ctf_dprintf("Failed to add symbol %s->%d: %s\n", ! name, cmo->cmo_tid, ! ctf_errmsg(ctf_errno(fp))); ! return (err); } } } ! return (0); } static int ! ctf_merge_functions(ctf_merge_t *cmh, ctf_file_t *fp) { int err; ! ulong_t i; ! ctf_funcinfo_t fi; ! uintptr_t symbase = (uintptr_t)fp->ctf_symtab.cts_data; ! uintptr_t strbase = (uintptr_t)fp->ctf_strtab.cts_data; ! for (i = 0; i < fp->ctf_nsyms; i++) { ! const char *name; ! ctf_merge_input_t *cmi; ! ctf_merge_funcmap_t *cmf; ! if (fp->ctf_symtab.cts_entsize == sizeof (Elf32_Sym)) { ! const Elf32_Sym *symp = (Elf32_Sym *)symbase + i; ! int type = ELF32_ST_TYPE(symp->st_info); ! if (ELF32_ST_TYPE(symp->st_info) != STT_FUNC) continue; ! if (ctf_sym_valid(strbase, type, symp->st_shndx, ! symp->st_value, symp->st_name) == B_FALSE) continue; ! name = (char *)(strbase + symp->st_name); } else { ! const Elf64_Sym *symp = (Elf64_Sym *)symbase + i; ! int type = ELF64_ST_TYPE(symp->st_info); ! if (ELF64_ST_TYPE(symp->st_info) != STT_FUNC) continue; ! if (ctf_sym_valid(strbase, type, symp->st_shndx, ! symp->st_value, symp->st_name) == B_FALSE) continue; - name = (char *)(strbase + symp->st_name); } ! ! cmf = NULL; ! for (cmi = list_head(&cmh->cmh_inputs); cmi != NULL; ! cmi = list_next(&cmh->cmh_inputs, cmi)) { ! for (cmf = list_head(&cmi->cmi_fmap); cmf != NULL; ! cmf = list_next(&cmi->cmi_fmap, cmf)) { ! if (strcmp(cmf->cmf_name, name) == 0) ! goto found; } } ! found: ! if (cmf != NULL) { ! fi.ctc_return = cmf->cmf_rtid; ! fi.ctc_argc = cmf->cmf_argc; ! fi.ctc_flags = cmf->cmf_flags; ! if ((err = ctf_add_function(fp, i, &fi, ! cmf->cmf_args)) != 0) ! return (err); } } return (0); - } int ctf_merge_merge(ctf_merge_t *cmh, ctf_file_t **outp) { --- 1245,1441 ---- cmh->cmh_pname = dup; cmh->cmh_unique = u; return (0); } ! /* ! * Symbol matching rules: the purpose of this is to verify that the type ! * information that we have for a given symbol actually matches the output ! * symbol. This is unfortunately complicated by several different factors: ! * ! * 1. When merging multiple .o's into a single item, the symbol table index will ! * not match. ! * ! * 2. Visibility of a symbol may not be identical to the object file or the ! * DWARF information due to symbol reduction via a mapfile. ! * ! * As such, we have to employ the following rules: ! * ! * 1. A global symbol table entry always matches a global CTF symbol with the ! * same name. ! * ! * 2. A local symbol table entry always matches a local CTF symbol if they have ! * the same name and they belong to the same file. ! * ! * 3. A weak symbol matches a non-weak symbol. This happens if we find that the ! * types match, the values match, the sizes match, and the section indexes ! * match. This happens when we do a conversion in one pass, it almost never ! * happens when we're merging multiple object files. If we match a CTF global ! * symbol, that's a fixed match, otherwise it's a fuzzy match. ! * ! * 4. A local symbol table entry matches a global CTF entry if the ! * other pieces fail, but they have the same name. This is considered a fuzzy ! * match and is not used unless we have no other options. ! * ! * 5. A weak symbol table entry matches a weak CTF entry if the other pieces ! * fail, but they have the same name. This is considered a fuzzy match and is ! * not used unless we have no other options. When merging independent .o files, ! * this is often the only recourse we have to matching weak symbols. ! * ! * In the end, this would all be much simpler if we were able to do this as part ! * of libld which would be able to do all the symbol transformations. ! */ ! static boolean_t ! ctf_merge_symbol_match(const char *ctf_file, const char *ctf_name, ! const Elf64_Sym *ctf_symp, const char *symtab_file, const char *symtab_name, ! const Elf64_Sym *symtab_symp, boolean_t *is_fuzzy) { ! *is_fuzzy = B_FALSE; ! uint_t symtab_bind, ctf_bind; ! symtab_bind = ELF64_ST_BIND(symtab_symp->st_info); ! ctf_bind = ELF64_ST_BIND(ctf_symp->st_info); ! ctf_dprintf("comparing merge match for %s/%s/%u->%s/%s/%u\n", ! symtab_file, symtab_name, symtab_bind, ! ctf_file, ctf_name, ctf_bind); ! if (strcmp(ctf_name, symtab_name) != 0) { ! return (B_FALSE); ! } ! if (symtab_bind == STB_GLOBAL && ctf_bind == STB_GLOBAL) { ! return (B_TRUE); ! } else if (symtab_bind == STB_GLOBAL) { ! return (B_FALSE); } ! if (ctf_bind == STB_LOCAL && ctf_bind == symtab_bind && ! ctf_file != NULL && symtab_file != NULL && ! strcmp(ctf_file, symtab_file) == 0) { ! return (B_TRUE); } + + if (symtab_bind == STB_WEAK && ctf_bind != STB_WEAK && + ELF64_ST_TYPE(symtab_symp->st_info) == + ELF64_ST_TYPE(ctf_symp->st_info) && + symtab_symp->st_value == ctf_symp->st_value && + symtab_symp->st_size == ctf_symp->st_size && + symtab_symp->st_shndx == ctf_symp->st_shndx) { + if (ctf_bind == STB_GLOBAL) { + return (B_TRUE); } ! ! if (ctf_bind == STB_LOCAL && ctf_file != NULL && ! symtab_file != NULL && strcmp(ctf_file, symtab_file) == 0) { ! *is_fuzzy = B_TRUE; ! return (B_TRUE); } } + + if (ctf_bind == STB_GLOBAL || + (ctf_bind == STB_WEAK && symtab_bind == STB_WEAK)) { + *is_fuzzy = B_TRUE; + return (B_TRUE); } ! return (B_FALSE); } + /* + * For each symbol, try and find a match. We will attempt to find an exact + * match; however, we will settle for a fuzzy match in general. There is one + * case where we will not opt to use a fuzzy match, which is when performing the + * deduplication of a container. In such a case we are trying to reduce common + * types and a fuzzy match would be inappropriate as if we're in the context of + * a single container, the conversion process should have identified any exact + * or fuzzy matches that were required. + */ static int ! ctf_merge_symbols(const Elf64_Sym *symp, ulong_t idx, const char *file, ! const char *name, boolean_t primary, void *arg) { int err; ! uint_t type, bind; ! ctf_merge_symbol_arg_t *csa = arg; ! ctf_file_t *fp = csa->cmsa_out; ! type = ELF64_ST_TYPE(symp->st_info); ! bind = ELF64_ST_BIND(symp->st_info); ! ctf_dprintf("Trying to find match for %s/%s/%u\n", file, name, ! ELF64_ST_BIND(symp->st_info)); ! if (type == STT_OBJECT) { ! ctf_merge_objmap_t *cmo, *match = NULL; ! ! for (cmo = list_head(csa->cmsa_objmap); cmo != NULL; ! cmo = list_next(csa->cmsa_objmap, cmo)) { ! boolean_t is_fuzzy = B_FALSE; ! if (ctf_merge_symbol_match(cmo->cmo_file, cmo->cmo_name, ! &cmo->cmo_sym, file, name, symp, &is_fuzzy)) { ! if (is_fuzzy && csa->cmsa_dedup && ! bind != STB_WEAK) { continue; ! } ! match = cmo; ! if (is_fuzzy) { continue; ! } ! break; ! } ! } ! ! if (match == NULL) { ! return (0); ! } ! ! if ((err = ctf_add_object(fp, idx, match->cmo_tid)) != 0) { ! ctf_dprintf("Failed to add symbol %s->%d: %s\n", name, ! match->cmo_tid, ctf_errmsg(ctf_errno(fp))); ! return (ctf_errno(fp)); ! } ! ctf_dprintf("mapped object into output %s/%s->%ld\n", file, ! name, match->cmo_tid); } else { ! ctf_merge_funcmap_t *cmf, *match = NULL; ! ctf_funcinfo_t fi; ! ! for (cmf = list_head(csa->cmsa_funcmap); cmf != NULL; ! cmf = list_next(csa->cmsa_funcmap, cmf)) { ! boolean_t is_fuzzy = B_FALSE; ! if (ctf_merge_symbol_match(cmf->cmf_file, cmf->cmf_name, ! &cmf->cmf_sym, file, name, symp, &is_fuzzy)) { ! if (is_fuzzy && csa->cmsa_dedup && ! bind != STB_WEAK) { continue; ! } ! match = cmf; ! if (is_fuzzy) { continue; } ! break; } } ! ! if (match == NULL) { ! return (0); } + + fi.ctc_return = match->cmf_rtid; + fi.ctc_argc = match->cmf_argc; + fi.ctc_flags = match->cmf_flags; + if ((err = ctf_add_function(fp, idx, &fi, match->cmf_args)) != + 0) { + ctf_dprintf("Failed to add function %s: %s\n", name, + ctf_errmsg(ctf_errno(fp))); + return (ctf_errno(fp)); } + ctf_dprintf("mapped function into output %s/%s\n", file, + name); + } return (0); } int ctf_merge_merge(ctf_merge_t *cmh, ctf_file_t **outp) {
*** 1320,1329 **** --- 1444,1454 ---- ctf_id_t ltype; mergeq_t *mqp; ctf_merge_input_t *final; ctf_file_t *out; + ctf_dprintf("Beginning ctf_merge_merge()\n"); if (cmh->cmh_label != NULL && cmh->cmh_unique != NULL) { const char *label = ctf_label_topmost(cmh->cmh_unique); if (label == NULL) return (ECTF_NOLABEL); if (strcmp(label, cmh->cmh_label) != 0)
*** 1385,1411 **** return (ctf_errno(out)); } ctf_dprintf("merging symbols and the like\n"); if (cmh->cmh_msyms == B_TRUE) { ! err = ctf_merge_symbols(cmh, out); if (err != 0) { ctf_close(out); ! return (ctf_errno(out)); } - - err = ctf_merge_functions(cmh, out); - if (err != 0) { - ctf_close(out); - return (ctf_errno(out)); } - } err = ctf_update(out); if (err != 0) { ctf_close(out); ! return (ctf_errno(out)); } *outp = out; return (0); } --- 1510,1536 ---- return (ctf_errno(out)); } ctf_dprintf("merging symbols and the like\n"); if (cmh->cmh_msyms == B_TRUE) { ! ctf_merge_symbol_arg_t arg; ! arg.cmsa_objmap = &final->cmi_omap; ! arg.cmsa_funcmap = &final->cmi_fmap; ! arg.cmsa_out = out; ! arg.cmsa_dedup = B_FALSE; ! err = ctf_symtab_iter(out, ctf_merge_symbols, &arg); if (err != 0) { ctf_close(out); ! return (err); } } err = ctf_update(out); if (err != 0) { + err = ctf_errno(out); ctf_close(out); ! return (err); } *outp = out; return (0); }
*** 1503,1542 **** ret = ctf_update(cm.cm_out); if (ret != 0) goto err; ctf_dprintf("Successfully deduped types\n"); ! ctf_phase_dump(cm.cm_out, "dedup-pre-syms"); /* * Now we need to fix up the object and function maps. */ ! ctf_merge_fixup_nontypes(&cm, cmi); if (cmp->cmh_msyms == B_TRUE) { ! ret = ctf_merge_symbols(cmp, cm.cm_out); if (ret != 0) { - ret = ctf_errno(cm.cm_out); ctf_dprintf("failed to dedup symbols: %s\n", ctf_errmsg(ret)); goto err; } - - ret = ctf_merge_functions(cmp, cm.cm_out); - if (ret != 0) { - ret = ctf_errno(cm.cm_out); - ctf_dprintf("failed to dedup functions: %s\n", - ctf_errmsg(ret)); - goto err; } - } ret = ctf_update(cm.cm_out); if (ret == 0) { cmc->cmi_input = NULL; *outp = cm.cm_out; } err: ctf_merge_types_fini(&cm); ctf_diff_fini(cdp); return (ret); } --- 1628,1664 ---- ret = ctf_update(cm.cm_out); if (ret != 0) goto err; ctf_dprintf("Successfully deduped types\n"); ! ctf_phase_dump(cm.cm_out, "dedup-pre-syms", NULL); /* * Now we need to fix up the object and function maps. */ ! ctf_merge_fixup_symmaps(&cm, cmi); if (cmp->cmh_msyms == B_TRUE) { ! ctf_merge_symbol_arg_t arg; ! arg.cmsa_objmap = &cmi->cmi_omap; ! arg.cmsa_funcmap = &cmi->cmi_fmap; ! arg.cmsa_out = cm.cm_out; ! arg.cmsa_dedup = B_TRUE; ! ret = ctf_symtab_iter(cm.cm_out, ctf_merge_symbols, &arg); if (ret != 0) { ctf_dprintf("failed to dedup symbols: %s\n", ctf_errmsg(ret)); goto err; } } ret = ctf_update(cm.cm_out); if (ret == 0) { cmc->cmi_input = NULL; *outp = cm.cm_out; } + ctf_phase_dump(cm.cm_out, "dedup-post-syms", NULL); err: ctf_merge_types_fini(&cm); ctf_diff_fini(cdp); return (ret); }