Commit 694bf407b06113f5e0f71764756f11903126fec0
Committed by
Arnaldo Carvalho de Melo
1 parent
3187790860
Exists in
master
and in
4 other branches
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 | /* |