aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--tools/perf/util/symbol.c161
-rw-r--r--tools/perf/util/symbol.h2
2 files changed, 122 insertions, 41 deletions
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index e88296899470..4dfdefd5ec7e 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -27,6 +27,44 @@ enum dso_origin {
27static void dsos__add(struct dso *dso); 27static void dsos__add(struct dso *dso);
28static struct dso *dsos__find(const char *name); 28static struct dso *dsos__find(const char *name);
29 29
30static struct rb_root kernel_maps;
31
32static void dso__set_symbols_end(struct dso *self)
33{
34 struct rb_node *nd, *prevnd = rb_first(&self->syms);
35
36 if (prevnd == NULL)
37 return;
38
39 for (nd = rb_next(prevnd); nd; nd = rb_next(nd)) {
40 struct symbol *prev = rb_entry(prevnd, struct symbol, rb_node),
41 *curr = rb_entry(nd, struct symbol, rb_node);
42
43 if (prev->end == prev->start)
44 prev->end = curr->start - 1;
45 prevnd = nd;
46 }
47}
48
49static void kernel_maps__fixup_sym_end(void)
50{
51 struct map *prev, *curr;
52 struct rb_node *nd, *prevnd = rb_first(&kernel_maps);
53
54 if (prevnd == NULL)
55 return;
56
57 curr = rb_entry(prevnd, struct map, rb_node);
58 dso__set_symbols_end(curr->dso);
59
60 for (nd = rb_next(prevnd); nd; nd = rb_next(nd)) {
61 prev = curr;
62 curr = rb_entry(nd, struct map, rb_node);
63 prev->end = curr->start - 1;
64 dso__set_symbols_end(curr->dso);
65 }
66}
67
30static struct symbol *symbol__new(u64 start, u64 len, const char *name, 68static struct symbol *symbol__new(u64 start, u64 len, const char *name,
31 unsigned int priv_size, int v) 69 unsigned int priv_size, int v)
32{ 70{
@@ -162,10 +200,9 @@ size_t dso__fprintf(struct dso *self, FILE *fp)
162 return ret; 200 return ret;
163} 201}
164 202
165static int dso__load_kallsyms(struct dso *self, struct map *map, 203static int maps__load_kallsyms(symbol_filter_t filter, int use_modules, int v)
166 symbol_filter_t filter, int v)
167{ 204{
168 struct rb_node *nd, *prevnd; 205 struct map *map = kernel_map;
169 char *line = NULL; 206 char *line = NULL;
170 size_t n; 207 size_t n;
171 FILE *file = fopen("/proc/kallsyms", "r"); 208 FILE *file = fopen("/proc/kallsyms", "r");
@@ -179,6 +216,7 @@ static int dso__load_kallsyms(struct dso *self, struct map *map,
179 struct symbol *sym; 216 struct symbol *sym;
180 int line_len, len; 217 int line_len, len;
181 char symbol_type; 218 char symbol_type;
219 char *module, *symbol_name;
182 220
183 line_len = getline(&line, &n, file); 221 line_len = getline(&line, &n, file);
184 if (line_len < 0) 222 if (line_len < 0)
@@ -201,40 +239,50 @@ static int dso__load_kallsyms(struct dso *self, struct map *map,
201 */ 239 */
202 if (symbol_type != 'T' && symbol_type != 'W') 240 if (symbol_type != 'T' && symbol_type != 'W')
203 continue; 241 continue;
242
243 symbol_name = line + len + 2;
244 module = strchr(symbol_name, '\t');
245 if (module) {
246 char *module_name_end;
247
248 if (!use_modules)
249 continue;
250 *module = '\0';
251 module = strchr(module + 1, '[');
252 if (!module)
253 continue;
254 module_name_end = strchr(module + 1, ']');
255 if (!module_name_end)
256 continue;
257 *(module_name_end + 1) = '\0';
258 if (strcmp(map->dso->name, module)) {
259 map = kernel_maps__find_by_dso_name(module);
260 if (!map) {
261 fputs("/proc/{kallsyms,modules} "
262 "inconsistency!\n", stderr);
263 return -1;
264 }
265 }
266 start = map->map_ip(map, start);
267 } else
268 map = kernel_map;
204 /* 269 /*
205 * Well fix up the end later, when we have all sorted. 270 * Well fix up the end later, when we have all sorted.
206 */ 271 */
207 sym = symbol__new(start, 0xdead, line + len + 2, 272 sym = symbol__new(start, 0, symbol_name,
208 self->sym_priv_size, v); 273 map->dso->sym_priv_size, v);
209 274
210 if (sym == NULL) 275 if (sym == NULL)
211 goto out_delete_line; 276 goto out_delete_line;
212 277
213 if (filter && filter(map, sym)) 278 if (filter && filter(map, sym))
214 symbol__delete(sym, self->sym_priv_size); 279 symbol__delete(sym, map->dso->sym_priv_size);
215 else { 280 else {
216 dso__insert_symbol(self, sym); 281 dso__insert_symbol(map->dso, sym);
217 count++; 282 count++;
218 } 283 }
219 } 284 }
220 285
221 /*
222 * Now that we have all sorted out, just set the ->end of all
223 * symbols
224 */
225 prevnd = rb_first(&self->syms);
226
227 if (prevnd == NULL)
228 goto out_delete_line;
229
230 for (nd = rb_next(prevnd); nd; nd = rb_next(nd)) {
231 struct symbol *prev = rb_entry(prevnd, struct symbol, rb_node),
232 *curr = rb_entry(nd, struct symbol, rb_node);
233
234 prev->end = curr->start - 1;
235 prevnd = nd;
236 }
237
238 free(line); 286 free(line);
239 fclose(file); 287 fclose(file);
240 288
@@ -246,6 +294,24 @@ out_failure:
246 return -1; 294 return -1;
247} 295}
248 296
297static size_t kernel_maps__fprintf(FILE *fp)
298{
299 size_t printed = fprintf(stderr, "Kernel maps:\n");
300 struct rb_node *nd;
301
302 printed += map__fprintf(kernel_map, fp);
303 printed += dso__fprintf(kernel_map->dso, fp);
304
305 for (nd = rb_first(&kernel_maps); nd; nd = rb_next(nd)) {
306 struct map *pos = rb_entry(nd, struct map, rb_node);
307
308 printed += map__fprintf(pos, fp);
309 printed += dso__fprintf(pos->dso, fp);
310 }
311
312 return printed + fprintf(stderr, "END kernel maps\n");
313}
314
249static int dso__load_perf_map(struct dso *self, struct map *map, 315static int dso__load_perf_map(struct dso *self, struct map *map,
250 symbol_filter_t filter, int v) 316 symbol_filter_t filter, int v)
251{ 317{
@@ -598,6 +664,7 @@ static int dso__load_sym(struct dso *self, struct map *map, const char *name,
598 char *demangled; 664 char *demangled;
599 int is_label = elf_sym__is_label(&sym); 665 int is_label = elf_sym__is_label(&sym);
600 const char *section_name; 666 const char *section_name;
667 u64 sh_offset = 0;
601 668
602 if (!is_label && !elf_sym__is_function(&sym)) 669 if (!is_label && !elf_sym__is_function(&sym))
603 continue; 670 continue;
@@ -613,14 +680,18 @@ static int dso__load_sym(struct dso *self, struct map *map, const char *name,
613 680
614 section_name = elf_sec__name(&shdr, secstrs); 681 section_name = elf_sec__name(&shdr, secstrs);
615 682
683 if ((kernel || kmodule)) {
684 if (strstr(section_name, ".init"))
685 sh_offset = shdr.sh_offset;
686 }
687
616 if (self->adjust_symbols) { 688 if (self->adjust_symbols) {
617 if (v >= 2) 689 if (v >= 2)
618 printf("adjusting symbol: st_value: %Lx sh_addr: %Lx sh_offset: %Lx\n", 690 printf("adjusting symbol: st_value: %Lx sh_addr: %Lx sh_offset: %Lx\n",
619 (u64)sym.st_value, (u64)shdr.sh_addr, (u64)shdr.sh_offset); 691 (u64)sym.st_value, (u64)shdr.sh_addr, (u64)shdr.sh_offset);
620 692
621 sym.st_value -= shdr.sh_addr - shdr.sh_offset; 693 sym.st_value -= shdr.sh_addr - shdr.sh_offset;
622 } else if (kmodule) 694 }
623 sym.st_value += shdr.sh_offset;
624 /* 695 /*
625 * We need to figure out if the object was created from C++ sources 696 * We need to figure out if the object was created from C++ sources
626 * DWARF DW_compile_unit has this, but we don't always have access 697 * DWARF DW_compile_unit has this, but we don't always have access
@@ -631,7 +702,7 @@ static int dso__load_sym(struct dso *self, struct map *map, const char *name,
631 if (demangled != NULL) 702 if (demangled != NULL)
632 elf_name = demangled; 703 elf_name = demangled;
633 704
634 f = symbol__new(sym.st_value, sym.st_size, elf_name, 705 f = symbol__new(sym.st_value + sh_offset, sym.st_size, elf_name,
635 self->sym_priv_size, v); 706 self->sym_priv_size, v);
636 free(demangled); 707 free(demangled);
637 if (!f) 708 if (!f)
@@ -804,7 +875,6 @@ out:
804 return ret; 875 return ret;
805} 876}
806 877
807static struct rb_root kernel_maps;
808struct map *kernel_map; 878struct map *kernel_map;
809 879
810static void kernel_maps__insert(struct map *map) 880static void kernel_maps__insert(struct map *map)
@@ -975,8 +1045,7 @@ static struct map *map__new2(u64 start, struct dso *dso)
975 return self; 1045 return self;
976} 1046}
977 1047
978int dsos__load_modules(unsigned int sym_priv_size, 1048static int dsos__load_modules(unsigned int sym_priv_size)
979 symbol_filter_t filter, int v)
980{ 1049{
981 char *line = NULL; 1050 char *line = NULL;
982 size_t n; 1051 size_t n;
@@ -1034,8 +1103,7 @@ int dsos__load_modules(unsigned int sym_priv_size,
1034 free(line); 1103 free(line);
1035 fclose(file); 1104 fclose(file);
1036 1105
1037 v = 1; 1106 return 0;
1038 return dsos__load_modules_sym(filter, v);
1039 1107
1040out_delete_line: 1108out_delete_line:
1041 free(line); 1109 free(line);
@@ -1075,25 +1143,37 @@ int dsos__load_kernel(const char *vmlinux, unsigned int sym_priv_size,
1075 1143
1076 kernel_map->map_ip = vdso__map_ip; 1144 kernel_map->map_ip = vdso__map_ip;
1077 1145
1146 if (use_modules && dsos__load_modules(sym_priv_size) < 0) {
1147 fprintf(stderr, "Failed to load list of modules in use! "
1148 "Continuing...\n");
1149 use_modules = 0;
1150 }
1151
1078 if (vmlinux) { 1152 if (vmlinux) {
1079 err = dso__load_vmlinux(dso, kernel_map, vmlinux, filter, v); 1153 err = dso__load_vmlinux(dso, kernel_map, vmlinux, filter, v);
1080 if (err > 0 && use_modules) { 1154 if (err > 0 && use_modules) {
1081 int syms = dsos__load_modules(sym_priv_size, filter, v); 1155 int syms = dsos__load_modules_sym(filter, v);
1082 1156
1083 if (syms < 0) { 1157 if (syms < 0)
1084 fprintf(stderr, "dsos__load_modules failed!\n"); 1158 fprintf(stderr, "Failed to read module symbols!"
1085 return syms; 1159 " Continuing...\n");
1086 } 1160 else
1087 err += syms; 1161 err += syms;
1088 } 1162 }
1089 } 1163 }
1090 1164
1091 if (err <= 0) 1165 if (err <= 0)
1092 err = dso__load_kallsyms(dso, kernel_map, filter, v); 1166 err = maps__load_kallsyms(filter, use_modules, v);
1093 1167
1094 if (err > 0) { 1168 if (err > 0) {
1095 struct rb_node *node = rb_first(&dso->syms); 1169 struct rb_node *node = rb_first(&dso->syms);
1096 struct symbol *sym = rb_entry(node, struct symbol, rb_node); 1170 struct symbol *sym = rb_entry(node, struct symbol, rb_node);
1171 /*
1172 * Now that we have all sorted out, just set the ->end of all
1173 * symbols that still don't have it.
1174 */
1175 dso__set_symbols_end(dso);
1176 kernel_maps__fixup_sym_end();
1097 1177
1098 kernel_map->start = sym->start; 1178 kernel_map->start = sym->start;
1099 node = rb_last(&dso->syms); 1179 node = rb_last(&dso->syms);
@@ -1106,6 +1186,9 @@ int dsos__load_kernel(const char *vmlinux, unsigned int sym_priv_size,
1106 * kernel_maps__insert(kernel_map) 1186 * kernel_maps__insert(kernel_map)
1107 */ 1187 */
1108 dsos__add(dso); 1188 dsos__add(dso);
1189
1190 if (v > 0)
1191 kernel_maps__fprintf(stderr);
1109 } 1192 }
1110 1193
1111 return err; 1194 return err;
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index 5339fd82ec96..2e4522edeb07 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -70,8 +70,6 @@ struct symbol *dso__find_symbol(struct dso *self, u64 ip);
70 70
71int dsos__load_kernel(const char *vmlinux, unsigned int sym_priv_size, 71int dsos__load_kernel(const char *vmlinux, unsigned int sym_priv_size,
72 symbol_filter_t filter, int verbose, int modules); 72 symbol_filter_t filter, int verbose, int modules);
73int dsos__load_modules(unsigned int sym_priv_size, symbol_filter_t filter,
74 int verbose);
75int dso__load(struct dso *self, struct map *map, symbol_filter_t filter, 73int dso__load(struct dso *self, struct map *map, symbol_filter_t filter,
76 int verbose); 74 int verbose);
77struct dso *dsos__findnew(const char *name); 75struct dso *dsos__findnew(const char *name);