mirror of
https://git.proxmox.com/git/mirror_ubuntu-kernels.git
synced 2025-12-30 14:06:39 +00:00
perf symbols: Allow for static executables with .plt
A statically linked executable can have a .plt due to IFUNCs, in which
case .symtab is used not .dynsym. Check the section header link to see
if that is the case, and then use symtab instead.
Example:
Before:
$ cat tstifunc.c
#include <stdio.h>
void thing1(void)
{
printf("thing1\n");
}
void thing2(void)
{
printf("thing2\n");
}
typedef void (*thing_fn_t)(void);
thing_fn_t thing_ifunc(void)
{
int x;
if (x & 1)
return thing2;
return thing1;
}
void thing(void) __attribute__ ((ifunc ("thing_ifunc")));
int main()
{
thing();
return 0;
}
$ gcc --version
gcc (Ubuntu 11.3.0-1ubuntu1~22.04) 11.3.0
Copyright (C) 2021 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
$ gcc -static -Wall -Wextra -Wno-uninitialized -o tstifuncstatic tstifunc.c
$ readelf -SW tstifuncstatic | grep 'Name\|plt\|dyn'
[Nr] Name Type Address Off Size ES Flg Lk Inf Al
[ 4] .rela.plt RELA 00000000004002e8 0002e8 000258 18 AI 29 20 8
[ 6] .plt PROGBITS 0000000000401020 001020 000190 00 AX 0 0 16
[20] .got.plt PROGBITS 00000000004c5000 0c4000 0000e0 08 WA 0 0 8
$ perf record -e intel_pt//u --filter 'filter main @ ./tstifuncstatic' ./tstifuncstatic
thing1
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.008 MB perf.data ]
$ perf script --itrace=be --ns -F+flags,-event,+addr,-period,-comm,-tid,-cpu,-dso
15786.690189535: tr strt 0 [unknown] => 4017cd main+0x0
15786.690189535: tr end call 4017d5 main+0x8 => 401170 [unknown]
15786.690197660: tr strt 0 [unknown] => 4017da main+0xd
15786.690197660: tr end return 4017e0 main+0x13 => 401c1a __libc_start_call_main+0x6a
After:
$ perf script --itrace=be --ns -F+flags,-event,+addr,-period,-comm,-tid,-cpu,-dso
15786.690189535: tr strt 0 [unknown] => 4017cd main+0x0
15786.690189535: tr end call 4017d5 main+0x8 => 401170 thing_ifunc@plt+0x0
15786.690197660: tr strt 0 [unknown] => 4017da main+0xd
15786.690197660: tr end return 4017e0 main+0x13 => 401c1a __libc_start_call_main+0x6a
Reviewed-by: Namhyung Kim <namhyung@kernel.org>
Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Cc: Ian Rogers <irogers@google.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Link: https://lore.kernel.org/r/20230131131625.6964-8-adrian.hunter@intel.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
parent
60fbb3e49a
commit
a1ab12856f
@ -483,7 +483,6 @@ int dso__synthesize_plt_symbols(struct dso *dso, struct symsrc *ss)
|
||||
GElf_Shdr shdr_rel_plt, shdr_dynsym;
|
||||
Elf_Data *syms, *symstrs;
|
||||
Elf_Scn *scn_plt_rel, *scn_symstrs, *scn_dynsym;
|
||||
size_t dynsym_idx;
|
||||
GElf_Ehdr ehdr;
|
||||
char sympltname[1024];
|
||||
Elf *elf;
|
||||
@ -530,13 +529,6 @@ int dso__synthesize_plt_symbols(struct dso *dso, struct symsrc *ss)
|
||||
lazy_plt = true;
|
||||
}
|
||||
|
||||
scn_dynsym = ss->dynsym;
|
||||
shdr_dynsym = ss->dynshdr;
|
||||
dynsym_idx = ss->dynsym_idx;
|
||||
|
||||
if (scn_dynsym == NULL)
|
||||
return 0;
|
||||
|
||||
scn_plt_rel = elf_section_by_name(elf, &ehdr, &shdr_rel_plt,
|
||||
".rela.plt", NULL);
|
||||
if (scn_plt_rel == NULL) {
|
||||
@ -550,8 +542,25 @@ int dso__synthesize_plt_symbols(struct dso *dso, struct symsrc *ss)
|
||||
shdr_rel_plt.sh_type != SHT_REL)
|
||||
return 0;
|
||||
|
||||
if (shdr_rel_plt.sh_link != dynsym_idx)
|
||||
if (!shdr_rel_plt.sh_link)
|
||||
return 0;
|
||||
|
||||
if (shdr_rel_plt.sh_link == ss->dynsym_idx) {
|
||||
scn_dynsym = ss->dynsym;
|
||||
shdr_dynsym = ss->dynshdr;
|
||||
} else if (shdr_rel_plt.sh_link == ss->symtab_idx) {
|
||||
/*
|
||||
* A static executable can have a .plt due to IFUNCs, in which
|
||||
* case .symtab is used not .dynsym.
|
||||
*/
|
||||
scn_dynsym = ss->symtab;
|
||||
shdr_dynsym = ss->symshdr;
|
||||
} else {
|
||||
goto out_elf_end;
|
||||
}
|
||||
|
||||
if (!scn_dynsym)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Fetch the relocation section to find the idxes to the GOT
|
||||
@ -1077,8 +1086,9 @@ int symsrc__init(struct symsrc *ss, struct dso *dso, const char *name,
|
||||
|
||||
ss->is_64_bit = (gelf_getclass(elf) == ELFCLASS64);
|
||||
|
||||
ss->symtab_idx = 0;
|
||||
ss->symtab = elf_section_by_name(elf, &ehdr, &ss->symshdr, ".symtab",
|
||||
NULL);
|
||||
&ss->symtab_idx);
|
||||
if (ss->symshdr.sh_type != SHT_SYMTAB)
|
||||
ss->symtab = NULL;
|
||||
|
||||
|
||||
@ -26,6 +26,7 @@ struct symsrc {
|
||||
GElf_Shdr opdshdr;
|
||||
|
||||
Elf_Scn *symtab;
|
||||
size_t symtab_idx;
|
||||
GElf_Shdr symshdr;
|
||||
|
||||
Elf_Scn *dynsym;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user