aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArnaldo Carvalho de Melo <acme@redhat.com>2010-12-21 22:08:36 -0500
committerArnaldo Carvalho de Melo <acme@redhat.com>2010-12-22 17:31:45 -0500
commit3b01a413c196c91040d41c86e5b56f76bb369f74 (patch)
treeea6888c58add31852a641c0a4e37840ac2197676
parent9fb67204d7a00a6444bc121f221527034613d338 (diff)
perf symbols: Improve kallsyms symbol end addr calculation
For kallsyms we don't have the symbol address end, so we do an extra pass and set the symbol end addr as being the start of the next minus one. But this was being done just after we filtered the symbols of a particular type (functions, variables), so the symbol end was sometimes after what it really is. Fixing up symbol end also was falling apart when we have symbol aliases, then the end address of all but the last alias was being set to be before its start. Fix it up by checking for symbol aliases and making the kallsyms__parse routine use the next symbol, whatever its type, as the limit for the previous symbol, passing that end address to the callback. This was detected by the 'perf test' synthetic paranoid regression tests, fix it up so that even that case doesn't mislead us. Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: Mike Galbraith <efault@gmx.de> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Paul Mackerras <paulus@samba.org> Cc: Stephane Eranian <eranian@google.com> LKML-Reference: <new-submission> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-rw-r--r--tools/perf/util/event.c3
-rw-r--r--tools/perf/util/symbol.c56
-rw-r--r--tools/perf/util/symbol.h2
3 files changed, 45 insertions, 16 deletions
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 183aedd4db83..2302ec051bb4 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -332,7 +332,8 @@ struct process_symbol_args {
332 u64 start; 332 u64 start;
333}; 333};
334 334
335static int find_symbol_cb(void *arg, const char *name, char type, u64 start) 335static int find_symbol_cb(void *arg, const char *name, char type,
336 u64 start, u64 end __used)
336{ 337{
337 struct process_symbol_args *args = arg; 338 struct process_symbol_args *args = arg;
338 339
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 561db6361f57..2ea1a2e4c0c2 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -22,6 +22,10 @@
22#include <limits.h> 22#include <limits.h>
23#include <sys/utsname.h> 23#include <sys/utsname.h>
24 24
25#ifndef KSYM_NAME_LEN
26#define KSYM_NAME_LEN 128
27#endif
28
25#ifndef NT_GNU_BUILD_ID 29#ifndef NT_GNU_BUILD_ID
26#define NT_GNU_BUILD_ID 3 30#define NT_GNU_BUILD_ID 3
27#endif 31#endif
@@ -93,7 +97,7 @@ static void symbols__fixup_end(struct rb_root *self)
93 prev = curr; 97 prev = curr;
94 curr = rb_entry(nd, struct symbol, rb_node); 98 curr = rb_entry(nd, struct symbol, rb_node);
95 99
96 if (prev->end == prev->start) 100 if (prev->end == prev->start && prev->end != curr->start)
97 prev->end = curr->start - 1; 101 prev->end = curr->start - 1;
98 } 102 }
99 103
@@ -426,16 +430,25 @@ size_t dso__fprintf(struct dso *self, enum map_type type, FILE *fp)
426 430
427int kallsyms__parse(const char *filename, void *arg, 431int kallsyms__parse(const char *filename, void *arg,
428 int (*process_symbol)(void *arg, const char *name, 432 int (*process_symbol)(void *arg, const char *name,
429 char type, u64 start)) 433 char type, u64 start, u64 end))
430{ 434{
431 char *line = NULL; 435 char *line = NULL;
432 size_t n; 436 size_t n;
433 int err = 0; 437 int err = -1;
438 u64 prev_start = 0;
439 char prev_symbol_type = 0;
440 char *prev_symbol_name;
434 FILE *file = fopen(filename, "r"); 441 FILE *file = fopen(filename, "r");
435 442
436 if (file == NULL) 443 if (file == NULL)
437 goto out_failure; 444 goto out_failure;
438 445
446 prev_symbol_name = malloc(KSYM_NAME_LEN);
447 if (prev_symbol_name == NULL)
448 goto out_close;
449
450 err = 0;
451
439 while (!feof(file)) { 452 while (!feof(file)) {
440 u64 start; 453 u64 start;
441 int line_len, len; 454 int line_len, len;
@@ -455,14 +468,33 @@ int kallsyms__parse(const char *filename, void *arg,
455 continue; 468 continue;
456 469
457 symbol_type = toupper(line[len]); 470 symbol_type = toupper(line[len]);
458 symbol_name = line + len + 2; 471 len += 2;
472 symbol_name = line + len;
473 len = line_len - len;
459 474
460 err = process_symbol(arg, symbol_name, symbol_type, start); 475 if (len >= KSYM_NAME_LEN) {
461 if (err) 476 err = -1;
462 break; 477 break;
478 }
479
480 if (prev_symbol_type) {
481 u64 end = start;
482 if (end != prev_start)
483 --end;
484 err = process_symbol(arg, prev_symbol_name,
485 prev_symbol_type, prev_start, end);
486 if (err)
487 break;
488 }
489
490 memcpy(prev_symbol_name, symbol_name, len + 1);
491 prev_symbol_type = symbol_type;
492 prev_start = start;
463 } 493 }
464 494
495 free(prev_symbol_name);
465 free(line); 496 free(line);
497out_close:
466 fclose(file); 498 fclose(file);
467 return err; 499 return err;
468 500
@@ -484,7 +516,7 @@ static u8 kallsyms2elf_type(char type)
484} 516}
485 517
486static int map__process_kallsym_symbol(void *arg, const char *name, 518static int map__process_kallsym_symbol(void *arg, const char *name,
487 char type, u64 start) 519 char type, u64 start, u64 end)
488{ 520{
489 struct symbol *sym; 521 struct symbol *sym;
490 struct process_kallsyms_args *a = arg; 522 struct process_kallsyms_args *a = arg;
@@ -493,11 +525,8 @@ static int map__process_kallsym_symbol(void *arg, const char *name,
493 if (!symbol_type__is_a(type, a->map->type)) 525 if (!symbol_type__is_a(type, a->map->type))
494 return 0; 526 return 0;
495 527
496 /* 528 sym = symbol__new(start, end - start + 1,
497 * Will fix up the end later, when we have all symbols sorted. 529 kallsyms2elf_type(type), name);
498 */
499 sym = symbol__new(start, 0, kallsyms2elf_type(type), name);
500
501 if (sym == NULL) 530 if (sym == NULL)
502 return -ENOMEM; 531 return -ENOMEM;
503 /* 532 /*
@@ -650,7 +679,6 @@ int dso__load_kallsyms(struct dso *self, const char *filename,
650 if (dso__load_all_kallsyms(self, filename, map) < 0) 679 if (dso__load_all_kallsyms(self, filename, map) < 0)
651 return -1; 680 return -1;
652 681
653 symbols__fixup_end(&self->symbols[map->type]);
654 if (self->kernel == DSO_TYPE_GUEST_KERNEL) 682 if (self->kernel == DSO_TYPE_GUEST_KERNEL)
655 self->origin = DSO__ORIG_GUEST_KERNEL; 683 self->origin = DSO__ORIG_GUEST_KERNEL;
656 else 684 else
@@ -2162,7 +2190,7 @@ struct process_args {
2162}; 2190};
2163 2191
2164static int symbol__in_kernel(void *arg, const char *name, 2192static int symbol__in_kernel(void *arg, const char *name,
2165 char type __used, u64 start) 2193 char type __used, u64 start, u64 end __used)
2166{ 2194{
2167 struct process_args *args = arg; 2195 struct process_args *args = arg;
2168 2196
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index bcd2f986927e..7b8c27bb1e6b 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -215,7 +215,7 @@ bool __dsos__read_build_ids(struct list_head *head, bool with_hits);
215int build_id__sprintf(const u8 *self, int len, char *bf); 215int build_id__sprintf(const u8 *self, int len, char *bf);
216int kallsyms__parse(const char *filename, void *arg, 216int kallsyms__parse(const char *filename, void *arg,
217 int (*process_symbol)(void *arg, const char *name, 217 int (*process_symbol)(void *arg, const char *name,
218 char type, u64 start)); 218 char type, u64 start, u64 end));
219 219
220void machine__destroy_kernel_maps(struct machine *self); 220void machine__destroy_kernel_maps(struct machine *self);
221int __machine__create_kernel_maps(struct machine *self, struct dso *kernel); 221int __machine__create_kernel_maps(struct machine *self, struct dso *kernel);