summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr/src/cmd/dis/dis_target.c29
1 files changed, 22 insertions, 7 deletions
diff --git a/usr/src/cmd/dis/dis_target.c b/usr/src/cmd/dis/dis_target.c
index 37ab5cc3bc..ec280628b9 100644
--- a/usr/src/cmd/dis/dis_target.c
+++ b/usr/src/cmd/dis/dis_target.c
@@ -68,7 +68,7 @@ typedef struct sym_entry {
* mess up symbol resolution (which uses the virtual address).
*/
typedef struct dis_shnmap {
- const char *dm_name; /* name of section */
+ const char *dm_name; /* name of section */
uint64_t dm_start; /* virtual address of section */
size_t dm_length; /* address length */
boolean_t dm_mapped; /* did we assign the mapping */
@@ -157,6 +157,8 @@ sym_compare(const void *a, const void *b)
const sym_entry_t *symb = b;
const char *aname = syma->se_name;
const char *bname = symb->se_name;
+ size_t alen;
+ size_t blen;
if (syma->se_sym.st_value < symb->se_sym.st_value)
return (-1);
@@ -179,9 +181,9 @@ sym_compare(const void *a, const void *b)
* For symbols with the same address and type, we sort them according to
* a hierarchy:
*
- * 1. weak symbols (common name)
- * 2. global symbols (external name)
- * 3. local symbols
+ * 1. weak symbols (common name)
+ * 2. global symbols (external name)
+ * 3. local symbols
*/
if (GELF_ST_BIND(syma->se_sym.st_info) !=
GELF_ST_BIND(symb->se_sym.st_info)) {
@@ -224,10 +226,23 @@ sym_compare(const void *a, const void *b)
return (1);
/*
- * We really do have two identical symbols for some reason. Just report
- * them as equal, and to the lucky one go the spoils.
+ * We really do have two identical symbols, choose the one with the
+ * shortest name if we can, heuristically taking it to be the most
+ * representative.
*/
- return (0);
+ alen = strlen(syma->se_name);
+ blen = strlen(symb->se_name);
+
+ if (alen < blen)
+ return (-1);
+ else if (alen > blen)
+ return (1);
+
+ /*
+ * If all else fails, compare the names, so that we give a stable
+ * sort
+ */
+ return (strcmp(syma->se_name, symb->se_name));
}
/*