aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util/symbol.c
diff options
context:
space:
mode:
authorArnaldo Carvalho de Melo <acme@redhat.com>2009-10-05 13:26:17 -0400
committerIngo Molnar <mingo@elte.hu>2009-10-05 14:35:23 -0400
commitaf427bf529c5991be8d1a36f43e2d0141f532f63 (patch)
tree9a90fcac2b44ef1b70ca9ca5b4ed6792179b976a /tools/perf/util/symbol.c
parent5c2068059a0e852f72b7c2608d92170b752d821f (diff)
perf tools: Create maps for modules when processing kallsyms
So that we get kallsyms processing closer to vmlinux + modules symtabs processing. One change in behaviour is that since when one specifies --vmlinux -m should be used to ask for modules, so it is now for kallsyms as well. Also continue if one manages to load the vmlinux data but module processing fails, so that at least some analisys can be done with part of the needed symbols. Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Frédéric Weisbecker <fweisbec@gmail.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Mike Galbraith <efault@gmx.de> LKML-Reference: <new-submission> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'tools/perf/util/symbol.c')
-rw-r--r--tools/perf/util/symbol.c161
1 files changed, 122 insertions, 39 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;