diff options
author | Arnaldo Carvalho de Melo <acme@redhat.com> | 2010-01-04 13:19:26 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2010-01-13 04:09:08 -0500 |
commit | 682b335a5bccf9e5b7e74380784aa2f145d04444 (patch) | |
tree | 98a2be405f1a162964935d9b33a1acccedec2ea3 /tools/perf/util/symbol.c | |
parent | 60666c630bdb33983a894b050b588b663f38f368 (diff) |
perf symbols: Generalise the kallsyms parsing routine
Will be used to find an specific symbol by name on 'perf record'
to support relocation reference symbols to support relocatable
kernels.
Still have to conver the perf trace tools to use it instead of
their current reimplementation.
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Frédéric Weisbecker <fweisbec@gmail.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Paul Mackerras <paulus@samba.org>
LKML-Reference: <1262629169-22797-1-git-send-email-acme@infradead.org>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'tools/perf/util/symbol.c')
-rw-r--r-- | tools/perf/util/symbol.c | 74 |
1 files changed, 48 insertions, 26 deletions
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index 79ca6a099f96..b9e0da57d84b 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c | |||
@@ -383,16 +383,12 @@ size_t dso__fprintf(struct dso *self, enum map_type type, FILE *fp) | |||
383 | return ret; | 383 | return ret; |
384 | } | 384 | } |
385 | 385 | ||
386 | /* | 386 | int kallsyms__parse(void *arg, int (*process_symbol)(void *arg, const char *name, |
387 | * Loads the function entries in /proc/kallsyms into kernel_map->dso, | 387 | char type, u64 start)) |
388 | * so that we can in the next step set the symbol ->end address and then | ||
389 | * call kernel_maps__split_kallsyms. | ||
390 | */ | ||
391 | static int dso__load_all_kallsyms(struct dso *self, struct map *map) | ||
392 | { | 388 | { |
393 | char *line = NULL; | 389 | char *line = NULL; |
394 | size_t n; | 390 | size_t n; |
395 | struct rb_root *root = &self->symbols[map->type]; | 391 | int err = 0; |
396 | FILE *file = fopen("/proc/kallsyms", "r"); | 392 | FILE *file = fopen("/proc/kallsyms", "r"); |
397 | 393 | ||
398 | if (file == NULL) | 394 | if (file == NULL) |
@@ -400,7 +396,6 @@ static int dso__load_all_kallsyms(struct dso *self, struct map *map) | |||
400 | 396 | ||
401 | while (!feof(file)) { | 397 | while (!feof(file)) { |
402 | u64 start; | 398 | u64 start; |
403 | struct symbol *sym; | ||
404 | int line_len, len; | 399 | int line_len, len; |
405 | char symbol_type; | 400 | char symbol_type; |
406 | char *symbol_name; | 401 | char *symbol_name; |
@@ -421,35 +416,62 @@ static int dso__load_all_kallsyms(struct dso *self, struct map *map) | |||
421 | continue; | 416 | continue; |
422 | 417 | ||
423 | symbol_type = toupper(line[len]); | 418 | symbol_type = toupper(line[len]); |
424 | if (!symbol_type__is_a(symbol_type, map->type)) | ||
425 | continue; | ||
426 | |||
427 | symbol_name = line + len + 2; | 419 | symbol_name = line + len + 2; |
428 | /* | ||
429 | * Will fix up the end later, when we have all symbols sorted. | ||
430 | */ | ||
431 | sym = symbol__new(start, 0, symbol_name); | ||
432 | 420 | ||
433 | if (sym == NULL) | 421 | err = process_symbol(arg, symbol_name, symbol_type, start); |
434 | goto out_delete_line; | 422 | if (err) |
435 | /* | 423 | break; |
436 | * We will pass the symbols to the filter later, in | ||
437 | * map__split_kallsyms, when we have split the maps per module | ||
438 | */ | ||
439 | symbols__insert(root, sym); | ||
440 | } | 424 | } |
441 | 425 | ||
442 | free(line); | 426 | free(line); |
443 | fclose(file); | 427 | fclose(file); |
428 | return err; | ||
444 | 429 | ||
445 | return 0; | ||
446 | |||
447 | out_delete_line: | ||
448 | free(line); | ||
449 | out_failure: | 430 | out_failure: |
450 | return -1; | 431 | return -1; |
451 | } | 432 | } |
452 | 433 | ||
434 | struct process_kallsyms_args { | ||
435 | struct map *map; | ||
436 | struct dso *dso; | ||
437 | }; | ||
438 | |||
439 | static int map__process_kallsym_symbol(void *arg, const char *name, | ||
440 | char type, u64 start) | ||
441 | { | ||
442 | struct symbol *sym; | ||
443 | struct process_kallsyms_args *a = arg; | ||
444 | struct rb_root *root = &a->dso->symbols[a->map->type]; | ||
445 | |||
446 | if (!symbol_type__is_a(type, a->map->type)) | ||
447 | return 0; | ||
448 | |||
449 | /* | ||
450 | * Will fix up the end later, when we have all symbols sorted. | ||
451 | */ | ||
452 | sym = symbol__new(start, 0, name); | ||
453 | |||
454 | if (sym == NULL) | ||
455 | return -ENOMEM; | ||
456 | /* | ||
457 | * We will pass the symbols to the filter later, in | ||
458 | * map__split_kallsyms, when we have split the maps per module | ||
459 | */ | ||
460 | symbols__insert(root, sym); | ||
461 | return 0; | ||
462 | } | ||
463 | |||
464 | /* | ||
465 | * Loads the function entries in /proc/kallsyms into kernel_map->dso, | ||
466 | * so that we can in the next step set the symbol ->end address and then | ||
467 | * call kernel_maps__split_kallsyms. | ||
468 | */ | ||
469 | static int dso__load_all_kallsyms(struct dso *self, struct map *map) | ||
470 | { | ||
471 | struct process_kallsyms_args args = { .map = map, .dso = self, }; | ||
472 | return kallsyms__parse(&args, map__process_kallsym_symbol); | ||
473 | } | ||
474 | |||
453 | /* | 475 | /* |
454 | * Split the symbols into maps, making sure there are no overlaps, i.e. the | 476 | * Split the symbols into maps, making sure there are no overlaps, i.e. the |
455 | * kernel range is broken in several maps, named [kernel].N, as we don't have | 477 | * kernel range is broken in several maps, named [kernel].N, as we don't have |