summaryrefslogtreecommitdiffstats
path: root/tools/perf
diff options
context:
space:
mode:
authorMasami Hiramatsu <mhiramat@kernel.org>2020-07-10 15:11:33 +0200
committerArnaldo Carvalho de Melo <acme@redhat.com>2020-07-17 14:09:47 +0200
commit3de2bf9dfb93be3db4f06968339a7b6da1091bb3 (patch)
tree15a98966a55342798f7278570d714b509cc86d84 /tools/perf
parentperf probe: Fix memory leakage when the probe point is not found (diff)
downloadlinux-3de2bf9dfb93be3db4f06968339a7b6da1091bb3.tar.xz
linux-3de2bf9dfb93be3db4f06968339a7b6da1091bb3.zip
perf probe: Warn if the target function is a GNU indirect function
Warn if the probe target function is a GNU indirect function (GNU_IFUNC) because it may not be what the user wants to probe. The GNU indirect function ( https://sourceware.org/glibc/wiki/GNU_IFUNC ) is the dynamic symbol solved at runtime. An IFUNC function is a selector which is invoked from the ELF loader, but the symbol address of the function which will be modified by the IFUNC is the same as the IFUNC in the symbol table. This can confuse users trying to probe such functions. For example, memcpy is an IFUNC. probe_libc:memcpy (on __new_memcpy_ifunc@x86_64/multiarch/memcpy.c in /usr/lib64/libc-2.30.so) the probe is put on an IFUNC. perf 1742 [000] 26201.715632: probe_libc:memcpy: (7fdaa53824c0) 7fdaa53824c0 __new_memcpy_ifunc+0x0 (inlined) 7fdaa5d4a980 elf_machine_rela+0x6c0 (inlined) 7fdaa5d4a980 elf_dynamic_do_Rela+0x6c0 (inlined) 7fdaa5d4a980 _dl_relocate_object+0x6c0 (/usr/lib64/ld-2.30.so) 7fdaa5d42155 dl_main+0x1cc5 (/usr/lib64/ld-2.30.so) 7fdaa5d5831a _dl_sysdep_start+0x54a (/usr/lib64/ld-2.30.so) 7fdaa5d3ffeb _dl_start_final+0x25b (inlined) 7fdaa5d3ffeb _dl_start+0x25b (/usr/lib64/ld-2.30.so) 7fdaa5d3f117 .annobin_rtld.c+0x7 (inlined) And the event is invoked from the ELF loader instead of the target program's main code. Moreover, at this moment, we can not probe on the function which will be selected by the IFUNC, because it is determined at runtime. But uprobe will be prepared before running the target binary. Thus, I decided to warn user when 'perf probe' detects that the probe point is on an GNU IFUNC symbol. Someone who wants to probe an IFUNC symbol to debug the IFUNC function can ignore this warning. Committer notes: I.e., this warning will be emitted if the probe point is an IFUNC: "Warning: The probe function (%s) is a GNU indirect function.\n" "Consider identifying the final function used at run time and set the probe directly on that.\n" Complete set of steps: # readelf -sW /lib64/libc-2.29.so | grep IFUNC | tail 22196: 0000000000109a80 183 IFUNC GLOBAL DEFAULT 14 __memcpy_chk 22214: 00000000000b7d90 191 IFUNC GLOBAL DEFAULT 14 __gettimeofday 22336: 000000000008b690 60 IFUNC GLOBAL DEFAULT 14 memchr 22350: 000000000008b9b0 89 IFUNC GLOBAL DEFAULT 14 __stpcpy 22420: 000000000008bb10 76 IFUNC GLOBAL DEFAULT 14 __strcasecmp_l 22582: 000000000008a970 60 IFUNC GLOBAL DEFAULT 14 strlen 22585: 00000000000a54d0 92 IFUNC WEAK DEFAULT 14 wmemset 22600: 000000000010b030 92 IFUNC GLOBAL DEFAULT 14 __wmemset_chk 22618: 000000000008b8a0 183 IFUNC GLOBAL DEFAULT 14 __mempcpy 22675: 000000000008ba70 76 IFUNC WEAK DEFAULT 14 strcasecmp # # perf probe -x /lib64/libc-2.29.so strlen Warning: The probe function (strlen) is a GNU indirect function. Consider identifying the final function used at run time and set the probe directly on that. Added new event: probe_libc:strlen (on strlen in /usr/lib64/libc-2.29.so) You can now use it in all perf tools, such as: perf record -e probe_libc:strlen -aR sleep 1 # Reported-by: Andi Kleen <andi@firstfloor.org> Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org> Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Andi Kleen <ak@linux.intel.com> Cc: Oleg Nesterov <oleg@redhat.com> Cc: Srikar Dronamraju <srikar@linux.vnet.ibm.com> Link: http://lore.kernel.org/lkml/159438669349.62703.5978345670436126948.stgit@devnote2 Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf')
-rw-r--r--tools/perf/util/probe-event.c8
1 files changed, 6 insertions, 2 deletions
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index 4316348961c4..99d36ac77c08 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -375,9 +375,13 @@ static int find_alternative_probe_point(struct debuginfo *dinfo,
/* Find the address of given function */
map__for_each_symbol_by_name(map, pp->function, sym) {
- if (uprobes)
+ if (uprobes) {
address = sym->start;
- else
+ if (sym->type == STT_GNU_IFUNC)
+ pr_warning("Warning: The probe function (%s) is a GNU indirect function.\n"
+ "Consider identifying the final function used at run time and set the probe directly on that.\n",
+ pp->function);
+ } else
address = map->unmap_ip(map, sym->start) - map->reloc;
break;
}