aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/perf/util/symbol.c88
1 files changed, 88 insertions, 0 deletions
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 0d94ddb55bd7..870b3b8c649b 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -86,6 +86,92 @@ bool symbol_type__is_a(char symbol_type, enum map_type map_type)
86 } 86 }
87} 87}
88 88
89static 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
102static 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
146static 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);
155again:
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
89static void symbols__fixup_end(struct rb_root *symbols) 175static void symbols__fixup_end(struct rb_root *symbols)
90{ 176{
91 struct rb_node *nd, *prevnd = rb_first(symbols); 177 struct rb_node *nd, *prevnd = rb_first(symbols);
@@ -692,6 +778,7 @@ int dso__load_kallsyms(struct dso *dso, const char *filename,
692 if (dso__load_all_kallsyms(dso, filename, map) < 0) 778 if (dso__load_all_kallsyms(dso, filename, map) < 0)
693 return -1; 779 return -1;
694 780
781 symbols__fixup_duplicate(&dso->symbols[map->type]);
695 symbols__fixup_end(&dso->symbols[map->type]); 782 symbols__fixup_end(&dso->symbols[map->type]);
696 783
697 if (dso->kernel == DSO_TYPE_GUEST_KERNEL) 784 if (dso->kernel == DSO_TYPE_GUEST_KERNEL)
@@ -1269,6 +1356,7 @@ new_symbol:
1269 * For misannotated, zeroed, ASM function sizes. 1356 * For misannotated, zeroed, ASM function sizes.
1270 */ 1357 */
1271 if (nr > 0) { 1358 if (nr > 0) {
1359 symbols__fixup_duplicate(&dso->symbols[map->type]);
1272 symbols__fixup_end(&dso->symbols[map->type]); 1360 symbols__fixup_end(&dso->symbols[map->type]);
1273 if (kmap) { 1361 if (kmap) {
1274 /* 1362 /*