perf symbols: Generalise the kallsyms parsing routine
authorArnaldo Carvalho de Melo <acme@redhat.com>
Mon, 4 Jan 2010 18:19:26 +0000 (16:19 -0200)
committerIngo Molnar <mingo@elte.hu>
Wed, 13 Jan 2010 09:09:08 +0000 (10:09 +0100)
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>
tools/perf/util/symbol.c
tools/perf/util/symbol.h

index 79ca6a0..b9e0da5 100644 (file)
@@ -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
index f27e158..21313e8 100644 (file)
@@ -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);