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?