Skip to content

Commit b2f7605

Browse files
libin2015acmel
authored andcommitted
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 can'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. The plt section is as follows: Disassembly of section .plt: 000004a0 <__cxa_finalize@plt-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. The plt section is as follows: Disassembly of section .plt: 0000000000000560 <__cxa_finalize@plt-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 <[email protected]> Acked-by: Namhyung Kim <[email protected]> Cc: Alexander Shishkin <[email protected]> Cc: Alexis Berlemont <[email protected]> Cc: David Tolnay <[email protected]> Cc: Hanjun Guo <[email protected]> Cc: Hemant Kumar <[email protected]> Cc: Masami Hiramatsu <[email protected]> Cc: Milian Wolff <[email protected]> Cc: Namhyung Kim <[email protected]> Cc: Peter Zijlstra <[email protected]> Cc: Wang Nan <[email protected]> Cc: [email protected] Link: http://lkml.kernel.org/r/[email protected] Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
1 parent 2c29461 commit b2f7605

File tree

1 file changed

+22
-5
lines changed

1 file changed

+22
-5
lines changed

tools/perf/util/symbol-elf.c

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,7 @@ int dso__synthesize_plt_symbols(struct dso *dso, struct symsrc *ss, struct map *
259259
{
260260
uint32_t nr_rel_entries, idx;
261261
GElf_Sym sym;
262-
u64 plt_offset;
262+
u64 plt_offset, plt_header_size, plt_entry_size;
263263
GElf_Shdr shdr_plt;
264264
struct symbol *f;
265265
GElf_Shdr shdr_rel_plt, shdr_dynsym;
@@ -326,6 +326,23 @@ int dso__synthesize_plt_symbols(struct dso *dso, struct symsrc *ss, struct map *
326326

327327
nr_rel_entries = shdr_rel_plt.sh_size / shdr_rel_plt.sh_entsize;
328328
plt_offset = shdr_plt.sh_offset;
329+
switch (ehdr.e_machine) {
330+
case EM_ARM:
331+
plt_header_size = 20;
332+
plt_entry_size = 12;
333+
break;
334+
335+
case EM_AARCH64:
336+
plt_header_size = 32;
337+
plt_entry_size = 16;
338+
break;
339+
340+
default: /* FIXME: s390/alpha/mips/parisc/poperpc/sh/sparc/xtensa need to be checked */
341+
plt_header_size = shdr_plt.sh_entsize;
342+
plt_entry_size = shdr_plt.sh_entsize;
343+
break;
344+
}
345+
plt_offset += plt_header_size;
329346

330347
if (shdr_rel_plt.sh_type == SHT_RELA) {
331348
GElf_Rela pos_mem, *pos;
@@ -335,7 +352,6 @@ int dso__synthesize_plt_symbols(struct dso *dso, struct symsrc *ss, struct map *
335352
const char *elf_name = NULL;
336353
char *demangled = NULL;
337354
symidx = GELF_R_SYM(pos->r_info);
338-
plt_offset += shdr_plt.sh_entsize;
339355
gelf_getsym(syms, symidx, &sym);
340356

341357
elf_name = elf_sym__name(&sym, symstrs);
@@ -346,11 +362,12 @@ int dso__synthesize_plt_symbols(struct dso *dso, struct symsrc *ss, struct map *
346362
"%s@plt", elf_name);
347363
free(demangled);
348364

349-
f = symbol__new(plt_offset, shdr_plt.sh_entsize,
365+
f = symbol__new(plt_offset, plt_entry_size,
350366
STB_GLOBAL, sympltname);
351367
if (!f)
352368
goto out_elf_end;
353369

370+
plt_offset += plt_entry_size;
354371
symbols__insert(&dso->symbols[map->type], f);
355372
++nr;
356373
}
@@ -361,7 +378,6 @@ int dso__synthesize_plt_symbols(struct dso *dso, struct symsrc *ss, struct map *
361378
const char *elf_name = NULL;
362379
char *demangled = NULL;
363380
symidx = GELF_R_SYM(pos->r_info);
364-
plt_offset += shdr_plt.sh_entsize;
365381
gelf_getsym(syms, symidx, &sym);
366382

367383
elf_name = elf_sym__name(&sym, symstrs);
@@ -372,11 +388,12 @@ int dso__synthesize_plt_symbols(struct dso *dso, struct symsrc *ss, struct map *
372388
"%s@plt", elf_name);
373389
free(demangled);
374390

375-
f = symbol__new(plt_offset, shdr_plt.sh_entsize,
391+
f = symbol__new(plt_offset, plt_entry_size,
376392
STB_GLOBAL, sympltname);
377393
if (!f)
378394
goto out_elf_end;
379395

396+
plt_offset += plt_entry_size;
380397
symbols__insert(&dso->symbols[map->type], f);
381398
++nr;
382399
}

0 commit comments

Comments
 (0)