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