From nobody Sat Sep 13 18:42:52 2025 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 5CE1AC636D4 for ; Tue, 31 Jan 2023 13:16:46 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231480AbjAaNQp (ORCPT ); Tue, 31 Jan 2023 08:16:45 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53366 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230008AbjAaNQn (ORCPT ); Tue, 31 Jan 2023 08:16:43 -0500 Received: from mga11.intel.com (mga11.intel.com [192.55.52.93]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 0F6B110C9; Tue, 31 Jan 2023 05:16:41 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1675171001; x=1706707001; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=bDKkyRtHwSFPxVEw6hcGJuHrCfS3E8nNGIlQ35mRFSA=; b=VLi80FMgmSaNNzfdEZPaax8C2iOYBp715qh3DrEhO66yT40bLrzDWnMO JDTj/AN3HVIjRdn1YKQg5E8A//sM8RlmKKRDOTpFyIs30RBmUclsQVB80 h4VS8AF111BZ0qjhyamUk/U9n/29jYuvjSm1Vd3SyQIngti/GyvaJnbtG aCBMjphhVqyxrJKR12IwZmNZ208J9E0h4d0UtUyMYOUtWQy8Xl2x30rBm xfQpNOH11e+BTBGhldUEy2LSWXDPciLGt1b8ZO1slegLioecedSt6wgHy sLQjE54h2mn/yzAQgOZeVHynPmU7DxDax4B8rqFY2abKK9EqTR7WS+d+W g==; X-IronPort-AV: E=McAfee;i="6500,9779,10606"; a="325534141" X-IronPort-AV: E=Sophos;i="5.97,261,1669104000"; d="scan'208";a="325534141" Received: from orsmga007.jf.intel.com ([10.7.209.58]) by fmsmga102.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 31 Jan 2023 05:16:40 -0800 X-IronPort-AV: E=McAfee;i="6500,9779,10606"; a="657864791" X-IronPort-AV: E=Sophos;i="5.97,261,1669104000"; d="scan'208";a="657864791" Received: from ahunter6-mobl1.ger.corp.intel.com (HELO ahunter-VirtualBox.home\044ger.corp.intel.com) ([10.252.47.218]) by orsmga007-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 31 Jan 2023 05:16:38 -0800 From: Adrian Hunter To: Arnaldo Carvalho de Melo Cc: Jiri Olsa , Namhyung Kim , Ian Rogers , linux-kernel@vger.kernel.org, linux-perf-users@vger.kernel.org Subject: [PATCH V2 1/9] perf symbols: Correct plt entry sizes for x86 Date: Tue, 31 Jan 2023 15:16:17 +0200 Message-Id: <20230131131625.6964-2-adrian.hunter@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230131131625.6964-1-adrian.hunter@intel.com> References: <20230131131625.6964-1-adrian.hunter@intel.com> MIME-Version: 1.0 Organization: Intel Finland Oy, Registered Address: PL 281, 00181 Helsinki, Business Identity Code: 0357606 - 4, Domiciled in Helsinki Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" In 32-bit executables the .plt entry size can be set to 4 when it is really 16. In fact the only sizes used for x86 (32 or 64 bit) are 8 or 16, so check for those and, if not, use the alignment to choose which it is. Example on Ubuntu 22.04 gcc 11.3: Before: $ cat tstpltlib.c void fn1(void) {} void fn2(void) {} void fn3(void) {} void fn4(void) {} $ cat tstplt.c void fn1(void); void fn2(void); void fn3(void); void fn4(void); int main() { fn4(); fn1(); 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 PURP= OSE. $ gcc -m32 -Wall -Wextra -shared -o libtstpltlib32.so tstpltlib.c $ gcc -m32 -Wall -Wextra -o tstplt32 tstplt.c -L . -ltstpltlib32 -Wl,-r= path=3D$(pwd) $ perf record -e intel_pt//u --filter 'filter main @ ./tstplt32' ./tstp= lt32 [ perf record: Woken up 1 times to write data ] [ perf record: Captured and wrote 0.011 MB perf.data ] $ readelf -SW tstplt32 | grep 'plt\|Name' [Nr] Name Type Addr Off Size ES Flg = Lk Inf Al [10] .rel.plt REL 0000041c 00041c 000028 08 AI = 5 22 4 [12] .plt PROGBITS 00001030 001030 000060 04 AX = 0 0 16 <- ES is 0x04, should be 0x10 [13] .plt.got PROGBITS 00001090 001090 000008 08 AX = 0 0 8 $ perf script --itrace=3Dbe --ns -F+flags,-event,+addr,-period,-comm,-t= id,-cpu,-dso 17894.383903029: tr strt 0 [unknown] = =3D> 565b81cd main+0x0 17894.383903029: tr end call 565b81d4 main+0x7 =3D= > 565b80d0 __x86.get_pc_thunk.bx+0x0 17894.383903031: tr strt 0 [unknown] = =3D> 565b81d9 main+0xc 17894.383903031: tr end call 565b81df main+0x12 = =3D> 565b8070 [unknown] 17894.383903032: tr strt 0 [unknown] = =3D> 565b81e4 main+0x17 17894.383903032: tr end call 565b81e4 main+0x17 = =3D> 565b8050 [unknown] 17894.383903033: tr strt 0 [unknown] = =3D> 565b81e9 main+0x1c 17894.383903033: tr end call 565b81e9 main+0x1c = =3D> 565b8080 [unknown] 17894.383903033: tr strt 0 [unknown] = =3D> 565b81ee main+0x21 17894.383903033: tr end call 565b81ee main+0x21 = =3D> 565b8060 [unknown] 17894.383903237: tr strt 0 [unknown] = =3D> 565b81f3 main+0x26 17894.383903237: tr end return 565b81fc main+0x2f = =3D> f7c21519 [unknown] After: $ perf script --itrace=3Dbe --ns -F+flags,-event,+addr,-period,-comm,-t= id,-cpu,-dso 17894.383903029: tr strt 0 [unknown] = =3D> 565b81cd main+0x0 17894.383903029: tr end call 565b81d4 main+0x7 =3D= > 565b80d0 __x86.get_pc_thunk.bx+0x0 17894.383903031: tr strt 0 [unknown] = =3D> 565b81d9 main+0xc 17894.383903031: tr end call 565b81df main+0x12 = =3D> 565b8070 fn4@plt+0x0 17894.383903032: tr strt 0 [unknown] = =3D> 565b81e4 main+0x17 17894.383903032: tr end call 565b81e4 main+0x17 = =3D> 565b8050 fn1@plt+0x0 17894.383903033: tr strt 0 [unknown] = =3D> 565b81e9 main+0x1c 17894.383903033: tr end call 565b81e9 main+0x1c = =3D> 565b8080 fn2@plt+0x0 17894.383903033: tr strt 0 [unknown] = =3D> 565b81ee main+0x21 17894.383903033: tr end call 565b81ee main+0x21 = =3D> 565b8060 fn3@plt+0x0 17894.383903237: tr strt 0 [unknown] = =3D> 565b81f3 main+0x26 17894.383903237: tr end return 565b81fc main+0x2f = =3D> f7c21519 [unknown] Signed-off-by: Adrian Hunter Reviewed-by: Namhyung Kim --- tools/perf/util/symbol-elf.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c index aa62735aea7b..9328c162d68f 100644 --- a/tools/perf/util/symbol-elf.c +++ b/tools/perf/util/symbol-elf.c @@ -360,14 +360,23 @@ static bool get_plt_sizes(struct dso *dso, GElf_Ehdr = *ehdr, GElf_Shdr *shdr_plt, *plt_header_size =3D 128; *plt_entry_size =3D 32; return true; + case EM_386: + case EM_X86_64: + *plt_entry_size =3D shdr_plt->sh_entsize; + /* Size is 8 or 16, if not, assume alignment indicates size */ + if (*plt_entry_size !=3D 8 && *plt_entry_size !=3D 16) + *plt_entry_size =3D shdr_plt->sh_addralign =3D=3D 8 ? 8 : 16; + *plt_header_size =3D *plt_entry_size; + break; default: /* FIXME: s390/alpha/mips/parisc/poperpc/sh/xtensa need to be ch= ecked */ *plt_header_size =3D shdr_plt->sh_entsize; *plt_entry_size =3D shdr_plt->sh_entsize; - if (*plt_entry_size) - return true; - pr_debug("Missing PLT entry size for %s\n", dso->long_name); - return false; + break; } + if (*plt_entry_size) + return true; + pr_debug("Missing PLT entry size for %s\n", dso->long_name); + return false; } =20 /* --=20 2.34.1 From nobody Sat Sep 13 18:42:52 2025 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 06833C636D3 for ; Tue, 31 Jan 2023 13:16:50 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230076AbjAaNQs (ORCPT ); Tue, 31 Jan 2023 08:16:48 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53414 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231407AbjAaNQo (ORCPT ); Tue, 31 Jan 2023 08:16:44 -0500 Received: from mga11.intel.com (mga11.intel.com [192.55.52.93]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 6EFFC2D4D; Tue, 31 Jan 2023 05:16:43 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1675171003; x=1706707003; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=EaD2lkLbiSUPIvN7w5iSQEWoS+/2QEnz2PV2lI9JMV8=; b=JCd0m3Vx/ANxHc1y8ubVgrCHU6eBZBlWpeM6qSJgLZLm71f0fNN4tOE4 QA4zR714uglyLZtPMMrsE7giEb3rbyDpi7sU1hLp/RhloZond35FmroIM 5Y5kK3avtILDw2WvRw3d33frOc15qnQnKJqFF+wFTgKAXE0vUazOzzFq5 IjNirywNyYBd6QNKX7J+Vrqb3QEl9CmUCPK9GAw9IORwtEWEcVKS+M/oa a7RbE7VrCfDHzKjruZXCqkrqAlkb3I2YMdivUkBjvEVkN9TaFxI/Y7Xdj Q6iGlqBfm/MXFs2kcqBlxayLWQvRsq44rLbYbGYV+sFc5HNJ8EAGgggMd A==; X-IronPort-AV: E=McAfee;i="6500,9779,10606"; a="325534148" X-IronPort-AV: E=Sophos;i="5.97,261,1669104000"; d="scan'208";a="325534148" Received: from orsmga007.jf.intel.com ([10.7.209.58]) by fmsmga102.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 31 Jan 2023 05:16:43 -0800 X-IronPort-AV: E=McAfee;i="6500,9779,10606"; a="657864800" X-IronPort-AV: E=Sophos;i="5.97,261,1669104000"; d="scan'208";a="657864800" Received: from ahunter6-mobl1.ger.corp.intel.com (HELO ahunter-VirtualBox.home\044ger.corp.intel.com) ([10.252.47.218]) by orsmga007-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 31 Jan 2023 05:16:40 -0800 From: Adrian Hunter To: Arnaldo Carvalho de Melo Cc: Jiri Olsa , Namhyung Kim , Ian Rogers , linux-kernel@vger.kernel.org, linux-perf-users@vger.kernel.org Subject: [PATCH V2 2/9] perf symbols: Add support for x86 .plt.sec Date: Tue, 31 Jan 2023 15:16:18 +0200 Message-Id: <20230131131625.6964-3-adrian.hunter@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230131131625.6964-1-adrian.hunter@intel.com> References: <20230131131625.6964-1-adrian.hunter@intel.com> MIME-Version: 1.0 Organization: Intel Finland Oy, Registered Address: PL 281, 00181 Helsinki, Business Identity Code: 0357606 - 4, Domiciled in Helsinki Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" The section .plt.sec was originally added for MPX and was first called .plt.bnd. While MPX has been deprecated, .plt.sec is now also used for IBT. On x86_64, IBT may be enabled by default, but can be switched off using gcc option -fcf-protection=3Dnone, or switched on by -z ibt or -z ibtplt. On 32-bit, option -z ibt or -z ibtplt will enable IBT. With .plt.sec, calls are made into .plt.sec instead of .plt, so it makes more sense to put the symbols there instead of .plt. A notable difference is that .plt.sec does not have a header entry. For x86, when synthesizing symbols for plt, use offset and entry size of .plt.sec instead of .plt when there is a .plt.sec section. Example on Ubuntu 22.04 gcc 11.3: Before: $ cat tstpltlib.c void fn1(void) {} void fn2(void) {} void fn3(void) {} void fn4(void) {} $ cat tstplt.c void fn1(void); void fn2(void); void fn3(void); void fn4(void); int main() { fn4(); fn1(); 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 PURP= OSE. $ gcc -Wall -Wextra -shared -o libtstpltlib.so tstpltlib.c $ gcc -Wall -Wextra -z ibt -o tstplt tstplt.c -L . -ltstpltlib -Wl,-rpa= th=3D$(pwd) $ readelf -SW tstplt | grep 'plt\|Name' [Nr] Name Type Address Off Size = ES Flg Lk Inf Al [11] .rela.plt RELA 0000000000000698 000698 000060= 18 AI 6 24 8 [13] .plt PROGBITS 0000000000001020 001020 000050= 10 AX 0 0 16 [14] .plt.got PROGBITS 0000000000001070 001070 000010= 10 AX 0 0 16 [15] .plt.sec PROGBITS 0000000000001080 001080 000040= 10 AX 0 0 16 $ perf record -e intel_pt//u --filter 'filter main @ ./tstplt' ./tstplt [ perf record: Woken up 1 times to write data ] [ perf record: Captured and wrote 0.015 MB perf.data ] $ perf script --itrace=3Dbe --ns -F+flags,-event,+addr,-period,-comm,-t= id,-cpu,-dso 38970.522546686: tr strt 0 [unknown] = =3D> 55fc222a81a9 main+0x0 38970.522546686: tr end call 55fc222a81b1 main+0x8 =3D= > 55fc222a80a0 [unknown] 38970.522546687: tr strt 0 [unknown] = =3D> 55fc222a81b6 main+0xd 38970.522546687: tr end call 55fc222a81b6 main+0xd =3D= > 55fc222a8080 [unknown] 38970.522546688: tr strt 0 [unknown] = =3D> 55fc222a81bb main+0x12 38970.522546688: tr end call 55fc222a81bb main+0x12 = =3D> 55fc222a80b0 [unknown] 38970.522546688: tr strt 0 [unknown] = =3D> 55fc222a81c0 main+0x17 38970.522546688: tr end call 55fc222a81c0 main+0x17 = =3D> 55fc222a8090 [unknown] 38970.522546689: tr strt 0 [unknown] = =3D> 55fc222a81c5 main+0x1c 38970.522546894: tr end return 55fc222a81cb main+0x22 = =3D> 7f3a4dc29d90 __libc_start_call_main+0x80 After: $ perf script --itrace=3Dbe --ns -F+flags,-event,+addr,-period,-comm,-t= id,-cpu,-dso 38970.522546686: tr strt 0 [unknown] = =3D> 55fc222a81a9 main+0x0 38970.522546686: tr end call 55fc222a81b1 main+0x8 =3D= > 55fc222a80a0 fn4@plt+0x0 38970.522546687: tr strt 0 [unknown] = =3D> 55fc222a81b6 main+0xd 38970.522546687: tr end call 55fc222a81b6 main+0xd =3D= > 55fc222a8080 fn1@plt+0x0 38970.522546688: tr strt 0 [unknown] = =3D> 55fc222a81bb main+0x12 38970.522546688: tr end call 55fc222a81bb main+0x12 = =3D> 55fc222a80b0 fn2@plt+0x0 38970.522546688: tr strt 0 [unknown] = =3D> 55fc222a81c0 main+0x17 38970.522546688: tr end call 55fc222a81c0 main+0x17 = =3D> 55fc222a8090 fn3@plt+0x0 38970.522546689: tr strt 0 [unknown] = =3D> 55fc222a81c5 main+0x1c 38970.522546894: tr end return 55fc222a81cb main+0x22 = =3D> 7f3a4dc29d90 __libc_start_call_main+0x80 Signed-off-by: Adrian Hunter Reviewed-by: Namhyung Kim --- tools/perf/util/symbol-elf.c | 30 +++++++++++++++++++++++------- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c index 9328c162d68f..bb1b5cb3ff12 100644 --- a/tools/perf/util/symbol-elf.c +++ b/tools/perf/util/symbol-elf.c @@ -379,6 +379,11 @@ static bool get_plt_sizes(struct dso *dso, GElf_Ehdr *= ehdr, GElf_Shdr *shdr_plt, return false; } =20 +static bool machine_is_x86(GElf_Half e_machine) +{ + return e_machine =3D=3D EM_386 || e_machine =3D=3D EM_X86_64; +} + /* * We need to check if we have a .dynsym, so that we can handle the * .plt, synthesizing its symbols, that aren't on the symtabs (be it @@ -391,8 +396,8 @@ int dso__synthesize_plt_symbols(struct dso *dso, struct= symsrc *ss) uint32_t nr_rel_entries, idx; GElf_Sym sym; u64 plt_offset, plt_header_size, plt_entry_size; - GElf_Shdr shdr_plt; - struct symbol *f; + GElf_Shdr shdr_plt, plt_sec_shdr; + struct symbol *f, *plt_sym; GElf_Shdr shdr_rel_plt, shdr_dynsym; Elf_Data *syms, *symstrs; Elf_Scn *scn_plt_rel, *scn_symstrs, *scn_dynsym; @@ -422,10 +427,23 @@ int dso__synthesize_plt_symbols(struct dso *dso, stru= ct symsrc *ss) return 0; =20 /* Add a symbol for .plt header */ - f =3D symbol__new(shdr_plt.sh_offset, plt_header_size, STB_GLOBAL, STT_FU= NC, ".plt"); - if (!f) + plt_sym =3D symbol__new(shdr_plt.sh_offset, plt_header_size, STB_GLOBAL, = STT_FUNC, ".plt"); + if (!plt_sym) goto out_elf_end; - symbols__insert(&dso->symbols, f); + symbols__insert(&dso->symbols, plt_sym); + + /* Only x86 has .plt.sec */ + if (machine_is_x86(ehdr.e_machine) && + elf_section_by_name(elf, &ehdr, &plt_sec_shdr, ".plt.sec", NULL)) { + if (!get_plt_sizes(dso, &ehdr, &plt_sec_shdr, &plt_header_size, &plt_ent= ry_size)) + return 0; + /* Extend .plt symbol to entire .plt */ + plt_sym->end =3D plt_sym->start + shdr_plt.sh_size; + /* Use .plt.sec offset */ + plt_offset =3D plt_sec_shdr.sh_offset; + } else { + plt_offset =3D shdr_plt.sh_offset + plt_header_size; + } =20 scn_dynsym =3D ss->dynsym; shdr_dynsym =3D ss->dynshdr; @@ -474,8 +492,6 @@ int dso__synthesize_plt_symbols(struct dso *dso, struct= symsrc *ss) goto out_elf_end; =20 nr_rel_entries =3D shdr_rel_plt.sh_size / shdr_rel_plt.sh_entsize; - plt_offset =3D shdr_plt.sh_offset; - plt_offset +=3D plt_header_size; =20 ri.is_rela =3D shdr_rel_plt.sh_type =3D=3D SHT_RELA; =20 --=20 2.34.1 From nobody Sat Sep 13 18:42:52 2025 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 32C96C38142 for ; Tue, 31 Jan 2023 13:16:53 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231714AbjAaNQv (ORCPT ); Tue, 31 Jan 2023 08:16:51 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53464 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231527AbjAaNQr (ORCPT ); Tue, 31 Jan 2023 08:16:47 -0500 Received: from mga11.intel.com (mga11.intel.com [192.55.52.93]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D24691AF; Tue, 31 Jan 2023 05:16:45 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1675171005; x=1706707005; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=MSYyxIYpIcGvKGW9ILNeoVixG2YK5UrzbYtuW8oYj7s=; b=HNE4221oBCciKgKpAxUxvevqE9wPdnVdKzaThSZwUduXSVMgBd+lTc6R va+ozpL/s58Q7hRP2dHhgGwBmZx1zGu8kt41Sb1vrdPP7qbkG429TU0jC v61LadzRlN+97FTTc/VE8NFHhcAJpnCdwRonoLHi3lFr59VIZ0ftBsTJb +KrXYKVyG6N8I1OM1nxX45Dy52B4APQEesSueyuw9ur8CWVEJnCIKVfXr P+tZivxTaKYZcuWte/EmDTMwkSWnItFzykeIktKVYfbm/Xoiwm7uDgtfZ j1l4kooHANTvm+WfWZ5AsS2d3Vhm0MWMMgZ6YDBvcM4eanrm77tLHGFe6 g==; X-IronPort-AV: E=McAfee;i="6500,9779,10606"; a="325534157" X-IronPort-AV: E=Sophos;i="5.97,261,1669104000"; d="scan'208";a="325534157" Received: from orsmga007.jf.intel.com ([10.7.209.58]) by fmsmga102.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 31 Jan 2023 05:16:45 -0800 X-IronPort-AV: E=McAfee;i="6500,9779,10606"; a="657864807" X-IronPort-AV: E=Sophos;i="5.97,261,1669104000"; d="scan'208";a="657864807" Received: from ahunter6-mobl1.ger.corp.intel.com (HELO ahunter-VirtualBox.home\044ger.corp.intel.com) ([10.252.47.218]) by orsmga007-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 31 Jan 2023 05:16:43 -0800 From: Adrian Hunter To: Arnaldo Carvalho de Melo Cc: Jiri Olsa , Namhyung Kim , Ian Rogers , linux-kernel@vger.kernel.org, linux-perf-users@vger.kernel.org Subject: [PATCH V2 3/9] perf symbols: Sort plt relocations for x86 Date: Tue, 31 Jan 2023 15:16:19 +0200 Message-Id: <20230131131625.6964-4-adrian.hunter@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230131131625.6964-1-adrian.hunter@intel.com> References: <20230131131625.6964-1-adrian.hunter@intel.com> MIME-Version: 1.0 Organization: Intel Finland Oy, Registered Address: PL 281, 00181 Helsinki, Business Identity Code: 0357606 - 4, Domiciled in Helsinki Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" For x86, with the addition of IFUNCs, relocation information becomes disordered with respect to plt. Correct that by sorting the relocations by offset. Example: Before: $ cat tstpltlib.c void fn1(void) {} void fn2(void) {} void fn3(void) {} void fn4(void) {} $ cat tstpltifunc.c #include 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 PURP= OSE. $ gcc -Wall -Wextra -shared -o libtstpltlib.so tstpltlib.c $ gcc -Wall -Wextra -Wno-uninitialized -o tstpltifunc tstpltifunc.c -L = . -ltstpltlib -Wl,-rpath=3D"$(pwd)" $ readelf -rW tstpltifunc | grep -A99 plt Relocation section '.rela.plt' at offset 0x738 contains 8 entries: Offset Info Type Symbol's Val= ue Symbol's Name + Addend 0000000000003f98 0000000300000007 R_X86_64_JUMP_SLOT 0000000000000= 000 puts@GLIBC_2.2.5 + 0 0000000000003fa8 0000000400000007 R_X86_64_JUMP_SLOT 0000000000000= 000 __stack_chk_fail@GLIBC_2.4 + 0 0000000000003fb0 0000000500000007 R_X86_64_JUMP_SLOT 0000000000000= 000 fn1 + 0 0000000000003fb8 0000000600000007 R_X86_64_JUMP_SLOT 0000000000000= 000 fn3 + 0 0000000000003fc0 0000000800000007 R_X86_64_JUMP_SLOT 0000000000000= 000 fn4 + 0 0000000000003fc8 0000000900000007 R_X86_64_JUMP_SLOT 0000000000000= 000 fn2 + 0 0000000000003fd0 0000000b00000007 R_X86_64_JUMP_SLOT 0000000000000= 000 getrandom@GLIBC_2.25 + 0 0000000000003fa0 0000000000000025 R_X86_64_IRELATIVE = 125d $ perf record -e intel_pt//u --filter 'filter main @ ./tstpltifunc' ./t= stpltifunc thing2 [ perf record: Woken up 1 times to write data ] [ perf record: Captured and wrote 0.029 MB perf.data ] $ perf script --itrace=3Dbe --ns -F+flags,-event,+addr,-period,-comm,-t= id,-cpu,-dso 20417.302513948: tr strt 0 [unknown] = =3D> 5629a74892be main+0x0 20417.302513948: tr end call 5629a74892c6 main+0x8 =3D= > 5629a7489110 fn2@plt+0x0 20417.302513949: tr strt 0 [unknown] = =3D> 5629a74892cb main+0xd 20417.302513949: tr end call 5629a74892cb main+0xd =3D= > 5629a74890f0 fn3@plt+0x0 20417.302513950: tr strt 0 [unknown] = =3D> 5629a74892d0 main+0x12 20417.302513950: tr end call 5629a74892d0 main+0x12 = =3D> 5629a74890d0 __stack_chk_fail@plt+0x0 20417.302528114: tr strt 0 [unknown] = =3D> 5629a74892d5 main+0x17 20417.302528114: tr end call 5629a74892d5 main+0x17 = =3D> 5629a7489120 getrandom@plt+0x0 20417.302528115: tr strt 0 [unknown] = =3D> 5629a74892da main+0x1c 20417.302528115: tr end call 5629a74892da main+0x1c = =3D> 5629a7489100 fn4@plt+0x0 20417.302528115: tr strt 0 [unknown] = =3D> 5629a74892df main+0x21 20417.302528115: tr end return 5629a74892e5 main+0x27 = =3D> 7ff14da29d90 __libc_start_call_main+0x80 After: $ perf script --itrace=3Dbe --ns -F+flags,-event,+addr,-period,-comm,-t= id,-cpu,-dso 20417.302513948: tr strt 0 [unknown] = =3D> 5629a74892be main+0x0 20417.302513948: tr end call 5629a74892c6 main+0x8 =3D= > 5629a7489110 fn4@plt+0x0 20417.302513949: tr strt 0 [unknown] = =3D> 5629a74892cb main+0xd 20417.302513949: tr end call 5629a74892cb main+0xd =3D= > 5629a74890f0 fn1@plt+0x0 20417.302513950: tr strt 0 [unknown] = =3D> 5629a74892d0 main+0x12 20417.302513950: tr end call 5629a74892d0 main+0x12 = =3D> 5629a74890d0 offset_0x10d0@plt+0x0 20417.302528114: tr strt 0 [unknown] = =3D> 5629a74892d5 main+0x17 20417.302528114: tr end call 5629a74892d5 main+0x17 = =3D> 5629a7489120 fn2@plt+0x0 20417.302528115: tr strt 0 [unknown] = =3D> 5629a74892da main+0x1c 20417.302528115: tr end call 5629a74892da main+0x1c = =3D> 5629a7489100 fn3@plt+0x0 20417.302528115: tr strt 0 [unknown] = =3D> 5629a74892df main+0x21 20417.302528115: tr end return 5629a74892e5 main+0x27 = =3D> 7ff14da29d90 __libc_start_call_main+0x80 Signed-off-by: Adrian Hunter Reviewed-by: Namhyung Kim --- tools/perf/util/symbol-elf.c | 60 ++++++++++++++++++++++++++++++++++-- 1 file changed, 57 insertions(+), 3 deletions(-) diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c index bb1b5cb3ff12..07cfcf8f40e3 100644 --- a/tools/perf/util/symbol-elf.c +++ b/tools/perf/util/symbol-elf.c @@ -324,6 +324,8 @@ static char *demangle_sym(struct dso *dso, int kmodule,= const char *elf_name) } =20 struct rel_info { + u32 nr_entries; + u32 *sorted; bool is_rela; Elf_Data *reldata; GElf_Rela rela; @@ -332,6 +334,7 @@ struct rel_info { =20 static u32 get_rel_symidx(struct rel_info *ri, u32 idx) { + idx =3D ri->sorted ? ri->sorted[idx] : idx; if (ri->is_rela) { gelf_getrela(ri->reldata, idx, &ri->rela); return GELF_R_SYM(ri->rela.r_info); @@ -340,6 +343,49 @@ static u32 get_rel_symidx(struct rel_info *ri, u32 idx) return GELF_R_SYM(ri->rel.r_info); } =20 +static u64 get_rel_offset(struct rel_info *ri, u32 x) +{ + if (ri->is_rela) { + GElf_Rela rela; + + gelf_getrela(ri->reldata, x, &rela); + return rela.r_offset; + } else { + GElf_Rel rel; + + gelf_getrel(ri->reldata, x, &rel); + return rel.r_offset; + } +} + +static int rel_cmp(const void *a, const void *b, void *r) +{ + struct rel_info *ri =3D r; + u64 a_offset =3D get_rel_offset(ri, *(const u32 *)a); + u64 b_offset =3D get_rel_offset(ri, *(const u32 *)b); + + return a_offset < b_offset ? -1 : (a_offset > b_offset ? 1 : 0); +} + +static int sort_rel(struct rel_info *ri) +{ + size_t sz =3D sizeof(ri->sorted[0]); + u32 i; + + ri->sorted =3D calloc(ri->nr_entries, sz); + if (!ri->sorted) + return -1; + for (i =3D 0; i < ri->nr_entries; i++) + ri->sorted[i] =3D i; + qsort_r(ri->sorted, ri->nr_entries, sz, rel_cmp, ri); + return 0; +} + +static void exit_rel(struct rel_info *ri) +{ + free(ri->sorted); +} + static bool get_plt_sizes(struct dso *dso, GElf_Ehdr *ehdr, GElf_Shdr *shd= r_plt, u64 *plt_header_size, u64 *plt_entry_size) { @@ -393,7 +439,7 @@ static bool machine_is_x86(GElf_Half e_machine) */ int dso__synthesize_plt_symbols(struct dso *dso, struct symsrc *ss) { - uint32_t nr_rel_entries, idx; + uint32_t idx; GElf_Sym sym; u64 plt_offset, plt_header_size, plt_entry_size; GElf_Shdr shdr_plt, plt_sec_shdr; @@ -491,11 +537,18 @@ int dso__synthesize_plt_symbols(struct dso *dso, stru= ct symsrc *ss) if (symstrs->d_size =3D=3D 0) goto out_elf_end; =20 - nr_rel_entries =3D shdr_rel_plt.sh_size / shdr_rel_plt.sh_entsize; + ri.nr_entries =3D shdr_rel_plt.sh_size / shdr_rel_plt.sh_entsize; =20 ri.is_rela =3D shdr_rel_plt.sh_type =3D=3D SHT_RELA; =20 - for (idx =3D 0; idx < nr_rel_entries; idx++) { + /* + * x86 doesn't insert IFUNC relocations in .plt order, so sort to get + * back in order. + */ + if (machine_is_x86(ehdr.e_machine) && sort_rel(&ri)) + goto out_elf_end; + + for (idx =3D 0; idx < ri.nr_entries; idx++) { const char *elf_name =3D NULL; char *demangled =3D NULL; =20 @@ -523,6 +576,7 @@ int dso__synthesize_plt_symbols(struct dso *dso, struct= symsrc *ss) =20 err =3D 0; out_elf_end: + exit_rel(&ri); if (err =3D=3D 0) return nr; pr_debug("%s: problems reading %s PLT info.\n", --=20 2.34.1 From nobody Sat Sep 13 18:42:52 2025 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 4BB66C636CC for ; Tue, 31 Jan 2023 13:16:56 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231786AbjAaNQy (ORCPT ); Tue, 31 Jan 2023 08:16:54 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53526 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230136AbjAaNQt (ORCPT ); Tue, 31 Jan 2023 08:16:49 -0500 Received: from mga11.intel.com (mga11.intel.com [192.55.52.93]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 49A753401A; Tue, 31 Jan 2023 05:16:48 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1675171008; x=1706707008; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=PgoaMa5uG1on8jbmDVSgzzslCJYjltgwG8UjBjeDNrE=; b=h4K8YnoI+cdSsw9JmRrEGtkP7mLHgsKsWBl9fogKRN67MI/+uv6fJTIX 7mkLtKsVCcWWf8a46vPRz7ipgO5xgCHBqHKEU0wXTz0QDK9w0yv4O1xgN HSNBjj8AhLr+PtHdUbrRNvrr8+FN9lO1HyNQQDLg0eph5U1CiAzIceVmg WeUPo0PNkGgd2vhImCEf8xYupvmLKp6aOQrbXbbwOLGPtDDSirAlU38cr r5BK2WTiyssxb2rh1MGO2pXm4zfF3nsC2AtnP8BgpLuKoiaY8+/ieYULt e2l9rCRHO9zDN/+S2zb3UbdsMJpLAj/4s9ZnUYEJYX2EcPw76PNS6prqR w==; X-IronPort-AV: E=McAfee;i="6500,9779,10606"; a="325534169" X-IronPort-AV: E=Sophos;i="5.97,261,1669104000"; d="scan'208";a="325534169" Received: from orsmga007.jf.intel.com ([10.7.209.58]) by fmsmga102.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 31 Jan 2023 05:16:47 -0800 X-IronPort-AV: E=McAfee;i="6500,9779,10606"; a="657864813" X-IronPort-AV: E=Sophos;i="5.97,261,1669104000"; d="scan'208";a="657864813" Received: from ahunter6-mobl1.ger.corp.intel.com (HELO ahunter-VirtualBox.home\044ger.corp.intel.com) ([10.252.47.218]) by orsmga007-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 31 Jan 2023 05:16:45 -0800 From: Adrian Hunter To: Arnaldo Carvalho de Melo Cc: Jiri Olsa , Namhyung Kim , Ian Rogers , linux-kernel@vger.kernel.org, linux-perf-users@vger.kernel.org Subject: [PATCH V2 4/9] perf symbols: Record whether a symbol is an alias for an IFUNC symbol Date: Tue, 31 Jan 2023 15:16:20 +0200 Message-Id: <20230131131625.6964-5-adrian.hunter@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230131131625.6964-1-adrian.hunter@intel.com> References: <20230131131625.6964-1-adrian.hunter@intel.com> MIME-Version: 1.0 Organization: Intel Finland Oy, Registered Address: PL 281, 00181 Helsinki, Business Identity Code: 0357606 - 4, Domiciled in Helsinki Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" To assist with synthesizing plt symbols for IFUNCs, record whether a symbol is an alias of an IFUNC symbol. Signed-off-by: Adrian Hunter Reviewed-by: Namhyung Kim --- tools/perf/util/symbol.c | 4 ++++ tools/perf/util/symbol.h | 2 ++ 2 files changed, 6 insertions(+) diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index a024f06f75d8..d05727fcb30d 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -201,10 +201,14 @@ void symbols__fixup_duplicate(struct rb_root_cached *= symbols) continue; =20 if (choose_best_symbol(curr, next) =3D=3D SYMBOL_A) { + if (next->type =3D=3D STT_GNU_IFUNC) + curr->ifunc_alias =3D true; rb_erase_cached(&next->rb_node, symbols); symbol__delete(next); goto again; } else { + if (curr->type =3D=3D STT_GNU_IFUNC) + next->ifunc_alias =3D true; nd =3D rb_next(&curr->rb_node); rb_erase_cached(&curr->rb_node, symbols); symbol__delete(curr); diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h index 2fdeb22bd02f..7558735543c2 100644 --- a/tools/perf/util/symbol.h +++ b/tools/perf/util/symbol.h @@ -64,6 +64,8 @@ struct symbol { u8 inlined:1; /** Has symbol__annotate2 been performed. */ u8 annotate2:1; + /** Symbol is an alias of an STT_GNU_IFUNC */ + u8 ifunc_alias:1; /** Architecture specific. Unused except on PPC where it holds st_other. = */ u8 arch_sym; /** The name of length namelen associated with the symbol. */ --=20 2.34.1 From nobody Sat Sep 13 18:42:52 2025 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8EB72C38142 for ; Tue, 31 Jan 2023 13:17:01 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231725AbjAaNQ7 (ORCPT ); Tue, 31 Jan 2023 08:16:59 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53618 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231726AbjAaNQw (ORCPT ); Tue, 31 Jan 2023 08:16:52 -0500 Received: from mga11.intel.com (mga11.intel.com [192.55.52.93]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 14670442EE; Tue, 31 Jan 2023 05:16:50 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1675171011; x=1706707011; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=buNnSEAE01t7rtwc1PFmnTIysYUAolAqo25T7Ol7MAM=; b=lwLEejvtrg4vLcqc2PrdZiEWiFZ3wyst1LRkGE3YeXCPUjXEGgxwr0Do YJiG1LtqZaf1eBkdZGMF/l7drdg2lFgQp8U+IZuyemFnNVF4bSUQMSXG0 gYabLir51Cls0y4WDiw9Vb5kmVa74y+hscS+eiYCbw4sGbdaV+PBXdkI0 88V3tc0mOostwgIs8esvlWlM5BD/IT8By8xAz4QRbgjdnolrri7+idIxW Rj3s28Ea04riNUpX7hYq+TGM1kL/QdT2k4KcGfZu4z6WxXjpb5YAg1GAz THSBQf/PzTR0u3w1FqX+f13z2dXhi9tNDx5/8EhwTQGyYQTxJUY9wHAna w==; X-IronPort-AV: E=McAfee;i="6500,9779,10606"; a="325534180" X-IronPort-AV: E=Sophos;i="5.97,261,1669104000"; d="scan'208";a="325534180" Received: from orsmga007.jf.intel.com ([10.7.209.58]) by fmsmga102.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 31 Jan 2023 05:16:50 -0800 X-IronPort-AV: E=McAfee;i="6500,9779,10606"; a="657864820" X-IronPort-AV: E=Sophos;i="5.97,261,1669104000"; d="scan'208";a="657864820" Received: from ahunter6-mobl1.ger.corp.intel.com (HELO ahunter-VirtualBox.home\044ger.corp.intel.com) ([10.252.47.218]) by orsmga007-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 31 Jan 2023 05:16:48 -0800 From: Adrian Hunter To: Arnaldo Carvalho de Melo Cc: Jiri Olsa , Namhyung Kim , Ian Rogers , 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 Message-Id: <20230131131625.6964-6-adrian.hunter@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230131131625.6964-1-adrian.hunter@intel.com> References: <20230131131625.6964-1-adrian.hunter@intel.com> MIME-Version: 1.0 Organization: Intel Finland Oy, Registered Address: PL 281, 00181 Helsinki, Business Identity Code: 0357606 - 4, Domiciled in Helsinki Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" 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 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 PURP= OSE. $ gcc -Wall -Wextra -shared -o libtstpltlib.so tstpltlib.c $ gcc -Wall -Wextra -Wno-uninitialized -o tstpltifunc tstpltifunc.c -L = . -ltstpltlib -Wl,-rpath=3D"$(pwd)" $ readelf -rW tstpltifunc | grep -A99 plt Relocation section '.rela.plt' at offset 0x738 contains 8 entries: Offset Info Type Symbol's Val= ue Symbol's Name + Addend 0000000000003f98 0000000300000007 R_X86_64_JUMP_SLOT 0000000000000= 000 puts@GLIBC_2.2.5 + 0 0000000000003fa8 0000000400000007 R_X86_64_JUMP_SLOT 0000000000000= 000 __stack_chk_fail@GLIBC_2.4 + 0 0000000000003fb0 0000000500000007 R_X86_64_JUMP_SLOT 0000000000000= 000 fn1 + 0 0000000000003fb8 0000000600000007 R_X86_64_JUMP_SLOT 0000000000000= 000 fn3 + 0 0000000000003fc0 0000000800000007 R_X86_64_JUMP_SLOT 0000000000000= 000 fn4 + 0 0000000000003fc8 0000000900000007 R_X86_64_JUMP_SLOT 0000000000000= 000 fn2 + 0 0000000000003fd0 0000000b00000007 R_X86_64_JUMP_SLOT 0000000000000= 000 getrandom@GLIBC_2.25 + 0 0000000000003fa0 0000000000000025 R_X86_64_IRELATIVE = 125d $ perf record -e intel_pt//u --filter 'filter main @ ./tstpltifunc' ./t= stpltifunc thing2 [ perf record: Woken up 1 times to write data ] [ perf record: Captured and wrote 0.016 MB perf.data ] $ perf script --itrace=3Dbe --ns -F+flags,-event,+addr,-period,-comm,-t= id,-cpu,-dso 21860.073683659: tr strt 0 [unknown] = =3D> 561e212c42be main+0x0 21860.073683659: tr end call 561e212c42c6 main+0x8 =3D= > 561e212c4110 fn4@plt+0x0 21860.073683661: tr strt 0 [unknown] = =3D> 561e212c42cb main+0xd 21860.073683661: tr end call 561e212c42cb main+0xd =3D= > 561e212c40f0 fn1@plt+0x0 21860.073683661: tr strt 0 [unknown] = =3D> 561e212c42d0 main+0x12 21860.073683661: tr end call 561e212c42d0 main+0x12 = =3D> 561e212c40d0 offset_0x10d0@plt+0x0 21860.073698451: tr strt 0 [unknown] = =3D> 561e212c42d5 main+0x17 21860.073698451: tr end call 561e212c42d5 main+0x17 = =3D> 561e212c4120 fn2@plt+0x0 21860.073698451: tr strt 0 [unknown] = =3D> 561e212c42da main+0x1c 21860.073698451: tr end call 561e212c42da main+0x1c = =3D> 561e212c4100 fn3@plt+0x0 21860.073698452: tr strt 0 [unknown] = =3D> 561e212c42df main+0x21 21860.073698452: tr end return 561e212c42e5 main+0x27 = =3D> 7fb51cc29d90 __libc_start_call_main+0x80 After: $ perf script --itrace=3Dbe --ns -F+flags,-event,+addr,-period,-comm,-t= id,-cpu,-dso 21860.073683659: tr strt 0 [unknown] = =3D> 561e212c42be main+0x0 21860.073683659: tr end call 561e212c42c6 main+0x8 =3D= > 561e212c4110 fn4@plt+0x0 21860.073683661: tr strt 0 [unknown] = =3D> 561e212c42cb main+0xd 21860.073683661: tr end call 561e212c42cb main+0xd =3D= > 561e212c40f0 fn1@plt+0x0 21860.073683661: tr strt 0 [unknown] = =3D> 561e212c42d0 main+0x12 21860.073683661: tr end call 561e212c42d0 main+0x12 = =3D> 561e212c40d0 thing_ifunc@plt+0x0 21860.073698451: tr strt 0 [unknown] = =3D> 561e212c42d5 main+0x17 21860.073698451: tr end call 561e212c42d5 main+0x17 = =3D> 561e212c4120 fn2@plt+0x0 21860.073698451: tr strt 0 [unknown] = =3D> 561e212c42da main+0x1c 21860.073698451: tr end call 561e212c42da main+0x1c = =3D> 561e212c4100 fn3@plt+0x0 21860.073698452: tr strt 0 [unknown] = =3D> 561e212c42df main+0x21 21860.073698452: tr end return 561e212c42e5 main+0x27 = =3D> 7fb51cc29d90 __libc_start_call_main+0x80 Signed-off-by: Adrian Hunter Reviewed-by: Namhyung Kim --- 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; } =20 +/* + * For x86_64, the GNU linker is putting IFUNC information in the relocati= on + * addend. + */ +static bool addend_may_be_ifunc(GElf_Ehdr *ehdr, struct rel_info *ri) +{ + return ehdr->e_machine =3D=3D EM_X86_64 && ri->is_rela && + GELF_R_TYPE(ri->rela.r_info) =3D=3D 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 =3D 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 -=3D phdr.p_vaddr - phdr.p_offset; + + sym =3D dso__find_symbol_nocache(dso, addr); + + /* Expecting the address to be an IFUNC or IFUNC alias */ + if (!sym || sym->start !=3D addr || (sym->type !=3D 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 =3D demangled; if (*elf_name) snprintf(sympltname, sizeof(sympltname), "%s@plt", elf_name); - else + else if (!get_ifunc_name(elf, dso, &ehdr, &ri, sympltname, sizeof(symplt= name))) snprintf(sympltname, sizeof(sympltname), "offset_%#" PRIx64 "@plt", plt_offset); free(demangled); --=20 2.34.1 From nobody Sat Sep 13 18:42:52 2025 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id C900CC38142 for ; Tue, 31 Jan 2023 13:17:08 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231863AbjAaNRH (ORCPT ); Tue, 31 Jan 2023 08:17:07 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53798 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231705AbjAaNQ4 (ORCPT ); Tue, 31 Jan 2023 08:16:56 -0500 Received: from mga11.intel.com (mga11.intel.com [192.55.52.93]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2DF3E367DF; Tue, 31 Jan 2023 05:16:53 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1675171013; x=1706707013; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=xv79CpMJX0N54gB4CsU1GJfMgJBj74HpxOAnf609a00=; b=IhcUoNCcvxeTkKYkaetKU6zRIrEZ2kdUNru73cPRsr76mFGWraU7pHVW Sp4/mID7U3oMUcjCId2k8/nBNYoRLtikf9HZA3MNsSRf5HnZc3Ahl2Wsi sCnzmh/f9rjKrUQZNiw9nJyfzjZPwd2/qV0MQZ3Xd/l8/vODLmnulNehn chpLda/0YFBjT/T7hEy+Ai8mZTFh+bMEr3Xj3R4lmIel1PZeyWKZq4lKL Y2bdQsgN0Lg29VvwB0urDYZPOEvQ3x2WNlub0MKE+L7wOELw0Hz0zvuji WKWS9awXRJAHz9jqF5U4jpveeaLIutanZPXXzN7Yj3A3DtkMbaz48rghj A==; X-IronPort-AV: E=McAfee;i="6500,9779,10606"; a="325534189" X-IronPort-AV: E=Sophos;i="5.97,261,1669104000"; d="scan'208";a="325534189" Received: from orsmga007.jf.intel.com ([10.7.209.58]) by fmsmga102.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 31 Jan 2023 05:16:52 -0800 X-IronPort-AV: E=McAfee;i="6500,9779,10606"; a="657864838" X-IronPort-AV: E=Sophos;i="5.97,261,1669104000"; d="scan'208";a="657864838" Received: from ahunter6-mobl1.ger.corp.intel.com (HELO ahunter-VirtualBox.home\044ger.corp.intel.com) ([10.252.47.218]) by orsmga007-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 31 Jan 2023 05:16:50 -0800 From: Adrian Hunter To: Arnaldo Carvalho de Melo Cc: Jiri Olsa , Namhyung Kim , Ian Rogers , linux-kernel@vger.kernel.org, linux-perf-users@vger.kernel.org Subject: [PATCH V2 6/9] perf symbols: Allow for .plt without header Date: Tue, 31 Jan 2023 15:16:22 +0200 Message-Id: <20230131131625.6964-7-adrian.hunter@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230131131625.6964-1-adrian.hunter@intel.com> References: <20230131131625.6964-1-adrian.hunter@intel.com> MIME-Version: 1.0 Organization: Intel Finland Oy, Registered Address: PL 281, 00181 Helsinki, Business Identity Code: 0357606 - 4, Domiciled in Helsinki Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" A static executable can have a .plt due to the presence of IFUNCs. In that case the .plt does not have a header. Check for whether there is a header by comparing the number of entries to the number of relocation entries. Signed-off-by: Adrian Hunter Reviewed-by: Namhyung Kim --- tools/perf/util/symbol-elf.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c index a002fc0bea03..8f7802097c72 100644 --- a/tools/perf/util/symbol-elf.c +++ b/tools/perf/util/symbol-elf.c @@ -489,6 +489,7 @@ int dso__synthesize_plt_symbols(struct dso *dso, struct= symsrc *ss) Elf *elf; int nr =3D 0, err =3D -1; struct rel_info ri =3D { .is_rela =3D false }; + bool lazy_plt; =20 elf =3D ss->elf; ehdr =3D ss->ehdr; @@ -523,8 +524,10 @@ int dso__synthesize_plt_symbols(struct dso *dso, struc= t symsrc *ss) plt_sym->end =3D plt_sym->start + shdr_plt.sh_size; /* Use .plt.sec offset */ plt_offset =3D plt_sec_shdr.sh_offset; + lazy_plt =3D false; } else { - plt_offset =3D shdr_plt.sh_offset + plt_header_size; + plt_offset =3D shdr_plt.sh_offset; + lazy_plt =3D true; } =20 scn_dynsym =3D ss->dynsym; @@ -577,6 +580,17 @@ int dso__synthesize_plt_symbols(struct dso *dso, struc= t symsrc *ss) =20 ri.is_rela =3D shdr_rel_plt.sh_type =3D=3D SHT_RELA; =20 + if (lazy_plt) { + /* + * Assume a .plt with the same number of entries as the number + * of relocation entries is not lazy and does not have a header. + */ + if (ri.nr_entries * plt_entry_size =3D=3D shdr_plt.sh_size) + dso__delete_symbol(dso, plt_sym); + else + plt_offset +=3D plt_header_size; + } + /* * x86 doesn't insert IFUNC relocations in .plt order, so sort to get * back in order. --=20 2.34.1 From nobody Sat Sep 13 18:42:52 2025 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id D19BBC38142 for ; Tue, 31 Jan 2023 13:17:17 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231907AbjAaNRQ (ORCPT ); Tue, 31 Jan 2023 08:17:16 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53936 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231887AbjAaNQ7 (ORCPT ); Tue, 31 Jan 2023 08:16:59 -0500 Received: from mga11.intel.com (mga11.intel.com [192.55.52.93]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A66482CC60; Tue, 31 Jan 2023 05:16:55 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1675171015; x=1706707015; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=R3NgJAtWb7jXyeV9uKKrkT8nXL2hEwhW5ncNONVpuSY=; b=WNKtOIUCtc2VlDs+m4l43nzpq9bWZ6A+VXf/D89m5UVnCzTBU7YyNw3e 0fBB0cOX8jLg/8jJ7u1JKvwQwvuy5qfnu24p9cIzNZsVLwqPe8ir+ruy8 GX8kJS5T2nutgjFiJYFZ+1ydBUU2itKQUrA10zU8qOJUChjQnW6d5VRl8 jp1BAlkXg3Upg3tGoF4QKDzwFYOl3i00znJU52BkqoHhV6UgsI42vC/W/ qk3887ZicYX/hrRcsI5f1gVBVlfU/R4GlcFzOYdD+9ZL8zize9q8860xg Kn6W83pifb5EP/FoDLmAsP8T+CuI/6u49KwewcSIX7UlgE1nRvoq8aRD5 g==; X-IronPort-AV: E=McAfee;i="6500,9779,10606"; a="325534199" X-IronPort-AV: E=Sophos;i="5.97,261,1669104000"; d="scan'208";a="325534199" Received: from orsmga007.jf.intel.com ([10.7.209.58]) by fmsmga102.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 31 Jan 2023 05:16:55 -0800 X-IronPort-AV: E=McAfee;i="6500,9779,10606"; a="657864849" X-IronPort-AV: E=Sophos;i="5.97,261,1669104000"; d="scan'208";a="657864849" Received: from ahunter6-mobl1.ger.corp.intel.com (HELO ahunter-VirtualBox.home\044ger.corp.intel.com) ([10.252.47.218]) by orsmga007-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 31 Jan 2023 05:16:52 -0800 From: Adrian Hunter To: Arnaldo Carvalho de Melo Cc: Jiri Olsa , Namhyung Kim , Ian Rogers , linux-kernel@vger.kernel.org, linux-perf-users@vger.kernel.org Subject: [PATCH V2 7/9] perf symbols: Allow for static executables with .plt Date: Tue, 31 Jan 2023 15:16:23 +0200 Message-Id: <20230131131625.6964-8-adrian.hunter@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230131131625.6964-1-adrian.hunter@intel.com> References: <20230131131625.6964-1-adrian.hunter@intel.com> MIME-Version: 1.0 Organization: Intel Finland Oy, Registered Address: PL 281, 00181 Helsinki, Business Identity Code: 0357606 - 4, Domiciled in Helsinki Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" 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 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 PURP= OSE. $ gcc -static -Wall -Wextra -Wno-uninitialized -o tstifuncstatic tstifu= nc.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=3Dbe --ns -F+flags,-event,+addr,-period,-comm,-t= id,-cpu,-dso 15786.690189535: tr strt 0 [unknown] = =3D> 4017cd main+0x0 15786.690189535: tr end call 4017d5 main+0x8 =3D= > 401170 [unknown] 15786.690197660: tr strt 0 [unknown] = =3D> 4017da main+0xd 15786.690197660: tr end return 4017e0 main+0x13 = =3D> 401c1a __libc_start_call_main+0x6a After: $ perf script --itrace=3Dbe --ns -F+flags,-event,+addr,-period,-comm,-t= id,-cpu,-dso 15786.690189535: tr strt 0 [unknown] = =3D> 4017cd main+0x0 15786.690189535: tr end call 4017d5 main+0x8 =3D= > 401170 thing_ifunc@plt+0x0 15786.690197660: tr strt 0 [unknown] = =3D> 4017da main+0xd 15786.690197660: tr end return 4017e0 main+0x13 = =3D> 401c1a __libc_start_call_main+0x6a Signed-off-by: Adrian Hunter Reviewed-by: Namhyung Kim --- tools/perf/util/symbol-elf.c | 30 ++++++++++++++++++++---------- tools/perf/util/symsrc.h | 1 + 2 files changed, 21 insertions(+), 10 deletions(-) diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c index 8f7802097c72..9e265a726418 100644 --- a/tools/perf/util/symbol-elf.c +++ b/tools/perf/util/symbol-elf.c @@ -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, struc= t symsrc *ss) lazy_plt =3D true; } =20 - scn_dynsym =3D ss->dynsym; - shdr_dynsym =3D ss->dynshdr; - dynsym_idx =3D ss->dynsym_idx; - - if (scn_dynsym =3D=3D NULL) - return 0; - scn_plt_rel =3D elf_section_by_name(elf, &ehdr, &shdr_rel_plt, ".rela.plt", NULL); if (scn_plt_rel =3D=3D NULL) { @@ -550,8 +542,25 @@ int dso__synthesize_plt_symbols(struct dso *dso, struc= t symsrc *ss) shdr_rel_plt.sh_type !=3D SHT_REL) return 0; =20 - if (shdr_rel_plt.sh_link !=3D dynsym_idx) + if (!shdr_rel_plt.sh_link) + return 0; + + if (shdr_rel_plt.sh_link =3D=3D ss->dynsym_idx) { + scn_dynsym =3D ss->dynsym; + shdr_dynsym =3D ss->dynshdr; + } else if (shdr_rel_plt.sh_link =3D=3D ss->symtab_idx) { + /* + * A static executable can have a .plt due to IFUNCs, in which + * case .symtab is used not .dynsym. + */ + scn_dynsym =3D ss->symtab; + shdr_dynsym =3D ss->symshdr; + } else { goto out_elf_end; + } + + if (!scn_dynsym) + return 0; =20 /* * 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, =20 ss->is_64_bit =3D (gelf_getclass(elf) =3D=3D ELFCLASS64); =20 + ss->symtab_idx =3D 0; ss->symtab =3D elf_section_by_name(elf, &ehdr, &ss->symshdr, ".symtab", - NULL); + &ss->symtab_idx); if (ss->symshdr.sh_type !=3D SHT_SYMTAB) ss->symtab =3D NULL; =20 diff --git a/tools/perf/util/symsrc.h b/tools/perf/util/symsrc.h index 2665b4bde751..edf82028c9e6 100644 --- a/tools/perf/util/symsrc.h +++ b/tools/perf/util/symsrc.h @@ -26,6 +26,7 @@ struct symsrc { GElf_Shdr opdshdr; =20 Elf_Scn *symtab; + size_t symtab_idx; GElf_Shdr symshdr; =20 Elf_Scn *dynsym; --=20 2.34.1 From nobody Sat Sep 13 18:42:52 2025 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 68195C38142 for ; Tue, 31 Jan 2023 13:17:21 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231983AbjAaNRU (ORCPT ); Tue, 31 Jan 2023 08:17:20 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:54040 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231992AbjAaNRC (ORCPT ); Tue, 31 Jan 2023 08:17:02 -0500 Received: from mga11.intel.com (mga11.intel.com [192.55.52.93]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C81D342DE5; Tue, 31 Jan 2023 05:16:58 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1675171018; x=1706707018; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=gSCQ96tg4l0FNHIgMJQtf3tGIwORYZgZx/efj/0fnbo=; b=l8q9ApxIiu+CUwlfKvp5I1t3eh3tu5L6J+4L5WKYemboLFPanBxdbueI hVuSvd2ey0T7TkboWRLzXUBlcs0Jalsd/VxfvDppuMwlG45cbmlab4iVa uzDJ1VampeZ+XfYOpBtqx97mrXu/krkmDIgQVssmKUOZ35ffDtl5ks7/V ASRTKcIqVNelcEBCeF3iLgG450DlJP9332lhWJWIvf1X6xE5Z/1GJPnlW VusWHSce+cuEumI6StcgMFfK/b7xq+JIztjMw8kmNteFzI7aCgbssx9Qb 7ZuhLgjh5CZWxyxS9YmhqRuDIx4r8FUfRAB9yz1Mi5fWQejycVCXaR+ly g==; X-IronPort-AV: E=McAfee;i="6500,9779,10606"; a="325534214" X-IronPort-AV: E=Sophos;i="5.97,261,1669104000"; d="scan'208";a="325534214" Received: from orsmga007.jf.intel.com ([10.7.209.58]) by fmsmga102.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 31 Jan 2023 05:16:58 -0800 X-IronPort-AV: E=McAfee;i="6500,9779,10606"; a="657864857" X-IronPort-AV: E=Sophos;i="5.97,261,1669104000"; d="scan'208";a="657864857" Received: from ahunter6-mobl1.ger.corp.intel.com (HELO ahunter-VirtualBox.home\044ger.corp.intel.com) ([10.252.47.218]) by orsmga007-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 31 Jan 2023 05:16:55 -0800 From: Adrian Hunter To: Arnaldo Carvalho de Melo Cc: Jiri Olsa , Namhyung Kim , Ian Rogers , linux-kernel@vger.kernel.org, linux-perf-users@vger.kernel.org Subject: [PATCH V2 8/9] perf symbols: Start adding support for .plt.got for x86 Date: Tue, 31 Jan 2023 15:16:24 +0200 Message-Id: <20230131131625.6964-9-adrian.hunter@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230131131625.6964-1-adrian.hunter@intel.com> References: <20230131131625.6964-1-adrian.hunter@intel.com> MIME-Version: 1.0 Organization: Intel Finland Oy, Registered Address: PL 281, 00181 Helsinki, Business Identity Code: 0357606 - 4, Domiciled in Helsinki Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" For x86, .plt.got is used, for example, when the address is taken of a dynamically linked function. Start adding support by synthesizing a symbol for each entry. A subsequent patch will attempt to get a better name for the symbol. Example: Before: $ cat tstpltlib.c void fn1(void) {} void fn2(void) {} void fn3(void) {} void fn4(void) {} $ cat tstpltgot.c void fn1(void); void fn2(void); void fn3(void); void fn4(void); void callfn(void (*fn)(void)) { fn(); } int main() { fn4(); fn1(); callfn(fn3); 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 PURP= OSE. $ gcc -Wall -Wextra -shared -o libtstpltlib.so tstpltlib.c $ gcc -Wall -Wextra -o tstpltgot tstpltgot.c -L . -ltstpltlib -Wl,-rpat= h=3D"$(pwd)" $ readelf -SW tstpltgot | grep 'Name\|plt\|dyn' [Nr] Name Type Address Off Size = ES Flg Lk Inf Al [ 6] .dynsym DYNSYM 00000000000003d8 0003d8 0000f0= 18 A 7 1 8 [ 7] .dynstr STRTAB 00000000000004c8 0004c8 0000c6= 00 A 0 0 1 [10] .rela.dyn RELA 00000000000005d8 0005d8 0000d8= 18 A 6 0 8 [11] .rela.plt RELA 00000000000006b0 0006b0 000048= 18 AI 6 24 8 [13] .plt PROGBITS 0000000000001020 001020 000040= 10 AX 0 0 16 [14] .plt.got PROGBITS 0000000000001060 001060 000020= 10 AX 0 0 16 [15] .plt.sec PROGBITS 0000000000001080 001080 000030= 10 AX 0 0 16 [23] .dynamic DYNAMIC 0000000000003d90 002d90 000210= 10 WA 7 0 8 $ perf record -e intel_pt//u --filter 'filter main @ ./tstpltgot , filt= er callfn @ ./tstpltgot' ./tstpltgot [ perf record: Woken up 1 times to write data ] [ perf record: Captured and wrote 0.011 MB perf.data ] $ perf script --itrace=3Dbe --ns -F+flags,-event,+addr,-period,-comm,-t= id,-cpu,-dso 28393.810326915: tr strt 0 [unknown] = =3D> 562350baa1b2 main+0x0 28393.810326915: tr end call 562350baa1ba main+0x8 =3D= > 562350baa090 fn4@plt+0x0 28393.810326917: tr strt 0 [unknown] = =3D> 562350baa1bf main+0xd 28393.810326917: tr end call 562350baa1bf main+0xd =3D= > 562350baa080 fn1@plt+0x0 28393.810326917: tr strt 0 [unknown] = =3D> 562350baa1c4 main+0x12 28393.810326917: call 562350baa1ce main+0x1c = =3D> 562350baa199 callfn+0x0 28393.810326917: tr end call 562350baa1ad callfn+0x14 = =3D> 7f607d36110f fn3+0x0 28393.810326922: tr strt 0 [unknown] = =3D> 562350baa1af callfn+0x16 28393.810326922: return 562350baa1b1 callfn+0x18 = =3D> 562350baa1d3 main+0x21 28393.810326922: tr end call 562350baa1d3 main+0x21 = =3D> 562350baa0a0 fn2@plt+0x0 28393.810326924: tr strt 0 [unknown] = =3D> 562350baa1d8 main+0x26 28393.810326924: tr end call 562350baa1d8 main+0x26 = =3D> 562350baa060 [unknown] <- call to fn3 via .plt.got 28393.810326925: tr strt 0 [unknown] = =3D> 562350baa1dd main+0x2b 28393.810326925: tr end return 562350baa1e3 main+0x31 = =3D> 7f607d029d90 __libc_start_call_main+0x80 After: $ perf script --itrace=3Dbe --ns -F+flags,-event,+addr,-period,-comm,-t= id,-cpu,-dso 28393.810326915: tr strt 0 [unknown] = =3D> 562350baa1b2 main+0x0 28393.810326915: tr end call 562350baa1ba main+0x8 =3D= > 562350baa090 fn4@plt+0x0 28393.810326917: tr strt 0 [unknown] = =3D> 562350baa1bf main+0xd 28393.810326917: tr end call 562350baa1bf main+0xd =3D= > 562350baa080 fn1@plt+0x0 28393.810326917: tr strt 0 [unknown] = =3D> 562350baa1c4 main+0x12 28393.810326917: call 562350baa1ce main+0x1c = =3D> 562350baa199 callfn+0x0 28393.810326917: tr end call 562350baa1ad callfn+0x14 = =3D> 7f607d36110f fn3+0x0 28393.810326922: tr strt 0 [unknown] = =3D> 562350baa1af callfn+0x16 28393.810326922: return 562350baa1b1 callfn+0x18 = =3D> 562350baa1d3 main+0x21 28393.810326922: tr end call 562350baa1d3 main+0x21 = =3D> 562350baa0a0 fn2@plt+0x0 28393.810326924: tr strt 0 [unknown] = =3D> 562350baa1d8 main+0x26 28393.810326924: tr end call 562350baa1d8 main+0x26 = =3D> 562350baa060 offset_0x1060@plt+0x0 28393.810326925: tr strt 0 [unknown] = =3D> 562350baa1dd main+0x2b 28393.810326925: tr end return 562350baa1e3 main+0x31 = =3D> 7f607d029d90 __libc_start_call_main+0x80 Signed-off-by: Adrian Hunter Reviewed-by: Namhyung Kim --- tools/perf/util/symbol-elf.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c index 9e265a726418..254116d40e59 100644 --- a/tools/perf/util/symbol-elf.c +++ b/tools/perf/util/symbol-elf.c @@ -466,6 +466,30 @@ static bool machine_is_x86(GElf_Half e_machine) return e_machine =3D=3D EM_386 || e_machine =3D=3D EM_X86_64; } =20 +static int dso__synthesize_plt_got_symbols(struct dso *dso, Elf *elf, + GElf_Ehdr *ehdr, + char *buf, size_t buf_sz) +{ + struct symbol *sym; + GElf_Shdr shdr; + Elf_Scn *scn; + size_t i; + + scn =3D elf_section_by_name(elf, ehdr, &shdr, ".plt.got", NULL); + if (!scn || !shdr.sh_entsize) + return 0; + + for (i =3D 0; i < shdr.sh_size; i +=3D shdr.sh_entsize) { + snprintf(buf, buf_sz, "offset_%#zx@plt", shdr.sh_offset + i); + sym =3D symbol__new(shdr.sh_offset + i, shdr.sh_entsize, STB_GLOBAL, STT= _FUNC, buf); + if (!sym) + return -1; + symbols__insert(&dso->symbols, sym); + } + + return 0; +} + /* * We need to check if we have a .dynsym, so that we can handle the * .plt, synthesizing its symbols, that aren't on the symtabs (be it @@ -514,6 +538,11 @@ int dso__synthesize_plt_symbols(struct dso *dso, struc= t symsrc *ss) goto out_elf_end; symbols__insert(&dso->symbols, plt_sym); =20 + /* Only x86 has .plt.got */ + if (machine_is_x86(ehdr.e_machine) && + dso__synthesize_plt_got_symbols(dso, elf, &ehdr, sympltname, sizeof(s= ympltname))) + goto out_elf_end; + /* Only x86 has .plt.sec */ if (machine_is_x86(ehdr.e_machine) && elf_section_by_name(elf, &ehdr, &plt_sec_shdr, ".plt.sec", NULL)) { --=20 2.34.1 From nobody Sat Sep 13 18:42:52 2025 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 28227C636CC for ; Tue, 31 Jan 2023 13:17:25 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230109AbjAaNRX (ORCPT ); Tue, 31 Jan 2023 08:17:23 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53928 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231872AbjAaNRM (ORCPT ); Tue, 31 Jan 2023 08:17:12 -0500 Received: from mga11.intel.com (mga11.intel.com [192.55.52.93]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 281841AF; Tue, 31 Jan 2023 05:17:01 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1675171021; x=1706707021; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=kTyPY0p6KFVL1tyOf3fj9sx3LfQomRM5zqwDxyFvz7M=; b=XxVxCTWLp1JwsVJoOtBS1NIuJfj62DlWrGgZCR8EHk46d6OqhoIwZTuZ bvL10sZjar5yvhGswruTnqs8PgQDVrzrQ4454yqfpn6ZmSWV96mkDG61W ReS8qmOBek1AJqyp9fUbGrBHIFn6Fh2HnjcLbXg5WWSQfTRKYfVo/tESC wA7gAIbEZfCBb8sLJHlU+WINo2a3XQcBnDp8N8jGFbLBowmBAxLajHy1w B8rwmtbTK1GwNCzF8jbdim8EHflIVqyl8MzS9lG27tq6a9x788fLIz6Lb znqz8JtX7jIbJwCB0czKHW+tevb7nS4ZLxetyErm74MjJszlXqpVG8ftZ A==; X-IronPort-AV: E=McAfee;i="6500,9779,10606"; a="325534225" X-IronPort-AV: E=Sophos;i="5.97,261,1669104000"; d="scan'208";a="325534225" Received: from orsmga007.jf.intel.com ([10.7.209.58]) by fmsmga102.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 31 Jan 2023 05:17:00 -0800 X-IronPort-AV: E=McAfee;i="6500,9779,10606"; a="657864862" X-IronPort-AV: E=Sophos;i="5.97,261,1669104000"; d="scan'208";a="657864862" Received: from ahunter6-mobl1.ger.corp.intel.com (HELO ahunter-VirtualBox.home\044ger.corp.intel.com) ([10.252.47.218]) by orsmga007-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 31 Jan 2023 05:16:58 -0800 From: Adrian Hunter To: Arnaldo Carvalho de Melo Cc: Jiri Olsa , Namhyung Kim , Ian Rogers , linux-kernel@vger.kernel.org, linux-perf-users@vger.kernel.org Subject: [PATCH V2 9/9] perf symbols: Get symbols for .plt.got for x86-64 Date: Tue, 31 Jan 2023 15:16:25 +0200 Message-Id: <20230131131625.6964-10-adrian.hunter@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230131131625.6964-1-adrian.hunter@intel.com> References: <20230131131625.6964-1-adrian.hunter@intel.com> MIME-Version: 1.0 Organization: Intel Finland Oy, Registered Address: PL 281, 00181 Helsinki, Business Identity Code: 0357606 - 4, Domiciled in Helsinki Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" For x86_64, determine a symbol for .plt.got entries. That requires computing the target offset and finding that in .rela.dyn, which in turn means .rela.dyn needs to be sorted by offset. Example: In this example, the GNU C Library is using .plt.got for malloc and free. Before: $ 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 PURP= OSE. $ perf record -e intel_pt//u uname Linux [ perf record: Woken up 1 times to write data ] [ perf record: Captured and wrote 0.027 MB perf.data ] $ perf script --itrace=3Dbe --ns -F-event,+addr,-period,-comm,-tid,-cpu= > /tmp/cmp1.txt After: $ perf script --itrace=3Dbe --ns -F-event,+addr,-period,-comm,-tid,-cpu= > /tmp/cmp2.txt $ diff /tmp/cmp1.txt /tmp/cmp2.txt | head -12 15509,15510c15509,15510 < 27046.755390907: 7f0b2943e3ab _nl_normalize_codeset+0x5b (/usr/l= ib/x86_64-linux-gnu/libc.so.6) =3D> 7f0b29428380 offset_0x28380@plt+0x0= (/usr/lib/x86_64-linux-gnu/libc.so.6) < 27046.755390907: 7f0b29428384 offset_0x28380@plt+0x4 (/usr/lib/x= 86_64-linux-gnu/libc.so.6) =3D> 7f0b294a5120 malloc+0x0 (/usr/lib/x86_6= 4-linux-gnu/libc.so.6) --- > 27046.755390907: 7f0b2943e3ab _nl_normalize_codeset+0x5b (/usr/l= ib/x86_64-linux-gnu/libc.so.6) =3D> 7f0b29428380 malloc@plt+0x0 (/usr/l= ib/x86_64-linux-gnu/libc.so.6) > 27046.755390907: 7f0b29428384 malloc@plt+0x4 (/usr/lib/x86_64-li= nux-gnu/libc.so.6) =3D> 7f0b294a5120 malloc+0x0 (/usr/lib/x86_64-linux-= gnu/libc.so.6) 15821,15822c15821,15822 < 27046.755394865: 7f0b2943850c _nl_load_locale_from_archive+0x5bc= (/usr/lib/x86_64-linux-gnu/libc.so.6) =3D> 7f0b29428370 offset_0x28370= @plt+0x0 (/usr/lib/x86_64-linux-gnu/libc.so.6) < 27046.755394865: 7f0b29428374 offset_0x28370@plt+0x4 (/usr/lib/x= 86_64-linux-gnu/libc.so.6) =3D> 7f0b294a5460 cfree@GLIBC_2.2.5+0x0 (/us= r/lib/x86_64-linux-gnu/libc.so.6) --- > 27046.755394865: 7f0b2943850c _nl_load_locale_from_archive+0x5bc= (/usr/lib/x86_64-linux-gnu/libc.so.6) =3D> 7f0b29428370 free@plt+0x0 (= /usr/lib/x86_64-linux-gnu/libc.so.6) > 27046.755394865: 7f0b29428374 free@plt+0x4 (/usr/lib/x86_64-linu= x-gnu/libc.so.6) =3D> 7f0b294a5460 cfree@GLIBC_2.2.5+0x0 (/usr/lib/x86_= 64-linux-gnu/libc.so.6) Signed-off-by: Adrian Hunter Reviewed-by: Namhyung Kim --- tools/perf/util/symbol-elf.c | 161 ++++++++++++++++++++++++++++++++++- 1 file changed, 157 insertions(+), 4 deletions(-) diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c index 254116d40e59..b149cfea73d0 100644 --- a/tools/perf/util/symbol-elf.c +++ b/tools/perf/util/symbol-elf.c @@ -466,28 +466,181 @@ static bool machine_is_x86(GElf_Half e_machine) return e_machine =3D=3D EM_386 || e_machine =3D=3D EM_X86_64; } =20 +struct rela_dyn { + GElf_Addr offset; + u32 sym_idx; +}; + +struct rela_dyn_info { + struct dso *dso; + Elf_Data *plt_got_data; + u32 nr_entries; + struct rela_dyn *sorted; + Elf_Data *dynsym_data; + Elf_Data *dynstr_data; + Elf_Data *rela_dyn_data; +}; + +static void exit_rela_dyn(struct rela_dyn_info *di) +{ + free(di->sorted); +} + +static int cmp_offset(const void *a, const void *b) +{ + const struct rela_dyn *va =3D a; + const struct rela_dyn *vb =3D b; + + return va->offset < vb->offset ? -1 : (va->offset > vb->offset ? 1 : 0); +} + +static int sort_rela_dyn(struct rela_dyn_info *di) +{ + u32 i, n; + + di->sorted =3D calloc(di->nr_entries, sizeof(di->sorted[0])); + if (!di->sorted) + return -1; + + /* Get data for sorting: the offset and symbol index */ + for (i =3D 0, n =3D 0; i < di->nr_entries; i++) { + GElf_Rela rela; + u32 sym_idx; + + gelf_getrela(di->rela_dyn_data, i, &rela); + sym_idx =3D GELF_R_SYM(rela.r_info); + if (sym_idx) { + di->sorted[n].sym_idx =3D sym_idx; + di->sorted[n].offset =3D rela.r_offset; + n +=3D 1; + } + } + + /* Sort by offset */ + di->nr_entries =3D n; + qsort(di->sorted, n, sizeof(di->sorted[0]), cmp_offset); + + return 0; +} + +static void get_rela_dyn_info(Elf *elf, GElf_Ehdr *ehdr, struct rela_dyn_i= nfo *di, Elf_Scn *scn) +{ + GElf_Shdr rela_dyn_shdr; + GElf_Shdr shdr; + + di->plt_got_data =3D elf_getdata(scn, NULL); + + scn =3D elf_section_by_name(elf, ehdr, &rela_dyn_shdr, ".rela.dyn", NULL); + if (!scn || !rela_dyn_shdr.sh_link || !rela_dyn_shdr.sh_entsize) + return; + + di->nr_entries =3D rela_dyn_shdr.sh_size / rela_dyn_shdr.sh_entsize; + di->rela_dyn_data =3D elf_getdata(scn, NULL); + + scn =3D elf_getscn(elf, rela_dyn_shdr.sh_link); + if (!scn || !gelf_getshdr(scn, &shdr) || !shdr.sh_link) + return; + + di->dynsym_data =3D elf_getdata(scn, NULL); + di->dynstr_data =3D elf_getdata(elf_getscn(elf, shdr.sh_link), NULL); + + if (!di->plt_got_data || !di->dynstr_data || !di->dynsym_data || !di->rel= a_dyn_data) + return; + + /* Sort into offset order */ + sort_rela_dyn(di); +} + +/* Get instruction displacement from a plt entry for x86_64 */ +static u32 get_x86_64_plt_disp(const u8 *p) +{ + u8 endbr64[] =3D {0xf3, 0x0f, 0x1e, 0xfa}; + int n =3D 0; + + /* Skip endbr64 */ + if (!memcmp(p, endbr64, sizeof(endbr64))) + n +=3D sizeof(endbr64); + /* Skip bnd prefix */ + if (p[n] =3D=3D 0xf2) + n +=3D 1; + /* jmp with 4-byte displacement */ + if (p[n] =3D=3D 0xff && p[n + 1] =3D=3D 0x25) { + n +=3D 2; + /* Also add offset from start of entry to end of instruction */ + return n + 4 + le32toh(*(const u32 *)(p + n)); + } + return 0; +} + +static bool get_plt_got_name(GElf_Shdr *shdr, size_t i, + struct rela_dyn_info *di, + char *buf, size_t buf_sz) +{ + struct rela_dyn vi, *vr; + const char *sym_name; + char *demangled; + GElf_Sym sym; + u32 disp; + + if (!di->sorted) + return false; + + disp =3D get_x86_64_plt_disp(di->plt_got_data->d_buf + i); + if (!disp) + return false; + + /* Compute target offset of the .plt.got entry */ + vi.offset =3D shdr->sh_offset + di->plt_got_data->d_off + i + disp; + + /* Find that offset in .rela.dyn (sorted by offset) */ + vr =3D bsearch(&vi, di->sorted, di->nr_entries, sizeof(di->sorted[0]), cm= p_offset); + if (!vr) + return false; + + /* Get the associated symbol */ + gelf_getsym(di->dynsym_data, vr->sym_idx, &sym); + sym_name =3D elf_sym__name(&sym, di->dynstr_data); + demangled =3D demangle_sym(di->dso, 0, sym_name); + if (demangled !=3D NULL) + sym_name =3D demangled; + + snprintf(buf, buf_sz, "%s@plt", sym_name); + + free(demangled); + + return *sym_name; +} + static int dso__synthesize_plt_got_symbols(struct dso *dso, Elf *elf, GElf_Ehdr *ehdr, char *buf, size_t buf_sz) { + struct rela_dyn_info di =3D { .dso =3D dso }; struct symbol *sym; GElf_Shdr shdr; Elf_Scn *scn; + int err =3D -1; size_t i; =20 scn =3D elf_section_by_name(elf, ehdr, &shdr, ".plt.got", NULL); if (!scn || !shdr.sh_entsize) return 0; =20 + if (ehdr->e_machine =3D=3D EM_X86_64) + get_rela_dyn_info(elf, ehdr, &di, scn); + for (i =3D 0; i < shdr.sh_size; i +=3D shdr.sh_entsize) { - snprintf(buf, buf_sz, "offset_%#zx@plt", shdr.sh_offset + i); + if (!get_plt_got_name(&shdr, i, &di, buf, buf_sz)) + snprintf(buf, buf_sz, "offset_%#zx@plt", shdr.sh_offset + i); sym =3D symbol__new(shdr.sh_offset + i, shdr.sh_entsize, STB_GLOBAL, STT= _FUNC, buf); if (!sym) - return -1; + goto out; symbols__insert(&dso->symbols, sym); } - - return 0; + err =3D 0; +out: + exit_rela_dyn(&di); + return err; } =20 /* --=20 2.34.1