perf tools: Insert split maps correctly into origin group
authorJiri Olsa <jolsa@redhat.com>
Wed, 4 Nov 2015 14:08:11 +0000 (15:08 +0100)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Thu, 5 Nov 2015 14:39:38 +0000 (11:39 -0300)
When new maps are cloned out of split map they are added into origin
map's group, but their groups pointer is not updated.

This could lead to a segfault, because map->groups is expected to be
always set as reported by Markus:

  __map__is_kernel (map=map@entry=0x1abb7a0) at util/map.c:238
  238             return __machine__kernel_map(map->groups->machine, map->type) =
  (gdb) bt
  #0  __map__is_kernel (map=map@entry=0x1abb7a0) at util/map.c:238
  #1  0x00000000004393e4 in symbol_filter (map=map@entry=0x1abb7a0, sym=sym@entry
  #2  0x00000000004fcd4d in dso__load_sym (dso=dso@entry=0x166dae0, map=map@entry
  #3  0x00000000004a64e0 in dso__load (dso=0x166dae0, map=map@entry=0x1abb7a0, fi
  #4  0x00000000004b941f in map__load (filter=0x4393c0 <symbol_filter>, map=<opti
  #5  map__find_symbol (map=0x1abb7a0, addr=40188, filter=0x4393c0 <symbol_filter
  ...

Adding __map_groups__insert function to add map into groups together
with map->groups pointer update. It takes no lock as opposed to existing
map_groups__insert, as maps__fixup_overlappings(), where it is being
called, already has the necessary lock held.

Using __map_groups__insert to add new maps after map split.

Reported-by: Markus Trippelsdorf <markus@trippelsdorf.de>
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Tested-by: Markus Trippelsdorf <markus@trippelsdorf.de>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: http://lkml.kernel.org/r/20151104140811.GA32664@krava.brq.redhat.com
Fixes: cfc5acd4c80b ("perf top: Filter symbols based on __map__is_kernel(map)")
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
tools/perf/util/map.c

index 4e38c39..afc6b56 100644 (file)
@@ -644,6 +644,12 @@ size_t map_groups__fprintf(struct map_groups *mg, FILE *fp)
        return printed;
 }
 
+static void __map_groups__insert(struct map_groups *mg, struct map *map)
+{
+       __maps__insert(&mg->maps[map->type], map);
+       map->groups = mg;
+}
+
 static int maps__fixup_overlappings(struct maps *maps, struct map *map, FILE *fp)
 {
        struct rb_root *root;
@@ -682,7 +688,7 @@ static int maps__fixup_overlappings(struct maps *maps, struct map *map, FILE *fp
                        }
 
                        before->end = map->start;
-                       __maps__insert(maps, before);
+                       __map_groups__insert(pos->groups, before);
                        if (verbose >= 2)
                                map__fprintf(before, fp);
                }
@@ -696,7 +702,7 @@ static int maps__fixup_overlappings(struct maps *maps, struct map *map, FILE *fp
                        }
 
                        after->start = map->end;
-                       __maps__insert(maps, after);
+                       __map_groups__insert(pos->groups, after);
                        if (verbose >= 2)
                                map__fprintf(after, fp);
                }