From: Adrian Hunter <adrian.hunter@intel.com>
To: Arnaldo Carvalho de Melo <acme@kernel.org>
Cc: Jiri Olsa <jolsa@redhat.com>, Namhyung Kim <namhyung@kernel.org>,
Ian Rogers <irogers@google.com>,
linux-kernel@vger.kernel.org, linux-perf-users@vger.kernel.org
Subject: [PATCH V2 5/9] perf symbols: Add support for IFUNC symbols for x86_64
Date: Tue, 31 Jan 2023 15:16:21 +0200 [thread overview]
Message-ID: <20230131131625.6964-6-adrian.hunter@intel.com> (raw)
In-Reply-To: <20230131131625.6964-1-adrian.hunter@intel.com>
For x86_64, the GNU linker is putting IFUNC information in the relocation
addend, so use it to try to find a symbol for plt entries that refer to
IFUNCs.
Example:
Before:
$ cat tstpltlib.c
void fn1(void) {}
void fn2(void) {}
void fn3(void) {}
void fn4(void) {}
$ cat tstpltifunc.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")));
void fn1(void);
void fn2(void);
void fn3(void);
void fn4(void);
int main()
{
fn4();
fn1();
thing();
fn2();
fn3();
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 -Wall -Wextra -shared -o libtstpltlib.so tstpltlib.c
$ gcc -Wall -Wextra -Wno-uninitialized -o tstpltifunc tstpltifunc.c -L . -ltstpltlib -Wl,-rpath="$(pwd)"
$ readelf -rW tstpltifunc | grep -A99 plt
Relocation section '.rela.plt' at offset 0x738 contains 8 entries:
Offset Info Type Symbol's Value Symbol's Name + Addend
0000000000003f98 0000000300000007 R_X86_64_JUMP_SLOT 0000000000000000 puts@GLIBC_2.2.5 + 0
0000000000003fa8 0000000400000007 R_X86_64_JUMP_SLOT 0000000000000000 __stack_chk_fail@GLIBC_2.4 + 0
0000000000003fb0 0000000500000007 R_X86_64_JUMP_SLOT 0000000000000000 fn1 + 0
0000000000003fb8 0000000600000007 R_X86_64_JUMP_SLOT 0000000000000000 fn3 + 0
0000000000003fc0 0000000800000007 R_X86_64_JUMP_SLOT 0000000000000000 fn4 + 0
0000000000003fc8 0000000900000007 R_X86_64_JUMP_SLOT 0000000000000000 fn2 + 0
0000000000003fd0 0000000b00000007 R_X86_64_JUMP_SLOT 0000000000000000 getrandom@GLIBC_2.25 + 0
0000000000003fa0 0000000000000025 R_X86_64_IRELATIVE 125d
$ perf record -e intel_pt//u --filter 'filter main @ ./tstpltifunc' ./tstpltifunc
thing2
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.016 MB perf.data ]
$ perf script --itrace=be --ns -F+flags,-event,+addr,-period,-comm,-tid,-cpu,-dso
21860.073683659: tr strt 0 [unknown] => 561e212c42be main+0x0
21860.073683659: tr end call 561e212c42c6 main+0x8 => 561e212c4110 fn4@plt+0x0
21860.073683661: tr strt 0 [unknown] => 561e212c42cb main+0xd
21860.073683661: tr end call 561e212c42cb main+0xd => 561e212c40f0 fn1@plt+0x0
21860.073683661: tr strt 0 [unknown] => 561e212c42d0 main+0x12
21860.073683661: tr end call 561e212c42d0 main+0x12 => 561e212c40d0 offset_0x10d0@plt+0x0
21860.073698451: tr strt 0 [unknown] => 561e212c42d5 main+0x17
21860.073698451: tr end call 561e212c42d5 main+0x17 => 561e212c4120 fn2@plt+0x0
21860.073698451: tr strt 0 [unknown] => 561e212c42da main+0x1c
21860.073698451: tr end call 561e212c42da main+0x1c => 561e212c4100 fn3@plt+0x0
21860.073698452: tr strt 0 [unknown] => 561e212c42df main+0x21
21860.073698452: tr end return 561e212c42e5 main+0x27 => 7fb51cc29d90 __libc_start_call_main+0x80
After:
$ perf script --itrace=be --ns -F+flags,-event,+addr,-period,-comm,-tid,-cpu,-dso
21860.073683659: tr strt 0 [unknown] => 561e212c42be main+0x0
21860.073683659: tr end call 561e212c42c6 main+0x8 => 561e212c4110 fn4@plt+0x0
21860.073683661: tr strt 0 [unknown] => 561e212c42cb main+0xd
21860.073683661: tr end call 561e212c42cb main+0xd => 561e212c40f0 fn1@plt+0x0
21860.073683661: tr strt 0 [unknown] => 561e212c42d0 main+0x12
21860.073683661: tr end call 561e212c42d0 main+0x12 => 561e212c40d0 thing_ifunc@plt+0x0
21860.073698451: tr strt 0 [unknown] => 561e212c42d5 main+0x17
21860.073698451: tr end call 561e212c42d5 main+0x17 => 561e212c4120 fn2@plt+0x0
21860.073698451: tr strt 0 [unknown] => 561e212c42da main+0x1c
21860.073698451: tr end call 561e212c42da main+0x1c => 561e212c4100 fn3@plt+0x0
21860.073698452: tr strt 0 [unknown] => 561e212c42df main+0x21
21860.073698452: tr end return 561e212c42e5 main+0x27 => 7fb51cc29d90 __libc_start_call_main+0x80
Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
---
tools/perf/util/symbol-elf.c | 38 +++++++++++++++++++++++++++++++++++-
1 file changed, 37 insertions(+), 1 deletion(-)
diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c
index 07cfcf8f40e3..a002fc0bea03 100644
--- a/tools/perf/util/symbol-elf.c
+++ b/tools/perf/util/symbol-elf.c
@@ -381,6 +381,42 @@ static int sort_rel(struct rel_info *ri)
return 0;
}
+/*
+ * For x86_64, the GNU linker is putting IFUNC information in the relocation
+ * addend.
+ */
+static bool addend_may_be_ifunc(GElf_Ehdr *ehdr, struct rel_info *ri)
+{
+ return ehdr->e_machine == EM_X86_64 && ri->is_rela &&
+ GELF_R_TYPE(ri->rela.r_info) == R_X86_64_IRELATIVE;
+}
+
+static bool get_ifunc_name(Elf *elf, struct dso *dso, GElf_Ehdr *ehdr,
+ struct rel_info *ri, char *buf, size_t buf_sz)
+{
+ u64 addr = ri->rela.r_addend;
+ struct symbol *sym;
+ GElf_Phdr phdr;
+
+ if (!addend_may_be_ifunc(ehdr, ri))
+ return false;
+
+ if (elf_read_program_header(elf, addr, &phdr))
+ return false;
+
+ addr -= phdr.p_vaddr - phdr.p_offset;
+
+ sym = dso__find_symbol_nocache(dso, addr);
+
+ /* Expecting the address to be an IFUNC or IFUNC alias */
+ if (!sym || sym->start != addr || (sym->type != STT_GNU_IFUNC && !sym->ifunc_alias))
+ return false;
+
+ snprintf(buf, buf_sz, "%s@plt", sym->name);
+
+ return true;
+}
+
static void exit_rel(struct rel_info *ri)
{
free(ri->sorted);
@@ -560,7 +596,7 @@ int dso__synthesize_plt_symbols(struct dso *dso, struct symsrc *ss)
elf_name = demangled;
if (*elf_name)
snprintf(sympltname, sizeof(sympltname), "%s@plt", elf_name);
- else
+ else if (!get_ifunc_name(elf, dso, &ehdr, &ri, sympltname, sizeof(sympltname)))
snprintf(sympltname, sizeof(sympltname),
"offset_%#" PRIx64 "@plt", plt_offset);
free(demangled);
--
2.34.1
next prev parent reply other threads:[~2023-01-31 13:16 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-01-31 13:16 [PATCH V2 0/9] perf symbols: Improve dso__synthesize_plt_symbols() for x86 Adrian Hunter
2023-01-31 13:16 ` [PATCH V2 1/9] perf symbols: Correct plt entry sizes " Adrian Hunter
2023-01-31 13:16 ` [PATCH V2 2/9] perf symbols: Add support for x86 .plt.sec Adrian Hunter
2023-01-31 13:16 ` [PATCH V2 3/9] perf symbols: Sort plt relocations for x86 Adrian Hunter
2023-01-31 13:16 ` [PATCH V2 4/9] perf symbols: Record whether a symbol is an alias for an IFUNC symbol Adrian Hunter
2023-01-31 13:16 ` Adrian Hunter [this message]
2023-01-31 13:16 ` [PATCH V2 6/9] perf symbols: Allow for .plt without header Adrian Hunter
2023-01-31 13:16 ` [PATCH V2 7/9] perf symbols: Allow for static executables with .plt Adrian Hunter
2023-01-31 13:16 ` [PATCH V2 8/9] perf symbols: Start adding support for .plt.got for x86 Adrian Hunter
2023-02-02 19:41 ` Arnaldo Carvalho de Melo
2023-01-31 13:16 ` [PATCH V2 9/9] perf symbols: Get symbols for .plt.got for x86-64 Adrian Hunter
2023-02-01 6:59 ` [PATCH V2 0/9] perf symbols: Improve dso__synthesize_plt_symbols() for x86 Namhyung Kim
2023-02-02 0:46 ` Arnaldo Carvalho de Melo
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20230131131625.6964-6-adrian.hunter@intel.com \
--to=adrian.hunter@intel.com \
--cc=acme@kernel.org \
--cc=irogers@google.com \
--cc=jolsa@redhat.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-perf-users@vger.kernel.org \
--cc=namhyung@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.