How to associate Elf with Dwfl_Module returned by dwfl_report_module

2018-03-17 Thread Milian Wolff
Hey there,

a recurring issue in the libdwfl integration of perf and perfparser are 
supposedly overlapping modules. The perf data file contains the exact mappings 
for all files corresponding to the actual mmap events that occurred during 
runtime, e.g.:

```
$ perf script --show-mmap-events | grep MMAP | grep stdc
heaptrack_print 13962 87163.483450: PERF_RECORD_MMAP2 13962/13962: 
[0x7fd0aea84000(0x387000) @ 0 08:03 413039 3864781083]: r-xp /usr/lib/libstdc+
+.so.6.0.24
heaptrack_print 13962 87163.483454: PERF_RECORD_MMAP2 13962/13962: 
[0x7fd0aebfc000(0x1ff000) @ 0x178000 08:03 413039 3864781083]: ---p /usr/lib/
libstdc++.so.6.0.24
heaptrack_print 13962 87163.483458: PERF_RECORD_MMAP2 13962/13962: 
[0x7fd0aedfb000(0xd000) @ 0x177000 08:03 413039 3864781083]: rw-p /usr/lib/
libstdc++.so.6.0.24
heaptrack_print 13962 87163.484860: PERF_RECORD_MMAP2 13962/13962: 
[0x7fd0aedfb000(0xc000) @ 0x177000 08:03 413039 3864781083]: r--p /usr/lib/
libstdc++.so.6.0.24
```
So far, both perf and perfparser are using dwfl_report_elf to report the file. 
But that API is deducing the mapping addresses internally, which may or may 
not be what we saw at runtime. I suspect that this is the reason for some 
issues we are seeing, such as supposedly overlapping modules. 

Looking at the Dwfl API, I cannot figure out how to feed the mapping directly. 
There's dwfl_report_module, but how would I associate an Elf* and int fd with 
it, as done by dwfl_report_elf?

Thanks
-- 
Milian Wolff
m...@milianw.de
http://milianw.de

signature.asc
Description: This is a digitally signed message part.


[PATCH] libdwfl: Use process_vm_readv when available.

2018-03-17 Thread Mark Wielaard
If possible use process_vm_readv to read 4K blocks instead of fetching
each word individually with ptrace. For unwinding this often means we
only have to do one process_vm_readv of the stack instead of dozens of
ptrace calls. There is one 4K cache per process, cleared whenever a
thread is detached.

Signed-off-by: Mark Wielaard 
---
 ChangeLog  |  4 +++
 configure.ac   |  6 ++--
 libdwfl/ChangeLog  | 11 +++
 libdwfl/libdwflP.h | 14 -
 libdwfl/linux-pid-attach.c | 74 +-
 5 files changed, 105 insertions(+), 4 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 279c3b2b..81542414 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+2018-03-17  Mark Wielaard  
+
+   * configure.ac (CHECK_FUNCS): Check for process_vm_readv.
+
 2018-02-09  Joshua Watt  
 
* configure.ac (HAVE_FALLTHROUGH): New define.
diff --git a/configure.ac b/configure.ac
index 4cdb12af..ab32cbc8 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,7 +1,7 @@
 dnl Process this file with autoconf to produce a configure script.
 dnl Configure input file for elfutils. -*-autoconf-*-
 dnl
-dnl Copyright (C) 1996-2017 Red Hat, Inc.
+dnl Copyright (C) 1996-2018 Red Hat, Inc.
 dnl
 dnl This file is part of elfutils.
 dnl
@@ -41,7 +41,7 @@ fi
 AC_CONFIG_AUX_DIR([config])
 AC_CONFIG_FILES([config/Makefile])
 
-AC_COPYRIGHT([Copyright (C) 1996-2017 The elfutils developers.])
+AC_COPYRIGHT([Copyright (C) 1996-2018 The elfutils developers.])
 AC_PREREQ(2.63)dnl Minimum Autoconf version required.
 
 dnl We use GNU make extensions; automake 1.10 defaults to -Wportability.
@@ -370,6 +370,8 @@ AC_CHECK_DECLS([mempcpy],[],[],
[#define _GNU_SOURCE
 #include ])
 
+AC_CHECK_FUNCS([process_vm_readv])
+
 AC_CHECK_LIB([stdc++], [__cxa_demangle], [dnl
 AC_DEFINE([USE_DEMANGLE], [1], [Defined if demangling is enabled])])
 AM_CONDITIONAL(DEMANGLE, test "x$ac_cv_lib_stdcpp___cxa_demangle" = "xyes")
diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog
index 1515c410..9776f1cb 100644
--- a/libdwfl/ChangeLog
+++ b/libdwfl/ChangeLog
@@ -1,3 +1,14 @@
+2018-03-17  Mark Wielaard  
+
+   * libdwflP.h (struct __libdwfl_remote_mem_cache): New.
+   (struct __libdwfl_pid_arg): Add mem_cache field.
+   * linux-pid-attach.c (read_cached_memory): New function.
+   (clear_cached_memory): Likewise.
+   (pid_memory_read): Call read_cached_memory.
+   (pid_detach): Free mem_cache.
+   (pid_thread_detach): Call clear_cached_memory.
+   (dwfl_linux_proc_attach): Initialize mem_cache to NULL.
+
 2018-03-05  Mark Wielaard  
 
* dwfl_build_id_find_elf.c (__libdwfl_open_by_build_id): Use
diff --git a/libdwfl/libdwflP.h b/libdwfl/libdwflP.h
index 7d5f795c..15ca0a11 100644
--- a/libdwfl/libdwflP.h
+++ b/libdwfl/libdwflP.h
@@ -1,5 +1,5 @@
 /* Internal definitions for libdwfl.
-   Copyright (C) 2005-2015 Red Hat, Inc.
+   Copyright (C) 2005-2015, 2018 Red Hat, Inc.
This file is part of elfutils.
 
This file is free software; you can redistribute it and/or modify
@@ -401,6 +401,14 @@ struct dwfl_arange
   size_t arange;   /* Index in Dwarf_Aranges.  */
 };
 
+#define __LIBDWFL_REMOTE_MEM_CACHE_SIZE 4096
+/* Structure for caching remote memory reads as used by __libdwfl_pid_arg.  */
+struct __libdwfl_remote_mem_cache
+{
+  Dwarf_Addr addr; /* Remote address.  */
+  Dwarf_Off len;   /* Zero if cleared, otherwise likely 4K. */
+  unsigned char buf[__LIBDWFL_REMOTE_MEM_CACHE_SIZE]; /* The actual cache.  */
+};
 
 /* Structure used for keeping track of ptrace attaching a thread.
Shared by linux-pid-attach and linux-proc-maps.  If it has been setup
@@ -411,6 +419,10 @@ struct __libdwfl_pid_arg
   DIR *dir;
   /* Elf for /proc/PID/exe.  Set to NULL if it couldn't be opened.  */
   Elf *elf;
+  /* Remote memory cache, NULL if there is no memory cached.
+ Should be cleared on detachment (because that makes the thread
+ runnable and the cache invalid).  */
+  struct __libdwfl_remote_mem_cache *mem_cache;
   /* fd for /proc/PID/exe.  Set to -1 if it couldn't be opened.  */
   int elf_fd;
   /* It is 0 if not used.  */
diff --git a/libdwfl/linux-pid-attach.c b/libdwfl/linux-pid-attach.c
index 2ab4109c..ea65618f 100644
--- a/libdwfl/linux-pid-attach.c
+++ b/libdwfl/linux-pid-attach.c
@@ -1,5 +1,5 @@
 /* Get Dwarf Frame state for target live PID process.
-   Copyright (C) 2013, 2014, 2015 Red Hat, Inc.
+   Copyright (C) 2013, 2014, 2015, 2018 Red Hat, Inc.
This file is part of elfutils.
 
This file is free software; you can redistribute it and/or modify
@@ -34,6 +34,7 @@
 #include "libdwflP.h"
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -115,12 +116,80 @@ __libdwfl_ptrace_attach (pid_t tid, bool 
*tid_was_stoppedp)
   return true;
 }
 
+#ifdef HAVE_PROCESS_VM_READV
+static bool
+read_cached_memory (struct __libdwfl_pid_arg