lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite for Android: free password hash cracker in your pocket
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-Id: <1542968726-20910-1-git-send-email-eric.saint.etienne@oracle.com>
Date:   Fri, 23 Nov 2018 02:25:26 -0800
From:   Eric Saint-Etienne <eric.saint.etienne@...cle.com>
To:     Linux Kernel <linux-kernel@...r.kernel.org>
Cc:     Alexander Shishkin <alexander.shishkin@...ux.intel.co>,
        Arnaldo Carvalho de Melo <acme@...nel.org>,
        Ingo Molnar <mingo@...hat.com>, Jiri Olsa <jolsa@...hat.com>,
        Peter Zijlstra <peterz@...radead.org>,
        Namhyung Kim <namhyung@...nel.org>,
        Darren Kenny <darren.kenny@...cle.com>,
        Eric Saint-Etienne <eric.saintetienne@...il.com>
Subject: [PATCH] perf symbols: Cannot disassemble some routines when debuginfo present

When the kernel is compiled with -ffunction-sections and perf uses the
kernel debuginfo, perf fails the very first symbol lookup and ends up with
an hex offset inside [kernel.vmlinux]. It's due to how perf loads the maps.

Indeed only .text gets loaded by map_groups__find() into al->map.
Consequently al->map address range encompass the whole code.
But map__load() has just loaded many function maps by splitting al->map,
which reduced al->map range drastically. Very likely the target address is
now in one of those newly created function maps, so we need to lookup the
map again to find that new map.

This issue is not specific to the kernel but to how the image is linked.
For the kernel, when we're not using the kernel debuginfo, perf will
fallback to using kallsyms and then the first lookup will work.

This patch makes sure that the event address we're looking-up is indeed
within the map we've found, otherwise we lookup another map again.
Only one extra lookup at most is required for the proper map to be found,
if it exists.

Signed-off-by: Eric Saint-Etienne <eric.saint.etienne@...cle.com>
Reviewed-by: Darren Kenny <darren.kenny@...cle.com>
---
 tools/perf/util/event.c | 23 ++++++++++++++++++++++-
 1 file changed, 22 insertions(+), 1 deletion(-)

diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index e9c108a..a69ef52 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -1571,7 +1571,28 @@ struct map *thread__find_map(struct thread *thread, u8 cpumode, u64 addr,
 		 */
 		if (load_map)
 			map__load(al->map);
-		al->addr = al->map->map_ip(al->map, al->addr);
+
+		/*
+		 * When using -ffunction-sections, only .text gets loaded by
+		 * map_groups__find() into al->map. Consequently al->map address
+		 * range encompass the whole code.
+		 *
+		 * But map__load() has just loaded many function maps by
+		 * splitting al->map, which reduced al->map range drastically.
+		 * Very likely the target address is now in one of those newly
+		 * created function maps, so we need to lookup the map again
+		 * to find that new map.
+		 */
+		if (al->addr < al->map->start || al->addr >= al->map->end)
+			al->map = map_groups__find(mg, al->addr);
+
+		/*
+		 * The new map *ought* to exist because the initial al->map
+		 * contained that address and subsequently has been split into
+		 * many *contiguous* maps.
+		 */
+		if (al->map != NULL)
+			al->addr = al->map->map_ip(al->map, al->addr);
 	}
 
 	return al->map;
-- 
1.8.3.1

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ