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-next>] [day] [month] [year] [list]
Message-ID: <1496622849-21877-1-git-send-email-huawei.libin@huawei.com>
Date:   Mon, 5 Jun 2017 08:34:09 +0800
From:   Li Bin <huawei.libin@...wei.com>
To:     <linux-kernel@...r.kernel.org>
CC:     <peterz@...radead.org>, <mingo@...hat.com>, <acme@...nel.org>,
        <alexander.shishkin@...ux.intel.com>, <mhiramat@...nel.org>,
        <namhyung@...nel.org>, <hemant@...ux.vnet.ibm.com>,
        <alexis.berlemont@...il.com>, <dtolnay@...il.com>,
        <milian.wolff@...b.com>, <wangnan0@...wei.com>,
        <guohanjun@...wei.com>, <zhangmengting@...wei.com>,
        <huawei.libin@...wei.com>
Subject: [PATCH] perf symbols: Fix plt entry calculation for ARM and AARCH64

On x86, the plt header size is as same as the plt entry size, and
can be identified from shdr's sh_entsize of the plt.
But we cann't assume that the sh_entsize of the plt shdr is always
the plt entry size in all architecture, and the plt header size may
be not as same as the plt entry size in some architecure.

On ARM, the plt header size is 20 bytes and the plt entry size is 12
bytes(don't consider the FOUR_WORD_PLT case)
that refer to the binutils implementation.
plt section is as follows:

Disassembly of section .plt:
000004a0 <__cxa_finalize@...-0x14>:
 4a0:   e52de004        push    {lr}            ; (str lr, [sp, #-4]!)
 4a4:   e59fe004        ldr     lr, [pc, #4]    ; 4b0 <_init+0x1c>
 4a8:   e08fe00e        add     lr, pc, lr
 4ac:   e5bef008        ldr     pc, [lr, #8]!
 4b0:   00008424        .word   0x00008424

000004b4 <__cxa_finalize@plt>:
 4b4:   e28fc600        add     ip, pc, #0, 12
 4b8:   e28cca08        add     ip, ip, #8, 20  ; 0x8000
 4bc:   e5bcf424        ldr     pc, [ip, #1060]!        ; 0x424

000004c0 <printf@plt>:
 4c0:   e28fc600        add     ip, pc, #0, 12
 4c4:   e28cca08        add     ip, ip, #8, 20  ; 0x8000
 4c8:   e5bcf41c        ldr     pc, [ip, #1052]!        ; 0x41c

On AARCH64, the plt header size is 32 bytes and the plt entry size is
16 bytes.
plt section is as follows:

Disassembly of section .plt:
0000000000000560 <__cxa_finalize@...-0x20>:
 560:   a9bf7bf0        stp     x16, x30, [sp,#-16]!
 564:   90000090        adrp    x16, 10000 <__FRAME_END__+0xf8a8>
 568:   f944be11        ldr     x17, [x16,#2424]
 56c:   9125e210        add     x16, x16, #0x978
 570:   d61f0220        br      x17
 574:   d503201f        nop
 578:   d503201f        nop
 57c:   d503201f        nop

0000000000000580 <__cxa_finalize@plt>:
 580:   90000090        adrp    x16, 10000 <__FRAME_END__+0xf8a8>
 584:   f944c211        ldr     x17, [x16,#2432]
 588:   91260210        add     x16, x16, #0x980
 58c:   d61f0220        br      x17

0000000000000590 <__gmon_start__@plt>:
 590:   90000090        adrp    x16, 10000 <__FRAME_END__+0xf8a8>
 594:   f944c611        ldr     x17, [x16,#2440]
 598:   91262210        add     x16, x16, #0x988
 59c:   d61f0220        br      x17

NOTES:
In addition to ARM and AARCH64, other architectures, such as
s390/alpha/mips/parisc/poperpc/sh/sparc/xtensa also need to consider
this issue.

Signed-off-by: Li Bin <huawei.libin@...wei.com>
---
 tools/perf/util/symbol-elf.c | 27 ++++++++++++++++++++++-----
 1 file changed, 22 insertions(+), 5 deletions(-)

diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c
index e7ee47f..1bccf71 100644
--- a/tools/perf/util/symbol-elf.c
+++ b/tools/perf/util/symbol-elf.c
@@ -259,7 +259,7 @@ int dso__synthesize_plt_symbols(struct dso *dso, struct symsrc *ss, struct map *
 {
 	uint32_t nr_rel_entries, idx;
 	GElf_Sym sym;
-	u64 plt_offset;
+	u64 plt_offset, plt_header_size, plt_entry_size;
 	GElf_Shdr shdr_plt;
 	struct symbol *f;
 	GElf_Shdr shdr_rel_plt, shdr_dynsym;
@@ -326,6 +326,23 @@ int dso__synthesize_plt_symbols(struct dso *dso, struct symsrc *ss, struct map *
 
 	nr_rel_entries = shdr_rel_plt.sh_size / shdr_rel_plt.sh_entsize;
 	plt_offset = shdr_plt.sh_offset;
+	switch (ehdr.e_machine) {
+		case EM_ARM:
+			plt_header_size = 20;
+			plt_entry_size = 12;
+			break;
+
+		case EM_AARCH64:
+			plt_header_size = 32;
+			plt_entry_size = 16;
+			break;
+
+		default: /* FIXME: s390/alpha/mips/parisc/poperpc/sh/sparc/xtensa need to be checked */
+			plt_header_size = shdr_plt.sh_entsize;
+			plt_entry_size = shdr_plt.sh_entsize;
+			break;
+	}
+	plt_offset += plt_header_size;
 
 	if (shdr_rel_plt.sh_type == SHT_RELA) {
 		GElf_Rela pos_mem, *pos;
@@ -335,7 +352,6 @@ int dso__synthesize_plt_symbols(struct dso *dso, struct symsrc *ss, struct map *
 			const char *elf_name = NULL;
 			char *demangled = NULL;
 			symidx = GELF_R_SYM(pos->r_info);
-			plt_offset += shdr_plt.sh_entsize;
 			gelf_getsym(syms, symidx, &sym);
 
 			elf_name = elf_sym__name(&sym, symstrs);
@@ -346,11 +362,12 @@ int dso__synthesize_plt_symbols(struct dso *dso, struct symsrc *ss, struct map *
 				 "%s@plt", elf_name);
 			free(demangled);
 
-			f = symbol__new(plt_offset, shdr_plt.sh_entsize,
+			f = symbol__new(plt_offset, plt_entry_size,
 					STB_GLOBAL, sympltname);
 			if (!f)
 				goto out_elf_end;
 
+			plt_offset += plt_entry_size;
 			symbols__insert(&dso->symbols[map->type], f);
 			++nr;
 		}
@@ -361,7 +378,6 @@ int dso__synthesize_plt_symbols(struct dso *dso, struct symsrc *ss, struct map *
 			const char *elf_name = NULL;
 			char *demangled = NULL;
 			symidx = GELF_R_SYM(pos->r_info);
-			plt_offset += shdr_plt.sh_entsize;
 			gelf_getsym(syms, symidx, &sym);
 
 			elf_name = elf_sym__name(&sym, symstrs);
@@ -372,11 +388,12 @@ int dso__synthesize_plt_symbols(struct dso *dso, struct symsrc *ss, struct map *
 				 "%s@plt", elf_name);
 			free(demangled);
 
-			f = symbol__new(plt_offset, shdr_plt.sh_entsize,
+			f = symbol__new(plt_offset, plt_entry_size,
 					STB_GLOBAL, sympltname);
 			if (!f)
 				goto out_elf_end;
 
+			plt_offset += plt_entry_size;
 			symbols__insert(&dso->symbols[map->type], f);
 			++nr;
 		}
-- 
1.7.12.4

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ