提交 0a9e41e2 编写于 作者: T Thomas Richter 提交者: Greg Kroah-Hartman

perf record: Fix module size on s390

commit 12a6d2940b5f02b4b9f71ce098e3bb02bc24a9ea upstream.

On s390 the modules loaded in memory have the text segment located after
the GOT and Relocation table. This can be seen with this output:

  [root@m35lp76 perf]# fgrep qeth /proc/modules
  qeth 151552 1 qeth_l2, Live 0x000003ff800b2000
  ...
  [root@m35lp76 perf]# cat /sys/module/qeth/sections/.text
  0x000003ff800b3990
  [root@m35lp76 perf]#

There is an offset of 0x1990 bytes. The size of the qeth module is
151552 bytes (0x25000 in hex).

The location of the GOT/relocation table at the beginning of a module is
unique to s390.

commit 203d8a4a ("perf s390: Fix 'start' address of module's map")
adjusts the start address of a module in the map structures, but does
not adjust the size of the modules. This leads to overlapping of module
maps as this example shows:

[root@m35lp76 perf] # ./perf report -D
     0 0 0xfb0 [0xa0]: PERF_RECORD_MMAP -1/0: [0x3ff800b3990(0x25000)
          @ 0]:  x /lib/modules/.../qeth.ko.xz
     0 0 0x1050 [0xb0]: PERF_RECORD_MMAP -1/0: [0x3ff800d85a0(0x8000)
          @ 0]:  x /lib/modules/.../ip6_tables.ko.xz

The module qeth.ko has an adjusted start address modified to b3990, but
its size is unchanged and the module ends at 0x3ff800d8990.  This end
address overlaps with the next modules start address of 0x3ff800d85a0.

When the size of the leading GOT/Relocation table stored in the
beginning of the text segment (0x1990 bytes) is subtracted from module
qeth end address, there are no overlaps anymore:

   0x3ff800d8990 - 0x1990 = 0x0x3ff800d7000

which is the same as

   0x3ff800b2000 + 0x25000 = 0x0x3ff800d7000.

To fix this issue, also adjust the modules size in function
arch__fix_module_text_start(). Add another function parameter named size
and reduce the size of the module when the text segment start address is
changed.

Output after:
     0 0 0xfb0 [0xa0]: PERF_RECORD_MMAP -1/0: [0x3ff800b3990(0x23670)
          @ 0]:  x /lib/modules/.../qeth.ko.xz
     0 0 0x1050 [0xb0]: PERF_RECORD_MMAP -1/0: [0x3ff800d85a0(0x7a60)
          @ 0]:  x /lib/modules/.../ip6_tables.ko.xz
Reported-by: NStefan Liebler <stli@linux.ibm.com>
Signed-off-by: NThomas Richter <tmricht@linux.ibm.com>
Acked-by: NHeiko Carstens <heiko.carstens@de.ibm.com>
Cc: Hendrik Brueckner <brueckner@linux.ibm.com>
Cc: Vasily Gorbik <gor@linux.ibm.com>
Cc: stable@vger.kernel.org
Fixes: 203d8a4a ("perf s390: Fix 'start' address of module's map")
Link: http://lkml.kernel.org/r/20190724122703.3996-1-tmricht@linux.ibm.comSigned-off-by: NArnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: NGreg Kroah-Hartman <gregkh@linuxfoundation.org>
上级 f1f66289
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
#include "debug.h" #include "debug.h"
#include "symbol.h" #include "symbol.h"
int arch__fix_module_text_start(u64 *start, const char *name) int arch__fix_module_text_start(u64 *start, u64 *size, const char *name)
{ {
u64 m_start = *start; u64 m_start = *start;
char path[PATH_MAX]; char path[PATH_MAX];
...@@ -18,6 +18,18 @@ int arch__fix_module_text_start(u64 *start, const char *name) ...@@ -18,6 +18,18 @@ int arch__fix_module_text_start(u64 *start, const char *name)
if (sysfs__read_ull(path, (unsigned long long *)start) < 0) { if (sysfs__read_ull(path, (unsigned long long *)start) < 0) {
pr_debug2("Using module %s start:%#lx\n", path, m_start); pr_debug2("Using module %s start:%#lx\n", path, m_start);
*start = m_start; *start = m_start;
} else {
/* Successful read of the modules segment text start address.
* Calculate difference between module start address
* in memory and module text segment start address.
* For example module load address is 0x3ff8011b000
* (from /proc/modules) and module text segment start
* address is 0x3ff8011b870 (from file above).
*
* Adjust the module size and subtract the GOT table
* size located at the beginning of the module.
*/
*size -= (*start - m_start);
} }
return 0; return 0;
......
...@@ -1295,6 +1295,7 @@ static int machine__set_modules_path(struct machine *machine) ...@@ -1295,6 +1295,7 @@ static int machine__set_modules_path(struct machine *machine)
return map_groups__set_modules_path_dir(&machine->kmaps, modules_path, 0); return map_groups__set_modules_path_dir(&machine->kmaps, modules_path, 0);
} }
int __weak arch__fix_module_text_start(u64 *start __maybe_unused, int __weak arch__fix_module_text_start(u64 *start __maybe_unused,
u64 *size __maybe_unused,
const char *name __maybe_unused) const char *name __maybe_unused)
{ {
return 0; return 0;
...@@ -1306,7 +1307,7 @@ static int machine__create_module(void *arg, const char *name, u64 start, ...@@ -1306,7 +1307,7 @@ static int machine__create_module(void *arg, const char *name, u64 start,
struct machine *machine = arg; struct machine *machine = arg;
struct map *map; struct map *map;
if (arch__fix_module_text_start(&start, name) < 0) if (arch__fix_module_text_start(&start, &size, name) < 0)
return -1; return -1;
map = machine__findnew_module_map(machine, start, name); map = machine__findnew_module_map(machine, start, name);
......
...@@ -219,7 +219,7 @@ struct symbol *machine__find_kernel_symbol_by_name(struct machine *machine, ...@@ -219,7 +219,7 @@ struct symbol *machine__find_kernel_symbol_by_name(struct machine *machine,
struct map *machine__findnew_module_map(struct machine *machine, u64 start, struct map *machine__findnew_module_map(struct machine *machine, u64 start,
const char *filename); const char *filename);
int arch__fix_module_text_start(u64 *start, const char *name); int arch__fix_module_text_start(u64 *start, u64 *size, const char *name);
int machine__load_kallsyms(struct machine *machine, const char *filename); int machine__load_kallsyms(struct machine *machine, const char *filename);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册