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