Bug ID 1180681
Summary perf does not resolve plt symbols from libstdc++ right
Classification openSUSE
Product openSUSE Tumbleweed
Version Current
Hardware Other
OS Other
Status NEW
Severity Normal
Priority P5 - None
Component Development
Assignee screening-team-bugs@suse.de
Reporter jslaby@suse.com
QA Contact qa-bugs@suse.de
CC martin.liska@suse.com, matz@suse.com, mliska@suse.cz, rguenther@suse.com, tonyj@suse.com
Found By ---
Blocker ---

+++ This bug was initially created as a clone of Bug #1180610 +++

There is a problem with *@plt symbols in some libraries, they are unresolved by
perf (memcmp@plt in this case):
>     0.26%  main2    /usr/lib64/libstdc++.so.6.0.28            0xa51a0            l [.] 0x00000000000a51a0

On the other hand, plt symbols in other libraries are fine (memset@plt in this
case):
>     0.17%  main2    /usr/lib64/libantlr4-runtime.so.4.8       0x4ed10            l [.] memset@plt

Dump of memcmp's nth .plt.rela entry:
/usr/lib64/libantlr4-runtime.so.4.8: 154th addr=4e9d0 plt_off=4e020 hdr=10
entry=10
/usr/lib64/libstdc++.so.6.0.28: 772th addr=a1070 plt_off=9e020 hdr=10 entry=10

The difference (offset) of stdc++'s memcmp is 0xa51a0 (correct) - 0xa1070
(perf's computed) = 0x4130.

The problem is perf assumes nth entry of .plt.rela to correspond to nth
function in .plt, but memcmp is in .plt.sec in libstdc++.so:

> Relocation section '.rela.plt' at offset 0x97900 contains 1018 entries:
>     Offset             Info             Type               Symbol's Value  Symbol's Name + Addend
> ...
> 00000000001dc838  0000007800000007 R_X86_64_JUMP_SLOT     0000000000000000 memcmp@GLIBC_2.2.5 + 0

See:
https://github.com/torvalds/linux/blob/f5e6c330254ae691f6d7befe61c786eb5056007e/tools/perf/util/symbol-elf.c#L385

It takes symbol index from sym.r_info. Then it resolves its name from .dynsym,
appending @plt to it. Then this name is added to symbol table along with
address which is computed as .rela.plt index multiplied by entry size
(shdr_plt.sh_entsize) plus plt header (shdr_plt.sh_entsize on x86_64 too).

And from this comes (almost) the offset above:
> $ objdump -h /usr/lib64/libstdc++.so.6|grep -E ' .plt(\.sec)? '
>  12 .plt          00003fb0  000000000009e020  000000000009e020  0009e020  2**4
>  14 .plt.sec      00003fa0  00000000000a2160  00000000000a2160  000a2160  2**4

0xa2160-0x9e020 = 0x4140. I assume the 0x10 difference is that perf adds
shdr_plt.sh_entsize (0x10) to the offset to skip the first .plt entry (header).

Now, what is .plt.sec? And how should perf find out whether to consider .plt or
.plt.sec? Or generally, how to properly find an address of *@plt like
memcmp@plt above?


You are receiving this mail because: