Commit 694bf407b06113f5e0f71764756f11903126fec0

Authored by Anton Blanchard
Committed by Arnaldo Carvalho de Melo
1 parent 3187790860

perf symbols: Add some heuristics for choosing the best duplicate symbol

Try and pick the best symbol based on a few heuristics:

-  Prefer a non weak symbol over a weak one
-  Prefer a global symbol over a non global one
-  Prefer a symbol with less underscores (idea taken from kallsyms.c)
-  If all else fails, choose the symbol with the longest name

Cc: Eric B Munson <emunson@mgebm.net>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/20110824065243.161953371@samba.org
Signed-off-by: Anton Blanchard <anton@samba.org>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

Showing 1 changed file with 88 additions and 0 deletions Side-by-side Diff

tools/perf/util/symbol.c
... ... @@ -86,6 +86,92 @@
86 86 }
87 87 }
88 88  
  89 +static int prefix_underscores_count(const char *str)
  90 +{
  91 + const char *tail = str;
  92 +
  93 + while (*tail == '_')
  94 + tail++;
  95 +
  96 + return tail - str;
  97 +}
  98 +
  99 +#define SYMBOL_A 0
  100 +#define SYMBOL_B 1
  101 +
  102 +static int choose_best_symbol(struct symbol *syma, struct symbol *symb)
  103 +{
  104 + s64 a;
  105 + s64 b;
  106 +
  107 + /* Prefer a symbol with non zero length */
  108 + a = syma->end - syma->start;
  109 + b = symb->end - symb->start;
  110 + if ((b == 0) && (a > 0))
  111 + return SYMBOL_A;
  112 + else if ((a == 0) && (b > 0))
  113 + return SYMBOL_B;
  114 +
  115 + /* Prefer a non weak symbol over a weak one */
  116 + a = syma->binding == STB_WEAK;
  117 + b = symb->binding == STB_WEAK;
  118 + if (b && !a)
  119 + return SYMBOL_A;
  120 + if (a && !b)
  121 + return SYMBOL_B;
  122 +
  123 + /* Prefer a global symbol over a non global one */
  124 + a = syma->binding == STB_GLOBAL;
  125 + b = symb->binding == STB_GLOBAL;
  126 + if (a && !b)
  127 + return SYMBOL_A;
  128 + if (b && !a)
  129 + return SYMBOL_B;
  130 +
  131 + /* Prefer a symbol with less underscores */
  132 + a = prefix_underscores_count(syma->name);
  133 + b = prefix_underscores_count(symb->name);
  134 + if (b > a)
  135 + return SYMBOL_A;
  136 + else if (a > b)
  137 + return SYMBOL_B;
  138 +
  139 + /* If all else fails, choose the symbol with the longest name */
  140 + if (strlen(syma->name) >= strlen(symb->name))
  141 + return SYMBOL_A;
  142 + else
  143 + return SYMBOL_B;
  144 +}
  145 +
  146 +static void symbols__fixup_duplicate(struct rb_root *symbols)
  147 +{
  148 + struct rb_node *nd;
  149 + struct symbol *curr, *next;
  150 +
  151 + nd = rb_first(symbols);
  152 +
  153 + while (nd) {
  154 + curr = rb_entry(nd, struct symbol, rb_node);
  155 +again:
  156 + nd = rb_next(&curr->rb_node);
  157 + next = rb_entry(nd, struct symbol, rb_node);
  158 +
  159 + if (!nd)
  160 + break;
  161 +
  162 + if (curr->start != next->start)
  163 + continue;
  164 +
  165 + if (choose_best_symbol(curr, next) == SYMBOL_A) {
  166 + rb_erase(&next->rb_node, symbols);
  167 + goto again;
  168 + } else {
  169 + nd = rb_next(&curr->rb_node);
  170 + rb_erase(&curr->rb_node, symbols);
  171 + }
  172 + }
  173 +}
  174 +
89 175 static void symbols__fixup_end(struct rb_root *symbols)
90 176 {
91 177 struct rb_node *nd, *prevnd = rb_first(symbols);
... ... @@ -692,6 +778,7 @@
692 778 if (dso__load_all_kallsyms(dso, filename, map) < 0)
693 779 return -1;
694 780  
  781 + symbols__fixup_duplicate(&dso->symbols[map->type]);
695 782 symbols__fixup_end(&dso->symbols[map->type]);
696 783  
697 784 if (dso->kernel == DSO_TYPE_GUEST_KERNEL)
... ... @@ -1269,6 +1356,7 @@
1269 1356 * For misannotated, zeroed, ASM function sizes.
1270 1357 */
1271 1358 if (nr > 0) {
  1359 + symbols__fixup_duplicate(&dso->symbols[map->type]);
1272 1360 symbols__fixup_end(&dso->symbols[map->type]);
1273 1361 if (kmap) {
1274 1362 /*