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: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <1452567507-54013-1-git-send-email-hekuang@huawei.com>
Date:	Tue, 12 Jan 2016 02:58:27 +0000
From:	He Kuang <hekuang@...wei.com>
To:	<peterz@...radead.org>, <mingo@...hat.com>, <acme@...nel.org>,
	<jolsa@...hat.com>, <rabin.vincent@...s.com>,
	<namhyung@...nel.org>, <wangnan0@...wei.com>,
	<mark.rutland@....com>, <hekuang@...wei.com>
CC:	<linux-kernel@...r.kernel.org>
Subject: [PATCH v2] perf symbols: Fix wrong symbol offset according to p_addr

Perf missed the 'VirtAddr' value in elf program_headers when adjusting
symbol address for dynamic libraries. This patch considers the p_addr
value and calculates the right symbol offset.

Before this patch, some symbols are not parsed correctly on android phone:

  init   369 [002]   339.970607: raw_syscalls:sys_enter: NR 22 (b, 7fd9e360a0, 10, ffffffff, 0, 8)
                     ...
                   230ac [unknown] (/system/lib64/libsurfaceflinger.so)
                    11a0 main (/system/bin/surfaceflinger)
                   1c3fc __libc_init (/system/lib64/libc.so)
                     fd0 _start (/system/bin/surfaceflinger)
                    29ec __dl__start (/system/bin/linker64)

After this patch:

  init   369 [002]   339.970607: raw_syscalls:sys_enter: NR 22 (b, 7fd9e360a0, 10, ffffffff, 0, 8)
                     ...
                   3a0ac _ZN7android14SurfaceFlinger3runEv (/system/lib64/libsurfaceflinger.so)
                    11a0 main (/system/bin/surfaceflinger)
                   1c3fc __libc_init (/system/lib64/libc.so)
                     fd0 _start (/system/bin/surfaceflinger)
                    29ec __dl__start (/system/bin/linker64)

Signed-off-by: He Kuang <hekuang@...wei.com>
---

Patch v1 to v2:
  - Modify commit message by following Ingo's suggestion.
  - Change ambiguous virable name 'vaddr' to 'load_virtaddr'.
  
---
 tools/perf/util/dso.c        |  6 ++++++
 tools/perf/util/dso.h        |  3 ++-
 tools/perf/util/event.c      |  6 +++++-
 tools/perf/util/map.h        |  7 +++++--
 tools/perf/util/symbol-elf.c | 20 ++++++++++++++++++++
 5 files changed, 38 insertions(+), 4 deletions(-)

diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
index e8e9a9d..afc51ce 100644
--- a/tools/perf/util/dso.c
+++ b/tools/perf/util/dso.c
@@ -1063,6 +1063,7 @@ struct dso *dso__new(const char *name)
 		dso->needs_swap = DSO_SWAP__UNSET;
 		RB_CLEAR_NODE(&dso->rb_node);
 		dso->root = NULL;
+		dso->load_virtaddr = 0;
 		INIT_LIST_HEAD(&dso->node);
 		INIT_LIST_HEAD(&dso->data.open_entry);
 		pthread_mutex_init(&dso->lock, NULL);
@@ -1367,3 +1368,8 @@ int dso__strerror_load(struct dso *dso, char *buf, size_t buflen)
 	scnprintf(buf, buflen, "%s", dso_load__error_str[idx]);
 	return 0;
 }
+
+u64 dso__get_load_virtaddr(struct dso *dso)
+{
+	return dso->load_virtaddr;
+}
diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h
index 45ec4d0..2a03b87 100644
--- a/tools/perf/util/dso.h
+++ b/tools/perf/util/dso.h
@@ -166,7 +166,8 @@ struct dso {
 	const char	 *long_name;
 	u16		 long_name_len;
 	u16		 short_name_len;
-	void		*dwfl;			/* DWARF debug info */
+	u64		 load_virtaddr;		/* Load virtual address */
+	void		 *dwfl;			/* DWARF debug info */
 	struct auxtrace_cache *auxtrace_cache;
 
 	/* dso data file */
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index cd61bb1..7f1dbdf 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -1273,8 +1273,12 @@ try_again:
 		 * Kernel maps might be changed when loading symbols so loading
 		 * must be done prior to using kernel maps.
 		 */
+		map__load(al->map, machine->symbol_filter);
+
+		/* exclude kernel kallsyms */
 		if (load_map)
-			map__load(al->map, machine->symbol_filter);
+			al->map->dso->load_virtaddr = 0;
+
 		al->addr = al->map->map_ip(al->map, al->addr);
 	}
 }
diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h
index 7309d64..db284a4 100644
--- a/tools/perf/util/map.h
+++ b/tools/perf/util/map.h
@@ -86,14 +86,17 @@ void map_groups__put(struct map_groups *mg);
 struct kmap *map__kmap(struct map *map);
 struct map_groups *map__kmaps(struct map *map);
 
+u64 dso__get_load_virtaddr(struct dso *dso);
 static inline u64 map__map_ip(struct map *map, u64 ip)
 {
-	return ip - map->start + map->pgoff;
+	return ip - map->start + map->pgoff +
+		dso__get_load_virtaddr(map->dso);
 }
 
 static inline u64 map__unmap_ip(struct map *map, u64 ip)
 {
-	return ip + map->start - map->pgoff;
+	return ip + map->start - map->pgoff -
+		dso__get_load_virtaddr(map->dso);
 }
 
 static inline u64 identity__map_ip(struct map *map __maybe_unused, u64 ip)
diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c
index 562b8eb..9a02b3e 100644
--- a/tools/perf/util/symbol-elf.c
+++ b/tools/perf/util/symbol-elf.c
@@ -15,6 +15,8 @@
 #define EM_AARCH64	183  /* ARM 64 bit */
 #endif
 
+static int elf_read_maps_ex(Elf * elf, bool exe, mapfn_t mapfn, void *data,
+			    struct map *map);
 
 #ifdef HAVE_CPLUS_DEMANGLE_SUPPORT
 extern char *cplus_demangle(const char *, int);
@@ -831,6 +833,10 @@ int dso__load_sym(struct dso *dso, struct map *map,
 	sec = syms_ss->symtab;
 	shdr = syms_ss->symshdr;
 
+	err = elf_read_maps_ex(elf, ehdr.e_type == ET_EXEC ||
+			       ehdr.e_type == ET_REL,
+			       NULL, NULL, map);
+
 	if (runtime_ss->opdsec)
 		opddata = elf_rawdata(runtime_ss->opdsec, NULL);
 
@@ -1116,6 +1122,13 @@ out_elf_end:
 
 static int elf_read_maps(Elf *elf, bool exe, mapfn_t mapfn, void *data)
 {
+
+	return elf_read_maps_ex(elf, exe, mapfn, data, NULL);
+}
+
+static int elf_read_maps_ex(Elf *elf, bool exe, mapfn_t mapfn, void *data,
+			    struct map *map)
+{
 	GElf_Phdr phdr;
 	size_t i, phdrnum;
 	int err;
@@ -1135,10 +1148,17 @@ static int elf_read_maps(Elf *elf, bool exe, mapfn_t mapfn, void *data)
 		} else {
 			if (!(phdr.p_flags & PF_R))
 				continue;
+			if (map && (phdr.p_flags & PF_X))
+				map->dso->load_virtaddr = phdr.p_vaddr;
 		}
+
 		sz = min(phdr.p_memsz, phdr.p_filesz);
 		if (!sz)
 			continue;
+
+		if (!mapfn)
+			continue;
+
 		err = mapfn(phdr.p_vaddr, sz, phdr.p_offset, data);
 		if (err)
 			return err;
-- 
1.8.5.2

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ