perf record: Fix s390 missing module symbol and warning for non-root users [Linux 4.14.129]

perf record: Fix s390 missing module symbol and warning for non-root users [Linux 4.14.129]

This Linux kernel change "perf record: Fix s390 missing module symbol and warning for non-root users" is included in the Linux 4.14.129 release. This change is authored by Thomas Richter <tmricht [at] linux.ibm.com> on Wed May 22 16:46:01 2019 +0200. The commit for this change in Linux stable tree is 810f6b9 (patch) which is from upstream commit 6738028. The same Linux upstream change may have been applied to various maintained Linux releases and you can find all Linux releases containing changes from upstream 6738028.

perf record: Fix s390 missing module symbol and warning for non-root users

[ Upstream commit 6738028dd57df064b969d8392c943ef3b3ae705d ]

Command 'perf record' and 'perf report' on a system without kernel
debuginfo packages uses /proc/kallsyms and /proc/modules to find
addresses for kernel and module symbols. On x86 this works for root and
non-root users.

On s390, when invoked as non-root user, many of the following warnings
are shown and module symbols are missing:

    proc/{kallsyms,modules} inconsistency while looking for
        "[sha1_s390]" module!

Command 'perf record' creates a list of module start addresses by
parsing the output of /proc/modules and creates a PERF_RECORD_MMAP
record for the kernel and each module. The following function call
sequence is executed:

  machine__create_kernel_maps
    machine__create_module
      modules__parse
        machine__create_module --> for each line in /proc/modules
          arch__fix_module_text_start

Function arch__fix_module_text_start() is s390 specific. It opens
file /sys/module/<name>/sections/.text to extract the module's .text
section start address. On s390 the module loader prepends a header
before the first section, whereas on x86 the module's text section
address is identical the the module's load address.

However module section files are root readable only. For non-root the
read operation fails and machine__create_module() returns an error.
Command perf record does not generate any PERF_RECORD_MMAP record
for loaded modules. Later command perf report complains about missing
module maps.

To fix this function arch__fix_module_text_start() always returns
success. For root users there is no change, for non-root users
the module's load address is used as module's text start address
(the prepended header then counts as part of the text section).

This enable non-root users to use module symbols and avoid the
warning when perf report is executed.

Output before:

  [[email protected] perf]$ ./perf report -D | fgrep MMAP
  0 0x168 [0x50]: PERF_RECORD_MMAP ... x [kernel.kallsyms]_text

Output after:

  [[email protected] perf]$ ./perf report -D | fgrep MMAP
  0 0x168 [0x50]: PERF_RECORD_MMAP ... x [kernel.kallsyms]_text
  0 0x1b8 [0x98]: PERF_RECORD_MMAP ... x /lib/modules/.../autofs4.ko.xz
  0 0x250 [0xa8]: PERF_RECORD_MMAP ... x /lib/modules/.../sha_common.ko.xz
  0 0x2f8 [0x98]: PERF_RECORD_MMAP ... x /lib/modules/.../des_generic.ko.xz

Signed-off-by: Thomas Richter <[email protected]>
Reviewed-by: Hendrik Brueckner <[email protected]>
Cc: Heiko Carstens <[email protected]>
Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
Signed-off-by: Sasha Levin <[email protected]>

There are 9 lines of Linux source code added/deleted in this change. Code changes to Linux kernel are as follows.

 tools/perf/arch/s390/util/machine.c | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/tools/perf/arch/s390/util/machine.c b/tools/perf/arch/s390/util/machine.c
index 0b20540..a19690a 100644
--- a/tools/perf/arch/s390/util/machine.c
+++ b/tools/perf/arch/s390/util/machine.c
@@ -5,16 +5,19 @@
 #include "util.h"
 #include "machine.h"
 #include "api/fs/fs.h"
+#include "debug.h"

 int arch__fix_module_text_start(u64 *start, const char *name)
 {
+   u64 m_start = *start;
    char path[PATH_MAX];

    snprintf(path, PATH_MAX, "module/%.*s/sections/.text",
                (int)strlen(name) - 2, name + 1);
-
-   if (sysfs__read_ull(path, (unsigned long long *)start) < 0)
-       return -1;
+   if (sysfs__read_ull(path, (unsigned long long *)start) < 0) {
+       pr_debug2("Using module %s start:%#lx\n", path, m_start);
+       *start = m_start;
+   }

    return 0;
 }

Leave a Reply

Your email address will not be published. Required fields are marked *