2019-10-03 17:03:22

by Greg Kroah-Hartman

[permalink] [raw]
Subject: [PATCH 5.3 111/344] perf unwind: Fix libunwind when tid != pid

From: John Keeping <[email protected]>

[ Upstream commit e8ba2906f6b9054102ad035ac9cafad9d4168589 ]

Commit e5adfc3e7e77 ("perf map: Synthesize maps only for thread group
leader") changed the recording side so that we no longer get mmap events
for threads other than the thread group leader (when synthesising these
events for threads which exist before perf is started).

When a file recorded after this change is loaded, the lack of mmap
records mean that unwinding is not set up for any other threads.

This can be seen in a simple record/report scenario:

perf record --call-graph=dwarf -t $TID
perf report

If $TID is a process ID then the report will show call graphs, but if
$TID is a secondary thread the output is as if --call-graph=none was
specified.

Following the rationale in that commit, move the libunwind fields into
struct map_groups and update the libunwind functions to take this
instead of the struct thread. This is only required for
unwind__finish_access which must now be called from map_groups__delete
and the others are changed for symmetry.

Note that unwind__get_entries keeps the thread argument since it is
required for symbol lookup and the libdw unwind provider uses the thread
ID.

Signed-off-by: John Keeping <[email protected]>
Reviewed-by: Jiri Olsa <[email protected]>
Cc: Alexander Shishkin <[email protected]>
Cc: Konstantin Khlebnikov <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Fixes: e5adfc3e7e77 ("perf map: Synthesize maps only for thread group leader")
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
Signed-off-by: Sasha Levin <[email protected]>
---
tools/perf/util/map.c | 3 ++-
tools/perf/util/map_groups.h | 4 +++
tools/perf/util/thread.c | 7 +++--
tools/perf/util/thread.h | 4 ---
tools/perf/util/unwind-libunwind-local.c | 18 ++++++-------
tools/perf/util/unwind-libunwind.c | 34 ++++++++++++------------
tools/perf/util/unwind.h | 25 ++++++++---------
7 files changed, 48 insertions(+), 47 deletions(-)

diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c
index 668410b1d426f..7666206d06fa7 100644
--- a/tools/perf/util/map.c
+++ b/tools/perf/util/map.c
@@ -647,6 +647,7 @@ struct map_groups *map_groups__new(struct machine *machine)
void map_groups__delete(struct map_groups *mg)
{
map_groups__exit(mg);
+ unwind__finish_access(mg);
free(mg);
}

@@ -887,7 +888,7 @@ int map_groups__clone(struct thread *thread, struct map_groups *parent)
if (new == NULL)
goto out_unlock;

- err = unwind__prepare_access(thread, new, NULL);
+ err = unwind__prepare_access(mg, new, NULL);
if (err)
goto out_unlock;

diff --git a/tools/perf/util/map_groups.h b/tools/perf/util/map_groups.h
index 5f25efa6d6bcd..77252e14008fb 100644
--- a/tools/perf/util/map_groups.h
+++ b/tools/perf/util/map_groups.h
@@ -31,6 +31,10 @@ struct map_groups {
struct maps maps;
struct machine *machine;
refcount_t refcnt;
+#ifdef HAVE_LIBUNWIND_SUPPORT
+ void *addr_space;
+ struct unwind_libunwind_ops *unwind_libunwind_ops;
+#endif
};

#define KMAP_NAME_LEN 256
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c
index 590793cc51424..bbf7816cba31c 100644
--- a/tools/perf/util/thread.c
+++ b/tools/perf/util/thread.c
@@ -105,7 +105,6 @@ void thread__delete(struct thread *thread)
}
up_write(&thread->comm_lock);

- unwind__finish_access(thread);
nsinfo__zput(thread->nsinfo);
srccode_state_free(&thread->srccode_state);

@@ -252,7 +251,7 @@ static int ____thread__set_comm(struct thread *thread, const char *str,
list_add(&new->list, &thread->comm_list);

if (exec)
- unwind__flush_access(thread);
+ unwind__flush_access(thread->mg);
}

thread->comm_set = true;
@@ -332,7 +331,7 @@ int thread__insert_map(struct thread *thread, struct map *map)
{
int ret;

- ret = unwind__prepare_access(thread, map, NULL);
+ ret = unwind__prepare_access(thread->mg, map, NULL);
if (ret)
return ret;

@@ -352,7 +351,7 @@ static int __thread__prepare_access(struct thread *thread)
down_read(&maps->lock);

for (map = maps__first(maps); map; map = map__next(map)) {
- err = unwind__prepare_access(thread, map, &initialized);
+ err = unwind__prepare_access(thread->mg, map, &initialized);
if (err || initialized)
break;
}
diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h
index e97ef6977eb91..bf06113be4f3f 100644
--- a/tools/perf/util/thread.h
+++ b/tools/perf/util/thread.h
@@ -44,10 +44,6 @@ struct thread {
struct thread_stack *ts;
struct nsinfo *nsinfo;
struct srccode_state srccode_state;
-#ifdef HAVE_LIBUNWIND_SUPPORT
- void *addr_space;
- struct unwind_libunwind_ops *unwind_libunwind_ops;
-#endif
bool filter;
int filter_entry_depth;
};
diff --git a/tools/perf/util/unwind-libunwind-local.c b/tools/perf/util/unwind-libunwind-local.c
index 71a788921b621..ebdbb056510cb 100644
--- a/tools/perf/util/unwind-libunwind-local.c
+++ b/tools/perf/util/unwind-libunwind-local.c
@@ -616,26 +616,26 @@ static unw_accessors_t accessors = {
.get_proc_name = get_proc_name,
};

-static int _unwind__prepare_access(struct thread *thread)
+static int _unwind__prepare_access(struct map_groups *mg)
{
- thread->addr_space = unw_create_addr_space(&accessors, 0);
- if (!thread->addr_space) {
+ mg->addr_space = unw_create_addr_space(&accessors, 0);
+ if (!mg->addr_space) {
pr_err("unwind: Can't create unwind address space.\n");
return -ENOMEM;
}

- unw_set_caching_policy(thread->addr_space, UNW_CACHE_GLOBAL);
+ unw_set_caching_policy(mg->addr_space, UNW_CACHE_GLOBAL);
return 0;
}

-static void _unwind__flush_access(struct thread *thread)
+static void _unwind__flush_access(struct map_groups *mg)
{
- unw_flush_cache(thread->addr_space, 0, 0);
+ unw_flush_cache(mg->addr_space, 0, 0);
}

-static void _unwind__finish_access(struct thread *thread)
+static void _unwind__finish_access(struct map_groups *mg)
{
- unw_destroy_addr_space(thread->addr_space);
+ unw_destroy_addr_space(mg->addr_space);
}

static int get_entries(struct unwind_info *ui, unwind_entry_cb_t cb,
@@ -660,7 +660,7 @@ static int get_entries(struct unwind_info *ui, unwind_entry_cb_t cb,
*/
if (max_stack - 1 > 0) {
WARN_ONCE(!ui->thread, "WARNING: ui->thread is NULL");
- addr_space = ui->thread->addr_space;
+ addr_space = ui->thread->mg->addr_space;

if (addr_space == NULL)
return -1;
diff --git a/tools/perf/util/unwind-libunwind.c b/tools/perf/util/unwind-libunwind.c
index c0811977d7d54..b843f9d0a9ea2 100644
--- a/tools/perf/util/unwind-libunwind.c
+++ b/tools/perf/util/unwind-libunwind.c
@@ -11,13 +11,13 @@ struct unwind_libunwind_ops __weak *local_unwind_libunwind_ops;
struct unwind_libunwind_ops __weak *x86_32_unwind_libunwind_ops;
struct unwind_libunwind_ops __weak *arm64_unwind_libunwind_ops;

-static void unwind__register_ops(struct thread *thread,
+static void unwind__register_ops(struct map_groups *mg,
struct unwind_libunwind_ops *ops)
{
- thread->unwind_libunwind_ops = ops;
+ mg->unwind_libunwind_ops = ops;
}

-int unwind__prepare_access(struct thread *thread, struct map *map,
+int unwind__prepare_access(struct map_groups *mg, struct map *map,
bool *initialized)
{
const char *arch;
@@ -28,7 +28,7 @@ int unwind__prepare_access(struct thread *thread, struct map *map,
if (!dwarf_callchain_users)
return 0;

- if (thread->addr_space) {
+ if (mg->addr_space) {
pr_debug("unwind: thread map already set, dso=%s\n",
map->dso->name);
if (initialized)
@@ -37,14 +37,14 @@ int unwind__prepare_access(struct thread *thread, struct map *map,
}

/* env->arch is NULL for live-mode (i.e. perf top) */
- if (!thread->mg->machine->env || !thread->mg->machine->env->arch)
+ if (!mg->machine->env || !mg->machine->env->arch)
goto out_register;

- dso_type = dso__type(map->dso, thread->mg->machine);
+ dso_type = dso__type(map->dso, mg->machine);
if (dso_type == DSO__TYPE_UNKNOWN)
return 0;

- arch = perf_env__arch(thread->mg->machine->env);
+ arch = perf_env__arch(mg->machine->env);

if (!strcmp(arch, "x86")) {
if (dso_type != DSO__TYPE_64BIT)
@@ -59,37 +59,37 @@ int unwind__prepare_access(struct thread *thread, struct map *map,
return 0;
}
out_register:
- unwind__register_ops(thread, ops);
+ unwind__register_ops(mg, ops);

- err = thread->unwind_libunwind_ops->prepare_access(thread);
+ err = mg->unwind_libunwind_ops->prepare_access(mg);
if (initialized)
*initialized = err ? false : true;
return err;
}

-void unwind__flush_access(struct thread *thread)
+void unwind__flush_access(struct map_groups *mg)
{
if (!dwarf_callchain_users)
return;

- if (thread->unwind_libunwind_ops)
- thread->unwind_libunwind_ops->flush_access(thread);
+ if (mg->unwind_libunwind_ops)
+ mg->unwind_libunwind_ops->flush_access(mg);
}

-void unwind__finish_access(struct thread *thread)
+void unwind__finish_access(struct map_groups *mg)
{
if (!dwarf_callchain_users)
return;

- if (thread->unwind_libunwind_ops)
- thread->unwind_libunwind_ops->finish_access(thread);
+ if (mg->unwind_libunwind_ops)
+ mg->unwind_libunwind_ops->finish_access(mg);
}

int unwind__get_entries(unwind_entry_cb_t cb, void *arg,
struct thread *thread,
struct perf_sample *data, int max_stack)
{
- if (thread->unwind_libunwind_ops)
- return thread->unwind_libunwind_ops->get_entries(cb, arg, thread, data, max_stack);
+ if (thread->mg->unwind_libunwind_ops)
+ return thread->mg->unwind_libunwind_ops->get_entries(cb, arg, thread, data, max_stack);
return 0;
}
diff --git a/tools/perf/util/unwind.h b/tools/perf/util/unwind.h
index 8a44a1569a21b..3a7d00c20d862 100644
--- a/tools/perf/util/unwind.h
+++ b/tools/perf/util/unwind.h
@@ -6,6 +6,7 @@
#include <linux/types.h>

struct map;
+struct map_groups;
struct perf_sample;
struct symbol;
struct thread;
@@ -19,9 +20,9 @@ struct unwind_entry {
typedef int (*unwind_entry_cb_t)(struct unwind_entry *entry, void *arg);

struct unwind_libunwind_ops {
- int (*prepare_access)(struct thread *thread);
- void (*flush_access)(struct thread *thread);
- void (*finish_access)(struct thread *thread);
+ int (*prepare_access)(struct map_groups *mg);
+ void (*flush_access)(struct map_groups *mg);
+ void (*finish_access)(struct map_groups *mg);
int (*get_entries)(unwind_entry_cb_t cb, void *arg,
struct thread *thread,
struct perf_sample *data, int max_stack);
@@ -46,20 +47,20 @@ int unwind__get_entries(unwind_entry_cb_t cb, void *arg,
#endif

int LIBUNWIND__ARCH_REG_ID(int regnum);
-int unwind__prepare_access(struct thread *thread, struct map *map,
+int unwind__prepare_access(struct map_groups *mg, struct map *map,
bool *initialized);
-void unwind__flush_access(struct thread *thread);
-void unwind__finish_access(struct thread *thread);
+void unwind__flush_access(struct map_groups *mg);
+void unwind__finish_access(struct map_groups *mg);
#else
-static inline int unwind__prepare_access(struct thread *thread __maybe_unused,
+static inline int unwind__prepare_access(struct map_groups *mg __maybe_unused,
struct map *map __maybe_unused,
bool *initialized __maybe_unused)
{
return 0;
}

-static inline void unwind__flush_access(struct thread *thread __maybe_unused) {}
-static inline void unwind__finish_access(struct thread *thread __maybe_unused) {}
+static inline void unwind__flush_access(struct map_groups *mg __maybe_unused) {}
+static inline void unwind__finish_access(struct map_groups *mg __maybe_unused) {}
#endif
#else
static inline int
@@ -72,14 +73,14 @@ unwind__get_entries(unwind_entry_cb_t cb __maybe_unused,
return 0;
}

-static inline int unwind__prepare_access(struct thread *thread __maybe_unused,
+static inline int unwind__prepare_access(struct map_groups *mg __maybe_unused,
struct map *map __maybe_unused,
bool *initialized __maybe_unused)
{
return 0;
}

-static inline void unwind__flush_access(struct thread *thread __maybe_unused) {}
-static inline void unwind__finish_access(struct thread *thread __maybe_unused) {}
+static inline void unwind__flush_access(struct map_groups *mg __maybe_unused) {}
+static inline void unwind__finish_access(struct map_groups *mg __maybe_unused) {}
#endif /* HAVE_DWARF_UNWIND_SUPPORT */
#endif /* __UNWIND_H */
--
2.20.1




2019-11-10 01:54:39

by Andres Freund

[permalink] [raw]
Subject: Re: [PATCH 5.3 111/344] perf unwind: Fix libunwind when tid != pid

Hi,

On 2019-10-03 17:51:16 +0200, Greg Kroah-Hartman wrote:
> From: John Keeping <[email protected]>
>
> [ Upstream commit e8ba2906f6b9054102ad035ac9cafad9d4168589 ]
>
> Commit e5adfc3e7e77 ("perf map: Synthesize maps only for thread group
> leader") changed the recording side so that we no longer get mmap events
> for threads other than the thread group leader (when synthesising these
> events for threads which exist before perf is started).
>
> When a file recorded after this change is loaded, the lack of mmap
> records mean that unwinding is not set up for any other threads.
>
> This can be seen in a simple record/report scenario:
>
> perf record --call-graph=dwarf -t $TID
> perf report
>
> If $TID is a process ID then the report will show call graphs, but if
> $TID is a secondary thread the output is as if --call-graph=none was
> specified.
>
> Following the rationale in that commit, move the libunwind fields into
> struct map_groups and update the libunwind functions to take this
> instead of the struct thread. This is only required for
> unwind__finish_access which must now be called from map_groups__delete
> and the others are changed for symmetry.
>
> Note that unwind__get_entries keeps the thread argument since it is
> required for symbol lookup and the libdw unwind provider uses the thread
> ID.
>
> Signed-off-by: John Keeping <[email protected]>
> Reviewed-by: Jiri Olsa <[email protected]>
> Cc: Alexander Shishkin <[email protected]>
> Cc: Konstantin Khlebnikov <[email protected]>
> Cc: Namhyung Kim <[email protected]>
> Cc: Peter Zijlstra <[email protected]>
> Fixes: e5adfc3e7e77 ("perf map: Synthesize maps only for thread group leader")
> Link: http://lkml.kernel.org/r/[email protected]
> Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
> Signed-off-by: Sasha Levin <[email protected]>

This unfortunately broke --call-graph dwarf on 5.3 (and presumably older
branches), because while this commit has been included in stable, the
prerequisite

commit ab6cd0e5276e24403751e0b3b8ed807738a8571f
Author: John Keeping <[email protected]>
AuthorDate: 2019-08-15 11:01:44 +0100
Commit: Arnaldo Carvalho de Melo <[email protected]>
CommitDate: 2019-08-16 12:25:23 -0300

perf map: Use zalloc for map_groups

In the next commit we will add new fields to map_groups and we need
these to be null if no value is assigned. The simplest way to achieve
this is to request zeroed memory from the allocator.

Signed-off-by: John Keeping <[email protected]>
Reviewed-by: Jiri Olsa <[email protected]>
Cc: Alexander Shishkin <[email protected]>
Cc: Konstantin Khlebnikov <[email protected]>
Cc: Namhyung Kim <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: john keeping <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>

has not.


The crash I get is:

Thread 1 "perf" received signal SIGSEGV, Segmentation fault.
0x0000555555872238 in unwind__flush_access (mg=0x555555c53b50) at util/unwind-libunwind.c:76
76 mg->unwind_libunwind_ops->flush_access(mg);
(gdb) bt
#0 0x0000555555872238 in unwind__flush_access (mg=0x555555c53b50) at util/unwind-libunwind.c:76
#1 0x0000555555800ac4 in ____thread__set_comm (exec=true, timestamp=325096707055731, str=0x7ffff7f96ed8 "sleep", thread=0x555555c53bc0) at util/thread.c:254
#2 __thread__set_comm (thread=thread@entry=0x555555c53bc0, str=str@entry=0x7ffff7f96ed8 "sleep", timestamp=325096707055731, exec=exec@entry=true)
at util/thread.c:268
#3 0x00005555557f132a in machine__process_comm_event (machine=0x555555c4bc68, event=0x7ffff7f96ec8, sample=0x7fffffff8f70) at util/machine.c:600
#4 0x00005555557fa93b in perf_session__deliver_event (session=0x555555c4baf0, event=0x7ffff7f96ec8, tool=0x555555acb9a0 <record>, file_offset=73416)
at util/session.c:1473
#5 0x00005555557feae8 in do_flush (show_progress=true, oe=0x555555c52610) at util/ordered-events.c:243
#6 __ordered_events__flush (oe=oe@entry=0x555555c52610, how=how@entry=OE_FLUSH__FINAL, timestamp=timestamp@entry=0) at util/ordered-events.c:322
#7 0x00005555557fef45 in __ordered_events__flush (timestamp=<optimized out>, how=<optimized out>, oe=<optimized out>) at util/ordered-events.c:338
#8 ordered_events__flush (how=OE_FLUSH__FINAL, oe=0x555555c52610) at util/ordered-events.c:340
#9 ordered_events__flush (oe=oe@entry=0x555555c52610, how=how@entry=OE_FLUSH__FINAL) at util/ordered-events.c:338
#10 0x00005555557fd17c in __perf_session__process_events (session=0x555555c4baf0) at util/session.c:2152
#11 perf_session__process_events (session=session@entry=0x555555c4baf0) at util/session.c:2181
#12 0x0000555555729379 in process_buildids (rec=0x555555acb9a0 <record>) at builtin-record.c:829
#13 record__finish_output (rec=0x555555acb9a0 <record>) at builtin-record.c:1037
#14 0x000055555572c000 in __cmd_record (rec=0x555555acb9a0 <record>, argv=<optimized out>, argc=2) at builtin-record.c:1661
#15 cmd_record (argc=2, argv=<optimized out>) at builtin-record.c:2450
#16 0x000055555579cd9d in run_builtin (p=0x555555ad4958 <commands+216>, argc=5, argv=0x7fffffffdcc0) at perf.c:304
#17 0x0000555555714baa in handle_internal_command (argv=0x7fffffffdcc0, argc=5) at perf.c:356
#18 run_argv (argcp=<synthetic pointer>, argv=<synthetic pointer>) at perf.c:400
#19 main (argc=5, argv=0x7fffffffdcc0) at perf.c:525

(gdb) p *mg
$7 = {maps = {entries = {rb_node = 0x0}, names = {rb_node = 0x0}, lock = {lock = pthread_rwlock_t = {Status = Not acquired, Shared = No,
Prefers = Readers}}}, machine = 0x555555c4bc68, refcnt = {refs = {counter = 1}}, addr_space = 0x693f6967632e6775,
unwind_libunwind_ops = 0xa32313438313d64}

(gdb) p mg->unwind_libunwind_ops
$8 = (struct unwind_libunwind_ops *) 0xa32313438313d64

(gdb) p *mg->unwind_libunwind_ops
Cannot access memory at address 0xa32313438313d64

which makes sense, because map_groups__new() allocates the group with
malloc, and map_groups__init() only initializes map_groups->{maps,machine,refcnt}


A bit surprised that nobody complained about this so far...


Greetings,

Andres Freund

2019-11-11 06:04:47

by Greg Kroah-Hartman

[permalink] [raw]
Subject: Re: [PATCH 5.3 111/344] perf unwind: Fix libunwind when tid != pid

On Sat, Nov 09, 2019 at 05:46:21PM -0800, Andres Freund wrote:
> Hi,
>
> On 2019-10-03 17:51:16 +0200, Greg Kroah-Hartman wrote:
> > From: John Keeping <[email protected]>
> >
> > [ Upstream commit e8ba2906f6b9054102ad035ac9cafad9d4168589 ]
> >
> > Commit e5adfc3e7e77 ("perf map: Synthesize maps only for thread group
> > leader") changed the recording side so that we no longer get mmap events
> > for threads other than the thread group leader (when synthesising these
> > events for threads which exist before perf is started).
> >
> > When a file recorded after this change is loaded, the lack of mmap
> > records mean that unwinding is not set up for any other threads.
> >
> > This can be seen in a simple record/report scenario:
> >
> > perf record --call-graph=dwarf -t $TID
> > perf report
> >
> > If $TID is a process ID then the report will show call graphs, but if
> > $TID is a secondary thread the output is as if --call-graph=none was
> > specified.
> >
> > Following the rationale in that commit, move the libunwind fields into
> > struct map_groups and update the libunwind functions to take this
> > instead of the struct thread. This is only required for
> > unwind__finish_access which must now be called from map_groups__delete
> > and the others are changed for symmetry.
> >
> > Note that unwind__get_entries keeps the thread argument since it is
> > required for symbol lookup and the libdw unwind provider uses the thread
> > ID.
> >
> > Signed-off-by: John Keeping <[email protected]>
> > Reviewed-by: Jiri Olsa <[email protected]>
> > Cc: Alexander Shishkin <[email protected]>
> > Cc: Konstantin Khlebnikov <[email protected]>
> > Cc: Namhyung Kim <[email protected]>
> > Cc: Peter Zijlstra <[email protected]>
> > Fixes: e5adfc3e7e77 ("perf map: Synthesize maps only for thread group leader")
> > Link: http://lkml.kernel.org/r/[email protected]
> > Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
> > Signed-off-by: Sasha Levin <[email protected]>
>
> This unfortunately broke --call-graph dwarf on 5.3 (and presumably older
> branches), because while this commit has been included in stable, the
> prerequisite
>
> commit ab6cd0e5276e24403751e0b3b8ed807738a8571f
> Author: John Keeping <[email protected]>
> AuthorDate: 2019-08-15 11:01:44 +0100
> Commit: Arnaldo Carvalho de Melo <[email protected]>
> CommitDate: 2019-08-16 12:25:23 -0300
>
> perf map: Use zalloc for map_groups
>
> In the next commit we will add new fields to map_groups and we need
> these to be null if no value is assigned. The simplest way to achieve
> this is to request zeroed memory from the allocator.
>
> Signed-off-by: John Keeping <[email protected]>
> Reviewed-by: Jiri Olsa <[email protected]>
> Cc: Alexander Shishkin <[email protected]>
> Cc: Konstantin Khlebnikov <[email protected]>
> Cc: Namhyung Kim <[email protected]>
> Cc: Peter Zijlstra <[email protected]>
> Cc: john keeping <[email protected]>
> Link: http://lkml.kernel.org/r/[email protected]
> Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
>
> has not.
>
>
> The crash I get is:
>
> Thread 1 "perf" received signal SIGSEGV, Segmentation fault.
> 0x0000555555872238 in unwind__flush_access (mg=0x555555c53b50) at util/unwind-libunwind.c:76
> 76 mg->unwind_libunwind_ops->flush_access(mg);
> (gdb) bt
> #0 0x0000555555872238 in unwind__flush_access (mg=0x555555c53b50) at util/unwind-libunwind.c:76
> #1 0x0000555555800ac4 in ____thread__set_comm (exec=true, timestamp=325096707055731, str=0x7ffff7f96ed8 "sleep", thread=0x555555c53bc0) at util/thread.c:254
> #2 __thread__set_comm (thread=thread@entry=0x555555c53bc0, str=str@entry=0x7ffff7f96ed8 "sleep", timestamp=325096707055731, exec=exec@entry=true)
> at util/thread.c:268
> #3 0x00005555557f132a in machine__process_comm_event (machine=0x555555c4bc68, event=0x7ffff7f96ec8, sample=0x7fffffff8f70) at util/machine.c:600
> #4 0x00005555557fa93b in perf_session__deliver_event (session=0x555555c4baf0, event=0x7ffff7f96ec8, tool=0x555555acb9a0 <record>, file_offset=73416)
> at util/session.c:1473
> #5 0x00005555557feae8 in do_flush (show_progress=true, oe=0x555555c52610) at util/ordered-events.c:243
> #6 __ordered_events__flush (oe=oe@entry=0x555555c52610, how=how@entry=OE_FLUSH__FINAL, timestamp=timestamp@entry=0) at util/ordered-events.c:322
> #7 0x00005555557fef45 in __ordered_events__flush (timestamp=<optimized out>, how=<optimized out>, oe=<optimized out>) at util/ordered-events.c:338
> #8 ordered_events__flush (how=OE_FLUSH__FINAL, oe=0x555555c52610) at util/ordered-events.c:340
> #9 ordered_events__flush (oe=oe@entry=0x555555c52610, how=how@entry=OE_FLUSH__FINAL) at util/ordered-events.c:338
> #10 0x00005555557fd17c in __perf_session__process_events (session=0x555555c4baf0) at util/session.c:2152
> #11 perf_session__process_events (session=session@entry=0x555555c4baf0) at util/session.c:2181
> #12 0x0000555555729379 in process_buildids (rec=0x555555acb9a0 <record>) at builtin-record.c:829
> #13 record__finish_output (rec=0x555555acb9a0 <record>) at builtin-record.c:1037
> #14 0x000055555572c000 in __cmd_record (rec=0x555555acb9a0 <record>, argv=<optimized out>, argc=2) at builtin-record.c:1661
> #15 cmd_record (argc=2, argv=<optimized out>) at builtin-record.c:2450
> #16 0x000055555579cd9d in run_builtin (p=0x555555ad4958 <commands+216>, argc=5, argv=0x7fffffffdcc0) at perf.c:304
> #17 0x0000555555714baa in handle_internal_command (argv=0x7fffffffdcc0, argc=5) at perf.c:356
> #18 run_argv (argcp=<synthetic pointer>, argv=<synthetic pointer>) at perf.c:400
> #19 main (argc=5, argv=0x7fffffffdcc0) at perf.c:525
>
> (gdb) p *mg
> $7 = {maps = {entries = {rb_node = 0x0}, names = {rb_node = 0x0}, lock = {lock = pthread_rwlock_t = {Status = Not acquired, Shared = No,
> Prefers = Readers}}}, machine = 0x555555c4bc68, refcnt = {refs = {counter = 1}}, addr_space = 0x693f6967632e6775,
> unwind_libunwind_ops = 0xa32313438313d64}
>
> (gdb) p mg->unwind_libunwind_ops
> $8 = (struct unwind_libunwind_ops *) 0xa32313438313d64
>
> (gdb) p *mg->unwind_libunwind_ops
> Cannot access memory at address 0xa32313438313d64
>
> which makes sense, because map_groups__new() allocates the group with
> malloc, and map_groups__init() only initializes map_groups->{maps,machine,refcnt}
>
>
> A bit surprised that nobody complained about this so far...

Thanks, I've queued up the other patch for 5.3.y now.

greg k-h