Commit 682b335a authored by Arnaldo Carvalho de Melo's avatar Arnaldo Carvalho de Melo Committed by Ingo Molnar

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: default avatarArnaldo 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: default avatarIngo Molnar <mingo@elte.hu>
parent 60666c63
......@@ -383,16 +383,12 @@ size_t dso__fprintf(struct dso *self, enum map_type type, FILE *fp)
return ret;
}
/*
* Loads the function entries in /proc/kallsyms into kernel_map->dso,
* so that we can in the next step set the symbol ->end address and then
* call kernel_maps__split_kallsyms.
*/
static int dso__load_all_kallsyms(struct dso *self, struct map *map)
int kallsyms__parse(void *arg, int (*process_symbol)(void *arg, const char *name,
char type, u64 start))
{
char *line = NULL;
size_t n;
struct rb_root *root = &self->symbols[map->type];
int err = 0;
FILE *file = fopen("/proc/kallsyms", "r");
if (file == NULL)
......@@ -400,7 +396,6 @@ static int dso__load_all_kallsyms(struct dso *self, struct map *map)
while (!feof(file)) {
u64 start;
struct symbol *sym;
int line_len, len;
char symbol_type;
char *symbol_name;
......@@ -421,35 +416,62 @@ static int dso__load_all_kallsyms(struct dso *self, struct map *map)
continue;
symbol_type = toupper(line[len]);
if (!symbol_type__is_a(symbol_type, map->type))
continue;
symbol_name = line + len + 2;
/*
* Will fix up the end later, when we have all symbols sorted.
*/
sym = symbol__new(start, 0, symbol_name);
if (sym == NULL)
goto out_delete_line;
/*
* We will pass the symbols to the filter later, in
* map__split_kallsyms, when we have split the maps per module
*/
symbols__insert(root, sym);
err = process_symbol(arg, symbol_name, symbol_type, start);
if (err)
break;
}
free(line);
fclose(file);
return err;
return 0;
out_delete_line:
free(line);
out_failure:
return -1;
}
struct process_kallsyms_args {
struct map *map;
struct dso *dso;
};
static int map__process_kallsym_symbol(void *arg, const char *name,
char type, u64 start)
{
struct symbol *sym;
struct process_kallsyms_args *a = arg;
struct rb_root *root = &a->dso->symbols[a->map->type];
if (!symbol_type__is_a(type, a->map->type))
return 0;
/*
* Will fix up the end later, when we have all symbols sorted.
*/
sym = symbol__new(start, 0, name);
if (sym == NULL)
return -ENOMEM;
/*
* We will pass the symbols to the filter later, in
* map__split_kallsyms, when we have split the maps per module
*/
symbols__insert(root, sym);
return 0;
}
/*
* Loads the function entries in /proc/kallsyms into kernel_map->dso,
* so that we can in the next step set the symbol ->end address and then
* call kernel_maps__split_kallsyms.
*/
static int dso__load_all_kallsyms(struct dso *self, struct map *map)
{
struct process_kallsyms_args args = { .map = map, .dso = self, };
return kallsyms__parse(&args, map__process_kallsym_symbol);
}
/*
* Split the symbols into maps, making sure there are no overlaps, i.e. the
* kernel range is broken in several maps, named [kernel].N, as we don't have
......
......@@ -135,6 +135,8 @@ int filename__read_build_id(const char *filename, void *bf, size_t size);
int sysfs__read_build_id(const char *filename, void *bf, size_t size);
bool dsos__read_build_ids(void);
int build_id__sprintf(u8 *self, int len, char *bf);
int kallsyms__parse(void *arg, int (*process_symbol)(void *arg, const char *name,
char type, u64 start));
int symbol__init(void);
int perf_session__create_kernel_maps(struct perf_session *self);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment