From patchwork Thu Feb 13 16:20:48 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Steven Rostedt X-Patchwork-Id: 13973799 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 bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 6A8C9C021A4 for ; Thu, 13 Feb 2025 17:43:13 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Content-Type:MIME-Version: References:Subject:Cc:To:From:Date:Message-ID:Reply-To: Content-Transfer-Encoding:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To: List-Owner; bh=wAgQgZ4WzvFvPIIB4bYsWu9GX3pb6DIbnFo4X26RB04=; b=xRvl1533OlU6oQ IFS2kNLK4b3wZR2ZKUSyjPub1ou9akN5e8SQeV5hmv3ABeWQz0NmNCa0p0eHkQgB/omDEHsa8En7R h3qZcQsa/+S9Osi7KpC8d5Ug4E74XDuaj6keEfQD3d+Dz2b2+Kgpw9rydHD0DVGTwE1x/SLVk+0LX 9d3jpbDzPNHdYufJoLxY0djssrM5wLTXjnG88nb2ZHvHybPB97HA9xltGpy91wplt6lNI6c0QwwMN lB9aTHUfDkZcd9dn4oSD16FtHSuEhRlbgp8zW+zh0MB+u+F3h9QqEnMx2yUKemnnkx/3VZpw8YWCd pTbkar/PaEYPhV5HFNug==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.98 #2 (Red Hat Linux)) id 1tidEl-0000000C3Pu-2D6u; Thu, 13 Feb 2025 17:42:55 +0000 Received: from dfw.source.kernel.org ([139.178.84.217]) by bombadil.infradead.org with esmtps (Exim 4.98 #2 (Red Hat Linux)) id 1tiby4-0000000Bk8v-13MW for linux-arm-kernel@lists.infradead.org; Thu, 13 Feb 2025 16:21:38 +0000 Received: from smtp.kernel.org (transwarp.subspace.kernel.org [100.75.92.58]) by dfw.source.kernel.org (Postfix) with ESMTP id 368A85C5837; Thu, 13 Feb 2025 16:20:56 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 3DF4FC4CEE7; Thu, 13 Feb 2025 16:21:35 +0000 (UTC) Received: from rostedt by gandalf with local (Exim 4.98) (envelope-from ) id 1tibyD-00000001qaV-2e9S; Thu, 13 Feb 2025 11:21:45 -0500 Message-ID: <20250213162145.477758854@goodmis.org> User-Agent: quilt/0.68 Date: Thu, 13 Feb 2025 11:20:48 -0500 From: Steven Rostedt To: linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org, linux-kbuild@vger.kernel.org, bpf , linux-arm-kernel@lists.infradead.org, linux-s390@vger.kernel.org Cc: Masami Hiramatsu , Mark Rutland , Mathieu Desnoyers , Andrew Morton , Peter Zijlstra , Linus Torvalds , Masahiro Yamada , Nathan Chancellor , Nicolas Schier , Zheng Yejian , Martin Kelly , Christophe Leroy , Josh Poimboeuf , Heiko Carstens , Catalin Marinas , Will Deacon , Vasily Gorbik , Alexander Gordeev Subject: [PATCH v3 1/6] arm64: scripts/sorttable: Implement sorting mcount_loc at boot for arm64 References: <20250213162047.306074881@goodmis.org> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20250213_082136_384974_0F10F099 X-CRM114-Status: GOOD ( 26.92 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org From: Steven Rostedt The mcount_loc section holds the addresses of the functions that get patched by ftrace when enabling function callbacks. It can contain tens of thousands of entries. These addresses must be sorted. If they are not sorted at compile time, they are sorted at boot. Sorting at boot does take some time and does have a small impact on boot performance. x86 and arm32 have the addresses in the mcount_loc section of the ELF file. But for arm64, the section just contains zeros. The .rela.dyn Elf_Rela section holds the addresses and they get patched at boot during the relocation phase. In order to sort these addresses, the Elf_Rela needs to be updated instead of the location in the binary that holds the mcount_loc section. Have the sorttable code, allocate an array to hold the functions, load the addresses from the Elf_Rela entries, sort them, then put them back in order into the Elf_rela entries so that they will be sorted at boot up without having to sort them during boot up. Cc: Will Deacon Cc: Mark Rutland Cc: Heiko Carstens Cc: Vasily Gorbik Cc: Alexander Gordeev Link: https://lore.kernel.org/20250211141139.03d2997e@gandalf.local.home Acked-by: Catalin Marinas Signed-off-by: Steven Rostedt (Google) --- arch/arm64/Kconfig | 1 + scripts/sorttable.c | 185 +++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 183 insertions(+), 3 deletions(-) diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index fcdd0ed3eca8..3c6c9dcd96aa 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -217,6 +217,7 @@ config ARM64 if DYNAMIC_FTRACE_WITH_ARGS select HAVE_SAMPLE_FTRACE_DIRECT select HAVE_SAMPLE_FTRACE_DIRECT_MULTI + select HAVE_BUILDTIME_MCOUNT_SORT select HAVE_EFFICIENT_UNALIGNED_ACCESS select HAVE_GUP_FAST select HAVE_FTRACE_GRAPH_FUNC diff --git a/scripts/sorttable.c b/scripts/sorttable.c index 9f41575afd7a..4a34c275123e 100644 --- a/scripts/sorttable.c +++ b/scripts/sorttable.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -79,10 +80,16 @@ typedef union { Elf64_Sym e64; } Elf_Sym; +typedef union { + Elf32_Rela e32; + Elf64_Rela e64; +} Elf_Rela; + static uint32_t (*r)(const uint32_t *); static uint16_t (*r2)(const uint16_t *); static uint64_t (*r8)(const uint64_t *); static void (*w)(uint32_t, uint32_t *); +static void (*w8)(uint64_t, uint64_t *); typedef void (*table_sort_t)(char *, int); static struct elf_funcs { @@ -102,6 +109,10 @@ static struct elf_funcs { uint32_t (*sym_name)(Elf_Sym *sym); uint64_t (*sym_value)(Elf_Sym *sym); uint16_t (*sym_shndx)(Elf_Sym *sym); + uint64_t (*rela_offset)(Elf_Rela *rela); + uint64_t (*rela_info)(Elf_Rela *rela); + uint64_t (*rela_addend)(Elf_Rela *rela); + void (*rela_write_addend)(Elf_Rela *rela, uint64_t val); } e; static uint64_t ehdr64_shoff(Elf_Ehdr *ehdr) @@ -262,6 +273,38 @@ SYM_ADDR(value) SYM_WORD(name) SYM_HALF(shndx) +#define __maybe_unused __attribute__((__unused__)) + +#define RELA_ADDR(fn_name) \ +static uint64_t rela64_##fn_name(Elf_Rela *rela) \ +{ \ + return r8((uint64_t *)&rela->e64.r_##fn_name); \ +} \ + \ +static uint64_t rela32_##fn_name(Elf_Rela *rela) \ +{ \ + return r((uint32_t *)&rela->e32.r_##fn_name); \ +} \ + \ +static uint64_t __maybe_unused rela_##fn_name(Elf_Rela *rela) \ +{ \ + return e.rela_##fn_name(rela); \ +} + +RELA_ADDR(offset) +RELA_ADDR(info) +RELA_ADDR(addend) + +static void rela64_write_addend(Elf_Rela *rela, uint64_t val) +{ + w8(val, (uint64_t *)&rela->e64.r_addend); +} + +static void rela32_write_addend(Elf_Rela *rela, uint64_t val) +{ + w(val, (uint32_t *)&rela->e32.r_addend); +} + /* * Get the whole file as a programming convenience in order to avoid * malloc+lseek+read+free of many pieces. If successful, then mmap @@ -341,6 +384,16 @@ static void wle(uint32_t val, uint32_t *x) put_unaligned_le32(val, x); } +static void w8be(uint64_t val, uint64_t *x) +{ + put_unaligned_be64(val, x); +} + +static void w8le(uint64_t val, uint64_t *x) +{ + put_unaligned_le64(val, x); +} + /* * Move reserved section indices SHN_LORESERVE..SHN_HIRESERVE out of * the way to -256..-1, to avoid conflicting with real section @@ -398,13 +451,12 @@ static inline void *get_index(void *start, int entsize, int index) static int extable_ent_size; static int long_size; +#define ERRSTR_MAXSZ 256 #ifdef UNWINDER_ORC_ENABLED /* ORC unwinder only support X86_64 */ #include -#define ERRSTR_MAXSZ 256 - static char g_err[ERRSTR_MAXSZ]; static int *g_orc_ip_table; static struct orc_entry *g_orc_table; @@ -499,7 +551,19 @@ static void *sort_orctable(void *arg) #endif #ifdef MCOUNT_SORT_ENABLED + +/* Only used for sorting mcount table */ +static void rela_write_addend(Elf_Rela *rela, uint64_t val) +{ + e.rela_write_addend(rela, val); +} + static pthread_t mcount_sort_thread; +static bool sort_reloc; + +static long rela_type; + +static char m_err[ERRSTR_MAXSZ]; struct elf_mcount_loc { Elf_Ehdr *ehdr; @@ -508,6 +572,103 @@ struct elf_mcount_loc { uint64_t stop_mcount_loc; }; +/* Sort the relocations not the address itself */ +static void *sort_relocs(Elf_Ehdr *ehdr, uint64_t start_loc, uint64_t size) +{ + Elf_Shdr *shdr_start; + Elf_Rela *rel; + unsigned int shnum; + unsigned int count; + int shentsize; + void *vals; + void *ptr; + + shdr_start = (Elf_Shdr *)((char *)ehdr + ehdr_shoff(ehdr)); + shentsize = ehdr_shentsize(ehdr); + + vals = malloc(long_size * size); + if (!vals) { + snprintf(m_err, ERRSTR_MAXSZ, "Failed to allocate sort array"); + pthread_exit(m_err); + return NULL; + } + + ptr = vals; + + shnum = ehdr_shnum(ehdr); + if (shnum == SHN_UNDEF) + shnum = shdr_size(shdr_start); + + for (int i = 0; i < shnum; i++) { + Elf_Shdr *shdr = get_index(shdr_start, shentsize, i); + void *end; + + if (shdr_type(shdr) != SHT_RELA) + continue; + + rel = (void *)ehdr + shdr_offset(shdr); + end = (void *)rel + shdr_size(shdr); + + for (; (void *)rel < end; rel = (void *)rel + shdr_entsize(shdr)) { + uint64_t offset = rela_offset(rel); + + if (offset >= start_loc && offset < start_loc + size) { + if (ptr + long_size > vals + size) { + free(vals); + snprintf(m_err, ERRSTR_MAXSZ, + "Too many relocations"); + pthread_exit(m_err); + return NULL; + } + + /* Make sure this has the correct type */ + if (rela_info(rel) != rela_type) { + free(vals); + snprintf(m_err, ERRSTR_MAXSZ, + "rela has type %lx but expected %lx\n", + (long)rela_info(rel), rela_type); + pthread_exit(m_err); + return NULL; + } + + if (long_size == 4) + *(uint32_t *)ptr = rela_addend(rel); + else + *(uint64_t *)ptr = rela_addend(rel); + ptr += long_size; + } + } + } + count = ptr - vals; + qsort(vals, count / long_size, long_size, compare_extable); + + ptr = vals; + for (int i = 0; i < shnum; i++) { + Elf_Shdr *shdr = get_index(shdr_start, shentsize, i); + void *end; + + if (shdr_type(shdr) != SHT_RELA) + continue; + + rel = (void *)ehdr + shdr_offset(shdr); + end = (void *)rel + shdr_size(shdr); + + for (; (void *)rel < end; rel = (void *)rel + shdr_entsize(shdr)) { + uint64_t offset = rela_offset(rel); + + if (offset >= start_loc && offset < start_loc + size) { + if (long_size == 4) + rela_write_addend(rel, *(uint32_t *)ptr); + else + rela_write_addend(rel, *(uint64_t *)ptr); + ptr += long_size; + } + } + } + free(vals); + return NULL; +} + /* Sort the addresses stored between __start_mcount_loc to __stop_mcount_loc in vmlinux */ static void *sort_mcount_loc(void *arg) { @@ -517,6 +678,9 @@ static void *sort_mcount_loc(void *arg) uint64_t count = emloc->stop_mcount_loc - emloc->start_mcount_loc; unsigned char *start_loc = (void *)emloc->ehdr + offset; + if (sort_reloc) + return sort_relocs(emloc->ehdr, emloc->start_mcount_loc, count); + qsort(start_loc, count/long_size, long_size, compare_extable); return NULL; } @@ -866,12 +1030,14 @@ static int do_file(char const *const fname, void *addr) r2 = r2le; r8 = r8le; w = wle; + w8 = w8le; break; case ELFDATA2MSB: r = rbe; r2 = r2be; r8 = r8be; w = wbe; + w8 = w8be; break; default: fprintf(stderr, "unrecognized ELF data encoding %d: %s\n", @@ -887,8 +1053,13 @@ static int do_file(char const *const fname, void *addr) } switch (r2(&ehdr->e32.e_machine)) { - case EM_386: case EM_AARCH64: +#ifdef MCOUNT_SORT_ENABLED + sort_reloc = true; + rela_type = 0x403; +#endif + /* fallthrough */ + case EM_386: case EM_LOONGARCH: case EM_RISCV: case EM_S390: @@ -932,6 +1103,10 @@ static int do_file(char const *const fname, void *addr) .sym_name = sym32_name, .sym_value = sym32_value, .sym_shndx = sym32_shndx, + .rela_offset = rela32_offset, + .rela_info = rela32_info, + .rela_addend = rela32_addend, + .rela_write_addend = rela32_write_addend, }; e = efuncs; @@ -965,6 +1140,10 @@ static int do_file(char const *const fname, void *addr) .sym_name = sym64_name, .sym_value = sym64_value, .sym_shndx = sym64_shndx, + .rela_offset = rela64_offset, + .rela_info = rela64_info, + .rela_addend = rela64_addend, + .rela_write_addend = rela64_write_addend, }; e = efuncs; From patchwork Thu Feb 13 16:20:49 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Steven Rostedt X-Patchwork-Id: 13973800 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 bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id E9F07C021A0 for ; Thu, 13 Feb 2025 17:44:31 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Content-Type:MIME-Version: References:Subject:Cc:To:From:Date:Message-ID:Reply-To: Content-Transfer-Encoding:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To: List-Owner; bh=/UbQxd2gHuwSazOzBCkfogNyge30ll4F/uTuo1uhry4=; b=m/DmsWvHrtubZf IeHO+Mt9Scyh6uat8UbiS9xsTYeBsYhJvG5od9yY6jSyOdfu33dvkAx9UqBjnblR/jkisuzokCKci BclEy3pf9I0wCLPZQ26Q3MPwQavIRarBm2xvVH955fGLpllt/yXQvrEA2R3CFkIwfdObwTUZm4j3G qrMwobI6QoAAWEi/wJrcRMvUqqySwOkhWb8C8Zmbj2CHNC0vJYiSW1UYBehvCE08Zjm5AzedC9b38 f5o1YSszzFV7kQWIegKDJmER6SAKiF3hZNBmHngXGGBxH9tu01fg4pVKiMtkV16QPVrGAgn2dYBzW WldOWE1Mm4NBVhmbq8XA==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.98 #2 (Red Hat Linux)) id 1tidGA-0000000C3jn-0vpj; Thu, 13 Feb 2025 17:44:22 +0000 Received: from dfw.source.kernel.org ([139.178.84.217]) by bombadil.infradead.org with esmtps (Exim 4.98 #2 (Red Hat Linux)) id 1tiby4-0000000Bk9n-3DsE for linux-arm-kernel@lists.infradead.org; Thu, 13 Feb 2025 16:21:38 +0000 Received: from smtp.kernel.org (transwarp.subspace.kernel.org [100.75.92.58]) by dfw.source.kernel.org (Postfix) with ESMTP id 60DC05C5846; Thu, 13 Feb 2025 16:20:56 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 5E7BDC4CEE8; Thu, 13 Feb 2025 16:21:35 +0000 (UTC) Received: from rostedt by gandalf with local (Exim 4.98) (envelope-from ) id 1tibyD-00000001qb0-3M01; Thu, 13 Feb 2025 11:21:45 -0500 Message-ID: <20250213162145.652220571@goodmis.org> User-Agent: quilt/0.68 Date: Thu, 13 Feb 2025 11:20:49 -0500 From: Steven Rostedt To: linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org, linux-kbuild@vger.kernel.org, bpf , linux-arm-kernel@lists.infradead.org, linux-s390@vger.kernel.org Cc: Masami Hiramatsu , Mark Rutland , Mathieu Desnoyers , Andrew Morton , Peter Zijlstra , Linus Torvalds , Masahiro Yamada , Nathan Chancellor , Nicolas Schier , Zheng Yejian , Martin Kelly , Christophe Leroy , Josh Poimboeuf , Heiko Carstens , Catalin Marinas , Will Deacon , Vasily Gorbik , Alexander Gordeev Subject: [PATCH v3 2/6] scripts/sorttable: Have mcount rela sort use direct values References: <20250213162047.306074881@goodmis.org> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20250213_082136_929602_990EB04D X-CRM114-Status: GOOD ( 16.49 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org From: Steven Rostedt The mcount_loc sorting for when the values are stored in the Elf_Rela entries uses the compare_extable() function to do the compares in the qsort(). That function does handle byte swapping if the machine being compiled for is a different endian than the host machine. But the sort_relocs() function sorts an array that pulled in the values from the Elf_Rela section and has already done the swapping. Create two new compare functions that will sort the direct values. One will sort 32 bit values and the other will sort the 64 bit value. One of these will be assigned to a compare_values function pointer and that will be used for sorting the Elf_Rela mcount values. Signed-off-by: Steven Rostedt (Google) --- scripts/sorttable.c | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/scripts/sorttable.c b/scripts/sorttable.c index 4a34c275123e..f62a91d8af0a 100644 --- a/scripts/sorttable.c +++ b/scripts/sorttable.c @@ -552,6 +552,28 @@ static void *sort_orctable(void *arg) #ifdef MCOUNT_SORT_ENABLED +static int compare_values_64(const void *a, const void *b) +{ + uint64_t av = *(uint64_t *)a; + uint64_t bv = *(uint64_t *)b; + + if (av < bv) + return -1; + return av > bv; +} + +static int compare_values_32(const void *a, const void *b) +{ + uint32_t av = *(uint32_t *)a; + uint32_t bv = *(uint32_t *)b; + + if (av < bv) + return -1; + return av > bv; +} + +static int (*compare_values)(const void *a, const void *b); + /* Only used for sorting mcount table */ static void rela_write_addend(Elf_Rela *rela, uint64_t val) { @@ -583,6 +605,8 @@ static void *sort_relocs(Elf_Ehdr *ehdr, uint64_t start_loc, uint64_t size) void *vals; void *ptr; + compare_values = long_size == 4 ? compare_values_32 : compare_values_64; + shdr_start = (Elf_Shdr *)((char *)ehdr + ehdr_shoff(ehdr)); shentsize = ehdr_shentsize(ehdr); @@ -640,7 +664,7 @@ static void *sort_relocs(Elf_Ehdr *ehdr, uint64_t start_loc, uint64_t size) } } count = ptr - vals; - qsort(vals, count / long_size, long_size, compare_extable); + qsort(vals, count / long_size, long_size, compare_values); ptr = vals; for (int i = 0; i < shnum; i++) { From patchwork Thu Feb 13 16:20:50 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Steven Rostedt X-Patchwork-Id: 13973803 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 bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 62B74C021A4 for ; Thu, 13 Feb 2025 17:48:57 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Content-Type:MIME-Version: References:Subject:Cc:To:From:Date:Message-ID:Reply-To: Content-Transfer-Encoding:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To: List-Owner; bh=5RbhS+zMfnJaqNmZ2hrpoGWgBgTc8EWmgM+o7CODprw=; b=UkCSf8Y+oTR0+5 TtPP6ArNGUnmP0uFwHuJ+LaWmiWkqNpvkd6Xv2PyO6r3H5zhjNqOQ+U6ku+psJIlGVOELKBd82NqD Wwi49dxnKcEgNl1Ua5iBTcwggPC2B44xO3Vgp/9IzfTikqHnWRNM+x1bZh2bEmT4T4I4XZmkxmE66 eMzyfdrHrxusNwwTBMToOkDFJDDQ21psNlkNSTXYaXrHj8j9W6aclqr7DAYF/QIygG3EEhaP1MS+j EWiNJIvdBO9UxH6GDzKeNZcob6tgYqZlmmURZDojsjK0zkGCW6UamvUPz9XvF4REhXduYnraSZmS8 +9oCaHLX0G4URxJB+YFw==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.98 #2 (Red Hat Linux)) id 1tidKO-0000000C4mV-0kMc; Thu, 13 Feb 2025 17:48:44 +0000 Received: from desiato.infradead.org ([2001:8b0:10b:1:d65d:64ff:fe57:4e05]) by bombadil.infradead.org with esmtps (Exim 4.98 #2 (Red Hat Linux)) id 1tibyC-0000000BkD5-1hHc for linux-arm-kernel@bombadil.infradead.org; Thu, 13 Feb 2025 16:21:44 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=desiato.20200630; h=Content-Type:MIME-Version:References: Subject:Cc:To:From:Date:Message-ID:Sender:Reply-To:Content-Transfer-Encoding: Content-ID:Content-Description:In-Reply-To; bh=5RbhS+zMfnJaqNmZ2hrpoGWgBgTc8EWmgM+o7CODprw=; b=IOkPOQ+wTziw3vWq8OMGaTQfMm CU66ugZj21YuwH7lehDL6ZwUJXJlNcp8bfIrkdS6WSMqSZw0ibSVEdrQYUCtEzFwEKktIJQVJcOpH Ofb7qBI+IzBWHGdH3YK8z5x4nHT0OkOOa7Hm7wE3vuTGV1gcDV+shHkoKSlzb0wTAhtWvg4QbTkLw DJhfeTw/6axcsL0wbCCcF9sBpuA/1NNv2k5m/C/JYKm5baVqzP85kZcPUuBLem8eNxshCoKLMihrg BIbAdpZJ2ZC3L2FR9Fsti8rLgIFgGWekiqhblygJSU22tYa7TQOAPYa5AnloR8ln6IE0xoUJPRkg8 d0VoxeUA==; Received: from dfw.source.kernel.org ([2604:1380:4641:c500::1]) by desiato.infradead.org with esmtps (Exim 4.98 #2 (Red Hat Linux)) id 1tiby8-000000012ru-3lTi for linux-arm-kernel@lists.infradead.org; Thu, 13 Feb 2025 16:21:43 +0000 Received: from smtp.kernel.org (transwarp.subspace.kernel.org [100.75.92.58]) by dfw.source.kernel.org (Postfix) with ESMTP id 657DC5C5849; Thu, 13 Feb 2025 16:20:56 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 6C06BC4CEED; Thu, 13 Feb 2025 16:21:35 +0000 (UTC) Received: from rostedt by gandalf with local (Exim 4.98) (envelope-from ) id 1tibyD-00000001qbV-43ID; Thu, 13 Feb 2025 11:21:45 -0500 Message-ID: <20250213162145.821148283@goodmis.org> User-Agent: quilt/0.68 Date: Thu, 13 Feb 2025 11:20:50 -0500 From: Steven Rostedt To: linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org, linux-kbuild@vger.kernel.org, bpf , linux-arm-kernel@lists.infradead.org, linux-s390@vger.kernel.org Cc: Masami Hiramatsu , Mark Rutland , Mathieu Desnoyers , Andrew Morton , Peter Zijlstra , Linus Torvalds , Masahiro Yamada , Nathan Chancellor , Nicolas Schier , Zheng Yejian , Martin Kelly , Christophe Leroy , Josh Poimboeuf , Heiko Carstens , Catalin Marinas , Will Deacon , Vasily Gorbik , Alexander Gordeev Subject: [PATCH v3 3/6] scripts/sorttable: Always use an array for the mcount_loc sorting References: <20250213162047.306074881@goodmis.org> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20250213_162141_357490_1AA4BC6E X-CRM114-Status: GOOD ( 21.06 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org From: Steven Rostedt The sorting of the mcount_loc section is done directly to the section for x86 and arm32 but it uses a separate array for arm64 as arm64 has the values for the mcount_loc stored in the rela sections of the vmlinux ELF file. In order to use the same code to remove weak functions, always use a separate array to do the sorting. This requires splitting up the filling of the array into one function and the placing the contents of the array back into the rela sections or into the mcount_loc section into a separate file. Signed-off-by: Steven Rostedt (Google) --- scripts/sorttable.c | 122 ++++++++++++++++++++++++++++++++------------ 1 file changed, 90 insertions(+), 32 deletions(-) diff --git a/scripts/sorttable.c b/scripts/sorttable.c index f62a91d8af0a..ec02a2852efb 100644 --- a/scripts/sorttable.c +++ b/scripts/sorttable.c @@ -594,31 +594,19 @@ struct elf_mcount_loc { uint64_t stop_mcount_loc; }; -/* Sort the relocations not the address itself */ -static void *sort_relocs(Elf_Ehdr *ehdr, uint64_t start_loc, uint64_t size) +/* Fill the array with the content of the relocs */ +static int fill_relocs(void *ptr, uint64_t size, Elf_Ehdr *ehdr, uint64_t start_loc) { Elf_Shdr *shdr_start; Elf_Rela *rel; unsigned int shnum; - unsigned int count; + unsigned int count = 0; int shentsize; - void *vals; - void *ptr; - - compare_values = long_size == 4 ? compare_values_32 : compare_values_64; + void *array_end = ptr + size; shdr_start = (Elf_Shdr *)((char *)ehdr + ehdr_shoff(ehdr)); shentsize = ehdr_shentsize(ehdr); - vals = malloc(long_size * size); - if (!vals) { - snprintf(m_err, ERRSTR_MAXSZ, "Failed to allocate sort array"); - pthread_exit(m_err); - return NULL; - } - - ptr = vals; - shnum = ehdr_shnum(ehdr); if (shnum == SHN_UNDEF) shnum = shdr_size(shdr_start); @@ -637,22 +625,18 @@ static void *sort_relocs(Elf_Ehdr *ehdr, uint64_t start_loc, uint64_t size) uint64_t offset = rela_offset(rel); if (offset >= start_loc && offset < start_loc + size) { - if (ptr + long_size > vals + size) { - free(vals); + if (ptr + long_size > array_end) { snprintf(m_err, ERRSTR_MAXSZ, "Too many relocations"); - pthread_exit(m_err); - return NULL; + return -1; } /* Make sure this has the correct type */ if (rela_info(rel) != rela_type) { - free(vals); snprintf(m_err, ERRSTR_MAXSZ, "rela has type %lx but expected %lx\n", (long)rela_info(rel), rela_type); - pthread_exit(m_err); - return NULL; + return -1; } if (long_size == 4) @@ -660,13 +644,28 @@ static void *sort_relocs(Elf_Ehdr *ehdr, uint64_t start_loc, uint64_t size) else *(uint64_t *)ptr = rela_addend(rel); ptr += long_size; + count++; } } } - count = ptr - vals; - qsort(vals, count / long_size, long_size, compare_values); + return count; +} + +/* Put the sorted vals back into the relocation elements */ +static void replace_relocs(void *ptr, uint64_t size, Elf_Ehdr *ehdr, uint64_t start_loc) +{ + Elf_Shdr *shdr_start; + Elf_Rela *rel; + unsigned int shnum; + int shentsize; + + shdr_start = (Elf_Shdr *)((char *)ehdr + ehdr_shoff(ehdr)); + shentsize = ehdr_shentsize(ehdr); + + shnum = ehdr_shnum(ehdr); + if (shnum == SHN_UNDEF) + shnum = shdr_size(shdr_start); - ptr = vals; for (int i = 0; i < shnum; i++) { Elf_Shdr *shdr = get_index(shdr_start, shentsize, i); void *end; @@ -689,8 +688,32 @@ static void *sort_relocs(Elf_Ehdr *ehdr, uint64_t start_loc, uint64_t size) } } } - free(vals); - return NULL; +} + +static int fill_addrs(void *ptr, uint64_t size, void *addrs) +{ + void *end = ptr + size; + int count = 0; + + for (; ptr < end; ptr += long_size, addrs += long_size, count++) { + if (long_size == 4) + *(uint32_t *)ptr = r(addrs); + else + *(uint64_t *)ptr = r8(addrs); + } + return count; +} + +static void replace_addrs(void *ptr, uint64_t size, void *addrs) +{ + void *end = ptr + size; + + for (; ptr < end; ptr += long_size, addrs += long_size) { + if (long_size == 4) + w(*(uint32_t *)ptr, addrs); + else + w8(*(uint64_t *)ptr, addrs); + } } /* Sort the addresses stored between __start_mcount_loc to __stop_mcount_loc in vmlinux */ @@ -699,14 +722,49 @@ static void *sort_mcount_loc(void *arg) struct elf_mcount_loc *emloc = (struct elf_mcount_loc *)arg; uint64_t offset = emloc->start_mcount_loc - shdr_addr(emloc->init_data_sec) + shdr_offset(emloc->init_data_sec); - uint64_t count = emloc->stop_mcount_loc - emloc->start_mcount_loc; + uint64_t size = emloc->stop_mcount_loc - emloc->start_mcount_loc; unsigned char *start_loc = (void *)emloc->ehdr + offset; + Elf_Ehdr *ehdr = emloc->ehdr; + void *e_msg = NULL; + void *vals; + int count; + + vals = malloc(long_size * size); + if (!vals) { + snprintf(m_err, ERRSTR_MAXSZ, "Failed to allocate sort array"); + pthread_exit(m_err); + } if (sort_reloc) - return sort_relocs(emloc->ehdr, emloc->start_mcount_loc, count); + count = fill_relocs(vals, size, ehdr, emloc->start_mcount_loc); + else + count = fill_addrs(vals, size, start_loc); + + if (count < 0) { + e_msg = m_err; + goto out; + } + + if (count != size / long_size) { + snprintf(m_err, ERRSTR_MAXSZ, "Expected %u mcount elements but found %u\n", + (int)(size / long_size), count); + e_msg = m_err; + goto out; + } + + compare_values = long_size == 4 ? compare_values_32 : compare_values_64; + + qsort(vals, count, long_size, compare_values); + + if (sort_reloc) + replace_relocs(vals, size, ehdr, emloc->start_mcount_loc); + else + replace_addrs(vals, size, start_loc); + +out: + free(vals); - qsort(start_loc, count/long_size, long_size, compare_extable); - return NULL; + pthread_exit(e_msg); } /* Get the address of __start_mcount_loc and __stop_mcount_loc in System.map */ From patchwork Thu Feb 13 16:20:51 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Steven Rostedt X-Patchwork-Id: 13973804 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 bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 6F5E8C021A0 for ; Thu, 13 Feb 2025 17:50:22 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Content-Type:MIME-Version: References:Subject:Cc:To:From:Date:Message-ID:Reply-To: Content-Transfer-Encoding:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To: List-Owner; bh=dXLLnRzv7FaM6gojcEQsfUmISkNhfeQtV1FeCi0KCOk=; b=Cc7i2YC0D72M1/ QII4jalngwCMuM47O11ZFC8i/Un4EKaEJaEe87ygGpWYnhMmY2rJN8mRg4qMbc8gDP5jUubFNRtrJ NHoX0wxDb91jU5q8JMUQefnajibkfBXnVwOoj6MIzV6ekyBBgJySQ6gqr+lMSw3XjLebNKjEt9Vwg AzAA8FrNUA12dta1vroUoFzTJo7Hi6mkHXnzScQZKXJHMJe7FZMscZYIRdBmqoO8gf4EKKN8OLduo T9ZMX8G0ntuB3UQgrizlQ/iFXBXFNT0K3louSgQPCIihevNlyhgSlkKN9KGpN21SeISx0r8fuj9/H niGVMEjBYdcrB2XaciGA==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.98 #2 (Red Hat Linux)) id 1tidLm-0000000C4tZ-3fY1; Thu, 13 Feb 2025 17:50:10 +0000 Received: from desiato.infradead.org ([2001:8b0:10b:1:d65d:64ff:fe57:4e05]) by bombadil.infradead.org with esmtps (Exim 4.98 #2 (Red Hat Linux)) id 1tibyC-0000000BkD9-25uu for linux-arm-kernel@bombadil.infradead.org; Thu, 13 Feb 2025 16:21:44 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=desiato.20200630; h=Content-Type:MIME-Version:References: Subject:Cc:To:From:Date:Message-ID:Sender:Reply-To:Content-Transfer-Encoding: Content-ID:Content-Description:In-Reply-To; bh=dXLLnRzv7FaM6gojcEQsfUmISkNhfeQtV1FeCi0KCOk=; b=UXdot7EORax5NpMh3ntvwOY4En U7rDQpd1DCTUd9SmnqXLRag8cG4VSRjzzSs9hg+GUUu8ddFWHzN+n3VOrQphC+2a8sE8ndbk/mJRO jZ3/RCHqZJUU/fP9miVUtR1RakVltUFsnGFOTbGIYzWBbafBek3D+lj8AL325sgJKTT8Pz/w6DPl4 EXXJFDJngiyDcBbzbZWpY7DjityUMyRh6M3p4XnyAFnmldLP60ZwMRqwR9zXOhkeldiGEfercnzig vbdheYiW/GYjF8WCfKntOaqonVNTNOos/KAtB6gTUjAh/EyxQF4qQ8+RP7+tV77DIh2tj8cPwNTQp lPXkVl9A==; Received: from nyc.source.kernel.org ([147.75.193.91]) by desiato.infradead.org with esmtps (Exim 4.98 #2 (Red Hat Linux)) id 1tiby8-000000012rs-1o8l for linux-arm-kernel@lists.infradead.org; Thu, 13 Feb 2025 16:21:43 +0000 Received: from smtp.kernel.org (transwarp.subspace.kernel.org [100.75.92.58]) by nyc.source.kernel.org (Postfix) with ESMTP id DE7B1A40122; Thu, 13 Feb 2025 16:19:50 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 9B8FDC4CEE5; Thu, 13 Feb 2025 16:21:35 +0000 (UTC) Received: from rostedt by gandalf with local (Exim 4.98) (envelope-from ) id 1tibyE-00000001qbz-0Zdm; Thu, 13 Feb 2025 11:21:46 -0500 Message-ID: <20250213162145.986887092@goodmis.org> User-Agent: quilt/0.68 Date: Thu, 13 Feb 2025 11:20:51 -0500 From: Steven Rostedt To: linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org, linux-kbuild@vger.kernel.org, bpf , linux-arm-kernel@lists.infradead.org, linux-s390@vger.kernel.org Cc: Masami Hiramatsu , Mark Rutland , Mathieu Desnoyers , Andrew Morton , Peter Zijlstra , Linus Torvalds , Masahiro Yamada , Nathan Chancellor , Nicolas Schier , Zheng Yejian , Martin Kelly , Christophe Leroy , Josh Poimboeuf , Heiko Carstens , Catalin Marinas , Will Deacon , Vasily Gorbik , Alexander Gordeev Subject: [PATCH v3 4/6] scripts/sorttable: Zero out weak functions in mcount_loc table References: <20250213162047.306074881@goodmis.org> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20250213_162140_849969_C7A20D5A X-CRM114-Status: GOOD ( 37.85 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org From: Steven Rostedt When a function is annotated as "weak" and is overridden, the code is not removed. If it is traced, the fentry/mcount location in the weak function will be referenced by the "__mcount_loc" section. This will then be added to the available_filter_functions list. Since only the address of the functions are listed, to find the name to show, a search of kallsyms is used. Since kallsyms will return the function by simply finding the function that the address is after but before the next function, an address of a weak function will show up as the function before it. This is because kallsyms does not save names of weak functions. This has caused issues in the past, as now the traced weak function will be listed in available_filter_functions with the name of the function before it. At best, this will cause the previous function's name to be listed twice. At worse, if the previous function was marked notrace, it will now show up as a function that can be traced. Note that it only shows up that it can be traced but will not be if enabled, which causes confusion. https://lore.kernel.org/all/20220412094923.0abe90955e5db486b7bca279@kernel.org/ The commit b39181f7c6907 ("ftrace: Add FTRACE_MCOUNT_MAX_OFFSET to avoid adding weak function") was a workaround to this by checking the function address before printing its name. If the address was too far from the function given by the name then instead of printing the name it would print: __ftrace_invalid_address___ The real issue is that these invalid addresses are listed in the ftrace table look up which available_filter_functions is derived from. A place holder must be listed in that file because set_ftrace_filter may take a series of indexes into that file instead of names to be able to do O(1) lookups to enable filtering (many tools use this method). Even if kallsyms saved the size of the function, it does not remove the need of having these place holders. The real solution is to not add a weak function into the ftrace table in the first place. To solve this, the sorttable.c code that sorts the mcount regions during the build is modified to take a "nm -S vmlinux" input, sort it, and any function listed in the mcount_loc section that is not within a boundary of the function list given by nm is considered a weak function and is zeroed out. Note, this does not mean they will remain zero when booting as KASLR will still shift those addresses. To handle this, the entries in the mcount_loc section will be ignored if they are zero or match the kaslr_offset() value. Before: ~# grep __ftrace_invalid_address___ /sys/kernel/tracing/available_filter_functions | wc -l 551 After: ~# grep __ftrace_invalid_address___ /sys/kernel/tracing/available_filter_functions | wc -l 0 Signed-off-by: Steven Rostedt (Google) --- Changes since v2: https://lore.kernel.org/20250102232651.173687711@goodmis.org - Removed need for adding a special "skip" variable which removes this patch https://lore.kernel.org/linux-trace-kernel/20250102232651.347490863@goodmis.org/ - Instead, check the kaslr_offset() against the value in the section. If the value is either zero or kaslr_offset() then simply skip it. - Built on top of the allocation of an array and not directly access the section itself. kernel/trace/ftrace.c | 6 +- scripts/link-vmlinux.sh | 4 +- scripts/sorttable.c | 128 +++++++++++++++++++++++++++++++++++++++- 3 files changed, 134 insertions(+), 4 deletions(-) diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index 728ecda6e8d4..e3f89924f603 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c @@ -7004,6 +7004,7 @@ static int ftrace_process_locs(struct module *mod, unsigned long count; unsigned long *p; unsigned long addr; + unsigned long kaslr; unsigned long flags = 0; /* Shut up gcc */ int ret = -ENOMEM; @@ -7052,6 +7053,9 @@ static int ftrace_process_locs(struct module *mod, ftrace_pages->next = start_pg; } + /* For zeroed locations that were shifted for core kernel */ + kaslr = !mod ? kaslr_offset() : 0; + p = start; pg = start_pg; while (p < end) { @@ -7063,7 +7067,7 @@ static int ftrace_process_locs(struct module *mod, * object files to satisfy alignments. * Skip any NULL pointers. */ - if (!addr) { + if (!addr || addr == kaslr) { skipped++; continue; } diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh index 56a077d204cf..59b07fe6fd00 100755 --- a/scripts/link-vmlinux.sh +++ b/scripts/link-vmlinux.sh @@ -177,12 +177,14 @@ mksysmap() sorttable() { - ${objtree}/scripts/sorttable ${1} + ${NM} -S ${1} > .tmp_vmlinux.nm-sort + ${objtree}/scripts/sorttable -s .tmp_vmlinux.nm-sort ${1} } cleanup() { rm -f .btf.* + rm -f .tmp_vmlinux.nm-sort rm -f System.map rm -f vmlinux rm -f vmlinux.map diff --git a/scripts/sorttable.c b/scripts/sorttable.c index ec02a2852efb..1647c5887e95 100644 --- a/scripts/sorttable.c +++ b/scripts/sorttable.c @@ -580,6 +580,98 @@ static void rela_write_addend(Elf_Rela *rela, uint64_t val) e.rela_write_addend(rela, val); } +struct func_info { + uint64_t addr; + uint64_t size; +}; + +/* List of functions created by: nm -S vmlinux */ +static struct func_info *function_list; +static int function_list_size; + +/* Allocate functions in 1k blocks */ +#define FUNC_BLK_SIZE 1024 +#define FUNC_BLK_MASK (FUNC_BLK_SIZE - 1) + +static int add_field(uint64_t addr, uint64_t size) +{ + struct func_info *fi; + int fsize = function_list_size; + + if (!(fsize & FUNC_BLK_MASK)) { + fsize += FUNC_BLK_SIZE; + fi = realloc(function_list, fsize * sizeof(struct func_info)); + if (!fi) + return -1; + function_list = fi; + } + fi = &function_list[function_list_size++]; + fi->addr = addr; + fi->size = size; + return 0; +} + +/* Only return match if the address lies inside the function size */ +static int cmp_func_addr(const void *K, const void *A) +{ + uint64_t key = *(const uint64_t *)K; + const struct func_info *a = A; + + if (key < a->addr) + return -1; + return key >= a->addr + a->size; +} + +/* Find the function in function list that is bounded by the function size */ +static int find_func(uint64_t key) +{ + return bsearch(&key, function_list, function_list_size, + sizeof(struct func_info), cmp_func_addr) != NULL; +} + +static int cmp_funcs(const void *A, const void *B) +{ + const struct func_info *a = A; + const struct func_info *b = B; + + if (a->addr < b->addr) + return -1; + return a->addr > b->addr; +} + +static int parse_symbols(const char *fname) +{ + FILE *fp; + char addr_str[20]; /* Only need 17, but round up to next int size */ + char size_str[20]; + char type; + + fp = fopen(fname, "r"); + if (!fp) { + perror(fname); + return -1; + } + + while (fscanf(fp, "%16s %16s %c %*s\n", addr_str, size_str, &type) == 3) { + uint64_t addr; + uint64_t size; + + /* Only care about functions */ + if (type != 't' && type != 'T') + continue; + + addr = strtoull(addr_str, NULL, 16); + size = strtoull(size_str, NULL, 16); + if (add_field(addr, size) < 0) + return -1; + } + fclose(fp); + + qsort(function_list, function_list_size, sizeof(struct func_info), cmp_funcs); + + return 0; +} + static pthread_t mcount_sort_thread; static bool sort_reloc; @@ -752,6 +844,21 @@ static void *sort_mcount_loc(void *arg) goto out; } + /* zero out any locations not found by function list */ + if (function_list_size) { + for (void *ptr = vals; ptr < vals + size; ptr += long_size) { + uint64_t key; + + key = long_size == 4 ? r((uint32_t *)ptr) : r8((uint64_t *)ptr); + if (!find_func(key)) { + if (long_size == 4) + *(uint32_t *)ptr = 0; + else + *(uint64_t *)ptr = 0; + } + } + } + compare_values = long_size == 4 ? compare_values_32 : compare_values_64; qsort(vals, count, long_size, compare_values); @@ -801,6 +908,8 @@ static void get_mcount_loc(struct elf_mcount_loc *emloc, Elf_Shdr *symtab_sec, return; } } +#else /* MCOUNT_SORT_ENABLED */ +static inline int parse_symbols(const char *fname) { return 0; } #endif static int do_sort(Elf_Ehdr *ehdr, @@ -1256,14 +1365,29 @@ int main(int argc, char *argv[]) int i, n_error = 0; /* gcc-4.3.0 false positive complaint */ size_t size = 0; void *addr = NULL; + int c; + + while ((c = getopt(argc, argv, "s:")) >= 0) { + switch (c) { + case 's': + if (parse_symbols(optarg) < 0) { + fprintf(stderr, "Could not parse %s\n", optarg); + return -1; + } + break; + default: + fprintf(stderr, "usage: sorttable [-s nm-file] vmlinux...\n"); + return 0; + } + } - if (argc < 2) { + if ((argc - optind) < 1) { fprintf(stderr, "usage: sorttable vmlinux...\n"); return 0; } /* Process each file in turn, allowing deep failure. */ - for (i = 1; i < argc; i++) { + for (i = optind; i < argc; i++) { addr = mmap_file(argv[i], &size); if (!addr) { ++n_error; From patchwork Thu Feb 13 16:20:52 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Steven Rostedt X-Patchwork-Id: 13973802 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 bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id B6479C021A0 for ; Thu, 13 Feb 2025 17:47:26 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Content-Type:MIME-Version: References:Subject:Cc:To:From:Date:Message-ID:Reply-To: Content-Transfer-Encoding:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To: List-Owner; bh=5GzUE8+22PDvx9TU35PcoTRaUTTz7IbxNCev5oEIp2I=; b=Z3ZDN7eoXzeCr5 FZxr1vpJe5fKr+UPbiXk/66+NEXwhV7KCJQ2F9L6EWn2ek6GM4vPd5jNdVDmR+sruuXN8hGIrYkAZ gD2RcCDS/I3GySDiSwQzRhnQ8pTDSZ/2vrL1ffZFk8A0m3elj2700gbIBUHo7h9EKXrREdWSo37aj oz7ikwkNvEnobaFZJ7WKcn0czb7I8xi4HDw17QAsMMq1I65C4rwGdv0kJwag+MUtitn16HAY7w9PB jMpfBp4CDKLvl322NkjSq7oymJEWNeRRu1rMCCX55udAoIZqzs8gU/yAbdy0jKgfvf4gOqXZNvK73 kojDby6DgtDm2B2z91DA==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.98 #2 (Red Hat Linux)) id 1tidIy-0000000C4XK-2IHY; Thu, 13 Feb 2025 17:47:16 +0000 Received: from dfw.source.kernel.org ([139.178.84.217]) by bombadil.infradead.org with esmtps (Exim 4.98 #2 (Red Hat Linux)) id 1tiby6-0000000BkBN-1LMP for linux-arm-kernel@lists.infradead.org; Thu, 13 Feb 2025 16:21:39 +0000 Received: from smtp.kernel.org (transwarp.subspace.kernel.org [100.75.92.58]) by dfw.source.kernel.org (Postfix) with ESMTP id 977BB5C5854; Thu, 13 Feb 2025 16:20:56 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id DF2A0C4CED1; Thu, 13 Feb 2025 16:21:35 +0000 (UTC) Received: from rostedt by gandalf with local (Exim 4.98) (envelope-from ) id 1tibyE-00000001qcT-1IiE; Thu, 13 Feb 2025 11:21:46 -0500 Message-ID: <20250213162146.158076547@goodmis.org> User-Agent: quilt/0.68 Date: Thu, 13 Feb 2025 11:20:52 -0500 From: Steven Rostedt To: linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org, linux-kbuild@vger.kernel.org, bpf , linux-arm-kernel@lists.infradead.org, linux-s390@vger.kernel.org Cc: Masami Hiramatsu , Mark Rutland , Mathieu Desnoyers , Andrew Morton , Peter Zijlstra , Linus Torvalds , Masahiro Yamada , Nathan Chancellor , Nicolas Schier , Zheng Yejian , Martin Kelly , Christophe Leroy , Josh Poimboeuf , Heiko Carstens , Catalin Marinas , Will Deacon , Vasily Gorbik , Alexander Gordeev Subject: [PATCH v3 5/6] ftrace: Update the mcount_loc check of skipped entries References: <20250213162047.306074881@goodmis.org> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20250213_082138_431226_21405D53 X-CRM114-Status: GOOD ( 14.14 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org From: Steven Rostedt Now that weak functions turn into skipped entries, update the check to make sure the amount that was allocated would fit both the entries that were allocated as well as those that were skipped. Signed-off-by: Steven Rostedt (Google) --- kernel/trace/ftrace.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index e3f89924f603..55d28c060784 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c @@ -7111,7 +7111,29 @@ static int ftrace_process_locs(struct module *mod, /* We should have used all pages unless we skipped some */ if (pg_unuse) { - WARN_ON(!skipped); + unsigned long pg_remaining, remaining; + unsigned long skip; + + /* Count the number of entries unused and compare it to skipped. */ + pg_remaining = (ENTRIES_PER_PAGE << pg->order) - pg->index; + + if (!WARN(skipped < pg_remaining, "Extra allocated pages for ftrace")) { + + skip = skipped - pg_remaining; + + for (pg = pg_unuse; pg; pg = pg->next) { + remaining += 1 << pg->order; + } + + skip = DIV_ROUND_UP(skip, ENTRIES_PER_PAGE); + + /* + * Check to see if the number of pages remaining would + * just fit the number of entries skipped. + */ + WARN(skip != remaining, "Extra allocated pages for ftrace: %lu with %lu skipped", + remaining, skipped); + } /* Need to synchronize with ftrace_location_range() */ synchronize_rcu(); ftrace_free_pages(pg_unuse); From patchwork Thu Feb 13 16:20:53 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Steven Rostedt X-Patchwork-Id: 13973801 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 bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 69104C021A4 for ; Thu, 13 Feb 2025 17:46:00 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender:List-Subscribe:List-Help :List-Post:List-Archive:List-Unsubscribe:List-Id:Content-Type:MIME-Version: References:Subject:Cc:To:From:Date:Message-ID:Reply-To: Content-Transfer-Encoding:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To: List-Owner; bh=0/mDtlBikO57slA120u7KN6mjQODM33+MQPnGr4fUrc=; b=dABXJIUdZPvEBJ ad1Y5ksAzzMDlsmG+A0ZKP61rLQR8wHvbiZaheGh9uzPb4AKPn46L1LntnHpkAv2bCAppgBw3IygC BZi31TVKkbYjgdkgqADVyUY5lJKKESJ904BqcqiJAESBhRAKUNqJir0djhMKty/XdvhsGKC+jlmXM LFv+Vk78SHwybDVHUyXA0+tCXun53LoBunoxMlEcjTEwhHm4UXgNA24O5IK0wifFBS2VWXf8wlDXr qhgwNe9+nC02aiMdqOjICyTt1f8mOsp+MxOqdjOYNMSeNWk6GJNIVp0rDWRh1vke9wFu6/83k1X3m djOVk5dQoEKiqdoApV2Q==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.98 #2 (Red Hat Linux)) id 1tidHY-0000000C47K-3Zov; Thu, 13 Feb 2025 17:45:48 +0000 Received: from dfw.source.kernel.org ([139.178.84.217]) by bombadil.infradead.org with esmtps (Exim 4.98 #2 (Red Hat Linux)) id 1tiby5-0000000BkAi-1itk for linux-arm-kernel@lists.infradead.org; Thu, 13 Feb 2025 16:21:39 +0000 Received: from smtp.kernel.org (transwarp.subspace.kernel.org [100.75.92.58]) by dfw.source.kernel.org (Postfix) with ESMTP id 9C7995C5857; Thu, 13 Feb 2025 16:20:56 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 006D4C4CEE7; Thu, 13 Feb 2025 16:21:36 +0000 (UTC) Received: from rostedt by gandalf with local (Exim 4.98) (envelope-from ) id 1tibyE-00000001qcx-21Ty; Thu, 13 Feb 2025 11:21:46 -0500 Message-ID: <20250213162146.332262157@goodmis.org> User-Agent: quilt/0.68 Date: Thu, 13 Feb 2025 11:20:53 -0500 From: Steven Rostedt To: linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org, linux-kbuild@vger.kernel.org, bpf , linux-arm-kernel@lists.infradead.org, linux-s390@vger.kernel.org Cc: Masami Hiramatsu , Mark Rutland , Mathieu Desnoyers , Andrew Morton , Peter Zijlstra , Linus Torvalds , Masahiro Yamada , Nathan Chancellor , Nicolas Schier , Zheng Yejian , Martin Kelly , Christophe Leroy , Josh Poimboeuf , Heiko Carstens , Catalin Marinas , Will Deacon , Vasily Gorbik , Alexander Gordeev Subject: [PATCH v3 6/6] ftrace: Have ftrace pages output reflect freed pages References: <20250213162047.306074881@goodmis.org> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20250213_082137_533698_8D99A4E1 X-CRM114-Status: GOOD ( 16.65 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org From: Steven Rostedt The amount of memory that ftrace uses to save the descriptors to manage the functions it can trace is shown at output. But if there are a lot of functions that are skipped because they were weak or the architecture added holes into the tables, then the extra pages that were allocated are freed. But these freed pages are not reflected in the numbers shown, and they can even be inconsistent with what is reported: ftrace: allocating 57482 entries in 225 pages ftrace: allocated 224 pages with 3 groups The above shows the number of original entries that are in the mcount_loc section and the pages needed to save them (225), but the second output reflects the number of pages that were actually used. The two should be consistent as: ftrace: allocating 56739 entries in 224 pages ftrace: allocated 224 pages with 3 groups The above also shows the accurate number of entires that were actually stored and does not include the entries that were removed. Signed-off-by: Steven Rostedt (Google) --- kernel/trace/ftrace.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index 55d28c060784..fa7c3417d995 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c @@ -7006,6 +7006,7 @@ static int ftrace_process_locs(struct module *mod, unsigned long addr; unsigned long kaslr; unsigned long flags = 0; /* Shut up gcc */ + unsigned long pages; int ret = -ENOMEM; count = end - start; @@ -7013,6 +7014,8 @@ static int ftrace_process_locs(struct module *mod, if (!count) return 0; + pages = DIV_ROUND_UP(count, ENTRIES_PER_PAGE); + /* * Sorting mcount in vmlinux at build time depend on * CONFIG_BUILDTIME_MCOUNT_SORT, while mcount loc in @@ -7125,6 +7128,8 @@ static int ftrace_process_locs(struct module *mod, remaining += 1 << pg->order; } + pages -= remaining; + skip = DIV_ROUND_UP(skip, ENTRIES_PER_PAGE); /* @@ -7138,6 +7143,13 @@ static int ftrace_process_locs(struct module *mod, synchronize_rcu(); ftrace_free_pages(pg_unuse); } + + if (!mod) { + count -= skipped; + pr_info("ftrace: allocating %ld entries in %ld pages\n", + count, pages); + } + return ret; } @@ -7783,9 +7795,6 @@ void __init ftrace_init(void) goto failed; } - pr_info("ftrace: allocating %ld entries in %ld pages\n", - count, DIV_ROUND_UP(count, ENTRIES_PER_PAGE)); - ret = ftrace_process_locs(NULL, __start_mcount_loc, __stop_mcount_loc);